/* ==========================================================================
   THE footer. Markup comes from footer.py; this is the only stylesheet for it.
   Loaded by every page, Framer-exported or generated.

   Two jobs:
     1. hide Framer's own footer, which we cannot delete (see below)
     2. style ours

   WHY FRAMER'S FOOTER IS HIDDEN AND NOT REMOVED
   ---------------------------------------------
   Framer ships the footer twice: in the exported HTML and inside its JS bundle.
   Delete it from the HTML and React re-inserts it at hydration - and, worse,
   the mismatch makes React re-render the surrounding tree, which is the exact
   fault that broke every footer link on this site (see the boot comment in
   enhance.js). So it stays in the DOM, untouched, and display:none keeps it off
   the page. React hydrates happily against markup it recognises; CSS is not
   something React can revert.
   ========================================================================== */

footer.framer-PFscP { display: none !important; }

/* Framer's header. Its root class is DIFFERENT on every page - framer-wv5hx on
   /, framer-1p6vm38 on /it, framer-pp04bk on /it/prezzi - so there is nothing
   stable to name. But every one of them is a <header> whose class begins with
   "framer-", and ours is <header class="sb-header">, so one structural rule
   separates them cleanly and no per-page <style> is needed. */
header[class^="framer-"] { display: none !important; }

/* Hiding the <footer> alone was not enough. Framer wraps it in a container that
   keeps its own reserved height, so the page still carried 1,223px of empty
   space between the FAQ and our CTA on desktop. :has() collapses the wrapper
   itself. The rule above stays as a fallback for anything without :has()
   support - there the old dead space returns, but the footer is still hidden,
   which is the safe direction to fail in. */
:has(> footer.framer-PFscP) { display: none !important; }

/* Framer's closing section reserves a huge padding-bottom - 500px on /, 518px
   on /contact, 400px on /pricing - because its absolutely-positioned CTA used
   to be laid ON TOP of that space. With the CTA rebuilt in normal flow that
   reservation is just a hole between the FAQ and the CTA. Measured dead space
   before this rule: 150-468px depending on page and width.

   Keyed on Framer's own data-framer-name. Each page has exactly one of these
   and it is always the closing section, verified across all eight pages. */
/* ^= and the `i` flag, not =. Framer writes data-framer-name="Contact Section "
   with a TRAILING SPACE on /contact and /it/contatti, so an exact match missed
   both pages and left 450px of hole there. The `i` also folds "Faq"/"FAQ",
   which Framer spells differently on different pages. */
[data-framer-name^="Faq Section" i],
[data-framer-name^="Contact Section" i] { padding-bottom: 72px !important; }

@media (max-width: 809px) {
  [data-framer-name^="Faq Section" i],
  [data-framer-name^="Contact Section" i] { padding-bottom: 48px !important; }
}

/* ============ tokens - self-contained, Framer pages do not define ours ===== */
.sb-footer {
  --sb-bg: rgb(0, 0, 0);
  --sb-fg: #fff;
  --sb-muted: rgba(248, 244, 241, .62);
  --sb-hair: rgba(248, 244, 241, .16);
  --sb-off: rgb(248, 244, 241);
  background: var(--sb-bg);
  font-family: "Satoshi", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  padding: 110px 0 0;
  margin: 0;
}
.sb-shell { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
.sb-footer *, .sb-footer *::before, .sb-footer *::after { box-sizing: border-box; }
.sb-footer p, .sb-footer ul, .sb-footer li { margin: 0; padding: 0; }
.sb-footer ul { list-style: none; }
.sb-footer img { display: block; max-width: 100%; }
.sb-nb { white-space: nowrap; }

/* ============ desktop grid ============ */
.sb-grid {
  display: grid;
  /* Daniel picked this after four attempts. The geometry, written down so
     nobody re-litigates it:

       EQUAL GUTTERS - identical space between one list and the next. Columns
                       then start at uneven intervals, because the lists are
                       different widths.
       EQUAL PITCH   - columns on a regular grid. The gutters then differ, for
                       exactly the same reason.

     You cannot have both unless every list is the same width, and ours run
     from "Home" to "Pre-Sales Consultation". This is EQUAL GUTTERS - 40px
     between every pair - with space-between so the block still spans from the
     brand to the right margin instead of leaving a hole on the right. */
  /* Daniel, 17 Aug: "move the company menu a couple points more left, as it's
     too close to product now". The brand column was 1fr, so it swallowed every
     spare pixel and pushed the five lists as far right as they would go.
     Fixing it at 210px hands 43px back: Company starts at 403 instead of 437,
     and space-between shares the rest so every gutter grows together, 40 ->
     49px. The block still ends flush with the right margin. */
  grid-template-columns: 210px repeat(5, max-content);
  justify-content: space-between;
  column-gap: 40px;
  row-gap: 0;
  padding-bottom: 88px;
}
/* .sb-footer prefix is required, not stylistic. The reset above is
   `.sb-footer p { margin: 0 }` - specificity 0,1,1. A bare `.sb-tagline` is
   0,1,0 and LOSES, so every margin in the brand block gets silently dropped and
   the logo, tagline and "Backed by" line stack flush against each other. */
.sb-footer .sb-logo { width: 52px; height: auto; }  /* the square mark */
.sb-footer .sb-tagline {
  color: var(--sb-muted);
  font-size: 14px;
  line-height: 1.5;
  margin-top: 18px;
}
.sb-footer .sb-backed {
  color: var(--sb-muted);
  font-size: 14px;
  margin-top: 44px;
  margin-bottom: 12px;
}
.sb-footer .sb-backed-img { width: 191px; height: auto; }

.sb-h4 {
  color: var(--sb-fg);
  font-size: 13.5px;
  font-weight: 500;
  display: block;
  margin-bottom: 16px;
}
.sb-grid > .sb-col-static { min-width: 128px; }
.sb-col li { margin-bottom: 9px; }
.sb-col a {
  color: var(--sb-muted);
  font-size: 14px;
  line-height: 1.35;
  text-decoration: none;
  transition: color .2s;
}
.sb-col a:hover, .sb-col a:focus-visible { color: var(--sb-fg); }

/* On desktop the <details> columns are plain columns: no marker, no pointer,
   and summary must not look clickable. They stay open - the markup ships with
   the open attribute and nothing here removes it above 810px. */
.sb-acc > summary {
  list-style: none;
  cursor: default;
  display: block;
}
.sb-acc > summary::-webkit-details-marker { display: none; }
.sb-acc > summary::marker { content: ""; }

/* ============ bottom row ============ */
.sb-bottom {
  border-top: 1px solid var(--sb-hair);
  padding: 26px 0 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
}
.sb-copy { color: var(--sb-off); font-size: 13.5px; opacity: .8;
  white-space: nowrap; }
.sb-legal { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.sb-legal a {
  color: var(--sb-off);
  font-size: 13.5px;
  opacity: .85;
  text-decoration: none;
  transition: opacity .2s;
}
.sb-legal a:hover, .sb-legal a:focus-visible { opacity: 1; }
.sb-legal img { width: 20px; height: 20px; }
/* The language switcher earns a border so it reads as a control, not legalese. */
.sb-legal a[data-lang-switch] {
  border: 1px solid var(--sb-hair);
  border-radius: 999px;
  padding: 5px 14px;
}
.sb-legal a[data-lang-switch]:hover { border-color: var(--sb-off); }

/* ============ phone ============ */
@media (max-width: 809px) {
  .sb-footer { padding-top: 64px; }
  .sb-shell { padding: 0 20px; }
  /* No padding here and no border on .sb-bottom below: the last accordion's
     border-bottom IS the divider. Having both drew two hairlines with an empty
     32px band between them, which read as a broken empty row. */
  .sb-grid {
    grid-template-columns: 1fr;
    gap: 0;
    padding-bottom: 0;
  }
  .sb-brand { margin-bottom: 40px; }
  .sb-footer .sb-backed { margin-top: 36px; }
  .sb-footer .sb-tagline { font-size: 15px; margin-top: 18px; }

  /* Static column keeps its heading spacing; collapsible ones become rows with
     a hairline, so the footer reads as a short list of sections rather than 24
     links in a stack. */
  .sb-col-static { margin-bottom: 28px; }
  .sb-col-static .sb-h4 { margin-bottom: 16px; }
  .sb-col li { margin-bottom: 12px; }
  .sb-col a { font-size: 17px; }

  .sb-acc { border-top: 1px solid var(--sb-hair); }
  .sb-acc:last-of-type { border-bottom: 1px solid var(--sb-hair); }
  .sb-acc > summary {
    cursor: pointer;
    padding: 18px 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    -webkit-tap-highlight-color: transparent;
  }
  .sb-acc > summary .sb-h4 { margin-bottom: 0; }
  /* Chevron, drawn in CSS so there is no icon file to lose. */
  .sb-acc > summary::after {
    content: "";
    width: 9px; height: 9px;
    border-right: 2px solid var(--sb-muted);
    border-bottom: 2px solid var(--sb-muted);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform .2s ease;
    flex: none;
  }
  .sb-acc[open] > summary::after { transform: rotate(-135deg) translate(-2px, -2px); }
  .sb-acc > ul { padding: 0 0 20px; }

  .sb-bottom {
    border-top: none;
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
    padding: 26px 0 40px;
  }
  .sb-copy { font-size: 13px; line-height: 1.5; white-space: normal; }
  .sb-legal { gap: 18px; }
  .sb-legal a { font-size: 15px; }
}

@media (prefers-reduced-motion: reduce) {
  .sb-footer *, .sb-footer *::after { transition: none !important; }
}

/* ==========================================================================
   THE closing CTA band. Markup from cta.py.

   Framer's version is absolutely positioned with pixel coordinates baked in:
   top:10366px on desktop, top:12216.8px on phone. On /about at 390px its
   container computed to top:-4597px - it rendered ABOVE the top of the page.
   On /it at 390px its content sat 939px above its own parent, on top of the
   FAQ. On desktop it left a dead ~900px gap before the footer.

   Framer's own copy is hidden by a per-page rule that tools/apply_footer.py
   injects into each page's <head> (see hide_legacy_cta_css there). It has to be
   CSS keyed on Framer's OWN class, not an attribute we add: React re-renders
   those nodes at hydration and strips anything we stamped on them - measured,
   three of eight pages lost the attribute. CSS it cannot revert.

   This one is in normal flow. No position:absolute, no magic numbers.
   ========================================================================== */

.sb-cta {
  display: block;
  padding: 0 24px;
  margin: 0 0 32px;
  font-family: "Satoshi", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.sb-cta *, .sb-cta *::before { box-sizing: border-box; }

/* Every number below was read off Framer's own rendering with getComputedStyle
   rather than eyeballed from a screenshot. At 1440 the card measures 1200x481,
   radius 40px, content inset 60px, and the pieces sit at y = 28 / 76 / 254 / 354.
   The gradient is Framer's background JPG sampled across its width:
   #F7FD47 -> #8DFE44 at the midpoint -> #2BFE41, flat vertically, so a plain
   90deg gradient reproduces it exactly and drops a 1200x481 image request. */
.sb-cta-card {
  max-width: 1200px;
  margin: 0 auto;
  background: linear-gradient(90deg, #F7FD47 0%, #8DFE44 50%, #2BFE41 100%);
  border-radius: 40px;
  padding: 33px 60px 76px;   /* 33, not 28: the chip's line box adds 5px of leading */
  text-align: center;
  position: relative;
  overflow: hidden;          /* keeps the decorative art inside the radius */
}

/* The chip is NOT centred - Framer sits it 40px in from the content edge and
   tilts it 6 degrees (matrix(0.994522, -0.104528, ...) is exactly -6deg). */
.sb-cta-eyebrow-row { text-align: left; padding-left: 40px; }
.sb-cta .sb-cta-eyebrow {
  display: inline-block;
  background: #fff;
  color: rgb(28, 28, 28);
  font-size: 14px;
  font-weight: 500;
  line-height: 23.8px;
  padding: 2px 16px;
  border-radius: 16px;
  transform: rotate(-6deg);
  position: relative;
  z-index: 2;
}

.sb-cta .sb-cta-h2 {
  color: rgb(0, 0, 0);
  font-size: 72px;
  font-weight: 700;
  letter-spacing: -2px;
  line-height: 1.15;
  margin: 15px 0 12px;
  position: relative;
  z-index: 2;
}
.sb-cta .sb-cta-body {
  color: rgb(0, 0, 0);
  font-size: 20px;
  font-weight: 400;
  line-height: 1.7;
  margin: 0 0 32px;
  position: relative;
  z-index: 2;
}
.sb-cta .sb-cta-btn {
  display: inline-block;
  background: rgb(11, 11, 12);
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  line-height: 27.2px;
  text-decoration: none;
  padding: 12px 30px;
  border-radius: 100px;
  position: relative;
  z-index: 2;
  transition: transform .2s ease, opacity .2s ease;
}
.sb-cta .sb-cta-btn:hover,
.sb-cta .sb-cta-btn:focus-visible { transform: translateY(-2px); opacity: .92; }

/* Framer's line-art flourish: 440x467 at x=713, y=7 inside the 1200x481 card,
   i.e. 47px from the right edge. It only renders on the widest variant - at
   1024 and 390 Framer does not show it - so neither do we. */
.sb-cta-decor {
  position: absolute;
  top: 7px;
  right: 47px;
  width: 440px;
  height: 467px;
  object-fit: cover;
  pointer-events: none;
  z-index: 1;
}

/* Framer's tablet variant: 56px headline, -2.24px tracking, 18px body. */
@media (max-width: 1199px) {
  .sb-cta-decor { display: none; }
  .sb-cta-card { padding: 28px 48px 64px; }
  .sb-cta .sb-cta-h2 { font-size: 56px; letter-spacing: -2.24px; }
  .sb-cta .sb-cta-body { font-size: 18px; }
}

/* Framer's phone variant: card 350x547, chip at y=51 and 17px in, headline
   36px/-2px, body 18px, button centred. Gaps measured at 36 / 12 / 32, and
   49px under the button. */
@media (max-width: 809px) {
  .sb-cta { padding: 0 20px; margin-bottom: 24px; }
  .sb-cta-card { padding: 56px 20px 49px; border-radius: 40px; }
  .sb-cta-eyebrow-row { padding-left: 17px; }
  .sb-cta .sb-cta-h2 { font-size: 36px; letter-spacing: -2px; margin: 42px 0 12px; }
  /* The <br> is a desktop line break; on a phone it lands mid-sentence, so let
     the headline wrap on its own. The space before it in cta.py keeps the two
     sentences apart once it is gone. */
  .sb-cta .sb-cta-h2 br,
  .sb-cta .sb-cta-body br { display: none; }
  .sb-cta .sb-cta-body { font-size: 18px; margin-bottom: 32px; }
}

@media (prefers-reduced-motion: reduce) {
  .sb-cta .sb-cta-btn { transition: none; }
}

/* ==========================================================================
   THE header. Markup from header.py.

   Framer's header is hidden by the same per-page mechanism as its CTA - a
   <style> injected by tools/apply_footer.py keyed on Framer's OWN class.

   Geometry read off Framer with getComputedStyle:
     wrapper  max-width 1200, padding 16px 30px, sticky at top 0
     shell    1140x88, radius 24px, #fff, padding 16px 70px
     logo     132px wide;  nav 16px/500 Satoshi, 48px gaps
     button   170x51, #CCFF00, radius 100px, padding 12px 30px, 16px/700
     phone    shell 330x60, radius 24px, logo 117px, burger 21x21
   ========================================================================== */

.sb-header {
  --sb-h-ink: rgb(0, 0, 0);
  --sb-h-lime: rgb(204, 255, 0);
  position: sticky;
  top: 0;
  z-index: 100;
  max-width: 1200px;
  margin: 0 auto;
  padding: 16px 30px;
  font-family: "Satoshi", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.sb-header *, .sb-header *::before { box-sizing: border-box; }

.sb-hdr-shell {
  background: #fff;
  border-radius: 24px;
  height: 88px;
  padding: 16px 34px 16px 40px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.sb-hdr-logo { display: block; flex: none; line-height: 0; }
.sb-hdr-logo img { width: 132px; height: auto; display: block; }

.sb-hdr-nav { display: flex; align-items: center; gap: 34px; }
.sb-hdr-nav a {
  font-size: 16px;
  font-weight: 500;
  line-height: 27.2px;
  color: var(--sb-h-ink);
  text-decoration: none;
  white-space: nowrap;
  transition: opacity .2s;
}
.sb-hdr-nav a:hover, .sb-hdr-nav a:focus-visible { opacity: .6; }
.sb-hdr-flag { display: inline-flex; line-height: 0; text-decoration: none; }
.sb-hdr-flag .sb-flag {
  display: block;
  border-radius: 4px;
  box-shadow: 0 0 0 1px rgba(18,10,11,.10);
  transition: transform .18s ease;
}
.sb-hdr-flag:hover .sb-flag { transform: scale(1.08); }

/* Two buttons, not one slab. The switcher sits with them, behind a hairline:
   it is a setting, not a destination. */
.sb-hdr-cta { flex: none; display: flex; align-items: center; gap: 10px; }
.sb-hdr-cta .sb-hdr-flag { margin-right: 4px; padding-right: 12px;
  border-right: 1px solid rgba(18,10,11,.12); }
.sb-hdr-btn {
  flex: none;
  display: inline-block;
  background: var(--sb-h-lime);
  color: var(--sb-h-ink);
  font-size: 15px;
  font-weight: 700;
  line-height: 27.2px;
  text-decoration: none;
  padding: 10px 22px;
  border-radius: 100px;
  white-space: nowrap;
  transition: transform .2s ease, background-color .2s ease, border-color .2s ease;
}
.sb-hdr-btn.sb-hdr-ghost {
  background: transparent;
  border: 1px solid rgba(18,10,11,.18);
  font-weight: 600;
}
.sb-hdr-btn.sb-hdr-ghost:hover, .sb-hdr-btn.sb-hdr-ghost:focus-visible {
  border-color: rgba(18,10,11,.45);
  background: rgba(18,10,11,.03);
  transform: none;
}
.sb-hdr-btn:hover, .sb-hdr-btn:focus-visible { transform: scale(1.04); }

/* Hidden until the hamburger breakpoint. A <button>, not a div, so it is
   focusable and announces its expanded state without extra ARIA plumbing. */
.sb-burger {
  display: none;
  flex: none;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  position: relative;
}
.sb-burger span {
  position: absolute;
  left: 5px;
  width: 22px;
  height: 2px;
  background: var(--sb-h-ink);
  border-radius: 2px;
  transition: transform .2s ease, opacity .2s ease;
}
.sb-burger span:first-child { top: 12px; }
.sb-burger span:last-child { top: 19px; }
.sb-open .sb-burger span:first-child { transform: translateY(3.5px) rotate(45deg); }
.sb-open .sb-burger span:last-child { transform: translateY(-3.5px) rotate(-45deg); }

.sb-panel { display: none; }

/* ---- 1024-1199: the nav stays but tightens ----
   This band is exactly where Framer's Italian header broke. At 48px gaps and
   70px shell padding the Italian labels (315px) plus the 132px logo plus the
   201px "Inizia il Pilota Gratuito" button overflow the shell and the button
   lands on top of "Contatti". At 24px gaps and 32px padding it clears. */
@media (max-width: 1199px) {
  .sb-hdr-shell { padding: 16px 32px; }
  .sb-hdr-nav { gap: 24px; }
}

/* ---- below 1024: hamburger ----
   Framer only switched at 768, but the Italian nav cannot fit above that: at
   768 the shell offers 644px of content and Italian needs 132 + 315 + 201.
   There is no arrangement that works, so the menu takes over earlier. */
@media (max-width: 1023px) {
  .sb-header { padding: 25px 30px; }
  .sb-hdr-shell { height: 60px; padding: 11px 29px; }
  .sb-hdr-logo img { width: 117px; }
  .sb-hdr-nav, .sb-hdr-btn, .sb-hdr-cta { display: none; }
  .sb-burger { display: block; margin-right: -5px; }

  .sb-panel {
    display: block;
    position: fixed;
    inset: 0;
    background: #fff;
    z-index: 99;
    padding: 110px 55px 40px;
    overflow-y: auto;
    opacity: 0;
    visibility: hidden;
    transition: opacity .18s ease;
  }
  .sb-open .sb-panel { opacity: 1; visibility: visible; }
  .sb-panel-inner { display: flex; flex-direction: column; gap: 35px; }
  .sb-panel-inner a {
    font-size: 20px;
    font-weight: 700;
    line-height: 1.35;
    color: var(--sb-h-ink);
    text-decoration: none;
  }
  .sb-panel-inner a:active { opacity: .6; }
  .sb-panel-inner .sb-hdr-flag .sb-flag { width: 30px; height: 20px; }
  /* The bar has to sit above its own panel, or the burger is unreachable. */
  .sb-hdr-shell { position: relative; z-index: 100; }
}

@media (prefers-reduced-motion: reduce) {
  .sb-header *, .sb-panel { transition: none !important; }
}

/* ---- nav dropdowns ----
   CSS-driven, opened by :hover and :focus-within, so keyboard users get the
   same menu without a line of JavaScript. The invisible bridge on ::after
   covers the gap between the label and the panel - without it the menu closes
   the instant the pointer leaves the text on its way down. */
.sb-nav-item { position: relative; display: inline-flex; align-items: center; }
.sb-nav-item::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 18px;
}
.sb-dd {
  position: absolute;
  top: calc(100% + 18px);
  /* LEFT-ALIGNED to the nav item, not centred on it: a 2-column panel centred
     on a 60px label hangs past the item on both sides and reads as belonging
     to whichever item it happens to sit under. -14px cancels the panel's own
     padding so the first LINK lines up with the label, not the panel edge. */
  left: -16px;
  transform: translateY(-6px);
  min-width: 260px;
  background: #fff;
  border-radius: 20px;
  padding: 14px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, .14);
  display: flex;
  flex-direction: column;
  gap: 2px;
  opacity: 0;
  visibility: hidden;
  transition: opacity .16s ease, transform .16s ease;
  z-index: 10;
}
.sb-nav-item:hover .sb-dd,
.sb-nav-item:focus-within .sb-dd {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.sb-hdr-nav .sb-dd a {
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
  padding: 9px 12px;
  border-radius: 10px;
  white-space: nowrap;
  transition: background .15s ease;
}
.sb-hdr-nav .sb-dd a:hover, .sb-hdr-nav .sb-dd a:focus-visible {
  background: rgba(0, 0, 0, .05);
  opacity: 1;
}
.sb-hdr-nav .sb-dd .sb-dd-all {
  margin-top: 6px;
  border-top: 1px solid rgba(0, 0, 0, .1);
  border-radius: 0 0 10px 10px;
  padding-top: 13px;
  font-weight: 700;
}

/* ---- two-column Use Cases menu: Workflows | Playbooks -------------------- */
/* One menu, two taxonomies. min-width, not width: the Playbooks column grows as
   playbooks are written, and a fixed width would either waste space today or
   clip the list in a month. */
.sb-dd-2col {
  flex-direction: row;
  align-items: flex-start;
  gap: 10px;
  min-width: 520px;
  padding: 16px;
}
.sb-dd-2col .sb-dd-col {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 232px;
}
/* The divider is a border on the second column rather than a separate element,
   so it cannot survive a column being removed. */
.sb-dd-2col .sb-dd-col + .sb-dd-col {
  border-left: 1px solid rgba(0, 0, 0, .1);
  padding-left: 12px;
}
.sb-hdr-nav .sb-dd-2col .sb-dd-head {
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: rgba(18, 10, 11, .45);
  padding: 6px 12px 8px;
}

/* The panel is absolutely positioned, so it must not be clipped or shifted by
   the shell. Below 1024 the whole nav is gone and the menu takes over. */
@media (max-width: 1023px) {
  .sb-dd { display: none; }
}

/* ==========================================================================
   THE homepage hero. Markup from hero.py, installed by tools/apply_footer.py.
   Only /index.html and /it.html carry it.

   Framer's hero is hidden rather than deleted, same reason as the footer: it
   ships in the JS bundle too, so removing the node makes React re-insert it
   and re-render the tree around it.

   The selector is Framer's OWN data-framer-name, not a class and not anything
   we stamp on. Class hashes differ per page (framer-15xj78c on /, framer-109wxoy
   on /it) and attributes WE add get stripped at hydration - that cost three of
   eight pages once already. data-framer-name survives because React is the
   thing writing it. Checked: "Title & Image Wrapper" exists on exactly these
   two pages, so the rule needs no per-page scoping.
   ========================================================================== */

[data-framer-name^="Title & Image" i] { display: none !important; }

/* The wrapper around it keeps its own padding and rounded top, so hiding the
   card alone leaves a white rounded stub above the logo band. Scoped with
   :has() because "Hero Section" also names the heroes on /about, /contact and
   their Italian twins - a bare rule would blank those pages. */
[data-framer-name^="Hero Section" i]:has([data-framer-name^="Title & Image" i]) {
  display: none !important;
}

/* ONE rule for both halves of the black slab. The hero card and the logo band
   below it are visually a single shape, and when they were owned by different
   things - ours and Framer's - they drifted apart above 1440px and the join
   showed a step. Sharing the selector makes that impossible rather than
   merely fixed. */
.sb-hero, .sb-logos {
  background: #fff;
  /* 30px + a max-width on the card, which together reproduce Framer exactly:
     x=30 at 1200, x=40 at 1440 (capped), x=280 at 1920 (capped and centred).
     The first version hard-coded 40px of padding with no cap, which matched at
     1440 and nowhere else - above that the card kept stretching while the Brand
     Logos band below it stayed at 1360, and the seam showed a step that got
     wider with the window. Measured against the band at 1200/1440/1600/1920/
     2200/2560. */
  padding: 16px 30px 0;
  /* Framer sets fonts per text node, never on a container, so anything we
     insert inherits nothing and lands on the UA default - the headline came out
     visibly wider and wrapped in the wrong place. The header carries the same
     stack for the same reason. */
  font-family: Satoshi, Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}
.sb-hero-card, .sb-logos-card {
  max-width: 1360px;
  margin: 0 auto;
}
.sb-hero-card {
  background: #000;
  border-radius: 24px 24px 0 0;
  /* Framer had padding: 50px 40px 591px, plus a 38px offset on the first child,
     so the eyebrow sat 88px below the card top. The 591px was NOT dead space -
     it reserved room for the absolutely-positioned wave video, which renders as
     a black rectangle in any browser that cannot decode H.264. Here the wave is
     a normal-flow child instead, so the reservation is just the 44px that sat
     below it. No horizontal padding: the wave spans the card edge to edge, so
     the side gutter belongs to .sb-hero-inner, not to the card. */
  padding: 88px 0 44px;
}
.sb-hero-inner {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

/* Measured off Framer: 1360x552 on desktop, 350x260 on a phone, and object-fit
   is `fill`, i.e. it stretches to whatever box it is given rather than keeping
   its aspect ratio. That is Framer's choice and changing it would change how
   the wave looks, so it is kept. */
.sb-hero-wave {
  display: block;
  width: 100%;
  height: 552px;
  object-fit: fill;
  background: #000;
  border: 0;
  pointer-events: none;
}
/* Belt and braces with the media query in hero.py's script: that one decides
   whether the file is ever fetched, this one decides whether the box exists.
   Both keyed on the same 810px so there is one boundary, not two. */
@media (max-width: 809px) {
  .sb-hero-wave { display: none; }
}
/* Framer runs a third variant between 768 and 1199.98: the wave is 466px tall
   there, not 552, with 26px under it instead of 44. Measured at 768/810/1000/
   1199/1200 - the step is exactly on Framer's 1200 breakpoint. */
@media (min-width: 810px) and (max-width: 1199.98px) {
  .sb-hero-wave { height: 466px; }
  .sb-hero-card { padding-bottom: 26px; }
}

/* THE HERO CHIP. Colour discipline: the two vendor marks keep their own
   brand colours (that is what makes them readable at 15px), everything else
   is white at three opacities, and the lime is reserved for the arrow. */
.sb-hero-chip {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  text-decoration: none;
  background: rgba(255, 255, 255, .05);
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: 999px;
  padding: 7px 17px 7px 13px;
  transition: background-color .2s ease, border-color .2s ease;
}
.sb-hero-chip:hover, .sb-hero-chip:focus-visible {
  background: rgba(255, 255, 255, .09);
  border-color: rgba(255, 255, 255, .26);
}
.sb-chip-seg { display: inline-flex; align-items: center; gap: 7px; }
.sb-chip-seg b { color: #f4f2ef; font-size: 14px; font-weight: 600; }
.sb-chip-seg span { color: rgba(244, 242, 239, .78); font-size: 14px; }
.sb-chip-sep { width: 1px; height: 16px; background: rgba(255, 255, 255, .18); }
.sb-chip-more { color: rgba(244, 242, 239, .6); font-size: 13.5px; }
.sb-chip-arrow { color: rgb(204, 255, 0); font-size: 14px; line-height: 1;
  transition: transform .2s ease; }
.sb-hero-chip:hover .sb-chip-arrow { transform: translateX(3px); }
.sb-chip-mark { display: block; flex: none; }
.sb-cflag { display: inline-block; vertical-align: -1px; border-radius: 3px;
  box-shadow: 0 0 0 1px rgba(255,255,255,.14); margin-right: 7px; }

/* phones: the long tail drops rather than wrapping the chip onto two lines */
@media (max-width: 640px) {
  .sb-hero-chip { gap: 9px; padding: 6px 14px 6px 11px; }
  .sb-chip-more, .sb-chip-sep:last-of-type { display: none; }
}

/* The lime eyebrow. It carries the category ("Managed Voice AI for
   e-commerce") so the headline is free to make the promise instead of naming
   the market. Sits between the Shopify chip and the h1: 30px below the chip,
   and the h1's own 16px top margin closes the gap under it. Satoshi 13px with
   the same .2em tracking as every other eyebrow on the site. */
.sb-hero-eyebrow {
  display: block;
  margin: 30px 0 -2px;
  font-size: 13px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgb(204, 255, 0);
}
.sb-hero-h1 {
  font-size: 72px;
  line-height: 82.8px;
  letter-spacing: -2px;
  font-weight: 700;
  color: #fff;
  margin: 16px 0 0;        /* measured off Framer: tag bottom to h1 top */
  max-width: 920px;
}
.sb-hero-sub {
  font-size: 20px;
  line-height: 34px;
  font-weight: 400;
  color: #fff;
  margin: 0;
  max-width: 660px;
}
.sb-hero-sub:first-of-type { margin-top: 16px; }
/* Framer sizes this holder per language - 644px on / and 800px on /it - so the
   Italian subhead keeps its three lines instead of spilling to four. */
.sb-hero[data-lang="it"] .sb-hero-sub { max-width: 800px; }

.sb-hero-hand {
  font-family: "Kalam", cursive;
  font-size: 19px;
  line-height: 1.1;
  color: #CCFF00;
  margin: 46px 0 0;
}

.sb-hero-nums {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
  width: min(880px, 100%);
  margin: 18px 0 0;
}
.sb-hero-num {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  text-decoration: none;
  background: rgba(255, 255, 255, .05);
  border: 1px solid rgba(255, 255, 255, .11);
  border-radius: 16px;
  padding: 18px 12px 16px;
  transition: background .16s ease, border-color .16s ease;
}
.sb-hero-num:hover, .sb-hero-num:focus-visible {
  background: rgba(204, 255, 0, .1);
  border-color: rgba(204, 255, 0, .45);
}
.sb-hero-cc {
  font-size: 11px;
  letter-spacing: 1.6px;
  font-weight: 700;
  text-transform: uppercase;
  color: rgba(255, 255, 255, .45);
}
/* Replaces the country label the moment the number is revealed, in the same
   grid cell so the line does not move. A revealed number with no affordance
   does not tell anyone that the next tap dials. */
/* This is the ONLY thing on the card that dials - clicking anywhere else
   toggles the number back off - so it has to read as a button, not a caption.
   The padding grows the tap target; the negative margin keeps the grid cell
   the same size it was, so the card does not change height when it opens. */
.sb-hero-call {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  font-size: 11px;
  letter-spacing: 1.6px;
  font-weight: 700;
  text-transform: uppercase;
  color: #CCFF00;
  white-space: nowrap;
  font-size: 10px;
  letter-spacing: 1.3px;
  background: rgba(204, 255, 0, .16);
  border-radius: 100px;
  /* Padding grows the tap target, the matching negative margin cancels its
     effect on layout, so the grid cell - and therefore the card - is exactly
     the same height open or closed. Kept tight here: with a mouse there is
     nothing to aim at, and the fat version read as a second button competing
     with the number underneath it. */
  padding: 3px 9px;
}
/* Touch has no hover and a fingertip is ~9mm, so the pill grows on phones and
   tablets. The matching negative margin keeps the row the same height, so the
   card does not change size between input types. */
@media (pointer: coarse) {
  .sb-hero-call { padding: 8px 12px; margin: -5px 0; }
}
.sb-hero-num.is-open:hover .sb-hero-call { background: rgba(204, 255, 0, .3); }
/* The number and the "Show number" prompt are stacked in the same cell, so the
   card is exactly as tall before the reveal as after it. Swapping one for the
   other with display:none would make the whole hero jump on every click. */
.sb-hero-slot { display: grid; justify-items: center; }
.sb-hero-slot > * { grid-area: 1 / 1; }
.sb-hero-no {
  font-size: 17px;
  font-weight: 700;
  color: #fff;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.3px;
  white-space: nowrap;
}
.sb-hero-reveal {
  font-size: 13.5px;
  font-weight: 600;
  color: rgba(204, 255, 0, .85);
  white-space: nowrap;
  align-self: center;
}

/* The CALL NOW row is always in the layout - only its visibility changes - so
   opening a card cannot resize it. That is why it is `visibility`, never
   `display`, throughout this block.

   Without JS the number is simply visible, neither prompt is, and every card is
   already a live tel: link on its first tap - see the comment on REVEAL_SCRIPT
   in hero.py. .sb-js inverts that. */
.sb-hero-reveal, .sb-hero-call { visibility: hidden; }
.sb-hero.sb-js .sb-hero-no { visibility: hidden; }
.sb-hero.sb-js .sb-hero-reveal { visibility: visible; }
.sb-hero.sb-js .sb-hero-num.is-open .sb-hero-no { visibility: visible; }
.sb-hero.sb-js .sb-hero-num.is-open .sb-hero-reveal { visibility: hidden; }
.sb-hero.sb-js .sb-hero-num.is-open .sb-hero-call { visibility: visible; }
.sb-hero.sb-js .sb-hero-num.is-open {
  background: rgba(204, 255, 0, .12);
  border-color: rgba(204, 255, 0, .5);
}

.sb-hero-listen {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin: 26px 0 0;
  color: rgba(255, 255, 255, .55);
  font-size: 14px;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, .3);
}
.sb-hero-listen:hover { color: #CCFF00; text-decoration-color: rgba(204, 255, 0, .6); }
.sb-hero-tri {
  width: 0; height: 0;
  border-left: 8px solid currentColor;
  border-top: 5.5px solid transparent;
  border-bottom: 5.5px solid transparent;
}

/* Framer's OWN phone boundary (767.98px), and the only thing keyed to it: the
   Brand Logos band below switches here too, so the card has to switch with it
   or the seam steps. Everything else about the hero switches at 809px, which is
   our own choice about type and the number grid - two boundaries because they
   answer two different questions. Below this the card is capped at 390px and
   centred, exactly as Framer does it. */
@media (max-width: 767.98px) {
  .sb-hero, .sb-logos { padding: 0 20px; }
  .sb-hero-card, .sb-logos-card { max-width: 390px; }
}

@media (max-width: 809px) {
  /* Framer's phone padding was 32px 40px 302px, again with the 38px child
     offset (70px to the eyebrow). Sides go to 22px rather than Framer's 40px:
     at 40px the content column is 270px and "+44 20 4525 8830" at 15px does not
     fit two-up. The headline still breaks to the same three lines. */
  /* No wave below 810px, so the card closes on the content instead of on the
     video: the 13px that used to sit under the wave becomes a normal bottom
     pad. */
  .sb-hero-card { padding: 70px 0 56px; }
  .sb-hero-inner { padding: 0 18px; }
  .sb-hero-eyebrow { margin: 22px 0 -2px; font-size: 11.5px; letter-spacing: .16em; }
  .sb-hero-h1 { font-size: 36px; line-height: 41.4px; margin-top: 18px; }
  .sb-hero-sub { font-size: 18px; line-height: 30.6px; }
  .sb-hero-hand { font-size: 17px; margin-top: 34px; }
  /* Two up at 390px leaves 141px of usable width per card. The longest number
     is the Naples one, +39 081 1818 1316, which needs 131px at 13.5px. The
     first pass used 15px in a 130px cell and clipped both it and the London
     number - real numbers are longer than the placeholders were, so this is
     measured against the real four, not guessed. */
  .sb-hero-nums { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
  .sb-hero-num { padding: 15px 6px 13px; }
  .sb-hero-cc, .sb-hero-call { font-size: 10px; letter-spacing: 1.2px; }
  .sb-hero-no { font-size: 13.5px; }
  .sb-hero-reveal { font-size: 13px; }
  .sb-hero-listen { font-size: 13px; margin-top: 22px; }
}

/* Narrower than 390 (iPhone 12/13/14, the common floor) two up cannot hold a
   13-digit Italian number: at 360px each cell has 126px of usable width and
   +39 081 1818 1316 needs 131. One column, four rows - taller, nothing clipped.
   Measured at 320, 360, 375, 390, 414 and 430. */
@media (max-width: 389px) {
  .sb-hero-nums { grid-template-columns: 1fr; }
  .sb-hero-no { font-size: 15px; }
}


/* ==========================================================================
   THE brand-logo band. Markup from logos.py. Framer's is hidden by its own
   data-framer-name, same technique as the hero.

   Width comes from the shared .sb-hero/.sb-logos rules above - that is the
   whole point of rebuilding this strip, so read those first.
   ========================================================================== */

/* Conditional on ours being present. An unscoped rule also blanked the small
   39px logo strip on /pricing and /it/prezzi, which Framer gives the same name
   but which is a different component in a different place. :has() ties the
   hiding to the replacement, so a page we have not rebuilt keeps what it had. */
body:has(.sb-logos) [data-framer-name^="Brand Logos" i] { display: none !important; }

/* The shared .sb-hero/.sb-logos rule carries `padding: 16px 30px 0` - the 16px
   is the white margin ABOVE the hero, and the band must not repeat it or a
   white line appears across the middle of the slab. Framer's gap between the
   two is exactly 0 at every width; measured. */
.sb-logos { padding-top: 0; }
.sb-logos-card {
  background: #000;
  border-radius: 0 0 24px 24px;
  padding: 74px 40px;
}
/* Locked, not derived from content: 74 + 32 + 74 = the 180px Framer reserves,
   so the band cannot grow if a logo file is ever swapped for a taller one. */
.sb-logos-viewport {
  height: 32px;
  overflow: hidden;
}
.sb-logos-track {
  display: flex;
  align-items: center;
  gap: 32px;
  width: max-content;
  margin: 0;
  padding: 0;
  list-style: none;
  /* Exactly two copies of the six, so -50% lands on the identical frame it
     started from. 1075px of content at Framer's measured 50px/s. */
  animation: sb-marquee 21.5s linear infinite;
}
.sb-logos-item {
  display: flex;
  align-items: center;
  gap: 32px;
}
.sb-logos-item img { display: block; }
.sb-logos-line {
  flex: 0 0 1px;
  width: 1px;
  height: 20px;
  background: rgb(248, 244, 241);
}

@keyframes sb-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
/* Framer's ticker ignores this. A logo strip is decoration; nobody should get
   motion sickness from it. */
@media (prefers-reduced-motion: reduce) {
  .sb-logos-track { animation: none; }
}

@media (max-width: 767.98px) {
  .sb-logos-card { padding: 32px 20px; }
  /* Only the gap BETWEEN items drops to 20px on a phone. The gap inside each
     item - logo to its separator line - stays 32px, which is what Framer does
     and is easy to get wrong: setting both to 20 shortened the set to 930px and
     the strip ran 7% slow. Set is 1002px, so 20.06s is the same 50px/s. */
  .sb-logos-track { gap: 20px; animation-duration: 20.06s; }
}

/* ==========================================================================
   THE proof widget - Creative Cables. Markup from proof.py.

   Emitted at the end of <body> and moved in front of the FAQ section after
   load; see the docstring in proof.py for why it cannot simply be written
   there at build time. It ships `hidden` so it never flashes at the bottom of
   the page before the move.
   ========================================================================== */

/* width: 100% on both, and it is load-bearing. This section gets MOVED inside
   Framer's tree at runtime, and the parent it lands in is a centring flex
   column - so the card is a flex item and shrink-to-fits its content. The
   moment the inner rail capped the content at 1040px the card quietly followed
   it down to 1152px and stopped lining up with the hero above it. Measured:
   card left edge went from 40px to 144px with no rule touching the card. */
.sb-proof { background: #fff; padding: 0 30px; width: 100%; box-sizing: border-box; }
.sb-proof[hidden] { display: none; }
/* The homepage copy is slotted between two Framer sections that bring their own
   vertical rhythm. An authored page has none to inherit, so the inline copy
   supplies it - 96px, the same top padding every other section on a playbook
   page uses, so "Success stories" is not glued to the section above it. */
/* .sb-proof.sb-proof-inline, not .sb-proof-inline: the phone block further down
   sets `padding: 0 20px` on .sb-proof, and a shorthand later in the file beats a
   single-class rule earlier in it - which is why the top padding was 96px on
   desktop and silently 0 on mobile. Two classes outrank one at any position. */
.sb-proof.sb-proof-inline { padding-top: 96px; }
@media (max-width: 767.98px) { .sb-proof.sb-proof-inline { padding-top: 64px; } }
.sb-proof-card {
  width: 100%;
  box-sizing: border-box;
  /* 1200, not 1360. The hero and the logo band run at 1360 because they are
     full-bleed openers; every CONTENT section on this site - the closing CTA
     band, the footer shell, Framer's FAQ - runs at 1200. This card sat 160px
     wider than the closing CTA band it shares a page with, and since both are
     big black rounded cards, that mismatch was the only thing you could see. */
  max-width: 1200px;
  margin: 0 auto;
  background: #000;
  border-radius: 24px;
  padding: 56px 56px 52px;
  color: #fff;
  font-family: Satoshi, Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}
/* Section header, on the white background ABOVE the black card - so it reads
   as a section of the page like Features or FAQ, not as a caption belonging to
   the card. Same 1360px rail as the hero and the logo band, so the left edge
   of "Success stories" lines up with everything else on the page. */
.sb-proof-head {
  width: 100%;
  box-sizing: border-box;
  max-width: 1200px;
  margin: 0 auto 30px;
  text-align: center;
  font-family: Satoshi, Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
.sb-proof-head h2 {
  margin: 0;
  font-size: 44px;
  line-height: 1.12;
  font-weight: 700;
  letter-spacing: -1.4px;
  color: #0A0A0A;
}
.sb-proof-head p {
  /* auto side margins, not just text-align: the 58ch cap would otherwise sit
     hard left and only its text would look centred. */
  margin: 12px auto 0;
  font-size: 18px;
  line-height: 1.55;
  color: rgba(10, 10, 10, .62);
  max-width: 58ch;
}

/* Name on the left, customer mark hard right, one line. Sized by height and
   not width: the next customer's logo will have completely different
   proportions and a fixed width would render one of them enormous. */
.sb-proof-by {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-top: 18px;
}
.sb-proof-logo {
  display: block;
  flex: 0 0 auto;
  height: 34px;
  width: auto;
  opacity: .92;
}
.sb-proof-eyebrow {
  margin: 0;
  font-size: 12px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  font-weight: 700;
  color: rgba(248, 244, 241, .5);
}

/* The numbers come SECOND now and are sized to look it. Daniel wanted Marco to
   outrank the metrics, and prominence is a budget: making the face and the
   quote bigger only reads as a hierarchy if the figures also come down. They
   were 54px above a 22px quote - the quote could not win at any size while
   that held. Below the quote, behind a top rule, they read as the receipt for
   what he just said, which is the job they were always doing. */
.sb-proof-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 28px;
  max-width: 1000px;
  margin: 38px auto 0;
  padding: 30px 0 0;
  border-top: 1px solid rgba(248, 244, 241, .16);
  text-align: center;
}
.sb-proof-num {
  display: block;
  font-size: 56px;
  line-height: 1.03;
  font-weight: 900;
  letter-spacing: -1.8px;
  color: #CCFF00;
  font-variant-numeric: tabular-nums;
}
.sb-proof-lab {
  display: block;
  /* auto margins for the same reason as the subtitle: a left-anchored 26ch box
     inside a centred cell centres the text but not the block. */
  margin: 10px auto 0;
  font-size: 14.5px;
  line-height: 1.45;
  color: rgba(248, 244, 241, .66);
  max-width: 26ch;
}

/* The hero of the card. `align-items: center` and not flex-start: with a 132px
   portrait next to two lines of quote, top-aligning leaves the face floating
   above a short block of text. */
/* INNER RAIL. The card keeps the site's 1360px width so its edges line up with
   the hero and the logo band, but the content inside runs at 1040px. At the
   full width a line of quote was ~110 characters, well past the 60-75 that
   reads comfortably, and the right-aligned logo ended up 690px from the name
   it belongs to - which is what read as "not aligned". Same rail on the stats
   below, so the three columns and the quote share one left and right edge. */
.sb-proof-quote {
  display: flex;
  align-items: center;
  gap: 44px;
  /* 1000 inside a 1200 card with 56px padding leaves a 44px inset each side -
     the same breathing room the 1040 rail had inside the old 1360 card. */
  max-width: 1000px;
  margin: 30px auto 0;
}
/* 260px and a 20px radius: EXACTLY what templates/customer.html gives the
   portrait on the case study page. Daniel asked for the same size, and taking
   the shape with it means the widget and the page it links to read as one
   thing rather than two designs of the same man. If that template changes,
   change this with it - the pairing is the point. */
.sb-proof-face {
  flex: 0 0 260px;
  width: 260px;
  height: 260px;
  border-radius: 50%;
  object-fit: cover;
  display: block;
  background: rgba(248, 244, 241, .1);
  /* The lime ring, back by request. At 260px it needs 3px to read as a ring
     rather than an artefact - 2px looked like a rendering seam at this size. */
  box-shadow: 0 0 0 3px rgba(204, 255, 0, .6);
}
.sb-proof-said { min-width: 0; }
.sb-proof-said blockquote {
  margin: 0;
  font-size: 27px;
  line-height: 1.42;
  font-weight: 500;
  letter-spacing: -.45px;
  /* Wider than the old 62ch so the bigger type does not run to five lines. */
  max-width: 56ch;
}
/* English runs shorter than Italian for the same quote, so it carries more size
   at the same line count. Per language, not global: at 30px the Italian quote
   spills to five lines and unbalances the card against the 260px portrait.
   Wrapped in min-width, because a language selector outranks a plain media
   query - unwrapped it also won on phones and pushed the English quote to
   EIGHT lines, a 1062px card against Italian's 898px. */
@media (min-width: 768px) {
  .sb-proof[data-lang="en"] .sb-proof-said blockquote {
    font-size: 30px;
    letter-spacing: -.55px;
  }
}
.sb-proof-who {
  margin: 0;
  min-width: 0;
  font-size: 15px;
  line-height: 1.5;
  color: rgba(248, 244, 241, .6);
}
.sb-proof-who b { display: block; color: #fff; font-weight: 700; }

.sb-proof-cta {
  /* flex + width:fit-content + auto margins. `inline-flex` cannot be centred by
     auto margins - it has no free space to distribute - which is why this is a
     block-level flex box rather than the inline one it started as. */
  display: flex;
  width: fit-content;
  align-items: center;
  margin: 34px auto 0;
  background: #CCFF00;
  color: #0A0A0A;
  border-radius: 100px;
  padding: 14px 28px;
  font-size: 16px;
  font-weight: 700;
  text-decoration: none;
  transition: transform .15s ease;
}
.sb-proof-cta:hover { transform: translateY(-1px); }
/* The arrow lives in its own span so the gap survives: a leading space inside
   an inline-flex child is collapsed away, which is why it read as "study→". */
.sb-proof-cta span { margin-left: 8px; }

@media (max-width: 767.98px) {
  .sb-proof { padding: 0 20px; }
  .sb-proof-head { margin-bottom: 20px; }
  .sb-proof-head h2 { font-size: 30px; letter-spacing: -.9px; }
  .sb-proof-head p { font-size: 16px; margin-top: 10px; }
  .sb-proof-card { padding: 30px 22px 30px; border-radius: 20px; }
  /* Three 54px numbers do not fit a 350px card. One column keeps each figure
     next to the label that explains it, which is the point of the figure. */
  /* Three columns, not one. As the SECOND element they are a supporting strip,
     and a strip is what a row reads as; three stacked 40px figures after the
     quote would take the prominence straight back. 26px still fits "39%" in a
     ~95px column at 350px card width - measured, not guessed. */
  .sb-proof-stats {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px; margin-top: 28px; padding-top: 24px;
  }
  .sb-proof-num { font-size: 34px; letter-spacing: -1.1px; }
  .sb-proof-lab { font-size: 11.5px; line-height: 1.35; max-width: none; }
  /* Centred here too, so the whole card reads on one axis on a phone. */
  .sb-proof-quote { flex-direction: column; align-items: center; text-align: center; gap: 22px; margin-top: 24px; }
  /* 180px, matching templates/customer.html's phone breakpoint for the same
     portrait, and round like its desktop self. */
  .sb-proof-face { flex: 0 0 180px; width: 180px; height: 180px; }
  .sb-proof-said blockquote { font-size: 20px; line-height: 1.5; letter-spacing: -.3px; }
  /* Stacked, not spread: name over logo. justify-content: space-between on a
     ~330px line pushed the mark so far right it read as a separate element. */
  .sb-proof-by { flex-direction: column; gap: 14px; margin-top: 16px; }
  .sb-proof-logo { height: 26px; }
  .sb-proof-cta { margin-top: 26px; font-size: 15px; padding: 13px 24px; }
}

/* ============================================================
   Cookie consent banner  (consent.py -> tools/inject_consent.py)
   ============================================================
   A THIN STRIP. One row on desktop: one line of text, three small buttons.
   It is meant to be answerable at a glance and ignorable while you read, which
   is also the compliant shape - no overlay, no cookie wall, page fully usable.

   Accept and reject stay the same size, same row, same layer. Small is fine;
   asymmetric is not. There is no bare X, because a close button that quietly
   means "accept" is the most-enforced dark pattern of the lot. */
.sb-consent {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 2147483000;
  padding: 0 16px 16px;
  font-family: var(--font, "Satoshi", "Inter", -apple-system, sans-serif);
}
.sb-consent[hidden] { display: none; }
.sb-c-card {
  /* rgb(0,0,0) - the same surface as .sb-footer, .cta-band, .queue-band and
     .sb-proof-card. NOT rgb(18,10,11): that is --ink, the primary TEXT colour,
     and it shipped here by mistake. It reads as a warm off-black patch sitting
     against the pure-black footer, which is exactly where this bar spends most
     of its life. Two tokens, two jobs - ink is for type, black is for surfaces. */
  max-width: 1200px; margin: 0 auto; background: rgb(0, 0, 0);
  border-radius: 14px; padding: 11px 16px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .26);
}
/* The row. Text takes the slack, buttons never shrink. */
.sb-c-bar { display: flex; align-items: center; gap: 16px; }
.sb-c-bar p {
  flex: 1 1 auto; margin: 0; font-size: 13.5px; line-height: 1.45;
  color: rgba(248, 244, 241, .8);
}
.sb-c-bar a { color: rgb(204, 255, 0); text-decoration: underline;
  text-underline-offset: 2px; white-space: nowrap; }

.sb-c-btns { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.sb-c-btn {
  font-family: inherit; font-size: 13px; font-weight: 700; line-height: 1;
  padding: 9px 16px; border-radius: 100px; border: 1px solid transparent;
  cursor: pointer; white-space: nowrap;
  transition: opacity .15s ease, background .15s ease;
}
.sb-c-btn:hover { opacity: .88; }
.sb-c-btn:focus-visible { outline: 2px solid rgb(204, 255, 0); outline-offset: 2px; }
.sb-c-primary { background: rgb(204, 255, 0); color: rgb(18, 10, 11); }
/* Identical box to primary. Only the fill differs. */
.sb-c-ghost { background: transparent; color: #fff;
  border-color: rgba(248, 244, 241, .4); }
.sb-c-text { background: transparent; color: rgba(248, 244, 241, .68);
  padding: 9px 6px; font-weight: 500; text-decoration: underline;
  text-underline-offset: 3px; }

/* Preferences: expands the strip downward, still compact. */
.sb-c-prefs { margin-top: 10px; border-top: 1px solid rgba(248, 244, 241, .14); }
.sb-c-row {
  display: flex; align-items: flex-start; gap: 14px; padding: 10px 0;
  border-bottom: 1px solid rgba(248, 244, 241, .09); cursor: pointer;
}
.sb-c-row:last-child { border-bottom: 0; }
.sb-c-rt { flex: 1; }
.sb-c-rt b { display: block; font-size: 13px; font-weight: 700; color: #fff; }
.sb-c-rt i {
  display: block; margin-top: 2px; font-style: normal; font-size: 12.5px;
  line-height: 1.5; color: rgba(248, 244, 241, .62);
}
.sb-c-row input { width: 17px; height: 17px; margin-top: 1px; flex: none;
  accent-color: rgb(204, 255, 0); cursor: pointer; }
.sb-c-row input:disabled { cursor: default; opacity: .5; }

/* With preferences open, "Save choices" is the action being asked for, so it
   takes the lime and accept drops to the outline. Accept and reject are then
   IDENTICAL, which satisfies equal prominence more strictly, not less. */
.sb-consent.sb-c-open .sb-c-btn[data-sb-c="accept"] {
  background: transparent; color: #fff; border-color: rgba(248, 244, 241, .4);
}

/* Below ~900px the sentence and three buttons stop fitting on one line, so the
   row wraps: text first, buttons under it. Accept and reject split the width
   evenly - on a phone a side-by-side pair at natural width shrinks the second
   one, which is exactly the asymmetry the rules are about. */
@media (max-width: 900px) {
  .sb-consent { padding: 0 10px 10px; }
  .sb-c-card { padding: 12px 14px; border-radius: 12px; }
  .sb-c-bar { flex-wrap: wrap; gap: 10px; }
  .sb-c-bar p { flex: 1 1 100%; font-size: 13px; }
  .sb-c-btns { flex: 1 1 100%; gap: 8px; }
  .sb-c-btns .sb-c-primary, .sb-c-btns .sb-c-ghost { flex: 1 1 0; }
  .sb-c-text { flex: 0 0 auto; }
}

/* ==========================================================================
   ABOUT: lift the hero.

   Daniel, 17 Aug: "in the about page the hero seems too down, make it go up a
   bit". Measured before touching it: the h1 sat at y=350 against 282 on
   /contact and 283 on /pricing, because Framer gave this one section 230px of
   top padding where the others have 162 and 63. So this is not a nudge, it is
   bringing the page back to the rest of the site.

   Two hashed classes because Framer generates a different one per language -
   /about is framer-15e5r8z, /it/chi-siamo is framer-24pj9z. Keyed on Framer's
   own class exactly like the legacy-CTA hide in tools/apply_footer.py; if a
   re-export ever changes them, the rule stops applying and the page goes back
   to its old spacing rather than breaking.
   ========================================================================== */
.framer-15e5r8z, .framer-24pj9z { padding-top: 150px !important; }

@media (max-width: 809px) {
  .framer-15e5r8z, .framer-24pj9z { padding-top: 96px !important; }
}

/* ---------------------------------------------------------------------------
   THE EYEBROW LABEL. Daniel, 17 Aug 2026: "is it the case of killing the red
   colour for the pills? I'm thinking it doesn't make sense". It doesn't.

   Red lived on ten Framer-origin pages and nowhere else: every page generated
   since - five product pages, nine use cases, six playbooks, nine industries,
   the blog - already uses a grey letter-spaced eyebrow. Red was the leftover,
   not the system. It also competed with the lime, which is the only colour on
   this site that should be pulling the eye, because it is the only one that
   means "do something".

   Replaced with a 7px lime dot and a grey label: the rhythm a long page needs
   from a repeating marker, our own brand colour rather than an orphan one, and
   a shape that cannot be mistaken for a button.

   SELECTOR. The pill is a shared Framer component (.framer-Ct5Fx) that also
   renders in lime on /about, white for "Get Started" and black on /404, so
   restyling the class would repaint all of them. What is unique to the red ones
   is the colour token Framer names inline, so the attribute selector keys on
   that instead. Change the token id here if the Framer project is republished
   with a new palette.
   --------------------------------------------------------------------------- */
[style*="16cbd617"] {
  background: transparent !important;
  border: 0 !important;
  border-radius: 0 !important;
  padding: 0 !important;
  display: inline-flex !important;
  align-items: center;
  gap: 9px;
}
[style*="16cbd617"]::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgb(204, 255, 0);
  flex: none;
}
[style*="16cbd617"] p,
[style*="16cbd617"] span {
  color: rgb(111, 106, 102) !important;
  font-size: 12px !important;
  line-height: 1.2 !important;
  font-weight: 700 !important;
  letter-spacing: .18em !important;
  text-transform: uppercase !important;
}
@media (max-width: 809px) {
  [style*="16cbd617"] { gap: 7px; }
  [style*="16cbd617"]::before { width: 6px; height: 6px; }
  [style*="16cbd617"] p,
  [style*="16cbd617"] span { font-size: 11px !important; letter-spacing: .15em !important; }
}
