/* ============================================================
   pronto-intervento24.it — global.css
   HOMEPAGE ONLY.

   Scoped strictly to what index.php, includes/header.php and
   includes/footer.php actually use. Nothing here is kept "in case
   another page needs it".

   Service pages load their own stylesheet:
     /assets/css/elettricista.css, fabbro.css, idraulico.css,
     caldaie.css, condizionatore.css, spurgo.css
   built from service-starter.css.

   Service files must never redefine tokens, .btn or .container —
   they only add sections this file does not have.

   Sections kept:
     0 fonts · 1 tokens · 2 reset · 3 container · 4 typography
     5 buttons · 6 header + mobile nav · 7 hero (split variant)
     8 tile strip · 9 about · 10 feature cards · 11 service cards
     12 FAQ · 13 CTA band · 14 region tabs · 15 coverage map
     16 city link groups · 19 footer · 20 sticky call bar
============================================================ */

/* ============================================================
   0. FONTS — system stack, nothing to download
   Owner's call, 24 Sep 2026. This section used to declare seven
   self-hosted @font-face rules (Archivo 600/700/800/900, Inter
   400/600/700) pointing at /assets/fonts/. That directory has never
   existed: all seven 404'd on every page load, every face sat in
   "error" state, and document.fonts.check() returned false for both
   families — so every page has in fact always rendered in the
   fallback, "Helvetica Neue"/Arial. Verified at request level before
   removing, not assumed (this was _PHASE-6-LOG.md A53).

   Archivo and Inter were the rebuild's own typography choice; the old
   WordPress site never used them either — its pages set
   "font-family: Arial" inline throughout. Removing the rules
   therefore changes nothing on screen and drops seven failed requests
   per page load, which matters on a site that is 85–95% mobile.

   The family names are gone from --font-display/--font-body below
   too, so the tokens say what actually renders. To reinstate the
   intended typography later: drop the seven .woff2 files into
   /assets/fonts/, restore these @font-face rules, and put "Archivo"
   and "Inter" back at the front of those two tokens.

   NOTE: 'Barlow Condensed' was referenced in the old section 13 but
   never loaded either. Removed at the same time.
============================================================ */


/* ============================================================
   1. DESIGN TOKENS  — the only :root in this file
============================================================ */
:root {
  /* --- Brand blues --- */
  --green-950:#1A1B27;  --green-900:#0e395e;  --green-800:#184069;
  --green-700:#2275ac;  --green-500:#2991d6;  --green-100:#e9f5fc;
  --green-050:#f7f8f1;
 
  /* --- Accent oranges --- */
  --amber-600:#F35A00;  --amber-500:#ff5100;  --amber-400:#fb8b4a;
  --amber-050:#f8f7f1;
 
  --gold-500:#d6a243;   --live-500:#28a745;
 
  /* --- Neutrals --- */
  --ink-900:#444444;  --ink-700:#626262;  --ink-500:#a8a8a8;
  --paper-000:#FFFFFF; --paper-050:#FCFCFC;
  --line-200:#EBEBEB; --line-100:#F2F2F2;
 
  /* --- Aliases kept so section 13's markup keeps working.
         Remapped onto the real palette (they previously pointed at a
         separate, unrelated colour set). --- */
  --ink:var(--green-900);
  --ember:var(--amber-500);
  --ember-dark:var(--amber-600);
  --cream:var(--amber-050);
  --line:var(--line-200);
  --paper:var(--paper-000);
 
  /* --- Type ---
     "Archivo"/"Inter" removed from the front of these two stacks on
     24 Sep 2026 along with their @font-face rules (see §0): the files
     never existed, so these are the families that were already
     rendering. The two tokens stay separate even though they now
     resolve identically — every component picks one deliberately, and
     keeping them distinct is what makes reinstating real display/body
     faces later a two-line change. */
  --font-display:"Helvetica Neue",Arial,sans-serif;
  --font-body:"Helvetica Neue",Arial,sans-serif;
  --font-head:var(--font-display);   /* alias, was Barlow Condensed */
 
  /* --- Spacing scale --- */
  --space-3xs:4px;  --space-2xs:8px;  --space-xs:12px;  --space-s:16px;
  --space-m:24px;   --space-l:32px;   --space-xl:48px;  --space-2xl:64px;
 
  /* --- Radius / shadow --- */
  --radius-s:10px; --radius-m:16px; --radius-l:26px;
  --radius:var(--radius-s);          /* alias */
  --shadow-card:0 1px 2px rgba(14,57,94,.06), 0 8px 24px rgba(14,57,94,.08);
  --shadow-pop:0 12px 40px rgba(14,57,94,.16);
  --shadow:var(--shadow-card);       /* alias */
 
  /* --- Layout --- */
  --max-w:1240px;
  --gutter:clamp(20px,5vw,64px);
 
  /* --- Fluid grid defaults. Override per component. --- */
  --col-min:280px;   /* narrowest a column may get before wrapping */
  --gap:var(--space-m);
  --cols-max:99;     /* hard ceiling on columns; 99 = uncapped */
 
  --header-h:88px;
  --logo-h:clamp(48px,12vw,66px);   /* header logo height, also feeds --mega-gap */
  --callbar-h:56px;
}


/* ============================================================
   2. RESET & BASE
============================================================ */
*,*::before,*::after { box-sizing:border-box; margin:0; padding:0; }
 
html { scroll-behavior:smooth; -webkit-text-size-adjust:100%; }
@media (prefers-reduced-motion:reduce){
  html { scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important;
  }
}
 
body{
  font-family:var(--font-body);
  color:var(--ink-700);
  background:var(--paper-050);
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;           /* belt-and-braces against mobile side-scroll */
}
 
img,svg,video,canvas{ display:block; max-width:100%; }
img,video{ height:auto; }
button,input,select,textarea{ font:inherit; color:inherit; }
button{ cursor:pointer; background:none; border:none; }
a{ text-decoration:none; color:inherit; }
ul,ol{ list-style:none; }
 
/* Long unbroken strings (phone numbers, URLs) must never widen the page */
p,li,td,th{ overflow-wrap:break-word; }
h1,h2:where(:not(.h1-look)),h3,h4,h5,h6,
h2:where(.h1-look){ overflow-wrap:normal; }
 
:target{ scroll-margin-top:calc(var(--header-h) + var(--space-s)); }
 
a:focus-visible,button:focus-visible,[tabindex]:focus-visible,
input:focus-visible,select:focus-visible,textarea:focus-visible,
summary:focus-visible{
  outline:3px solid var(--amber-500);
  outline-offset:3px;
  border-radius:4px;
}


/* ============================================================
   3. LAYOUT PRIMITIVES
   These are the pieces that make item counts irrelevant.
   Use them before writing any new grid CSS.
============================================================ */
 
/* --- Container: never overflows, no media queries needed --- */
.container,.wrap{
  width:min(100% - (var(--gutter) * 2), var(--max-w));
  margin-inline:auto;
}
 

 

 


 

 

 









 


 
section{ padding-block:clamp(56px,8vw,108px); }


/* ============================================================
   4. TYPOGRAPHY
============================================================ */
h1,h2:where(:not(.h1-look)),h3,h4,h5,h6,
/* ============================================================ 4. TYPOGRAPHY ============================================================ */ h2:where(.h1-look){
  font-family:var(--font-display);
  color:var(--ink-900);
  line-height:1.08;
  letter-spacing:-.01em;
  text-wrap:balance;
}
h1,
h2:where(.h1-look){ font-size:clamp(2rem,1.45rem + 2.4vw,3.25rem); font-weight:900; }
h2:where(:not(.h1-look)){ font-size:clamp(1.9rem,1.5rem + 1.8vw,3rem);   font-weight:800; }
h3{ font-size:clamp(1.15rem,1.05rem + .5vw,1.45rem); font-weight:700; }
h4{ font-size:clamp(1.1rem,1.02rem + .4vw,1.3rem);   font-weight:700; }
h5{ font-size:1.1rem; font-weight:700; }
h6{ font-size:1rem;   font-weight:700; }
 
p{ color:var(--ink-700); }
 
.section-kicker{
  display:inline-flex; align-items:center; gap:var(--space-2xs);
  font-family:var(--font-body); font-weight:600; font-size:.95rem;
  color:var(--green-700); margin-bottom:14px;
}
.section-kicker::before{
  content:""; width:8px; height:8px; border-radius:50%;
  background:var(--live-500); flex-shrink:0;
  animation:kicker-pulse 2s ease-out infinite;
}
/* A ring that grows out of the dot and fades. box-shadow does not affect layout,
   so nothing around it moves. The prefers-reduced-motion rule near the top of this
   file already cuts every animation to a single instant for visitors who ask. */
@keyframes kicker-pulse{
  0%  { box-shadow:0 0 0 0 color-mix(in srgb, var(--live-500) 60%, transparent); }
  70% { box-shadow:0 0 0 8px transparent; }
  100%{ box-shadow:0 0 0 0 transparent; }
}
 
 
.visually-hidden{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); white-space:nowrap;
}

/* head.php emits .skip-link but nothing styled it, so it rendered as a
   plain visible link and pushed the whole page (header included) ~25px
   down. Off-screen until focused, which is what a skip link is for —
   the link, its text and its target are untouched. */
.skip-link{
  position:absolute; left:-9999px; top:0;
  z-index:200;
  background:var(--green-900); color:var(--paper-000);
  padding:10px 18px; border-radius:0 0 var(--radius-s) 0;
  font-weight:700; font-size:.92rem;
}
.skip-link:focus{ left:0; }


/* ============================================================
   5. BUTTONS  — single source of truth
============================================================ */
.btn{
  display:inline-flex; align-items:center; justify-content:center;
  gap:10px;
  font-family:var(--font-body); font-weight:700; font-size:1rem;
  padding:16px 28px;
  border-radius:999px;
  border:2px solid transparent;
  min-height:44px;                     /* tap target — do not remove */
  white-space:nowrap;
  text-align:center;
  transition:transform .15s ease, box-shadow .15s ease,
             background .15s ease, color .15s ease, border-color .15s ease;
}
.btn:active{ transform:scale(.98); }
 
.btn--primary{
  background:var(--amber-500); color:var(--paper-000);
  box-shadow:0 10px 26px rgba(255,81,0,.35);
}
.btn--primary:hover{ background:var(--amber-600); box-shadow:0 14px 30px rgba(255,81,0,.45); }
 


 


 
/* Outlined secondary — pairs with .btn--primary on light backgrounds.
   .btn already reserves a 2px transparent border, so this swaps the
   colour in without changing the button's size. */
.btn--outline{
  background:var(--paper-000);
  color:var(--green-900);
  border-color:var(--green-900);
}
.btn--outline:hover{ background:var(--green-100); }

/* Ghost — a plain text link for a secondary action that must not
   compete with .btn--primary (e.g. "Vedi i prezzi" beside "Chiama
   subito"). No fill, no border, tighter padding: just coloured text
   with its icon, so attention stays on the primary button beside it.
   min-height:44px still comes from .btn, so the tap target holds. */
.btn--ghost{
  padding:8px 4px;
  background:none;
  border-color:transparent;
  box-shadow:none;
  color:var(--ink-700);
  text-decoration:underline;
  text-decoration-color:transparent;
  text-underline-offset:4px;
}
.btn--ghost:hover{ color:var(--green-900); text-decoration-color:currentColor; }
.btn--ghost svg{ width:18px; height:18px; }

/* Was referenced by .about__content but never defined. */
.btn--white{ background:var(--green-900); color:var(--paper-000); }
.btn--white:hover{ background:var(--green-800); color:var(--paper-000); }
 


 
.btn--lg{ padding:20px 40px; font-size:1.15rem; }

 
.icon-phone{ width:20px; height:20px; flex-shrink:0; }
 
/* On phones a lone primary button should fill the width */
@media (max-width:600px){
  .btn--lg{ width:100%; padding:17px 24px; font-size:1.05rem; }
}

/* Very small phones (320px class): long labels such as "Chiama Subito
   Pronto Intervento Elettricista 24" no longer fit on one line, so
   buttons may wrap and long words in headings may break instead of
   pushing the page wider than the screen. */
@media (max-width:359px){
  .btn{ white-space:normal; max-width:100%; line-height:1.25; }
  h1,h2:where(:not(.h1-look)),h3,h4,
h2:where(.h1-look){ overflow-wrap:anywhere; }
}


/* ============================================================
   6. HEADER + MOBILE NAV
============================================================ */
.site-header{
  position:sticky; top:0; z-index:130;
  background:rgba(255,255,255,.92);
  backdrop-filter:blur(10px);
  border-bottom:1px solid var(--line-200);
}
.site-header__inner{
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:nowrap;
  gap:clamp(8px,2vw,var(--space-s));
  padding-block:10px;
  min-width:0;
}
.site-logo{ flex-shrink:0;
  font-family:var(--font-display); font-weight:800; font-size:1.15rem;
  color:var(--green-950); display:flex; align-items:center; gap:10px;
  min-width:0; flex:0 1 auto;
}
/* Logo size. Was 44px, then 52px with the header held at 72px; the owner
   still found it small, so the header is now allowed to grow with it:
   66px logo + 2 x 10px padding + 1px border = ~87px on desktop, ~69px
   on a phone (48px logo, still taller than the 44px hamburger). The file
   is 275x101, so it stays sharp well past this. */
.site-logo img{ height:var(--logo-h); width:auto; flex-shrink:0; max-width:none; }
 
.site-nav{ display:none; }
.site-nav__list{
  display:flex;
  list-style:none; margin:0; padding:0;
  gap:clamp(16px,2vw,28px);
  font-weight:600; font-size:.95rem; color:var(--ink-700);
}
.nav-item > a{ padding-block:4px; white-space:nowrap; }
.nav-item > a:hover,.nav-item > a[aria-current="page"]{ color:var(--green-900); }

/* --- Mega-menu trigger (caret) — shown on mobile only; desktop opens
   the panel on hover/focus, see the ≥900px block below --- */
.nav-item__toggle{
  display:none;
  border:0; background:none; padding:0; margin:0; color:inherit; cursor:pointer;
}
.nav-item__caret{
  display:block; width:8px; height:8px;
  border-right:2px solid currentColor; border-bottom:2px solid currentColor;
  transform:rotate(45deg);
  transition:transform .2s ease;
}
/* Scoped to the service's own toggle — a plain descendant selector here
   outranks the region-chevron rule below and flips all of those too. */
.nav-item.is-open > .nav-item__toggle .nav-item__caret{ transform:rotate(-135deg); }

/* --- Mega-menu — one panel, two panes: a single column of region
   names, and the active region's cities beside it. Only one region's
   cities are ever rendered visible, so the panel never shows more than
   ~15 links at once and never grows with the service's total size.
   Positioning differs per breakpoint — see the two blocks below. --- */
.mega-menu__regions{ list-style:none; margin:0; padding:0; }
.mega-region__toggle{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  width:100%; text-align:left;
  border:0; border-radius:8px; background:none; padding:5px 10px; margin:0;
  font-family:var(--font-display); font-weight:600; font-size:.82rem;
  line-height:1.35; color:var(--green-900); cursor:pointer;
  transition:background .14s ease, color .14s ease;
}
.mega-region__toggle:hover{ background:var(--green-050); }
.mega-region.is-active > .mega-region__toggle{
  background:var(--amber-050); color:var(--amber-600);
}
.mega-region__toggle .nav-item__caret{
  opacity:.45; transform:rotate(-45deg); transition:opacity .14s ease;
}
.mega-region.is-active > .mega-region__toggle .nav-item__caret{ opacity:1; }

/* --- A region that is a page of its own: link + caret, two targets.

   The row splits so one tap means one thing on a phone — the name
   navigates, the caret opens the sub-list. On desktop it makes no odds,
   because the panel opens on hover over the whole row.

   The pair has to look identical to the single-button rows above it, so
   the <li> takes over the flex layout the button used to do, and the
   link and caret inherit the same type, padding and rounding. The
   highlight (hover, active, you-are-here) moves to the <li> too, so it
   spans the whole row rather than lighting only the half the pointer
   happens to be over. --- */
.mega-region--linked{
  display:flex; align-items:center; gap:4px;
  border-radius:8px;
  transition:background .14s ease;
}
.mega-region--linked:hover{ background:var(--green-050); }
.mega-region--linked.is-active{ background:var(--amber-050); }

/* Written as ".mega-menu a.mega-region__link" — 0,2,1 — for the same
   reason .mega-menu__title--link is (see the note further down): the
   later ".mega-menu a" rule is 0,1,1 and would otherwise win on source
   order, dropping this row to 500 weight and --ink-700. The linked rows
   then rendered visibly lighter and thinner than the plain ones beside
   them, which is exactly what the row must NOT do — it has to look like
   every other region in the list. */
.mega-menu a.mega-region__link{
  display:block;
  flex:1 1 auto; min-width:0;
  padding:5px 4px 5px 10px;
  font-family:var(--font-display); font-weight:600; font-size:.82rem;
  line-height:1.35; color:var(--green-900); text-decoration:none;
}
.mega-region--linked.is-active > a.mega-region__link{ color:var(--amber-600); }
.mega-menu a.mega-region__link:hover{ color:var(--amber-600); }

/* The caret keeps a 44px-wide tap target even though the glyph is tiny —
   it is the only way into the sub-list on a phone. */
.mega-region__toggle--caret{
  flex:0 0 auto;
  width:auto; min-width:34px;
  justify-content:center;
  padding:5px 10px 5px 4px;
  background:none;
}
.mega-region--linked:hover > .mega-region__toggle--caret,
.mega-region--linked.is-active > .mega-region__toggle--caret{ background:none; }

.mega-region__panel{ display:none; }
.mega-region__panel.is-active{ display:block; }
.mega-menu__title{
  font-family:var(--font-display); font-weight:700; font-size:.72rem;
  color:var(--ink-700); text-transform:uppercase; letter-spacing:.06em;
  margin:0 0 10px;
}
@media (min-width: 900px) {
  .mega-region__panel:not(.mega-region__panel--solo) .mega-menu__title {
    display: none;
  }
}
/* Six regions are pages of their own, so their panel heading is an <a>
   instead of a <p>. It has to keep reading as the heading of the list
   below it while showing it can be clicked, so it carries the same type
   as the <p> version and adds only an underline that warms on hover.

   Written as ".mega-menu a.mega-menu__title--link" — 0,2,1 — on purpose.
   Two later rules would otherwise win on source order at 0,1,1:
   ".mega-menu a" (weight 500) and, inside the desktop block,
   ".mega-menu__pane--cities a" (font-size .95rem). At plain
   "a.mega-menu__title--link" this heading rendered at 15.2px/500 and read
   as another city row instead of the heading above them. */
.mega-menu a.mega-menu__title--link{
  display:inline-block;
  padding:0;
  font-family:var(--font-display); font-weight:700; font-size:.72rem;
  line-height:inherit;
  color:var(--ink-700); text-transform:uppercase; letter-spacing:.06em;
  text-decoration:underline;
  /* --line-200 was invisible here: it is a border tint, and against the
     panel's own background the underline simply did not read, so the
     heading looked identical to the six that are not links. --ink-500 is
     the faintest token that still shows at 11.5px. */
  text-decoration-color:var(--ink-500);
  text-underline-offset:3px;
  transition:color .14s ease, text-decoration-color .14s ease;
}
.mega-menu a.mega-menu__title--link:hover{
  color:var(--amber-600);
  text-decoration-color:var(--amber-500);
}
/* On the region's own page the heading is the "you are here" marker. */
.mega-menu a.mega-menu__title--link[aria-current="page"]{
  color:var(--amber-600);
  text-decoration-color:var(--amber-500);
}

/* A region with no cities under it — Valle d'Aosta, in three services.
   Its pane holds the heading and nothing else, and at heading size that
   read as a caption stranded above an empty list rather than as the one
   thing there to click. Here the heading takes the type of a city row
   instead, because functionally that is what it is: the single
   destination in this pane. No wording changes, only its size. */
.mega-region__panel--solo a.mega-menu__title--link{
  font-family:var(--font-body);
  font-size:.95rem;
  font-weight:500;
  text-transform:none;
  letter-spacing:normal;
  padding:7px 0;
}

.mega-region__panel ul{ list-style:none; margin:0; padding:0; }

/* Sub-heading inside a grouped panel — "Apertura Porte" is the only region
   that has any. Its seven groups were each a top-level row in the old menu;
   they are one row now, so their names sit over their own links here.

   Deliberately lighter than .mega-menu__title above it: that one names the
   whole panel, these divide it, and if both shouted the panel would read as
   eight competing headings rather than one heading with sections. Same
   uppercase display type at a smaller size and a softer colour, so the
   hierarchy is legible at a glance.

   No top margin on the first one — .mega-menu__title already leaves 10px
   under itself, and doubling that detached the first group from the heading
   it belongs to. */
.mega-menu__subtitle{
  font-family:var(--font-display); font-weight:700; font-size:.66rem;
  color:var(--ink-500); text-transform:uppercase; letter-spacing:.05em;
  margin:14px 0 4px;
}
.mega-region__panel > .mega-menu__subtitle:first-of-type{ margin-top:0; }
.mega-menu a{
  display:block; padding:4px 0; font-weight:500; font-size:.85rem;
  line-height:1.4; color:var(--ink-700); white-space:normal;
}
.mega-menu a:hover{ color:var(--amber-600); }

/* --- You-are-here.

   On a city page the menu marks the whole path down to it: the service
   in the top bar, that service's region in the left pane, and the city
   itself. header.php also opens the panel on the visitor's own region
   rather than always the first, so the list they need is the one
   showing when the panel appears.

   .is-current is deliberately a different class from .is-active, which
   hover drives: moving the pointer to another region must swap which
   cities show WITHOUT erasing the marker saying where you actually
   are. The two can sit on the same region at once, and the rules below
   are written so that reads correctly either way.

   These rules must stay AFTER the .nav-item and .mega-menu rules
   above. Several of them tie on specificity with the hover and
   [aria-current] rules, so source order is what decides. --- */
.nav-item.is-current > a{
  position:relative;
  color:var(--amber-600);
}
.nav-item.is-current > a::after{
  content:"";
  position:absolute; left:0; right:0; bottom:-3px;
  height:2px; border-radius:2px;
  background:var(--amber-500);
}

.mega-region.is-current > .mega-region__toggle,
.mega-menu .mega-region.is-current > a.mega-region__link{
  color:var(--amber-600);
  font-weight:700;
}
/* Current AND hovered-off: keep the orange text, drop the fill so the
   region the pointer is on is still the one that looks selected. */
.mega-region.is-current:not(.is-active) > .mega-region__toggle{
  background:none;
}
.mega-region--linked.is-current:not(.is-active){ background:none; }

.mega-menu a.is-current{
  color:var(--amber-600);
  font-weight:700;
}

/* Back bar — mobile-only "drill-down" navigation; desktop shows both
   panes at once, so there is nothing to go back from. */
.mega-menu__back{
  display:none;
  align-items:center; gap:10px;
  border:0; border-radius:8px; background:var(--green-050);
  padding:11px 12px; margin:0 0 12px;
  font-family:var(--font-display); font-weight:700; font-size:.88rem;
  color:var(--green-900); cursor:pointer; width:100%; text-align:left;
}
.mega-menu__back-caret{
  display:block; width:8px; height:8px; flex-shrink:0;
  border-left:2px solid currentColor; border-bottom:2px solid currentColor;
  transform:rotate(45deg);
}

/* z-index sits above the mobile drawer (120) on purpose: the drawer is
   fixed from the very top of the viewport, so without this it paints
   over the hamburger and there is no visible way to close the menu. */
.site-header__call{
  display:flex; align-items:center;
  gap:clamp(6px,1.6vw,10px);
  flex-shrink:0; min-width:0;
  position:relative; z-index:125;
}
/* Iscriviti / Login. Two text buttons where the phone block and the
   call CTA used to be, so they have to share the room one button and a
   number had. Tighter padding, and nowrap so neither label ever breaks
   across two lines and grows the header. */
.site-header__cta{
  padding:11px 18px; font-size:.9rem;
  white-space:nowrap;
}

/* Mobile-drawer copy of the two buttons above (see header.php). Hidden
   here; the ≤899px block below turns it on and hides .site-header__cta's
   pair in its place, so exactly one pair is ever visible at once. */
.site-nav__actions{ display:none; }

/* --- Hamburger --- */
.nav-toggle{
  display:inline-flex; align-items:center; justify-content:center;
  width:44px; height:44px; border-radius:12px;
  border:1px solid var(--line-200); background:#fff; color:var(--green-900);
  flex-shrink:0;
}
.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after{
  content:""; display:block; width:20px; height:2px;
  background:currentColor; border-radius:2px;
  transition:transform .2s ease, opacity .2s ease, background .2s ease;
}
.nav-toggle__bars{ position:relative; }
.nav-toggle__bars::before{ position:absolute; top:-6px; }
.nav-toggle__bars::after { position:absolute; top:6px; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars{ background:transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before{ transform:translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after { transform:translateY(-6px) rotate(-45deg); }
 
/* --- Backdrop --- */
.nav-backdrop{
  position:fixed; inset:0; z-index:110;
  background:rgba(26,27,39,.45);
  opacity:0; transition:opacity .25s ease;
}
.nav-backdrop.is-open{ opacity:1; }
.nav-backdrop[hidden]{ display:none; }
 
/* ============================================================
   MOBILE — below 900px
   backdrop-filter is removed here on purpose: an element with
   backdrop-filter becomes the containing block for its fixed-position
   descendants, which would trap the drawer inside the header.
============================================================ */
@media (max-width:899px){
  .site-header{
    backdrop-filter:none;
    background:var(--paper-000);
  }
 
  /* Starts below the header rather than at the top of the viewport, so
     the header stays a whole, un-clipped bar with its close button in
     its normal place instead of the drawer sliding over the top of it.
     --header-bottom is measured by site.js; the static --header-h
     fallback is short of the header's actual rendered height. */
  .site-nav{
    position:fixed; inset:var(--header-bottom,var(--header-h)) 0 0 auto;
    width:min(86vw,340px);
    display:block;
    background:var(--paper-000);
    padding:var(--space-s) var(--space-m) var(--space-xl);
    box-shadow:var(--shadow-pop);
    border-top:1px solid var(--line-200);
    transform:translateX(100%);
    transition:transform .25s ease;
    overflow-y:auto;
    overscroll-behavior:contain;
    z-index:120;
  }
  .site-nav.is-open{ transform:translateX(0); }

  .site-nav__list{ flex-direction:column; gap:0; }
  .nav-item{ position:relative; border-bottom:1px solid var(--line-100); }
  .nav-item.has-mega > a{ padding-right:52px; }

  .nav-item > a{
    display:flex; align-items:center; min-height:52px;
    padding:var(--space-xs) 0;
    font-size:1.02rem; font-weight:700; color:var(--green-900);
    white-space:normal;
  }
  /* An open service stays visibly marked while you're inside it. */
  .nav-item.is-open > a{ color:var(--amber-600); }

  /* Tap-to-expand accordion — hover doesn't exist on touch. Tapping the
     service reveals its region list; tapping a region swaps to its
     cities as a second screen with a back bar, instead of nesting
     everything inline into a wall of indented rows. */
  .nav-item__toggle{
    display:flex; align-items:center; justify-content:center;
    position:absolute; top:0; right:-4px;
    width:52px; height:52px;
    border-radius:10px;
    color:var(--green-900);
  }
  .nav-item.is-open .nav-item__toggle{
    background:var(--amber-050); color:var(--amber-600);
  }

  .mega-menu{
    display:grid; grid-template-rows:0fr;
    transition:grid-template-rows .25s ease;
  }
  .mega-menu__panel{ overflow:hidden; min-height:0; }
  .nav-item.is-open .mega-menu{ grid-template-rows:1fr; }

  /* Inset + tinted so an open sub-level reads as "inside" its service
     rather than as more top-level rows. */
  .mega-menu__pane{
    padding:var(--space-xs);
    margin-bottom:var(--space-xs);
    background:var(--green-050);
    border-radius:var(--radius-s);
  }
  .mega-region__toggle{
    min-height:44px; font-size:.95rem; padding:8px 10px;
  }
  .mega-region__toggle .nav-item__caret{ opacity:.6; }

  /* Split rows on a phone: both halves get their own 44px target, and a
     hairline between them so it reads as two things to tap rather than
     one wide one. Without it a thumb aiming for the caret lands on the
     link and navigates away instead of opening the sub-list. */
  .mega-menu a.mega-region__link{
    min-height:44px; display:flex; align-items:center;
    font-size:.95rem; padding:8px 4px 8px 10px;
  }
  .mega-region__toggle--caret{
    min-height:44px; min-width:44px;
    padding:8px 10px;
    border-left:1px solid var(--line-200);
    border-radius:0 var(--radius-s) var(--radius-s) 0;
  }

  .mega-menu__pane--cities{ display:none; }
  .mega-menu.is-drilled .mega-menu__pane--regions{ display:none; }
  .mega-menu.is-drilled .mega-menu__pane--cities{ display:block; }
  .mega-menu__back{ display:flex; background:var(--paper-000); }
  .mega-menu__title{ padding-inline:10px; }
  .mega-menu a{ padding:9px 10px; font-size:.95rem; }

  body.nav-open{ overflow:hidden; }

  /* Iscriviti/Login move into the drawer below 899px, so the header bar
     itself only ever has to fit the logo and the hamburger — this is what
     replaces the old shrink-the-buttons rules that used to live below 620
     and 430px (removed; the buttons they targeted no longer render on
     that path at all, so there was nothing left for them to do). */
  .site-header__cta{ display:none; }
  .site-nav__actions{
    display:flex; gap:10px;
    margin-top:var(--space-m);
    padding-top:var(--space-m);
    border-top:1px solid var(--line-200);
  }
  /* Tightened from the .btn base (16px 28px, 1rem): the drawer is
     min(86vw,340px) wide with 24px of side padding, so two equal-width
     pills split ~292px minus the 10px gap between them. At the base size
     "Iscriviti" — the longer label — was tight against wrapping. */
  .site-nav__actions .btn{
    flex:1 1 0; min-width:0;
    padding:12px 14px; font-size:.92rem;
    white-space:nowrap;
  }
}

@media (min-width:900px){
  .site-nav{ display:flex; }
  .nav-toggle{ display:none; }
  .nav-backdrop{ display:none; }

  /* Hover/focus flyout.

     Anchored to the nav LIST, not to the individual nav item, and made
     wider than that list — so there is always panel directly beneath
     whichever service you're pointing at, and the panel's left edge is
     identical for all six (it can't walk off the right of the screen).

     --mega-gap is the dead strip between the bottom of a nav link and
     the top of the panel: half the row's spare height around the 24px nav line,
     (max(logo, 44px) - 24px) / 2, plus .site-header__inner's 10px padding-block plus
     the header's 1px bottom border. ::before re-covers exactly that
     strip, so moving the cursor straight down from a nav link never
     leaves :hover and the panel can't flicker shut mid-travel. */
  .site-nav__list{ position:relative; }
  .nav-item{ position:static; }
  /* Padding on an inline <a> grows the hover target without changing
     the header's height, so there's more to aim at on the way down. */
  .nav-item > a{ padding-block:10px; }

  .mega-menu{
    --mega-gap:calc((max(var(--logo-h),44px) - 24px) / 2 + 11px);
    position:absolute; top:calc(100% + var(--mega-gap)); left:0;
    width:min(640px,calc(100vw - 2 * var(--gutter)));
    background:var(--paper-000);
    border:1px solid var(--line-200);
    border-radius:var(--radius-m);
    box-shadow:var(--shadow-pop);
    /* No pointer-events here on purpose. visibility:hidden already makes
       the closed panel unclickable, and unlike pointer-events it is a
       transitioned property — so it stays "visible" (and therefore
       interactive) for the whole grace period below. With
       pointer-events:none the panel went inert the instant :hover was
       lost: still on screen, but the mouse fell through it to the page
       behind, so moving back onto it could not reopen it and the delay
       bought nothing. */
    opacity:0; visibility:hidden;
    transform:translateY(-4px);
    /* --mega-close-delay is a grace period on the CLOSING direction
       only: this rule is what applies once :hover is lost, so the delay
       here keeps the panel up while the cursor cuts a corner or crosses
       a gap. The :hover rule below zeroes it, so opening stays instant. */
    --mega-close-delay:.3s;
    transition:
      opacity .15s ease var(--mega-close-delay),
      transform .15s ease var(--mega-close-delay),
      visibility .15s var(--mega-close-delay);
    z-index:150;
  }
  .mega-menu::before{
    content:"";
    position:absolute; left:0; right:0;
    top:calc(-1 * var(--mega-gap)); height:var(--mega-gap);
  }
  .nav-item.has-mega:hover .mega-menu,
  .nav-item.has-mega:focus-within .mega-menu{
    opacity:1; visibility:visible;
    transform:translateY(0);
    --mega-close-delay:0s;              /* opens with no lag */
  }

  .mega-menu__panel{ display:flex; align-items:stretch; }

  /* One plain column of regions. Width is set so the longest names
     ("Apertura Porte Emilia – Romagna") stay on one line — wrapped rows
     were what pushed Fabbro's 20 regions past the cap into a scrollbar. */
  .mega-menu__pane--regions{
    /* Width is set so the longest name stays on one line AT THE SIZE
       ABOVE — 268px was right at .82rem and wraps "Apertura Porte
       Emilia – Romagna" at .9rem. A wrapped row is not just untidy: it
       costs a row's height in a column already capped for scrolling. */
    flex:0 0 296px;
    padding:10px;
    /* Raised with the type below. Measured from the space actually left
       under the header rather than a flat vh share, so the panel can't
       run past the bottom of a short window. Fabbro is the worst case:
       21 regions at 27px a row is 567px, so they fit down to roughly a
       730px-tall window and scroll below that. */
    max-height:min(calc(100vh - 120px),660px);
    overflow-y:auto;
  }
  /* Desktop type: larger than the mobile drawer's, and with real space
     between rows — these are pointing targets, not a dense list.

     The vertical padding is 4px, not 5px, because restoring Fabbro
     Valle d'Aosta took the fabbro menu from 20 regions to 21 (see
     _PHASE-6-LOG.md A15) and a 21st row at the old height pushed the
     column past the cap above, bringing the scrollbar back at window
     heights where it used to fit. 2px off each row buys back 42px,
     more than the 29px the new row costs, so 21 regions now clear the
     cap in slightly LESS height than 20 used to.

     This affects the desktop column only. The mobile drawer sets its
     own min-height:44px in the <=900px block and is untouched.

     The linked rows (a link plus a caret button) take the same size and
     vertical padding, so a row that happens to be a page of its own is
     indistinguishable from the rest of the column. Only the horizontal
     padding differs, because the row's 10px is split between the two
     halves instead of sitting on one element. */
  .mega-region__toggle{
    padding:4px 10px;
    font-size:.9rem;
  }
  .mega-menu a.mega-region__link{
    padding:4px 4px 4px 10px;
    font-size:.9rem;
  }
  .mega-region__toggle--caret{
    padding:4px 10px 4px 4px;
  }

  /* The cities for whichever region is pointed at. 15 is the most any
     one region has, which is well inside the cap. */
  .mega-menu__pane--cities{
    flex:1 1 auto; min-width:0;
    padding:16px 20px;
    border-left:1px solid var(--line-100);
    background:var(--paper-050);
    border-radius:0 var(--radius-m) var(--radius-m) 0;
    max-height:min(calc(100vh - 120px),660px);
    overflow-y:auto;
  }
  .mega-menu__pane--cities a{
    font-size:.95rem;
    padding:7px 0;
  }

  .mega-menu__back{ display:none; }
}


/* ============================================================
   7b. HERO — .hero--split variant
   APPEND THIS AT THE END OF SECTION 7 IN global.css
   (immediately before the "8. SERVICE TILE STRIP" comment)

   Two-column hero: copy left, photo right with floating stat cards.
   Overrides the photo-background hero without touching it, so the
   homepage's existing .hero and .hero--compact keep working.

   Selectors use .hero.hero--split (0,3,0) rather than .hero--split
   (0,2,0) so they beat the base .hero .hero__grid rules regardless
   of where this block ends up in the file.
============================================================ */

.hero.hero--split{
  position:relative;
  overflow:hidden;
  background:var(--green-050);
  padding-block:clamp(28px,5vw,72px);
  color:var(--ink-700);
}

/* Was a decorative gradient wash (purely visual, aria-hidden in
   markup) — removed in favour of the hero's own flat --green-050
   background. The element stays in the markup, just unrendered, so
   nothing else needs to change. */
.hero--split .hero__shape{ display:none; }

/* Reset everything the photo-hero set on the grid */
.hero.hero--split .hero__grid{
  position:relative;
  z-index:1;
  width:min(100% - (var(--gutter) * 2), var(--max-w));
  margin-inline:auto;
  padding-inline:0;
  padding-block:0;
  min-height:0;
  background-image:none;
  background-color:transparent;
  border-radius:0;
  box-shadow:none;
  display:grid;
  gap:clamp(32px,5vw,64px);
  align-items:center;
  grid-template-columns:minmax(0,1fr);
}
@media (min-width:980px){
  .hero.hero--split .hero__grid{
    grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr);
    gap:clamp(40px,5vw,80px);
  }
}

/* The copy is no longer a card sitting on a photo */
.hero.hero--split .hero__copy{
  background:transparent;
  box-shadow:none;
  border-radius:0;
  margin:0;
  padding:0;
  display:block;
}

.hero--split .hero__copy .section-kicker{ margin-bottom:16px; }

/* One hero title treatment for every page on this banner: same size,
   always capitals. text-transform rather than retyped copy, so a title
   written in sentence case in the source still reads as capitals and
   the source words stay untouched. Service stylesheets must not
   override the size — the longer titles simply wrap onto more lines. */
.hero.hero--split h1,
.hero.hero--split .hero__headline,
/* One hero title treatment for every page on this banner: same size, always capitals. text-transform rather than retyped copy, so a title written in sentence case in the source still reads as capitals and the source words stay untouched. Service stylesheets must not override the size — the longer titles simply wrap onto more lines. */ .hero.hero--split h2:where(.h1-look){ text-transform:uppercase; }
.hero.hero--split h1,
.hero.hero--split h2:where(.h1-look){
  font-size:clamp(2.1rem,1.4rem + 3vw,3.6rem);
  line-height:1.02;
  letter-spacing:-.02em;
}
/* Orange highlight inside the H1 */
.hero h1 .accent,
/* Orange highlight inside the H1 */ .hero h2:where(.h1-look) .accent{ color:var(--amber-500); }

.hero.hero--split .hero__sub{
  margin-top:16px;
  max-width:44ch;
}

.hero.hero--split .hero__actions{
  margin-top:26px;
  padding-top:0;
  border-top:0;
  max-width:none;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-xs);
}
/* One per row on phones, so neither button gets squeezed. */
@media (max-width:480px){
  .hero.hero--split .hero__actions{ flex-direction:column; align-items:stretch; }
}

/* --- Trust list: any number of items, 1 col on phones, 2 above --- */
.hero__trust{
  display:grid;
  gap:10px var(--space-m);
  grid-template-columns:repeat(auto-fit,minmax(min(200px,100%),1fr));
  margin-top:28px;
  padding-top:24px;
  border-top:1px solid var(--line-200);
  max-width:520px;
}
.hero__trust li{
  display:flex; align-items:center; gap:10px;
  font-size:.95rem; font-weight:600; color:var(--green-900);
  line-height:1.3;
}
.hero__trust svg{
  width:20px; height:20px; flex-shrink:0;
  color:var(--live-500);
}

/* ============================================================
   Visual column
   Mobile: image + stats flow as a grid, no absolute positioning.
   Desktop: stats float over the image corners.
============================================================ */
.hero.hero--split .hero__visual{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(150px,100%),1fr));
  gap:var(--space-2xs);
  position:relative;
  padding:0;
  align-items:stretch;
  justify-content:initial;
}

/* Landscape on purpose — wider than tall. object-fit:cover means a
   portrait source file gets cropped top and bottom to fit this box. */
.hero__img{
  grid-column:1 / -1;
  width:100%;
  height:auto;
  aspect-ratio:4/3;
  object-fit:cover;
  border-radius:var(--radius-l);
  box-shadow:var(--shadow-pop);
  margin-bottom:var(--space-2xs);
}

.hero__stat{
  display:flex; flex-direction:column; gap:2px;
  padding:14px 16px;
  background:var(--paper-000);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  box-shadow:var(--shadow-card);
}
.hero__stat-num{
  font-family:var(--font-display);
  font-weight:800;
  font-size:clamp(1.15rem,1.05rem + .5vw,1.5rem);
  line-height:1.1;
  color:var(--green-900);
  letter-spacing:-.01em;
}
.hero__stat-num sup{
  font-size:.55em; vertical-align:super;
  color:var(--amber-500); margin-left:1px;
}
.hero__stat-label{
  font-size:.78rem; font-weight:600;
  color:var(--ink-500); line-height:1.25;
}
.hero__stat--a .hero__stat-num{ color:var(--amber-600); }

@media (min-width:980px){
  .hero.hero--split .hero__visual{
    display:block;
    padding:0 clamp(12px,2vw,28px);
  }
  .hero__img{
    aspect-ratio:4/3;
    margin-bottom:0;
  }
  .hero__stat{
    position:absolute;
    z-index:2;
    min-width:150px;
    padding:15px 18px;
    backdrop-filter:blur(6px);
    background:rgba(255,255,255,.94);
  }
  /* Tucked slightly outside the photo: it's landscape, so it's much
     shorter than a portrait one and inset cards would crowd it. */
  .hero__stat--a{ top:-4%;    left:-2%;  }
  .hero__stat--d{ bottom:-6%; right:-2%; }
}

/* Tall-but-narrow desktops: pull the cards in so they don't collide */
@media (min-width:980px) and (max-width:1180px){
  .hero__stat{ min-width:132px; padding:12px 14px; }
  .hero__stat--a{ left:-2%; }
}

@media (max-width:420px){
  .hero.hero--split .hero__visual{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .hero__stat{ padding:12px 13px; }
  .hero__stat-label{ font-size:.73rem; }
}

/* ============================================================
   8. SERVICE TILE STRIP  — now any number of tiles
============================================================ */
.tile-strip{ background:var(--green-050); padding-block:clamp(36px,5vw,64px); }
 
.tile-strip__grid{
  --col-min:140px;
  --gap:clamp(12px,1.4vw,16px);
  --cols-max:6;                  /* raise or lower per page if needed */
  display:grid;
  gap:var(--gap);
  grid-template-columns:repeat(
    auto-fit,
    minmax(
      max(min(var(--col-min),100%),
          (100% - (var(--gap) * (var(--cols-max) - 1))) / var(--cols-max)),
      1fr
    )
  );
}
 
.tile{
  position:relative; isolation:isolate; overflow:hidden;
  display:flex; flex-direction:column; align-items:center;
  gap:14px; padding:26px 12px 22px;
  background:var(--paper-000);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  box-shadow:var(--shadow-card);
  text-align:center;
  height:100%;                   /* equal heights at any count */
  transition:transform .22s cubic-bezier(.2,.7,.3,1),
             box-shadow .22s cubic-bezier(.2,.7,.3,1),
             border-color .22s ease;
}
.tile::before{
  content:""; position:absolute; inset-inline:0; top:0; height:3px;
  background:linear-gradient(90deg,var(--amber-500),var(--amber-400));
  transform:scaleX(0); transform-origin:left;
  transition:transform .28s cubic-bezier(.2,.7,.3,1);
}
.tile:hover,.tile:focus-within{
  transform:translateY(-4px); border-color:transparent; box-shadow:var(--shadow-pop);
}
.tile:hover::before,.tile:focus-within::before{ transform:scaleX(1); }
 
.tile__media{
  display:grid; place-items:center;
  width:clamp(64px,9vw,84px); height:clamp(64px,9vw,84px);
  border-radius:50%; background:var(--green-100);
  transition:background .22s ease, transform .22s cubic-bezier(.2,.7,.3,1);
}
.tile:hover .tile__media,.tile:focus-within .tile__media{
  background:var(--amber-050); transform:scale(1.06);
}
.tile__media img{
  width:clamp(34px,5vw,48px); height:clamp(34px,5vw,48px);
  transition:transform .22s cubic-bezier(.2,.7,.3,1);
}
.tile:hover .tile__media img{ transform:scale(1.06); }
 
.tile__label{
  font-family:var(--font-display);
  font-size:clamp(13px,1.1vw,15px);
  font-weight:700; letter-spacing:-.01em;
  color:var(--green-900); line-height:1.25;
  display:inline-block; min-height:22px;
  margin-top:auto;               /* labels align even at uneven lengths */
  transition:color .18s ease;
}
.tile:hover .tile__label,.tile:focus-within .tile__label{ color:var(--amber-600); }
 
.tile a:focus-visible{ outline:3px solid var(--green-500); outline-offset:3px; border-radius:8px; }
 
@media (max-width:899px){
  .tile-strip__grid{ --cols-max:3; }
}
@media (max-width:480px){
  .tile{ padding:18px 8px 16px; gap:10px; }
}
@media (prefers-reduced-motion:reduce){
  .tile,.tile::before,.tile__media,.tile__media img{ transition:none; }
  .tile:hover{ transform:none; }
  .tile:hover .tile__media,.tile:focus-within .tile__media{ transform:none; }
}


/* ============================================================
   9. ABOUT  — collapses without a breakpoint
============================================================ */
.about__grid{
  display:grid;
  gap:clamp(32px,5vw,64px);
  grid-template-columns:repeat(auto-fit,minmax(min(340px,100%),1fr));
  align-items:center;
}
 
/* No panel behind the image: the gradient box, 4:5 ratio and contain
   padding were built for the small map PNG this slot used to hold. It
   holds a photo now, which fills the column at its own proportions. */
.about__media{
  position:relative; border-radius:var(--radius-l); overflow:hidden;
  max-width:400px; margin-inline:auto;   /* source is 724px wide — any
                                            larger and it renders soft */
}
.about__media img{ display:block; width:100%; height:auto; }
 
.about__content h2:where(:not(.h1-look)){ margin-bottom:8px; }
.about__subhead{
  color:var(--amber-500);
  font-size:clamp(1.15rem,1.05rem + .5vw,1.45rem);
  font-weight:700; margin-bottom:20px;
}
.about__content p{ margin-bottom:16px; max-width:70ch; }
.about__content p:last-child{ margin-bottom:0; }
.about__content a{ color:var(--green-500); font-weight:700; }
.about__content a:hover{ color:var(--green-700); }
.about__content a.btn--white,
.about__content a.btn--white:hover,
.about__content a.btn--white:focus-visible{ color:var(--paper-000); }
.about__content a.btn--white .icon-phone{ color:inherit; }
 
/* Justified text creates rivers on narrow screens */
.about__content p,.feature-card p,.faq-item__a-inner p{ text-align:left; }
@media (min-width:900px){
  .about__content p,.feature-card p,.faq-item__a-inner p{ text-align:justify; }
}


/* ============================================================
   10. FEATURE CARDS  — any number, accents cycle
============================================================ */
.features{ background:var(--green-050); }
.features__head{ max-width:620px; margin-bottom:var(--space-xl); }
.features__head--center{ margin-inline:auto; text-align:center; }
.features__head--center .section-kicker{ justify-content:center; }
 
.features__grid{
  --col-min:280px; --gap:var(--space-m); --cols-max:3;
  display:grid; gap:var(--gap);
  grid-template-columns:repeat(
    auto-fit,
    minmax(max(min(var(--col-min),100%),
               (100% - (var(--gap) * (var(--cols-max) - 1))) / var(--cols-max)),1fr)
  );
}
 
.feature-card{
  background:var(--paper-000);
  border-radius:var(--radius-m);
  padding:clamp(24px,3vw,34px) clamp(20px,2.5vw,28px);
  border-top:4px solid var(--amber-500);
  box-shadow:var(--shadow-card);
  height:100%;
}
/* Cycles every 3 — works with 3, 4, 7 or any other count */
.feature-card:nth-child(3n+2){ border-top-color:var(--green-700); }
.feature-card:nth-child(3n+3){ border-top-color:var(--green-950); }
 
.feature-card__icon{
  width:48px; height:48px; border-radius:12px;
  background:var(--green-100); color:var(--green-800);
  display:flex; align-items:center; justify-content:center;
  margin-bottom:20px;
}
.feature-card__icon svg{ width:24px; height:24px; }
.feature-card :is(h2:where(:not(.h1-look)),h3,h4,h5,h6){
  margin-bottom:12px;
  font-size:clamp(1.05rem,1rem + .3vw,1.2rem);
  font-weight:700; line-height:1.3; color:var(--green-900);
}
.feature-card :is(h2:where(:not(.h1-look)),h3,h4,h5,h6) a{ color:inherit; }
.feature-card :is(h2:where(:not(.h1-look)),h3,h4,h5,h6) a:hover{ color:var(--amber-600); }
.feature-card p{ font-size:.97rem; }


/* ============================================================
   11. SERVICE CARDS  — any number
============================================================ */
.services{ background:var(--paper-000); }
 
.services__grid{
  --col-min:280px; --gap:clamp(20px,2.2vw,24px); --cols-max:3;
  display:grid; gap:var(--gap);
  grid-template-columns:repeat(
    auto-fit,
    minmax(max(min(var(--col-min),100%),
               (100% - (var(--gap) * (var(--cols-max) - 1))) / var(--cols-max)),1fr)
  );
}
 
.service-card{
  background:var(--paper-000);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  overflow:hidden;
  display:flex; flex-direction:column;
  height:100%;
  transition:transform .22s ease, box-shadow .22s ease, border-color .22s ease;
}
.service-card:hover,.service-card:focus-within{
  transform:translateY(-6px); box-shadow:var(--shadow-pop); border-color:transparent;
}
.service-card__media{ position:relative; overflow:hidden; aspect-ratio:4/3; }
.service-card__media img{
  width:100%; height:100%; object-fit:cover; transition:transform .4s ease;
}
.service-card:hover .service-card__media img{ transform:scale(1.05); }
.service-card__body{
  padding:22px 24px 26px;
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--space-s); flex:1;
}
.service-card h4{ color:var(--green-900); }
.service-card__arrow{
  width:34px; height:34px; border-radius:50%;
  background:var(--amber-600); color:var(--paper-000);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
  transition:background .22s ease, color .22s ease, transform .22s ease;
}
.service-card__arrow svg{ width:16px; height:16px; }
.service-card:hover .service-card__arrow{
  background:var(--green-100); color:var(--green-800); transform:translateX(4px);
}

@media (max-width:899px){
  .services__grid{ --cols-max:2; }
  .services{display: none;}
}


/* ============================================================
   12. ACCORDION / FAQ
============================================================ */
.faq{ background:var(--amber-050); }
.faq__wrap{ max-width:820px; margin-inline:auto; }
 
.faq-item{
  background:var(--paper-000);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  margin-bottom:var(--space-xs);
  overflow:hidden;
  transition:box-shadow .2s ease, border-color .2s ease;
}
.faq-item:hover{ border-color:var(--amber-400); }
.faq-item.is-open{ box-shadow:var(--shadow-card); border-color:transparent; }
 
.faq-item__q{
  width:100%; text-align:left;
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--space-s);
  padding:clamp(16px,2.2vw,22px) clamp(16px,2.2vw,24px);
  min-height:44px;
  font-family:var(--font-display); font-weight:700;
  font-size:clamp(.97rem,.93rem + .25vw,1.06rem);
  line-height:1.35;
  color:var(--green-900);
  transition:color .18s ease;
}
.faq-item__q:hover{ color:var(--amber-600); }
 
.faq-item__plus{
  width:28px; height:28px; border-radius:50%;
  background:var(--green-100);
  flex-shrink:0; position:relative;
  transition:background .25s ease, transform .25s ease;
}
.faq-item__plus::before{
  content:"";
  position:absolute; top:47%; left:50%;
  width:8px; height:8px;
  border-right:2px solid var(--green-900);
  border-bottom:2px solid var(--green-900);
  transform:translate(-50%,-65%) rotate(45deg);
  transition:border-color .25s ease;
}
.faq-item__plus::after{ content:none; }
.faq-item__q:hover .faq-item__plus{ background:var(--amber-050); }
.faq-item.is-open .faq-item__plus{
  background:var(--amber-500); transform:rotate(180deg);
}
.faq-item.is-open .faq-item__plus::before{ border-color:#fff; }
 
/* Height-agnostic reveal. Padding lives on the inner element, which
   is fully clipped while collapsed. */
.faq-item__a{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows .3s ease;
}
.faq-item.is-open .faq-item__a{ grid-template-rows:1fr; }
 
.faq-item__a > *{
  overflow:hidden;
  min-height:0;
}
 
.faq-item__a-inner{
  padding:0 clamp(16px,2.2vw,24px);
  max-width:68ch;
}
.faq-item__a-inner > *:first-child{ margin-top:0; }
.faq-item.is-open .faq-item__a-inner{
  padding-bottom:clamp(18px,2.4vw,24px);
}
.faq-item__a-inner p{ font-size:.96rem; text-align:left; line-height:1.6; }
.faq-item__a-inner p + p{ margin-top:var(--space-xs); }
.faq-item__a-inner a{ color:var(--green-500); font-weight:700; text-decoration:underline; }
.faq-item__a-inner a:hover{ color:var(--green-700); }
 
@supports not (grid-template-rows:0fr){
  .faq-item__a{ max-height:0; overflow:hidden; transition:max-height .3s ease; }
  .faq-item.is-open .faq-item__a{ max-height:2000px; }
}


/* ============================================================
   13. CTA BAND
============================================================ */
.cta-band{
  position:relative; overflow:hidden;
  background:linear-gradient(100deg,var(--green-900) 0%,var(--green-800) 100%);
  color:#fff; padding-block:clamp(32px,5vw,60px);
}
.cta-band::before{
  content:""; position:absolute; inset-inline:0; top:0; height:3px;
  background:linear-gradient(90deg,var(--amber-500),var(--amber-400));
}
.cta-band__inner{
  position:relative;
  display:flex; flex-wrap:wrap;
  align-items:center; justify-content:space-between;
  gap:var(--space-m);
  text-align:center;
}
.cta-band__lead{
  font-family:var(--font-display); font-weight:800;
  font-size:clamp(1.05rem,.95rem + .7vw,1.5rem);
  line-height:1.2; letter-spacing:-.01em; color:#fff;
  flex:1 1 min(100%,420px);
  text-wrap:balance;
}
.cta-band__phone{
  font-family:var(--font-body); font-size:1rem; font-weight:700;
  padding:14px 28px; flex-shrink:0; margin-inline:auto;
}
@media (min-width:760px){
  .cta-band__inner{ text-align:left; flex-wrap:nowrap; gap:var(--space-l); }
  .cta-band__phone{ margin-inline:0; }
}
@media (max-width:600px){
  .cta-band__phone{ width:100%; }
}


/* ============================================================
   14. TABS  — generic, scrollable on mobile
   .region-tabs / .region-tab kept as aliases.
============================================================ */
.region-tabs{
  display:flex; flex-wrap:wrap; gap:9px;
}
/* On phones, don't wrap into four rows — scroll instead */
@media (max-width:640px){
  .region-tabs{
    flex-wrap:nowrap;
    overflow-x:auto;
    scroll-snap-type:x proximity;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
    padding-bottom:4px;
    margin-inline:calc(var(--gutter) * -1);
    padding-inline:var(--gutter);
  }
  .region-tabs::-webkit-scrollbar{ display:none; }
  .region-tab{ scroll-snap-align:start; flex:0 0 auto; }
}
 
.region-tab{
  border:1.5px solid var(--line-200); background:#fff; color:var(--green-900);
  padding:9px 16px; border-radius:999px;
  font-family:inherit; font-size:14px; font-weight:600;
  min-height:40px;
  transition:background .15s ease, border-color .15s ease, color .15s ease;
}
.region-tab:hover{ border-color:var(--amber-500); }
.region-tab.active,.region-tab[aria-selected="true"]{
  background:var(--green-900); border-color:var(--green-900); color:#fff;
}
 
.region-panel{
  margin-top:22px;
  background:var(--amber-050);
  border:1px solid var(--line-200);
  border-radius:var(--radius-s);
  padding:clamp(20px,2.6vw,28px);
  min-height:150px;
}
.region-panel[hidden]{ display:none; }
.region-panel h3{
  font-family:var(--font-body); font-size:15px; color:var(--amber-500);
  text-transform:uppercase; letter-spacing:.5px; margin-bottom:10px;
}
.region-panel p{ margin:0; color:var(--ink-700); font-size:15px; }
.region-panel p + p{ margin-top:var(--space-xs); }


/* ============================================================
   15. COVERAGE / REGIONS
============================================================ */
.coverage{ padding-block:clamp(56px,8vw,96px); }
.coverage-top{ text-align:center; max-width:640px; margin:0 auto clamp(32px,4vw,46px); }
.coverage-top h2:where(:not(.h1-look)){ font-size:clamp(26px,3.4vw,34px); }
.coverage-top p{ color:var(--ink-700); margin-top:12px; }
.coverage-top .btn{ margin-top:22px; }
 
.coverage-grid{
  display:grid;
  gap:clamp(32px,4vw,46px);
  grid-template-columns:repeat(auto-fit,minmax(min(380px,100%),1fr));
  align-items:start;
}
@media (min-width:1040px){
  .coverage-grid{ grid-template-columns:.9fr 1.1fr; }
}
 
.map-wrap{ display:flex; align-items:center; justify-content:center; }
.map-wrap svg{ width:100%; max-width:340px; height:auto; }
.region-path{ transition:fill .15s ease, stroke .15s ease; }
.region-path.covered{ fill:var(--amber-050); stroke:var(--green-900); stroke-width:1; cursor:pointer; }
.region-path.covered:hover{ fill:#F2E7D2; stroke:var(--amber-500); }
.region-path.covered.active{ fill:var(--amber-500); stroke:var(--amber-600); }
.region-path.uncovered{ fill:#EAE5D8; stroke:#CFC8B3; stroke-width:.7; }
 
@media (max-width:920px){ .map-wrap{ margin-top:28px; } }
/* The map is decorative on phones — the tabs carry the same information */
/* @media (max-width:560px){ .map-wrap{ display:none; } } */


/* ============================================================
   16. CITY / PARTNER LINK GROUPS — any number of groups or links
============================================================ */
.local{ background:var(--green-050); }

 
.local__groups{
  --col-min:280px; --gap:clamp(20px,2.2vw,24px); --cols-max:3;
  display:grid; gap:var(--gap);
  grid-template-columns:repeat(
    auto-fit,
    minmax(max(min(var(--col-min),100%),
               (100% - (var(--gap) * (var(--cols-max) - 1))) / var(--cols-max)),1fr)
  );
}
 
.local-group{
  position:relative; isolation:isolate; overflow:hidden;
  background:var(--paper-000);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  box-shadow:var(--shadow-card);
  padding:clamp(24px,3vw,30px) clamp(20px,2.6vw,28px) 22px;
  height:100%;
}
.local-group::before{
  content:""; position:absolute; inset-inline:0; top:0; height:3px;
  background:linear-gradient(90deg,var(--gold-500),var(--amber-400));
}
.local-group__head{
  display:flex; align-items:center; gap:14px;
  padding-bottom:18px; margin-bottom:6px;
  border-bottom:1px solid var(--line-200);
}
.local-group__icon{
  width:44px; height:44px; border-radius:12px;
  background:var(--green-900); color:var(--gold-500);
  display:flex; align-items:center; justify-content:center; flex-shrink:0;
}
.local-group__icon svg{ width:22px; height:22px; }
.local-group h3{
  font-family:var(--font-display); color:var(--green-900);
  font-size:1.05rem; line-height:1.25; letter-spacing:-.01em;
}
 
.local-group__chips{ display:flex; flex-direction:column; gap:0; }
 

 
.local-chip{
  position:relative; display:flex; align-items:center;
  min-height:44px; padding:11px 0 11px 16px;
  border-bottom:1px solid var(--line-100);
  font-size:.875rem; font-weight:600; line-height:1.4; color:var(--ink-700);
  transition:color .18s ease, padding-left .18s cubic-bezier(.2,.7,.3,1);
}
.local-group__chips .local-chip:last-child{ border-bottom:0; }
.local-chip::before{
  content:""; position:absolute; left:0; top:50%;
  width:3px; height:0; border-radius:999px; background:var(--amber-500);
  transform:translateY(-50%);
  transition:height .2s cubic-bezier(.2,.7,.3,1);
}
.local-chip:hover,.local-chip:focus-visible{ color:var(--green-900); padding-left:22px; }
.local-chip:hover::before,.local-chip:focus-visible::before{ height:20px; }
.local-chip:focus-visible{ outline:3px solid var(--green-500); outline-offset:2px; border-radius:6px; }
 
@media (prefers-reduced-motion:reduce){
  .local-chip,.local-chip::before{ transition:none; }
  .local-chip:hover,.local-chip:focus-visible{ padding-left:16px; }
}


/* ============================================================
   19. FOOTER  — any number of columns
============================================================ */
.site-footer{
  background:var(--green-950); color:rgba(255,255,255,.7);
  padding-block:56px 28px;
  padding-bottom:calc(28px + var(--callbar-h));   /* clears the call bar */
}
@media (min-width:769px){ .site-footer{ padding-bottom:28px; } }
 






/* justify-content is CENTER, not space-between. This row has exactly one
   child (footer.php's single <p>), and space-between parks a lone flex item
   at flex-start — which left the legal line hard against the left edge with
   ~700px of empty footer beside it at 1440px. text-align could not correct
   it: the <p> shrinks to its content width, so centring text inside a box
   that is already at the left just centres it within itself.
   If a second child is ever added here, center still reads correctly. */
.site-footer__legal{
  padding-top:24px;
  display:flex; flex-wrap:wrap; justify-content:center;
  gap:12px; font-size:.9rem; color:rgba(255,255,255,.7); text-align:center;
}
.site-footer__legal a{ color:#fff; }
@media (max-width:600px){
  .site-footer__legal{ flex-direction:column; }
}


/* ============================================================
   20. STICKY CALL BAR (mobile)
============================================================ */
.call-bar{
  position:fixed; bottom:0; left:0; width:100%; z-index:9999;
  display:none; align-items:center; justify-content:center; gap:10px;
  min-height:var(--callbar-h);
  padding:15px 0 calc(15px + env(safe-area-inset-bottom));
  background-color:var(--live-500); color:var(--paper-000);
  font-size:20px; font-weight:700; text-align:center;
  box-shadow:0 -2px 6px rgba(0,0,0,.2);
  transition:transform .25s ease;
}
.call-bar:hover{ background-color:#218838; color:var(--paper-000); }
.call-bar:active{ background-color:#000; color:var(--paper-000); }
.call-bar svg{ width:22px; height:22px; flex-shrink:0; }
@media (max-width:768px){
  .call-bar{ display:flex; }
  body{ padding-bottom:calc(var(--callbar-h) + env(safe-area-inset-bottom)); }
}

/* Slid out of view (site.js §4) while another call button — the hero
   CHIAMA, a mid-page CTA, the CTA band — is already on screen, so two
   "call us" prompts are never visible at once. body keeps its
   call-bar padding regardless: the bar still occupies its reserved
   strip, it is just translated below it, so nothing reflows when it
   toggles. */
.call-bar--hidden{ transform:translateY(100%); }


/* ============================================================
   21. UTILITIES
============================================================ */
/* ============================================================
   assets/css/prezzi.css
   Sections shared by EVERY service page (and, later, the city
   pages). Loaded by service pages only — never by the homepage,
   which uses none of it.

   Load order: global.css -> prezzi.css -> <service>.css
   so a page can still override a shared section locally.

   Tokens, .container, .btn and the header/footer/hero chrome stay
   in global.css and are never redefined here.

   Sections:
     1 pricing  ("Quanto costa un intervento ...")
     2 coverage ("Dove operiamo" — region cards + city links)

   Design is the /intervento-idraulico/ variant (left-aligned,
   1240px). The fabbro page previously carried a centred 1160px
   copy of the same section; both now render from this one
   definition.

   Deliberately NOT here: the "servizi"/"categorie" and "emergenza"
   blocks. They look shared from their class names but are genuinely
   different components on the two pages (fabbro's emergency is a
   centred text panel, idraulico's is two columns with a photo and a
   badge), so they stay page-local until a second page really does
   share the same design.
============================================================ */


/* ============================================================
   1. PRICING
============================================================ */
.svc-pricing{
  background:var(--paper-050);
  /* clamped rather than a flat 88px so it doesn't swallow a phone
     screen; identical to 88px from ~1250px up */
  padding:clamp(60px,7vw,88px) 5vw;
}
.svc-pricing-inner{ max-width:1240px; margin:0 auto; }

.svc-pricing-pill{
  display:inline-flex; align-items:center; gap:10px;
  background:var(--amber-600); color:var(--paper-000);
  font-size:13px; font-weight:700; letter-spacing:.03em;
  padding:10px 20px 10px 18px; border-radius:999px;
  margin-bottom:26px;
}
.svc-pricing-pill-bar{
  width:16px; height:2px; border-radius:2px; background:var(--paper-000);
}

.svc-pricing-title{
  margin:0 0 18px;
  font-family:var(--font-display);
  font-size:clamp(28px,3vw,38px); font-weight:800;
  color:var(--green-900); letter-spacing:-.01em;
}

.svc-pricing-intro{
  margin:0 0 8px;
  font-size:16.5px; line-height:1.65; color:var(--ink-700);
  max-width:760px;
}
.svc-pricing-intro a{
  color:var(--green-700); font-weight:700; text-decoration:underline;
}
.svc-pricing-link-full{
  display:inline-block; margin-top:4px;
  font-size:16px; font-weight:700;
  color:var(--green-900); text-decoration:underline;
}

.svc-pricing-cards{
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:24px; margin:48px 0 40px;
}
.svc-pricing-card{
  background:var(--paper-000);
  border:1px solid var(--line-200); border-radius:18px;
  padding:30px 28px;
  transition:transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.svc-pricing-card:hover{
  transform:translateY(-3px);
  box-shadow:0 16px 32px rgba(14,57,94,.1);
  border-color:transparent;
}

.svc-pricing-label{
  display:flex; align-items:center; gap:8px;
  font-size:12.5px; font-weight:700; letter-spacing:.03em;
  color:var(--green-700); margin-bottom:16px;
}
.svc-pricing-label-dot{
  width:7px; height:7px; border-radius:50%;
  background:var(--amber-500); flex-shrink:0;
}
.svc-pricing-value{
  font-family:var(--font-display);
  font-size:27px; font-weight:800; line-height:1.15;
  color:var(--green-900); margin-bottom:10px;
}
.svc-pricing-note{ font-size:14.5px; line-height:1.5; color:var(--ink-700); }

.svc-pricing-terms{
  font-size:14.5px; line-height:1.7; color:var(--ink-700);
  max-width:900px; margin:0 0 40px;
}
.svc-pricing-terms strong{ color:var(--green-900); }

.svc-pricing-cta{
  display:inline-flex; align-items:center;
  background:transparent; color:var(--green-900);
  border:2px solid var(--green-900);
  font-family:var(--font-display);
  font-size:15.5px; font-weight:700; text-decoration:none;
  padding:15px 28px; border-radius:999px;
  transition:background .15s ease, color .15s ease;
}
.svc-pricing-cta:hover{ background:var(--green-900); color:var(--paper-000); }


/* ============================================================
   2. COVERAGE — "Dove operiamo"
   <details> region cards holding the city links, so the disclosure
   works with JavaScript disabled.
============================================================ */
.svc-coverage{
  background:var(--green-050);
  padding:clamp(60px,7vw,88px) 5vw;
}
.svc-coverage-inner{ max-width:1240px; margin:0 auto; }
.svc-coverage-head{ max-width:640px; margin-bottom:44px; }

.svc-coverage-eyebrow{
  display:flex; align-items:center; gap:10px; margin-bottom:20px;
}
.svc-coverage-eyebrow-bar{
  width:28px; height:3px; border-radius:2px;
  background:var(--amber-600); flex-shrink:0;
}
.svc-coverage-eyebrow-text{
  font-size:13px; font-weight:700; letter-spacing:.03em;
  color:var(--amber-600);
}
.svc-coverage-title{
  margin:0 0 14px;
  font-family:var(--font-display);
  font-size:clamp(28px,3vw,38px); font-weight:800;
  color:var(--green-900); letter-spacing:-.01em;
}
.svc-coverage-sub{
  margin:0; font-size:16px; line-height:1.6; color:var(--ink-700);
}

.svc-region-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:18px;
}
.svc-region-card{
  background:var(--paper-000);
  border:1px solid var(--line-200); border-radius:16px;
  padding:4px 22px; height:max-content;
}
.svc-region-card summary{
  list-style:none; cursor:pointer;
  display:flex; align-items:center; gap:12px;
  padding:20px 0;
}
.svc-region-card summary::-webkit-details-marker{ display:none; }

.svc-region-pin{
  width:34px; height:34px; border-radius:10px;
  background:var(--green-100); color:var(--green-900);
  display:flex; align-items:center; justify-content:center;
  flex-shrink:0;
}
.svc-region-pin svg{ width:16px; height:16px; }

.svc-region-name-wrap{ flex:1; min-width:0; }
.svc-region-name{
  font-family:var(--font-display);
  font-size:15.5px; font-weight:700; color:var(--green-900);
}
.svc-region-count{
  display:block; font-size:12.5px; color:var(--ink-500); margin-top:2px;
}
.svc-region-plus{
  width:24px; height:24px; border-radius:50%;
  background:var(--amber-050); color:var(--amber-600);
  display:flex; align-items:center; justify-content:center;
  flex-shrink:0; font-size:17px; font-weight:700;
  transition:transform .15s ease;
}
.svc-region-card[open] .svc-region-plus{ transform:rotate(45deg); }

.svc-region-cities{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0 clamp(14px,1.8vw,26px);
  list-style:none; margin:0; padding:4px 0 22px;
}
/* A row is an <li> (fabbro) or a bare <a> (the other two hubs). */
.svc-region-cities > li,
.svc-region-cities > a{
  display:flex;
  /* flex-start, not center: a long city name wraps to two lines in a card
     this narrow, and centred would float the dot into the middle of them */
  align-items:flex-start; gap:9px;
  min-width:0;
  padding:8px 2px;
  border-bottom:1px solid var(--line-200);
}
.svc-region-cities > li::before,
.svc-region-cities > a::before{
  content:""; flex-shrink:0;
  width:5px; height:5px; border-radius:50%;
  background:var(--amber-500);
  /* nudged down to sit on the first line's centre rather than the row's */
  margin-top:7px;
}
.svc-region-cities a{
  min-width:0;
  font-size:13.5px; font-weight:600; line-height:1.45;
  color:var(--green-700); text-decoration:none;
  transition:color .15s ease;
}
.svc-region-cities a:hover{ color:var(--green-900); }
.svc-region-cities > li > a{ flex:1 1 auto; }

/* Optional CTA under the region grid (fabbro uses it). */
.svc-coverage-cta{ text-align:center; margin-top:40px; }


/* ============================================================
   RESPONSIVE
============================================================ */
@media (max-width:980px){
  .svc-region-grid{ grid-template-columns:repeat(2,1fr); }
}
@media (max-width:900px){
  .svc-pricing-cards{ grid-template-columns:1fr; }
}
@media (max-width:620px){
  .svc-region-grid{ grid-template-columns:1fr; }
}
@media (max-width:480px){
  .svc-pricing-card{ padding:24px 22px; }
  .svc-region-card{ padding:2px 18px; }
  .svc-pricing-cta{ justify-content:center; }
}


/* ============================================================
   3. /prezzi/ — TARIFFE
   ------------------------------------------------------------
   PAGE-SCOPED. Every selector below is prefixed .pz- and no .pz-
   class appears in the markup of any other page, so the 396
   service pages that load this file render exactly as before —
   they only carry the extra bytes.

   The price tables stay real <table>s. On phones each row folds
   into a card and every cell labels itself from the data-label
   attribute the source markup already carries, so nothing is
   duplicated in the HTML to get the card view. The <thead> is
   not hidden on mobile: it becomes a compact legend, which is
   the only place the time ranges ("Lun–Ven, 8:00–17:00") are
   written, and they would otherwise be lost.
============================================================ */

/* ---------- shared shell ---------- */
.pz-inner{ max-width:1240px; margin:0 auto; }
.pz-inner--narrow{ max-width:900px; }

.pz-section{ padding:clamp(60px,7vw,88px) 5vw; }
.pz-section--alt{ background:var(--paper-050); }
.pz-section--tint{ background:var(--green-050); }

.pz-head{ max-width:70ch; margin:0 0 clamp(28px,3.5vw,44px); }
.pz-head h2:where(:not(.h1-look)){
  margin:0 0 14px;
  color:var(--green-900);
  font-size:clamp(1.5rem,1.25rem + 1.2vw,2.15rem);
  line-height:1.14;
  letter-spacing:-.02em;
}
.pz-lead{
  margin:0;
  max-width:62ch;
  font-size:1.02rem;
  line-height:1.7;
  color:var(--ink-500);
}
.pz-note{
  margin:clamp(22px,3vw,32px) 0 0;
  padding:16px 20px;
  border-left:3px solid var(--amber-500);
  background:var(--amber-050);
  border-radius:0 var(--radius-s) var(--radius-s) 0;
  font-size:.95rem;
  line-height:1.65;
  color:var(--ink-700);
}
.pz-note strong{ color:var(--green-900); }


/* ============================================================
   3.1 HERO
============================================================ */
.pz-hero{
  position:relative;
  overflow:hidden;
  background:var(--green-050);
  padding:clamp(40px,6vw,76px) 5vw clamp(44px,6vw,80px);
}
.pz-hero__shape{
  position:absolute;
  top:-48%; right:-10%;
  width:min(60vw,680px); aspect-ratio:1;
  border-radius:50%;
  background:radial-gradient(circle at 35% 35%,
              rgba(41,145,214,.16) 0%,
              rgba(255,81,0,.08) 45%,
              transparent 70%);
  pointer-events:none;
  z-index:0;
}
.pz-hero__inner{ position:relative; z-index:1; max-width:1240px; margin:0 auto; }

.pz-hero h1,
.pz-hero h2:where(.h1-look){
  margin:0 0 18px;
  max-width:18ch;
  color:var(--green-900);
  font-size:clamp(1.95rem,1.4rem + 2.4vw,3.1rem);
  line-height:1.05;
  letter-spacing:-.025em;
}
.pz-hero__lead{
  margin:0 0 clamp(24px,3vw,32px);
  max-width:60ch;
  font-size:clamp(1rem,.97rem + .2vw,1.1rem);
  line-height:1.7;
  color:var(--ink-700);
}

.pz-points{
  display:flex;
  flex-wrap:wrap;
  gap:10px 12px;
  margin:0 0 clamp(26px,3.4vw,36px);
  padding:0;
}
.pz-point{
  display:inline-flex;
  align-items:center;
  gap:9px;
  padding:9px 16px 9px 13px;
  border:1px solid var(--line-200);
  border-radius:999px;
  background:var(--paper-000);
  font-size:.9rem;
  font-weight:600;
  line-height:1.3;
  color:var(--green-900);
}
.pz-point::before{
  content:"";
  flex-shrink:0;
  width:16px; height:16px;
  border-radius:50%;
  background:var(--green-700);
  /* white tick, drawn rather than shipped as an asset */
  -webkit-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") center/13px no-repeat,
        linear-gradient(#000,#000);
  -webkit-mask-composite:xor;
  mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E") center/13px no-repeat,
        linear-gradient(#000,#000);
  mask-composite:exclude;
}


/* ============================================================
   3.2 SERVICE TABS + PRICE TABLES
   ------------------------------------------------------------
   One table visible at a time, switched by clicking a service
   name — the behaviour the export has, rebuilt without JS.

   Three same-name radios sit before the panels; each :checked
   radio reveals its sibling panel and lights its own label.
   site.js is untouched. The radios are moved off-screen rather
   than display:none so they stay keyboard-reachable: arrow keys
   move between services, exactly like a real tab strip.

   The labels are NOT headings — the export carries these three
   words as <button>s and the page's heading hierarchy is
   reproduced exactly (hard rule 9).

   A link such as /prezzi/#fabbro picks the tab: site.js §5 ticks
   the matching radio and scrolls this heading into view.
============================================================ */
.pz-tabs{ position:relative; }
/* Where site.js scrolls to when a link names a service: keep the
   heading clear of the sticky header. */
.pz-section .pz-head{ scroll-margin-top:calc(var(--header-h) + var(--space-s)); }

.pz-tabs__input{
  position:absolute;
  width:1px; height:1px;
  margin:0;
  opacity:0;
  pointer-events:none;
}

.pz-tabs__list{
  display:flex;
  flex-wrap:wrap;
  gap:8px;
  margin:0 0 20px;
  padding:0;
}

.pz-tab{
  display:inline-flex;
  align-items:center;
  gap:10px;
  min-height:44px;                 /* tap target */
  padding:11px 22px;
  border:1px solid var(--line-200);
  border-radius:999px;
  background:var(--paper-000);
  cursor:pointer;
  font-family:var(--font-display);
  font-weight:700;
  font-size:clamp(.95rem,.92rem + .2vw,1.05rem);
  line-height:1.2;
  color:var(--ink-700);
  user-select:none;
  transition:background .18s ease, border-color .18s ease, color .18s ease;
}
.pz-tab::before{
  content:"";
  width:8px; height:8px;
  border-radius:50%;
  background:var(--line-200);
  flex-shrink:0;
  transition:background .18s ease, transform .18s ease;
}
.pz-tab:hover{ border-color:var(--amber-400); color:var(--green-900); }

/* Panels are hidden until their radio is checked. */
.pz-panel{ display:none; }

/* --- Elettricista --- */
#pz-r-elettricista:checked ~ .pz-tabs__list .pz-tab[for="pz-r-elettricista"],
#pz-r-idraulico:checked    ~ .pz-tabs__list .pz-tab[for="pz-r-idraulico"],
#pz-r-fabbro:checked       ~ .pz-tabs__list .pz-tab[for="pz-r-fabbro"]{
  background:var(--green-900);
  border-color:var(--green-900);
  color:var(--paper-000);
}
#pz-r-elettricista:checked ~ .pz-tabs__list .pz-tab[for="pz-r-elettricista"]::before,
#pz-r-idraulico:checked    ~ .pz-tabs__list .pz-tab[for="pz-r-idraulico"]::before,
#pz-r-fabbro:checked       ~ .pz-tabs__list .pz-tab[for="pz-r-fabbro"]::before{
  background:var(--amber-500);
  transform:scale(1.15);
}

#pz-r-elettricista:checked ~ #pz-p-elettricista,
#pz-r-idraulico:checked    ~ #pz-p-idraulico,
#pz-r-fabbro:checked       ~ #pz-p-fabbro{ display:block; }

/* Keyboard focus has to show on the label, since the radio itself
   is off-screen. */
#pz-r-elettricista:focus-visible ~ .pz-tabs__list .pz-tab[for="pz-r-elettricista"],
#pz-r-idraulico:focus-visible    ~ .pz-tabs__list .pz-tab[for="pz-r-idraulico"],
#pz-r-fabbro:focus-visible       ~ .pz-tabs__list .pz-tab[for="pz-r-fabbro"]{
  outline:3px solid var(--green-500);
  outline-offset:3px;
}

/* Printing a tabbed page would lose two services out of three. */
@media print{
  .pz-panel{ display:block !important; }
  .pz-tabs__list{ display:none; }
}

.pz-table-wrap{
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  background:var(--paper-000);
  box-shadow:var(--shadow-card);
  overflow:hidden;
}

.pz-table{
  width:100%;
  border-collapse:collapse;
  font-size:.93rem;
}

.pz-table thead th{
  padding:14px 18px;
  text-align:left;
  vertical-align:bottom;
  background:var(--green-900);
  color:var(--paper-000);
  font-family:var(--font-display);
  font-weight:700;
  font-size:.78rem;
  letter-spacing:.05em;
  text-transform:uppercase;
  line-height:1.25;
}
.pz-table thead th span{
  display:block;
  margin-top:5px;
  font-family:var(--font-body);
  font-weight:500;
  font-size:.72rem;
  letter-spacing:.01em;
  text-transform:none;
  color:rgba(255,255,255,.66);
  white-space:nowrap;
}

.pz-table tbody th{
  padding:14px 18px;
  text-align:left;
  vertical-align:middle;
  font-weight:650;
  line-height:1.45;
  color:var(--green-900);
  border-top:1px solid var(--line-100);
}
.pz-table tbody td{
  padding:14px 18px;
  text-align:left;
  vertical-align:middle;
  white-space:nowrap;
  font-variant-numeric:tabular-nums;
  font-weight:600;
  color:var(--ink-700);
  border-top:1px solid var(--line-100);
}
.pz-table tbody tr:nth-child(even) th,
.pz-table tbody tr:nth-child(even) td{ background:var(--green-050); }

/* Out-of-hours columns carry the premium — mark them, don't explain
   them in words the source does not have. */
.pz-table tbody td:nth-child(4),
.pz-table tbody td:nth-child(5){ color:var(--amber-600); }


/* ---------- phones: each row becomes a card ---------- */
@media (max-width:860px){
  .pz-table-wrap{ border:0; border-radius:0; background:none; box-shadow:none; overflow:visible; }
  .pz-table,
  .pz-table tbody,
  .pz-table tr,
  .pz-table tbody th,
  .pz-table tbody td{ display:block; width:100%; }

  /* The header row is the only place the time ranges are written,
     so it stays — reflowed as a legend above the cards. */
  .pz-table thead{ display:block; }
  .pz-table thead tr{
    display:grid;
    gap:8px;
    padding:16px 18px;
    border-radius:var(--radius-m);
    background:var(--green-900);
  }
  .pz-table thead th{
    padding:0;
    background:none;
    border:0;
    font-size:.74rem;
  }
  .pz-table thead th:first-child{
    padding-bottom:8px;
    border-bottom:1px solid rgba(255,255,255,.18);
  }
  .pz-table thead th span{ display:inline; margin:0 0 0 6px; }

  .pz-table tbody tr{
    margin-top:14px;
    border:1px solid var(--line-200);
    border-radius:var(--radius-m);
    background:var(--paper-000);
    box-shadow:var(--shadow-card);
    overflow:hidden;
  }
  .pz-table tbody tr:nth-child(even) th,
  .pz-table tbody tr:nth-child(even) td{ background:none; }

  .pz-table tbody th{
    padding:14px 16px;
    border-top:0;
    border-bottom:1px solid var(--line-200);
    background:var(--green-050);
    font-size:.97rem;
  }
  .pz-table tbody td{
    display:flex;
    align-items:baseline;
    justify-content:space-between;
    gap:16px;
    padding:11px 16px;
    border-top:0;
  }
  .pz-table tbody td + td{ border-top:1px solid var(--line-100); }

  /* The label comes from the attribute already in the markup. */
  .pz-table tbody td::before{
    content:attr(data-label);
    font-weight:600;
    font-size:.86rem;
    letter-spacing:.01em;
    color:var(--ink-500);
    text-transform:none;
    white-space:normal;
  }
}


/* ============================================================
   3.3 INCLUDED / NOT INCLUDED
============================================================ */
.pz-split{
  display:grid;
  gap:var(--space-m);
  grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));
}

.pz-card{
  padding:clamp(24px,3vw,34px) clamp(20px,2.5vw,30px);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  background:var(--paper-000);
  box-shadow:var(--shadow-card);
}
.pz-card h3{
  margin:0 0 16px;
  font-size:clamp(1.02rem,.98rem + .3vw,1.18rem);
  font-weight:700;
  line-height:1.3;
  color:var(--green-900);
}
.pz-card p{
  margin:0;
  font-size:.97rem;
  line-height:1.7;
  color:var(--ink-700);
}

.pz-card--yes{ border-top:4px solid var(--green-700); }
.pz-card--no{ border-top:4px solid var(--amber-500); }

.pz-list{
  display:grid;
  gap:11px;
  margin:0;
  padding:0;
  font-size:.97rem;
  line-height:1.6;
  color:var(--ink-700);
}
.pz-list li{ position:relative; padding-left:28px; }
.pz-list li::before{
  content:"";
  position:absolute;
  left:0; top:.34em;
  width:16px; height:16px;
  border-radius:50%;
  flex-shrink:0;
}
.pz-card--yes .pz-list li::before{
  background:var(--green-100);
  box-shadow:inset 0 0 0 1px var(--green-500);
}
.pz-card--no .pz-list li::before{
  background:var(--amber-050);
  box-shadow:inset 0 0 0 1px var(--amber-400);
}


/* ============================================================
   3.4 FACTORS
============================================================ */
.pz-grid{
  --col-min:260px; --gap:var(--space-m); --cols-max:3;
  display:grid; gap:var(--gap);
  grid-template-columns:repeat(
    auto-fit,
    minmax(max(min(var(--col-min),100%),
               (100% - (var(--gap) * (var(--cols-max) - 1))) / var(--cols-max)),1fr)
  );
}

.pz-factor{
  padding:clamp(22px,2.6vw,28px) clamp(20px,2.4vw,26px);
  border:1px solid var(--line-200);
  border-left:3px solid var(--green-700);
  border-radius:var(--radius-s);
  background:var(--paper-000);
}
.pz-factor h3{
  margin:0 0 10px;
  font-size:1.02rem;
  font-weight:700;
  line-height:1.3;
  color:var(--green-900);
}
.pz-factor p{
  margin:0;
  font-size:.94rem;
  line-height:1.65;
  color:var(--ink-700);
}


/* ============================================================
   3.5 STEPS
============================================================ */
.pz-steps{
  --col-min:240px; --gap:var(--space-m); --cols-max:4;
  display:grid; gap:var(--gap);
  grid-template-columns:repeat(
    auto-fit,
    minmax(max(min(var(--col-min),100%),
               (100% - (var(--gap) * (var(--cols-max) - 1))) / var(--cols-max)),1fr)
  );
  margin:0; padding:0;
}

.pz-step{
  position:relative;
  padding:clamp(24px,3vw,30px) clamp(20px,2.4vw,26px);
  border-radius:var(--radius-m);
  background:var(--paper-000);
  box-shadow:var(--shadow-card);
}
.pz-step__num{
  display:grid;
  place-items:center;
  width:40px; height:40px;
  margin-bottom:16px;
  border-radius:50%;
  background:var(--green-900);
  color:var(--paper-000);
  font-family:var(--font-display);
  font-weight:800;
  font-size:1rem;
  line-height:1;
}
.pz-step h3{
  margin:0 0 10px;
  font-size:1.02rem;
  font-weight:700;
  line-height:1.3;
  color:var(--green-900);
}
.pz-step p{
  margin:0;
  font-size:.94rem;
  line-height:1.65;
  color:var(--ink-700);
}


/* ============================================================
   3.6 CLOSING CTA COPY
   .cta-band itself is global.css; this only lets the band hold a
   heading plus a line of copy instead of a single lead.
============================================================ */
.pz-cta-copy{ flex:1 1 min(100%,520px); }
.pz-cta-copy h2:where(:not(.h1-look)){
  margin:0 0 8px;
  color:#fff;
  font-size:clamp(1.25rem,1.05rem + .9vw,1.75rem);
  line-height:1.15;
  letter-spacing:-.015em;
}
.pz-cta-copy p{
  margin:0;
  font-size:.98rem;
  line-height:1.6;
  color:rgba(255,255,255,.78);
}
/* ============================================================
   assets/css/fabbro.css
   /intervento-fabbro-h24/ — page-specific sections only.

   Tokens, .container, .btn and the .hero--split hero come from
   global.css; the pricing and coverage sections come from
   prezzi.css. Neither is redefined here (CLAUDE.md §"Section CSS",
   rule 2). Load order: global -> prezzi -> fabbro.

   Sections left in this file:
     1 steps · 2 services · 3 emergency (closing)
     (pricing + coverage now live in prezzi.css)
============================================================ */

/* ---------- shared bits ---------- */

.cta-btn{
  display:inline-flex; align-items:center; justify-content:center;
  text-align:center; gap:10px;
  background:var(--amber-600); color:var(--paper-000);
  font-family:var(--font-display);
  font-size:16px; font-weight:700; text-decoration:none;
  padding:17px 30px; border-radius:999px;
  /* keeps a label like "CHIAMA 0282397097" on one line; the button
     grows to fit rather than breaking the number onto its own row */
  white-space:nowrap;
  box-shadow:0 10px 24px rgba(243,90,0,.28);
  transition:transform .15s ease, box-shadow .15s ease;
}
.cta-btn:hover{
  transform:translateY(-1px);
  box-shadow:0 14px 28px rgba(243,90,0,.34);
}
.cta-btn svg{ flex-shrink:0; }

.cta-btn--secondary{
  background:var(--paper-000); color:var(--green-900);
  border:2px solid var(--green-900); box-shadow:none;
}
.cta-btn--secondary:hover{ background:var(--green-100); box-shadow:none; }

.cta-group{
  display:flex; flex-wrap:wrap; align-items:center;
  justify-content:center; gap:16px;
}

.fb-section-title{
  margin:0 0 18px;
  font-family:var(--font-display);
  font-size:clamp(28px,3vw,38px); font-weight:800;
  color:var(--green-900); letter-spacing:-.01em;
}

/* ============================================================
   1. HERO
   Nothing here. The hero is global.css §7b's .hero--split component,
   used as-is — including the landscape photo ratio and stat-card
   positions, which now live there so this page and the homepage
   can't drift apart.
============================================================ */

/* Left column stays left-aligned; only the buttons wrap as a row. */
.hero.hero--split .cta-group{ justify-content:flex-start; }

/* The number stays on the label's own line — .cta-btn is nowrap, so
   the button widens instead of breaking. It used to be display:block,
   which stacked it under "CHIAMA SUBITO!" and, once the button was
   stretched on a phone, left both lines ragged against the icon. */
.fb-hero-phone{
  font-weight:800; letter-spacing:.01em;
}

/* ============================================================
   2. STEPS — Contattaci / Specifica la zona / Richiedi
============================================================ */
.fb-steps{ background:var(--paper-000); padding:clamp(56px,7vw,84px) 5vw; }
.fb-steps-inner{ max-width:1160px; margin:0 auto; }

.fb-step-grid{
  display:grid; grid-template-columns:repeat(3,1fr); gap:24px;
}
.fb-step{
  background:var(--paper-050);
  border:1px solid var(--line-200);
  border-radius:20px;
  padding:32px 28px 34px;
  text-align:center;
  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.fb-step:hover{
  transform:translateY(-4px);
  box-shadow:0 18px 36px rgba(14,57,94,.12);
  border-color:transparent;
}
.fb-step-media{
  width:84px; height:84px; margin:0 auto 20px;
  border-radius:20px; background:var(--green-100);
  display:flex; align-items:center; justify-content:center;
}
.fb-step-media img{ width:48px; height:48px; display:block; }

/* Styled like a heading but kept as <p> — these are paragraphs on the
   old page, and the heading hierarchy must stay exactly as it was. */
.fb-step-title{
  margin:0 0 12px;
  font-family:var(--font-display);
  font-size:19px; font-weight:800; color:var(--green-900);
  line-height:1.3;
}
.fb-step p{
  margin:0; font-size:15px; line-height:1.65; color:var(--ink-700);
}

/* ============================================================
   4. SERVICES — 4 icon cards
============================================================ */
.fb-services{ background:var(--paper-000); padding:clamp(60px,7vw,88px) 5vw; }
.fb-services-inner{ max-width:1160px; margin:0 auto; text-align:center; }

.fb-services-rule{
  width:20%; min-width:120px; height:5px; border:0;
  background:var(--green-900); border-radius:3px;
  margin:0 auto 26px;
}
.fb-services h3{
  margin:0 0 10px;
  font-family:var(--font-display);
  font-size:clamp(19px,2.1vw,24px); font-weight:700;
  color:var(--green-900); line-height:1.35;
}
.fb-services-call{
  margin:0 0 44px;
  font-size:17px; font-weight:700; color:var(--amber-600);
}
.fb-services-call a{ color:var(--amber-600); text-decoration:none; }
.fb-services-call a:hover{ text-decoration:underline; }

.fb-service-grid{
  display:grid; grid-template-columns:repeat(4,1fr); gap:24px;
}
.fb-service-card{
  background:var(--paper-050);
  border-radius:24px;
  padding:34px 24px 32px;
  transition:transform .18s ease, box-shadow .18s ease;
}
.fb-service-card:hover{
  transform:translateY(-4px);
  box-shadow:0 20px 40px rgba(14,57,94,.14);
}
.fb-service-media{
  width:96px; height:96px; margin:0 auto 20px;
  border-radius:22px; background:var(--green-100);
  display:flex; align-items:center; justify-content:center;
}
.fb-service-media img{
  width:56px; height:56px; display:block;
  transition:transform .25s ease;
}
.fb-service-card:hover .fb-service-media img{ transform:scale(1.07); }

.fb-service-card h4{
  margin:0;
  font-family:var(--font-display);
  font-size:16px; font-weight:800; letter-spacing:.01em;
  color:var(--green-900); line-height:1.35;
}

/* ============================================================
   6. EMERGENCY — dark closing panel
============================================================ */
.fb-emergency{ background:var(--green-950); padding:clamp(60px,7vw,88px) 5vw; }
.fb-emergency-inner{ max-width:820px; margin:0 auto; text-align:center; }

.fb-emergency h2:where(:not(.h1-look)){
  margin:0 0 24px;
  font-family:var(--font-display);
  font-size:clamp(26px,3.4vw,38px); font-weight:800;
  color:var(--paper-000); letter-spacing:-.01em; line-height:1.15;
}
.fb-emergency p{
  font-size:16.5px; line-height:1.75; color:var(--green-100);
  margin:0 0 18px;
}
.fb-emergency p:last-of-type{ margin-bottom:32px; }

/* The common closing-band shape: no heading at all in the source, just
   a plain <p> label and a call button, single centred column (no photo,
   no taglist) — most city pages, not only Asti. Reuses the base
   .fb-emergency component with no modifier, the same way Roma's does,
   since there is no split or grid to add. The label still needs the
   same big/bold display treatment Torino's, Udine's and Alessandria's
   closing labels already get, despite being a <p> here rather than an
   <h2>/<h3>/<p> playing that role in --split/--twocol — visual weight
   is free under hard rule 9 even though the source never marked this
   one up as a heading, so it isn't promoted to one, only styled to
   match.

   :first-CHILD, not :first-of-type. The hub page, Roma and Biella all
   pair a real <h2>/<h3> with an ordinary body <p> right after it — that
   <p> is still the first <p> among its siblings (:first-of-type would
   match it), but it is the SECOND element in the block, behind the
   heading. :first-child only matches when the <p> has no element before
   it at all, which is true for the label-only pages above and false for
   every page with a real heading — so a normal 16.5px body paragraph
   never gets promoted to this display treatment by accident. Found on
   the apertura-porte page's closing band, which had exactly this
   collision; the hub page had the same bug, silently, until now. */
.fb-emergency-inner > p:first-child{
  margin:0 0 28px;
  font-family:var(--font-display);
  font-size:clamp(1.25rem,1rem + 1.1vw,1.85rem);
  font-weight:800; line-height:1.2;
  color:var(--paper-000);
  letter-spacing:.01em;
  text-wrap:balance;
}
/* .cta-btn is nowrap by design (fabbro.css §1's own comment: the number
   stays on one line, the button widens instead of breaking) — fine
   inside a flex column with room to grow, but this button is a direct
   child of a plain, narrow (max-width:820px, no split) centred block,
   and Asti's "CHIAMA SUBITO 01411706992!" doesn't fit 288px available
   at 320px without wrapping. A real ~37px overflow, not the usual
   sub-pixel residual — confirmed via the 8-width sweep, and worse than
   it looks: an overflowing position:fixed .call-bar (width:100%) reads
   the browser's own widened layout viewport at that point, not the
   device width, so it grows to match and compounds the overflow
   further. Only .fb-emergency-inner's own direct-child button is
   affected — Torino's, Udine's and Alessandria's buttons all sit one
   level deeper, inside .fb-emergency__copy/__areas, so their own
   nowrap behaviour is untouched. */
.fb-emergency-inner > .cta-btn{
  white-space:normal;
  max-width:100%;
}
/* The note above says the --split/--twocol pages' buttons sit one
   level deeper, inside .fb-emergency__copy, "so their own nowrap
   behaviour is untouched". A page has now actually hit that case:
   apertura-porte-blindate-torino's "CHIAMA SUBITO! 01118838241" is an
   11-digit number, the longest in the set, and overflowed 320px by
   2px. Same guard, one level deeper. white-space:normal only wraps
   when a line needs it, so every shorter number in the set renders
   exactly as before — re-checked on fabbro-torino/udine/alessandria
   after the change. */
.fb-emergency__copy .cta-btn{
  white-space:normal;
  max-width:100%;
}

/* Roma's closing band is not a CTA — it is an H2, an H3 and the list of
   zones covered, all set white on the dark fill by inline styles on the
   old page. The colour is why the band exists, so it moves here; the
   inline styles do not survive (CSS rule 3). */
.fb-emergency h3{
  margin:0 0 18px;
  font-family:var(--font-display);
  font-size:clamp(1.05rem,.95rem + .5vw,1.3rem);
  font-weight:700; line-height:1.3;
  color:var(--paper-000); letter-spacing:.01em;
}
/* Torino only: the source's zone-list sub-label is a real <h4>, one
   level below Roma's <h3> above. No .fb-emergency h4 existed, so this
   is new — same small-eyebrow visual language .fb-areas__title and
   .section-kicker already use elsewhere, recoloured to read on the
   dark fill instead of restyled from scratch. */
.fb-emergency h4{
  margin:0 0 10px;
  font-family:var(--font-body); font-weight:700;
  font-size:.82rem; letter-spacing:.06em; text-transform:uppercase;
  color:var(--green-100);
}
/* Zone chips on the dark fill: the light rules and dark ink of the
   default .fb-taglist are invisible here, so both invert. */
.fb-emergency .fb-taglist{ text-align:left; margin-top:4px; }
.fb-emergency .fb-tag{
  color:var(--paper-000);
  border-bottom-color:rgba(255,255,255,.16);
}
.fb-emergency .fb-tag::before{ background:var(--amber-400); }

/* Closing call button under the service cards — Valle d'Aosta.
   The old page ends that block with a call button of its own, centred
   under the last card. .features has no such slot, so one is defined
   here rather than reaching for an inline style (CSS rule 3). */
.features__cta{
  margin:clamp(34px,4vw,52px) 0 0;
  text-align:center;
}

/* 6b. Two-column closing band — Ticino and Valle d'Aosta.

   Both pages carry a standalone photo the city pages do not, wrapped in an
   empty <h4> by the old builder. It used to sit in a band of its own between
   the last service card and the call bar, where a single image in an
   otherwise empty strip read as a stray upload. The owner asked for it
   beside the closing CTA instead, so this modifier turns that band into two
   columns: copy and call button on the left, photo on the right.

   The base .fb-emergency-inner is a centred 820px column, so both the
   width cap and the centring have to be undone here, not just the
   text-align — otherwise the grid is squeezed into 820px in the middle of
   a full-width band and the photo never reaches the right. */
.fb-emergency--split .fb-emergency-inner{
  max-width:min(1100px,100%);
  display:grid;
  grid-template-columns:1fr;
  align-items:center;
  gap:clamp(28px,4vw,56px);
  text-align:center;
}
@media (min-width:860px){
  .fb-emergency--split .fb-emergency-inner{
    /* The photo's track is a SIZED track, not minmax(0,auto). The image is
       lazy and below the fold, so with an auto track the column measured 0px
       until the file arrived and then jumped to 537px as the reader scrolled
       into it — a layout shift, on a page targeting CLS < 0.05. A sized
       track reserves the column whether the image has loaded or not. */
    grid-template-columns:minmax(0,1fr) clamp(280px,40%,537px);
    text-align:left;
  }
}
/* The label keeps the band's white type; the button must not stretch to the
   column width, so the copy side is a column that shrink-wraps its button. */
.fb-emergency__copy{
  display:flex; flex-direction:column; align-items:center;
  gap:clamp(18px,2.2vw,26px);
  /* Same min-width:auto grid-item trap as .fb-tag above, one level up:
     this is itself the grid item sitting in .fb-emergency-inner's
     minmax(0,1fr) track. Without this, its own automatic minimum width
     is driven by its widest child's content instead of the track's
     available space — Torino's H3 label and CHIAMA SUBITO button (both
     long, unwrapped/undersquished content) were winning that tug-of-war
     and forcing the whole column past the viewport at 320px, the same
     failure shape as the taglist fix above but one layer higher. */
  min-width:0;
}
@media (min-width:860px){
  .fb-emergency__copy{ align-items:flex-start; }
}
/* p:last-of-type in the base block adds 32px under the label; inside this
   flex column the gap above already spaces it, so the margin is cleared.
   The label is also scaled up from the base 16.5px: beside a 537px photo
   it read as a caption rather than as the closing line of the page. Only
   the split variant is touched, so every other closing band is unchanged. */
/* :first-of-type, not every p. The band's LABEL is the display-size line;
   Udine's closing column also carries "Alcune delle zone dove operiamo…"
   and a list of towns after it, and those must stay at reading size. On
   every other split page the label is the only <p> here, so scoping this
   changes nothing for them. */
.fb-emergency--split .fb-emergency__copy > p:first-of-type{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(1.25rem,1rem + 1.1vw,1.85rem);
  font-weight:800; line-height:1.2;
  color:var(--paper-000);
  letter-spacing:.01em;
  text-wrap:balance;
}
/* Any later paragraph in that column is body copy. */
.fb-emergency--split .fb-emergency__copy > p ~ p{
  margin:0;
  font-size:16.5px; line-height:1.75;
  color:var(--green-100);
}

/* Udine's list of towns, inside that same column.

   width:100% is load-bearing again. .fb-emergency__copy is a flex column
   with align-items:flex-start (center below 860px), which stops a child
   stretching — so the grid shrank to ONE 210px track inside a 604px column
   and the 18 towns ran down a single file. The same trap as the media box
   above.

   Two explicit tracks rather than auto-fill: the column is a fixed ~604px
   whatever the viewport does, so auto-fill would always resolve to 2 anyway,
   and stating it keeps the count from drifting if the split ratio is ever
   retuned. Scoped to --split so Roma's wider centred band, which auto-fills
   to 3, is not touched.

   OWNER'S FIX, 22 Sep 2026 — moved inside the >=860px band. This was
   written for Udine's ~604px desktop column and was unconditional, so
   below 860px — where .fb-emergency--split stacks to one column and
   .fb-emergency__copy is the full (narrow) viewport width — it still
   forced 2 fixed tracks. minmax(0,…) only floors a TRACK; the grid
   ITEM sitting in it (and .fb-emergency-inner's own 1fr track above
   it) still defaults to min-width:auto, so the row's min-content
   width won instead of the viewport and the second column ran off the
   right edge. Never visible on Udine's shorter list, but Torino's
   longer one pushed it past the point of being a rounding error — a
   real ~20px overflow at 320px, not the usual decorative-shape false
   positive. Below 860px this now falls back to the general
   .fb-taglist auto-fill rule, which resolves to one column on its
   own in a narrow flex item. Re-verified Udine at 320–1440px after
   the change: unaffected, still 2 columns from 860px up. */
@media (min-width:860px){
  .fb-emergency--split .fb-emergency__copy .fb-taglist{
    width:100%;
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:clamp(16px,2vw,28px);
  }
}
/* Narrower tracks mean the longer names wrap, so the dot aligns to the
   first line instead of the middle of a two-line entry. */
.fb-emergency--split .fb-emergency__copy .fb-tag{ align-items:flex-start; }
.fb-emergency--split .fb-emergency__copy .fb-tag::before{ margin-top:6px; }

/* Alessandria only: a third .fb-emergency shape. Roma is one centred
   column with real headings; Udine/Torino are --split with a photo.
   This page's source closing band is two plain <p> columns side by
   side — a label+button column and a zone-list column — with no
   photo and no heading anywhere in either one. Reuses --split's
   two-column grid idea with no sized photo track, since there is
   nothing to reserve space for; the right column gets its own class
   (.fb-emergency__areas) rather than reusing .fb-emergency__copy
   twice, because the two columns' first paragraphs need different
   treatment (a big label on the left, a small eyebrow on the right)
   and one shared class name would have made that ambiguous to style. */
.fb-emergency--twocol .fb-emergency-inner{
  max-width:min(1100px,100%);
  display:grid;
  grid-template-columns:1fr;
  align-items:start;
  gap:clamp(28px,4vw,56px);
  text-align:center;
}
@media (min-width:860px){
  .fb-emergency--twocol .fb-emergency-inner{
    grid-template-columns:minmax(0,1fr) minmax(0,1.3fr);
    text-align:left;
  }
}
.fb-emergency--twocol .fb-emergency__copy > p:first-of-type{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(1.25rem,1rem + 1.1vw,1.85rem);
  font-weight:800; line-height:1.2;
  color:var(--paper-000);
  letter-spacing:.01em;
  text-wrap:balance;
}
.fb-emergency__areas{
  display:flex; flex-direction:column; align-items:center;
  gap:clamp(14px,1.8vw,20px);
  min-width:0;
}
@media (min-width:860px){
  .fb-emergency__areas{ align-items:flex-start; }
}
/* Same small-eyebrow visual language as .fb-emergency h4 (Torino) and
   .fb-areas__title (Mantova/Milano) — this line is a <p> in the
   source, not a heading, so it borrows that look via a class instead
   of promoting it to an element hard rule 9 would then have to treat
   as new heading structure. */
.fb-emergency__areas > p:first-of-type{
  margin:0;
  font-family:var(--font-body); font-weight:700;
  font-size:.82rem; letter-spacing:.06em; text-transform:uppercase;
  color:var(--green-100);
}
@media (min-width:860px){
  .fb-emergency__areas .fb-taglist{
    width:100%;
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:clamp(16px,2vw,28px);
  }
}
.fb-emergency__areas .fb-tag{ align-items:flex-start; }
.fb-emergency__areas .fb-tag::before{ margin-top:6px; }

.fb-emergency__media{
  border-radius:var(--radius-l);
  overflow:hidden;
  box-shadow:var(--shadow-pop);
  /* A pale sheet behind the photo, so the frame still reads as a frame
     while the file is missing from the local uploads copy (A14) and the
     <img> renders as nothing at all. */
  background:rgba(255,255,255,.06);
  /* width:100% is load-bearing. margin-inline:auto turns OFF a grid item's
     default stretch, so without an explicit width this box shrink-wrapped
     its content — and its only child is a lazy <img> that renders at zero
     until it loads. The frame measured 0x0 on arrival and snapped to full
     size as the reader scrolled in. With width:100% the box fills its
     track, and the auto margins only do anything in the single-column
     layout below 860px, where the cap actually bites. */
  width:100%;
  max-width:min(537px,100%);
  margin-inline:auto;
}
/* Chieti's closing photo is wrapped in an off-site link (hard rule 8 —
   flagged, not removed), so the anchor has to behave like the <img> it
   replaces. Without this it is an inline box that shrink-wraps, and the
   frame stops matching the picture. Inert on the pages whose photo is a
   bare <img>. */
.fb-emergency__media a:has(img){ display:block; width:100%; }
.fb-emergency__media img{
  display:block;
  width:100%; height:auto;
  /* No aspect-ratio here on purpose. An earlier version hardcoded 537/302,
     Ticino's photo — which would have squashed Valle d'Aosta's 541x333 into
     the wrong shape. With width:100%, height:auto and the width/height
     ATTRIBUTES both present in the markup, the browser derives the ratio
     from the attributes per image, so the height is reserved before the
     lazy file arrives without any per-page value here. */
}

/* Torino only: photo on the left, copy on the right — the mirror of
   every other .fb-emergency--split page — plus a smaller frame with a
   white ground instead of the pale sheet. Owner's call, 22 Sep 2026,
   purely visual (hard rule 9 protects heading level/text, not which
   side a block sits on or its frame colour). `order` swaps which grid
   track each child renders in without touching DOM order, so reading
   order and the underlying markup are unchanged. Scoped to this
   modifier only — Udine keeps its own copy-left/photo-right shape and
   pale sheet untouched. The photo's track stays an explicitly SIZED
   track (not minmax(0,auto)), same reason as the base rule above: it
   reserves the column before the lazy image arrives, so this still
   doesn't cost any CLS. */
@media (min-width:860px){
  .fb-emergency--media-left .fb-emergency-inner{
    grid-template-columns:clamp(220px,32%,420px) minmax(0,1fr);
  }
  .fb-emergency--media-left .fb-emergency__media{ order:1; }
  .fb-emergency--media-left .fb-emergency__copy{ order:2; }
}
.fb-emergency--media-left .fb-emergency__media{
  max-width:min(420px,100%);
  background:var(--paper-000);
}
/* Widened to match .container's own cap (--max-w, global.css) — the same
   width the service cards above this band render at — instead of the base
   component's 1100px. More room for the copy column means fewer comuni
   wrap onto a second line inside their cell. */
.fb-emergency--media-left .fb-emergency-inner{
  max-width:min(var(--max-w),100%);
}
/* The copy column is now the wide flexible track instead of Udine's fixed
   ~604px, so its taglist has room for more than the base 2-column rule
   above. Same per-column width as that already-proven 2-column layout
   (~147-155px) at both steps, just spread over more columns instead of
   fewer — checked against the measured column width at each breakpoint
   before picking these two numbers, not guessed. Source order matters
   here: same specificity (three classes) as the .fb-emergency--split rule
   above, so this only wins because it comes after it in the file. */
@media (min-width:860px){
  .fb-emergency--media-left .fb-emergency__copy .fb-taglist{
    grid-template-columns:repeat(3,minmax(0,1fr));
  }
}
@media (min-width:1150px){
  .fb-emergency--media-left .fb-emergency__copy .fb-taglist{
    grid-template-columns:repeat(4,minmax(0,1fr));
  }
}

/* ============================================================
   7. CITY PAGES  (fabbro-milano, fabbro-roma, ...)
   Nothing here is Milan-specific — every city page reuses it.

   These pages are built almost entirely from global.css
   components: .hero--split for the hero, .tile-strip/.tile for the
   service strip, .about__grid/__media/__content for the text+image
   splits, .features/.feature-card for the service cards, .btn for
   every button, and the sticky .call-bar. Pricing comes from
   prezzi.css. Only the five rules below are genuinely new.
============================================================ */

/* 7b. Alternating background for a second .about block on one page,
   so two text+image sections don't run together. */
.about--tint{ background:var(--green-050); }

/* An .about block whose text column carries a list rather than a
   paragraph needs more than half the row. 62/38 instead of 50/50 —
   enough for three comune columns, while the map still reads at its
   own scale. Only above 900px: below that global.css §9's auto-fit
   is already collapsing the grid, and this must not fight it. */
@media (min-width:900px){
  .about__grid--wide-text{
    grid-template-columns:minmax(0,1.62fr) minmax(0,1fr);
  }
}

/* global.css §9 colours every link inside .about__content green, and
   only exempts .btn--white — which turns a .btn--primary placed there
   into green-on-orange. Put the button's own colour back. */
.about__content a.btn--primary,
.about__content a.btn--primary:hover,
.about__content a.btn--primary:focus-visible{ color:var(--paper-000); }
.about__content a.btn--primary .icon-phone{ color:inherit; }

/* 7b-bis. A paragraph the old page hangs BELOW an .about row rather than
   inside either of its columns — Montesilvano.

   Its source row has three columns: copy left, photo right, and then a
   col-sm-12 carrying one more paragraph across the full width. Dropping
   that paragraph into .about__content would have put it beside the photo
   and after the call button, which reads as an afterthought to the CTA
   rather than as the close of the intro. So it sits outside .about__grid,
   inside the same .container.

   NO max-width: it runs the full container, which is what col-sm-12 means
   on the old page. An earlier version capped it at 78ch to keep the line
   length near the copy column's; that was overruled — the paragraph is the
   full-width close of the section and reads as one. */
.about__tail{
  margin:clamp(28px,3.4vw,44px) 0 0;
}
/* On Montesilvano .about__tail IS the paragraph. On Chieti that full-width
   column holds two things — the services line and the call button — so the
   class goes on a wrapper instead. global.css leaves <p> at margin:0 and
   lets each component space its own children, so that spacing is set here.
   Inert where the tail has no element children. */
.about__tail > * + *{ margin-top:clamp(18px,2.2vw,26px); }

/* 7c. .feature-card__icon is built for a 24px inline SVG; these pages
   put a PNG in it, at the artwork's own 128px so it stays crisp. The
   chip grows to fit rather than the image shrinking to fit the chip. */
.feature-card__icon img{
  width:128px; height:128px; object-fit:contain; display:block;
}
/* Bergamo puts two icons in one card (its page builder left the last
   two cards' artwork stranded in an earlier column). Stack them so the
   chip stays one icon wide instead of doubling the column. */
.feature-card__icon:has(img + img){
  flex-direction:column;
  gap:12px;
}
.feature-card__icon:has(img){
  /* fit-content, not auto: as a block child it would otherwise stretch
     the tint panel across the whole card on a phone */
  width:fit-content; height:auto;
  padding:16px; border-radius:20px;
}

/* Pisa only: the source's "Servizi" heading is a real <h2>, one level
   above every other page's <h3>/"I servizi" here — kept at its own
   level (hard rule 9 protects level and text, not visual weight).
   Unstyled, global.css's h2 is roughly double h3's size and would
   read as an oversized outlier next to every sibling page's section
   title, so this restyles it down to the exact size/weight h3 already
   renders at in this same context. */
.features__head--center h2:where(:not(.h1-look)){
  font-size:clamp(1.15rem,1.05rem + .5vw,1.45rem);
  font-weight:700;
}

/* 7c-bis. One card per row, artwork left and copy right — for the
   long service write-ups, where a three-up grid left each card a
   narrow column of dense text. Reusable on any city page.

   --cols-max is global.css's own grid knob (§"Fluid grids"), so the
   column count changes without redefining the grid.

   The card is a two-item flex row — artwork, then a .feature-card__body
   holding the heading and however many paragraphs the card has. A grid
   was the first attempt and was wrong: the icon's row sized to 160px,
   which pushed the first paragraph that far below the heading. */
.features__grid--rows{
  --cols-max:1;
}
.feature-card__body > :last-child{ margin-bottom:0; }
/* global.css leaves <p> at margin:0 and lets each component space its
   own paragraphs (§FAQ, §region-panel do the same). Feature cards never
   had the rule, so the two-paragraph cards ran together. */
.feature-card__body p + p{ margin-top:var(--space-xs); }

@media (max-width:859px){
  /* Below 860px the card is a stacked column — the icon-left/copy-right
     row below is ≥860px only — so a left-aligned chip sitting over
     left-aligned copy read as two things that happened to land on the
     left, not a deliberate single column. Centering both reads as one
     stack. Scoped here (not a bare rule reset again at ≥860px) so the
     existing row layout is untouched by construction.

     .feature-card__icon is already width:fit-content (7c, so the tint
     chip hugs a single 128px icon instead of stretching); margin-inline
     auto is what centers a fit-content block, and it also centers
     Bergamo's stacked two-icon case (:has(img + img) above) as one unit
     without a separate rule. */
  .features__grid--rows .feature-card{ text-align:center; }
  .features__grid--rows .feature-card__icon{ margin-inline:auto; }
  /* Icon trimmed a little: centred and full-size it read as heavier at
     the top of the card than the same 128px did sitting to the left. */
  .features__grid--rows .feature-card__icon img{ width:104px; height:104px; }
}

@media (min-width:860px){
  .features__grid--rows .feature-card{
    display:flex; align-items:flex-start;
    gap:clamp(28px,3.2vw,48px);
    padding:clamp(28px,3vw,38px) clamp(28px,3vw,38px) clamp(26px,2.8vw,34px);
  }
  .features__grid--rows .feature-card__icon{
    flex:none; margin-bottom:0;
  }
  /* min-width:0 so a long word can't push the column wider */
  .features__grid--rows .feature-card__body{ flex:1 1 auto; min-width:0; }
  /* the heading sits level with the top of the artwork */
  .features__grid--rows .feature-card__body > :first-child{ margin-top:2px; }

  /* Owner's rule, 21 Sep 2026 — moved here from the mobile block on the
     same day, at the owner's correction: an EVEN number of cards goes
     two-up on DESKTOP; an ODD count stays the single full-width row
     layout above, exactly as it already renders — untouched, because
     nothing here matches an odd count and no existing rule is edited.
     Mobile is back to always one stacked column, as it was before this.

     No JS and no per-page class: the standard pure-CSS "quantity query"
     (Heydon Pickering). :first-child:nth-last-child(even) matches an
     element only when it is BOTH the first child AND an even number of
     positions from the last — which happens for the first child only
     when the total sibling count is itself even. :has() lets the GRID
     react to that fact about its children, so the column count is a
     function of how many cards the page happens to have, decided at
     render time, not authored per page.

     min-width:0 on the card stops a long unbroken word (there aren't
     any in this copy, checked) from forcing the column wider than its
     share. */
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(even)){
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:clamp(24px,2.8vw,40px);
  }

  /* The icon-left/copy-right row above doesn't fit a half-width column
     the way it fits the full-width one: at ~600px wide that row was
     fine, but the same 128px icon and 48px gap left the two-up column
     cramped. So the two-up card is NOT the row layout, narrower — it is
     the mobile card's own stacked, centred treatment from the block
     above, reused rather than re-invented, with the icon at the same
     104px. Only .feature-card__body > :first-child's 2px margin-top
     (set for the row layout, to line the heading up with the icon's
     top edge) is left alone here — with everything centred and stacked
     it is not visible either way, so it isn't worth a fourth selector
     to reset it. */
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(even)) .feature-card{
    display:block;
    text-align:center;
    min-width:0;
  }
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(even)) .feature-card__icon{
    margin:0 auto 20px;
  }
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(even)) .feature-card__icon img{
    width:104px; height:104px;
  }

  /* Exactly six cards: same quantity-query technique, narrowed to a count
     of six. :nth-last-child(6) matches the first child only when it is
     also the 6th-from-last, which happens only when there are exactly
     six siblings total. Placed after the even-count rule above so it
     wins on equal specificity via source order; every other even count
     (4, 8, ...) still gets two columns from that rule. The centred,
     stacked card/icon treatment above already matches six along with
     every other even count, so only the column arrangement is
     overridden here.

     The owner's correction, same day: three-up read fine for the first
     three cards, but the last three each carry a third paragraph — at
     three-up that's noticeably too little width per column for the
     extra text, so they drop to two-up instead. One 6-column base grid
     covers both groups: the first three each span 2 of 6 (three-up),
     the last three each span 3 of 6 (two-up) — which leaves the sixth
     card with nothing to sit beside, so it spans the full width alone
     on its own row rather than sitting half-empty next to a gap. */
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(6)){
    grid-template-columns:repeat(6,minmax(0,1fr));
    column-gap:clamp(20px,2.4vw,32px);
  }
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(6)) .feature-card:nth-child(-n+3){
    grid-column:span 2;
  }
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(6)) .feature-card:nth-child(n+4){
    grid-column:span 3;
  }
  .features__grid--rows:has(.feature-card:first-child:nth-last-child(6)) .feature-card:nth-child(6){
    grid-column:span 6;
  }
}

/* 7c-ter. Lucca's third row pairs a real card with a plain coverage-map
   photo, not a fourth card — the source has no icon/heading for it,
   just a bare <img>. .feature-media sits in the same grid as
   .feature-card but skips the icon+body chrome entirely, matching the
   source's own plain treatment rather than inventing a card shell
   around it. */
.features__grid--rows .feature-media{
  display:flex; align-items:center; justify-content:center;
}
.features__grid--rows .feature-media img{
  max-width:100%; height:auto; border-radius:var(--radius-m);
}

/* 7c-ter DELETED — .features__closing is gone.

   It used to stack the closing photo and a call button under the last
   service card, on the light background. The owner rejected that shape on
   21 Sep 2026: the photo belongs INSIDE the closing CTA, as its right-hand
   column, which is exactly the ruling already given for Ticino on 18 Sep
   (F7). Pescara, Chieti, Teramo and Vicenza now all use
   .fb-emergency--split (§6b) like every other page that ends on a picture,
   and the duplicate call button above the photo is removed on the three
   that had one.

   Nothing references .features__closing any more, so it is deleted rather
   than left to rot — the same call made about .fb-shot when Ticino's band
   was dissolved. The only thing that block had which §6b did not is the
   linked-photo rule, which moves there. */

/* 7d. STORY — the long copy blocks as a numbered editorial run.
   Deliberately NOT cards: the page already has four card grids
   (tiles, pricing, services, chips) and a fifth made the whole thing
   read as one long row of boxes. Here the structure comes from a
   numbered marker and a hairline rail instead of borders.

   The numerals are a CSS counter, so they exist only in the render —
   nothing is added to the DOM or to the page's copy. */
.fb-story{ background:var(--paper-050); }
.fb-story__inner{
  max-width:940px;
  counter-reset:fb-story;
}

/* Roma opens its story section with an H2 and two paragraphs that sit
   above the numbered blocks and belong to none of them. Kept outside
   .fb-story__block on purpose: inside, it would take a counter numeral
   and a rail segment it has no business having. */
/* Full width of the inner, not a 68ch column.

   The 68ch cap left the head 605px wide inside a 940px inner while the
   numbered blocks below started 78px further right and ran to 952 — so the
   intro and the blocks shared neither edge, and ~335px sat empty beside the
   intro. The head now spans the section and the blocks are centred under it
   (see .fb-story__block), which gives the two parts one deliberate
   relationship instead of two accidental ones. */
.fb-story__head{
  margin:0 0 clamp(28px,3.5vw,44px);
}
.fb-story__head h2:where(:not(.h1-look)){
  margin:0 0 16px;
  font-family:var(--font-display);
  font-size:clamp(1.55rem,1.2rem + 1.4vw,2.3rem);
  font-weight:800; line-height:1.2;
  color:var(--green-900); letter-spacing:-.01em;
}
.fb-story__head p{
  margin:0 0 16px;
  font-size:16.5px; line-height:1.8;
  color:var(--ink-700); text-align:left;
}
.fb-story__head p:last-child{ margin-bottom:0; }
.fb-story__head strong{ color:var(--green-900); font-weight:700; }
.fb-story__head a{ color:var(--green-700); font-weight:700; }
.fb-story__head a:hover{ color:var(--amber-600); }

/* Centred as a group under the full-width head.

   The cap was 760px, which left ~624px of content — one track short of the
   three columns the keyword run used to get when blocks filled the section.
   880px restores that (about 800px of content, comfortably three 210px
   tracks) while keeping a visible inset inside the 940px section, so the
   blocks still read as centred rather than flush. */
.fb-story__block{
  position:relative;
  counter-increment:fb-story;
  padding:0 0 clamp(36px,4vw,52px) clamp(56px,6vw,78px);
  max-width:880px;
  margin-inline:auto;
}
.fb-story__block:last-child{ padding-bottom:0; }

/* The numeral sits in its own disc at the head of the rail. */
.fb-story__block::before{
  content:counter(fb-story,decimal-leading-zero);
  position:absolute; left:0; top:0;
  width:44px; height:44px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:var(--paper-000);
  border:1px solid var(--line-200);
  font-family:var(--font-display);
  font-size:.95rem; font-weight:800; letter-spacing:.02em;
  color:var(--amber-600);
}
/* Hairline rail joining one block to the next. */
.fb-story__block::after{
  content:""; position:absolute;
  left:22px; top:56px; bottom:12px; width:1px;
  background:linear-gradient(var(--line-200),transparent);
}
.fb-story__block:last-child::after{ display:none; }

.fb-story__block h3{
  margin:6px 0 16px;
  font-family:var(--font-display);
  font-size:clamp(1.2rem,1.05rem + .6vw,1.6rem);
  font-weight:800; line-height:1.25;
  color:var(--green-900); letter-spacing:-.01em;
}
.fb-story__block p{
  margin:0 0 16px;
  font-size:16.5px; line-height:1.8;
  color:var(--ink-700);
  /* left-aligned on purpose: justified text at this measure opens
     rivers, which is what made the old version look ragged */
  text-align:left;
  max-width:68ch;
}
.fb-story__block p:last-child{ margin-bottom:0; }
.fb-story__block strong{ color:var(--green-900); font-weight:700; }
.fb-story__block a{ color:var(--green-700); font-weight:700; }
.fb-story__block a:hover{ color:var(--amber-600); }
.fb-story__block .fb-taglist{ margin-top:20px; }
/* Three columns for the keyword run, stated rather than left to auto-fill.
   auto-fill resolves from the track floor, so a few pixels lost anywhere in
   the chain silently drops it to two — which is exactly what happened when
   the blocks were first capped. Below 900px it falls back to the auto-fill
   rule above, and below 620px to the explicit two-column phone rule. */
@media (min-width:900px){
  .fb-story__block .fb-taglist{ grid-template-columns:repeat(3,minmax(0,1fr)); }
}

@media (max-width:620px){
  .fb-story__block{ padding-left:0; padding-bottom:34px; }
  .fb-story__block::before{
    position:static; margin-bottom:14px;
    width:38px; height:38px; font-size:.85rem;
  }
  .fb-story__block::after{ display:none; }
}

/* Lets two .features sections sit next to each other without their
   backgrounds merging into one block. */
.features--plain{ background:var(--paper-000); }

/* 7e. Pipe-separated runs rendered as chips — see _taglist.php.
   Each entry gets its own pill with a dot marker; the original "|"
   characters are still in the DOM inside .fb-tag__sep, just not
   painted, so nothing is removed from the copy. */
/* An aligned index, not wrapped pills. Entries vary from "SOS Fabbro"
   to "Installazione Cilindri di Sicurezza", so free-flowing chips gave
   ragged rows with uneven gaps. Equal grid tracks line every entry up
   on both axes; the hairline under each one carries the eye across. */
.fb-taglist{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(210px,1fr));
  gap:0 clamp(20px,2.5vw,34px);
  list-style:none; margin:0; padding:0;
}
.fb-tag{
  display:flex; align-items:center; gap:10px;
  padding:10px 2px;
  border-bottom:1px solid var(--line-200);
  font-size:14px; font-weight:600; line-height:1.4;
  color:var(--green-900);
  /* A grid item defaults to min-width:auto (content-based), same as a
     flex item — the minmax(0,…) on the track above only sizes the
     TRACK, not this item sitting in it. Torino's zone list is the
     first taglist long enough to expose it: without this, a couple of
     tags in the narrow single-column mobile layout refused to shrink
     below their own min-content width and pushed the row past the
     viewport. Same fix already used on .feature-card elsewhere. */
  min-width:0;
}
.fb-tag::before{
  content:""; flex-shrink:0;
  width:5px; height:5px; border-radius:50%;
  background:var(--amber-500);
}
/* The separators stay in the DOM for crawlers and copy-paste. */
.fb-tag__sep{
  position:absolute; width:1px; height:1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap;
}

/* The "Fabbro Vicino a Me" index runs to 40 comuni and sits in the
   narrower about column (the map takes the other half), where auto-fill
   only ever found room for two tracks. Pin the count instead: two
   columns everywhere, three once the viewport is wide enough that the
   text column can carry them. minmax(0,1fr) lets a long comune wrap
   rather than push its track wider than the others.
   The 1200px floor is deliberate — below it the about grid is still
   two-up, so a third track would drop to ~130px and break names like
   "Fabbro a Trezzano sul Naviglio" across three lines. */
.fb-taglist--areas{
  grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:clamp(14px,1.6vw,24px);
}
@media (min-width:1200px){
  .fb-taglist--areas{ grid-template-columns:repeat(3,minmax(0,1fr)); }
}
/* Narrower tracks mean some names wrap, so the dot aligns to the
   first line rather than to the middle of a two-line entry. */
.fb-taglist--areas .fb-tag{ align-items:flex-start; }
.fb-taglist--areas .fb-tag::before{ background:var(--green-700); margin-top:6px; }

/* 7e-sexies. Closing media block.

   Rieti ends on a photo plus one call button. Dropped into the hub's
   .fb-closing-media the two just stacked hard-left in a 1240px block —
   a button floating above a raw photo with 850px of dead space beside
   them. This gives them a shape.

   DOM order is button then image, because that is the order the old
   page has and a crawler should see it unchanged. Visually the photo
   comes first and the button sits under it, which is the order that
   reads properly — column-reverse does that without touching the DOM. */
.fb-final{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  background:
    linear-gradient(160deg,
      var(--green-950) 0%,
      var(--green-900) 60%,
      var(--green-800) 100%);
  padding:clamp(44px,5vw,76px) 5vw;
}
/* Same off-centre amber light as the banner and the services panel. */
.fb-final::before{
  content:"";
  position:absolute; z-index:-1;
  inset:auto auto -45% -12%;
  width:min(620px,70%); aspect-ratio:1;
  border-radius:50%;
  background:radial-gradient(circle,rgba(255,81,0,.26) 0%,rgba(255,81,0,0) 70%);
  pointer-events:none;
}
/* Two columns above 900px: the closing line and its call button on the
   left, the photo on the right. Below that they stack, copy first. */
.fb-final__inner{
  display:grid;
  gap:clamp(26px,3.5vw,54px);
  align-items:center;
  max-width:var(--max-w);
  margin-inline:auto;
}
@media (min-width:900px){
  .fb-final__inner{
    grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  }
}

.fb-final__copy{ text-align:center; }
@media (min-width:900px){
  .fb-final__copy{ text-align:left; }
}
/* Scoped to beat ".fb-final__copy p" below, which is a type+class
   selector and would otherwise zero this margin and tuck the amber rule
   in behind the button. */
.fb-final__copy .fb-final__title{
  /* Bottom margin has to clear the amber rule below the text AND leave
     the button room. */
  margin:0 0 clamp(28px,3.2vw,40px);
  font-family:var(--font-display);
  font-size:clamp(1.5rem,1.1rem + 1.7vw,2.4rem);
  font-weight:800; line-height:1.15;
  color:var(--paper-000);
  letter-spacing:-.01em;
  text-wrap:balance;
}
/* Amber rule, matching the banner and the services title. */
.fb-final__title::after{
  content:"";
  display:block;
  width:56px; height:3px; border-radius:3px;
  margin:18px auto 0;
  background:var(--amber-500);
}
@media (min-width:900px){
  .fb-final__title::after{ margin-inline:0; }
}
.fb-final__copy p{ margin:0; }

/* The photo gets a frame so it reads as a finished element rather than
   a loose asset dropped on a dark field. */
.fb-final__media img{
  display:block;
  width:100%; height:auto;
  border-radius:var(--radius-l);
  border:1px solid rgba(255,255,255,.14);
  box-shadow:0 24px 60px rgba(0,0,0,.38);
}

/* 7e-quater. Full-width heading band.

   Tivoli carries a SECOND <h1> of its own — "FABBRO A TIVOLI" — in a
   full-width coloured row directly under the hero, set white by an
   inline style. The heading is reproduced at its original level (see
   that page's file for why it is not demoted); this band is what
   carries the white text now the inline style is gone.

   A flat block of navy with centred text read as a placeholder, so the
   band is built rather than filled: a diagonal brand gradient, one
   off-centre amber glow to stop the field going dead, and a short rule
   under the heading to tie it to the accent used elsewhere. All of it
   is ::before/::after and gradients — no extra DOM, no added copy. */
.fb-banner{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  padding:clamp(34px,4.6vw,58px) 5vw;
  text-align:center;
  background:
    linear-gradient(118deg,
      var(--green-950) 0%,
      var(--green-900) 52%,
      var(--green-800) 100%);
}
/* Soft amber light, off to one side so the band has a direction. */
.fb-banner::before{
  content:"";
  position:absolute; z-index:-1;
  inset:-60% -10% auto auto;
  width:min(560px,60%); aspect-ratio:1;
  border-radius:50%;
  background:radial-gradient(circle,rgba(255,81,0,.30) 0%,rgba(255,81,0,0) 68%);
  pointer-events:none;
}
/* Hairline top edge, so the band separates from the hero above it. */
.fb-banner::after{
  content:"";
  position:absolute; inset:0 0 auto 0; height:1px;
  background:linear-gradient(90deg,
    transparent, rgba(255,255,255,.18) 30%, rgba(255,255,255,.18) 70%, transparent);
}
/* h1 AND h2: Tivoli's band is still the page's second <h1>, Ticino's was
   demoted to <h2> on the owner's instruction (_PHASE-6-LOG.md A8). The band
   looks the same either way — the level is a document-outline decision, not
   a visual one — so both are styled here rather than duplicating the block. */
.fb-banner h1,
.fb-banner h2:where(:not(.h1-look)),
/* h1 AND h2: Tivoli's band is still the page's second <h1>, Ticino's was demoted to <h2> on the owner's instruction (_PHASE-6-LOG.md A8). The band looks the same either way — the level is a document-outline decision, not a visual one — so both are styled here rather than duplicating the block. */ .fb-banner h2:where(.h1-look){
  position:relative;
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(1.5rem,1.1rem + 1.6vw,2.35rem);
  font-weight:800; line-height:1.15;
  color:var(--paper-000);
  letter-spacing:.01em;
  text-wrap:balance;
}
/* Short amber rule under the heading. */
.fb-banner h1::after,
.fb-banner h2:where(:not(.h1-look))::after,
/* Short amber rule under the heading. */ .fb-banner h2:where(.h1-look)::after{
  content:"";
  display:block;
  width:64px; height:3px; border-radius:3px;
  margin:18px auto 0;
  background:var(--amber-500);
}

/* Ticino's band carries a call button of its own, where Tivoli's is
   heading-only. It sits under the amber rule, centred. Still a flex row
   that wraps: it held two buttons until the owner removed the duplicate
   "Vedi i prezzi", and one button must not be stranded if another returns. */
.fb-banner__actions{
  position:relative;
  margin-top:clamp(22px,2.6vw,30px);
  display:flex; flex-wrap:wrap; justify-content:center;
  gap:clamp(12px,1.4vw,16px);
}

/* 7e-quinquies. Services section for the city pages that have NO
   per-service cards — Velletri and Tivoli.

   Those pages are one heading, one long paragraph and a seven-item tick
   list. Run through .fb-story that came out as a narrow column of prose
   with the right-hand 40% of the page empty and the list hanging off the
   bottom: technically correct, visibly unfinished.

   Here the two halves are given jobs. The prose keeps a readable measure
   on the left; the tick list becomes a raised panel on the right that
   holds the column and sticks while the prose scrolls past it. Below
   1000px it stacks, panel last, which is the right reading order anyway.

   No copy is added — the panel has no heading of its own because the old
   page does not give it one. */
.fb-services{
  background:
    linear-gradient(180deg,var(--paper-000) 0%,var(--paper-050) 100%);
}
.fb-services__grid{
  display:grid;
  gap:clamp(28px,3.5vw,54px);
  /* stretch, not start: the panel fills the full height of the row so
     the column never ends in a stump of dead space under it */
  align-items:stretch;
}
@media (min-width:1000px){
  .fb-services__grid{
    grid-template-columns:minmax(0,1.32fr) minmax(320px,.8fr);
  }
}

.fb-services__title{
  margin:0 0 20px;
  font-family:var(--font-display);
  font-size:clamp(1.6rem,1.2rem + 1.6vw,2.45rem);
  font-weight:800; line-height:1.15;
  color:var(--green-900); letter-spacing:-.01em;
  text-wrap:balance;
}
/* Amber rule, matching the banner's, so the two read as one family. */
.fb-services__title::after{
  content:"";
  display:block;
  width:56px; height:3px; border-radius:3px;
  margin:16px 0 0;
  background:var(--amber-500);
}
.fb-services__lead p{
  margin:0 0 16px;
  font-size:16.5px; line-height:1.85;
  color:var(--ink-700);
  text-align:left;
}
.fb-services__lead p:last-child{ margin-bottom:0; }
.fb-services__lead strong{ color:var(--green-900); font-weight:700; }
.fb-services__lead a{ color:var(--green-700); font-weight:700; }
.fb-services__lead a:hover{ color:var(--amber-600); }

/* The tick list's panel.

   A white card with hairlines was the obvious thing and it looked like
   nothing — a list with a border round it. This is the opposite side of
   the page's contrast instead: a dark brand-green slab against the pale
   section, so the column reads as a deliberate block rather than
   leftover space. The rows sit on it as translucent chips.

   No sticky. The panel is nearly as tall as the prose, so sticking
   bought about 50px of travel and just felt like a bug. It stretches to
   the row height instead and the chips space themselves down it. */
.fb-services__panel{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  border-radius:var(--radius-l);
  padding:clamp(22px,2.6vw,34px);
  background:
    linear-gradient(158deg,
      var(--green-950) 0%,
      var(--green-900) 58%,
      var(--green-800) 100%);
  box-shadow:var(--shadow-pop);
  display:flex; flex-direction:column; justify-content:center;
}
/* Amber wash in the corner, the same light the banner uses. */
.fb-services__panel::before{
  content:"";
  position:absolute; z-index:-1;
  inset:auto -30% -40% auto;
  width:min(420px,85%); aspect-ratio:1;
  border-radius:50%;
  background:radial-gradient(circle,rgba(255,81,0,.28) 0%,rgba(255,81,0,0) 70%);
  pointer-events:none;
}
/* Accent bar across the top edge. */
.fb-services__panel::after{
  content:"";
  position:absolute; inset:0 0 auto 0; height:4px;
  background:linear-gradient(90deg,var(--amber-500),var(--amber-400) 55%,transparent);
}

.fb-services__panel .fb-checklist{
  margin:0;
  grid-template-columns:1fr;
  gap:clamp(8px,1vw,12px);
}
/* Each service is a chip on the dark field, not a row with a rule. */
.fb-services__panel .fb-checklist li{
  gap:14px;
  padding:12px 14px;
  border-bottom:0;
  border:1px solid rgba(255,255,255,.10);
  border-radius:14px;
  background:rgba(255,255,255,.06);
  color:var(--paper-000);
  font-size:15.5px; font-weight:600;
  transition:background .16s ease, border-color .16s ease, transform .16s ease;
}
.fb-services__panel .fb-checklist li:hover{
  background:rgba(255,255,255,.12);
  border-color:rgba(255,255,255,.22);
  transform:translateX(4px);
}
/* The tick sits in its own lighter tile so the orange always reads,
   whatever part of the gradient it lands on. */
.fb-services__panel .fb-checklist img{
  padding:6px;
  border-radius:10px;
  background:rgba(255,255,255,.12);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10);
}

/* 7e-ter. Tick list.

   Velletri lists its services as one paragraph of seven 23px check
   images separated by <br>. Rendered as a real <ul> here: the seven
   images, their alt text and every label survive unchanged, but a list
   of services becomes a list rather than a run-on line.

   The icons keep their own dimensions, so nothing is scaled. */
.fb-checklist{
  list-style:none; margin:20px 0 0; padding:0;
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:10px clamp(18px,2.5vw,32px);
}
.fb-checklist li{
  display:flex; align-items:center; gap:10px;
  padding:8px 2px;
  border-bottom:1px solid var(--line-200);
  font-size:15.5px; font-weight:600; line-height:1.4;
  color:var(--green-900);
}
.fb-checklist img{ flex-shrink:0; }

/* 7e-septies. Gorizia's two short benefit lists.

   The old page puts them in a pair of vc_col-sm-6 columns inside the intro,
   each headed by a one-line lead-in set in orange — "I vantaggi del servizio
   Fabbro:" and "Pronto Intervento Fabbro Gorizia offre:". The colour is the
   only thing marking those lines as headings, so it moves here as a token
   (CSS rule 3 bans the inline style, but dropping the emphasis entirely
   would flatten two labels into body text).

   Side by side from 700px up, stacked below it. The lists themselves reuse
   .fb-checklist, which inside a ~290px column resolves to a single track. */
.fb-perks{
  display:grid;
  grid-template-columns:1fr;
  gap:clamp(18px,2.4vw,30px);
  /* Bottom margin as well as top: the last list row ends on a hairline, and
     the CTA button that follows sat almost against it. */
  margin:clamp(22px,2.6vw,30px) 0 clamp(26px,3vw,36px);
}
@media (min-width:700px){
  .fb-perks{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
.fb-perks__lead{
  margin:0 0 10px;
  font-family:var(--font-display);
  font-size:15px; font-weight:800;
  color:var(--amber-600);
  letter-spacing:.01em;
}
.fb-perks .fb-checklist{ margin-top:0; }

/* 7e-bis. Some city pages write their section label as a paragraph
   rather than a heading — Cremona's "Servizi" is a <p><strong>, and
   promoting it to an H3 would add a heading the old page never had
   (hard rule 9). Keep the <p>; give it the presence the H3 has on the
   pages that do use one. Sizing matches global.css's h3. */
.fb-head-label{
  margin:0;
  font-family:var(--font-display);
  font-size:clamp(1.15rem,1.05rem + .5vw,1.45rem);
  font-weight:700; line-height:1.3;
  letter-spacing:-.01em;
  color:var(--ink-900);
}

/* Verbano Cusio Ossola only: the source's last row carries no label or
   heading at all, just one more CTA button beside the call bar — its
   own background was a Torino-branded photo (not this page's city),
   dropped as presentation rather than shown wrong (see the page's own
   header comment). No dark .fb-emergency treatment either: that
   component exists to carry a heading/label, and there is none here to
   justify it. Just enough padding so the lone button isn't flush
   against the cards above it. */
.fb-cta-plain{
  padding:clamp(40px,5vw,64px) 5vw;
}
/* Same nowrap overflow already fixed for Asti's closing button
   (fabbro.css §6, .fb-emergency-inner > .cta-btn): .cta-btn is nowrap
   by design, fine with room to grow, but this page's own number
   ("CHIAMA SUBITO 0323086546") doesn't fit 320px's available width
   without wrapping, and an overflowing button here compounds into the
   position:fixed .call-bar the same way it did there. */
.fb-cta-plain .cta-btn{
  white-space:normal;
  max-width:100%;
}

/* 7f. Closing coverage band — the Italy map some city pages end on.
   Centred on its own it read as a stray image in white space, so it
   now anchors one edge of a dark closing band with the call CTA
   anchored to the other: the same "map + phone" pairing the page is
   really making. Reusable on any city page that ends the same way. */
.fb-closing-media{
  background:var(--green-950);
  padding:clamp(40px,5vw,68px) 0;
  /* the map is allowed to run off the page edge below */
  overflow:hidden;
}
.fb-closing-media__grid{
  display:grid;
  grid-template-columns:1fr;
  align-items:center;
  justify-items:center;
  gap:clamp(26px,4vw,48px);
  padding-inline:var(--gutter);
}
.fb-closing-media__media img{
  display:block; height:auto;
  width:clamp(215px,46vw,320px);
}
/* the band is dark, so the outline button needs the light treatment */
.fb-closing-media .cta-btn--secondary{
  background:transparent; color:var(--paper-000);
  border-color:var(--paper-000);
}
.fb-closing-media .cta-btn--secondary:hover{
  background:var(--paper-000); color:var(--green-900);
}

@media (min-width:860px){
  /* Map and buttons are one centred lockup, not two items pinned to
     opposite edges of a 1240px band. Two tries at pinning them to the
     edges left either a hole down the middle or a map cropped to a
     sliver: the artwork is portrait and narrow, so it cannot carry a
     full-width row on its own. Capping the group keeps the pair
     balanced while the dark band still runs edge to edge. */
  .fb-closing-media__grid{
    grid-template-columns:auto auto;
    justify-content:center;
    align-items:center;
    gap:clamp(40px,6vw,80px);
    max-width:760px; margin-inline:auto;
  }
  /* Sized by width, never by height. With height set and width:auto the
     global img{max-width:100%} resolves against an auto grid column
     whose own width depends on the image — the browser breaks the loop
     by squashing the map (241px wide where its aspect needs 340px).
     A definite width sizes the column and the height follows. */
  .fb-closing-media__media img{
    width:clamp(250px,26vw,340px); height:auto;
    /* and max-width:100% has to go with it: against an auto track it
       clamps the image back to the track the image is meant to size.
       The width above is viewport-relative, so nothing can overflow. */
    max-width:none;
  }
  .fb-closing-media__actions{
    flex-direction:column; align-items:stretch;
    gap:14px;
  }
}

/* Eyebrow over a chip list. Needs real space above it — it follows a
   heading, and global's .about__content h2{margin-bottom:8px} leaves
   the two sitting on top of each other. */
.fb-areas__title{
  display:flex; align-items:center; gap:10px;
  font-family:var(--font-display);
  font-size:.82rem; font-weight:700; letter-spacing:.06em;
  color:var(--ink-500); text-transform:uppercase;
  margin:28px 0 14px;
}
.fb-areas__title::after{
  content:""; flex:1; height:1px; background:var(--line-200);
}

/* Faenza only: the source wraps its intro photo in its own <h2>
   caption. Hard rule 9 protects the heading's LEVEL and TEXT, not
   the old page's visual weight — global.css's default h2 (48px/800)
   read as an oversized, ugly floating headline over the photo, so
   it is restyled as a small pill tag here instead. Same visual
   language as .svc-pricing-pill (prezzi.css) and .section-kicker
   (global.css) already use elsewhere — no new tokens. */
.about__media-tag{
  display:inline-flex; align-items:center;
  font-family:var(--font-body); font-weight:700;
  font-size:.8rem; letter-spacing:.03em; text-transform:uppercase;
  color:var(--green-800); background:var(--green-100);
  padding:6px 16px; border-radius:999px;
  margin:0 0 14px;
}

/* ============================================================
   8. GENOVA-ONLY COMPONENTS

   This is the richest fabbro page built so far — five service
   write-ups instead of three or four, a keyword taxonomy rendered as
   nested <ul>s, and a closing band of twenty real <h5> headings. None
   of the existing card/list/tag components fit these three shapes, so
   three new ones are added here rather than force-fitting the markup
   into something that already existed for a simpler page.
============================================================ */

/* 8a. Genova's tile strip is the first with real per-tile links —
   three of its four tiles go to a sub-page or a related page instead
   of being plain icon+label. .tile stays a <div> (global.css expects
   an <a> CHILD for its :focus-within/.tile a:focus-visible rules, not
   the tile itself becoming the link), so the anchor here just has to
   pick up the column layout .tile normally provides directly. */
.tile > a{
  display:flex; flex-direction:column; align-items:center;
  gap:14px; width:100%;
  text-decoration:none; color:inherit;
}

/* 8b. Two short centred Q&A blurbs between the intro and the keyword
   list — "Pronto Intervento" / "Riparazione", each a real <h3> plus
   one short centred paragraph. Side by side above 700px, since two
   one-line questions stacked the full container width left a lot of
   empty measure either side of very short lines. */
.fb-blurbs{
  display:grid; grid-template-columns:1fr; gap:clamp(24px,3vw,40px);
  max-width:900px; margin:0 auto clamp(40px,4.5vw,64px);
  text-align:center;
}
@media (min-width:700px){
  .fb-blurbs{ grid-template-columns:repeat(2,1fr); }
}
.fb-blurbs h3{
  margin:0 0 10px;
  font-family:var(--font-display);
  font-size:clamp(1.1rem,1rem + .4vw,1.35rem);
  font-weight:800; color:var(--green-900);
}
.fb-blurbs p{
  margin:0; font-size:16px; line-height:1.7; color:var(--ink-700);
}

/* 8c. "In cosa possiamo aiutarti" — a keyword taxonomy the old page
   marks up as a real nested list (one top-level <li> naming the
   category, holding a <ul> of specific services). Reproduced as the
   same nested structure — hard rule 9 protects heading text and DOM
   meaning, not just headings, and rewriting this into flat chips would
   have thrown away the parent/child relationship the source encodes.

   Each category is its own card (background, border, radius — the
   same card language .tile/.fb-step/.feature-card already use), so
   three short lists don't just float in empty space. Three columns
   from 900px, two from 560px, one full-width card below that.

   Inside every card the sub-items are their own 2-column grid AT
   EVERY SIZE, not a single stacked list — the items are short enough
   ("riparazione infissi", "montaggio serramenti") that one column
   left a card's whole right half empty, on a phone as much as on a
   1280px screen (checked directly against the built page, not
   assumed). A few of the longer entries wrap to two lines in the
   narrower mobile column; a smaller size at that breakpoint (below)
   keeps that from feeling cramped. */
.fb-keyword-cols{
  display:grid; grid-template-columns:1fr; gap:16px;
}
@media (min-width:560px){
  .fb-keyword-cols{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (min-width:900px){
  .fb-keyword-cols{
    grid-template-columns:repeat(3,minmax(0,1fr));
    gap:clamp(20px,2.4vw,28px);
  }
}
.fb-keyword-cols > ul{
  margin:0; padding:clamp(20px,2.6vw,26px);
  list-style:none;
  background:var(--paper-050);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  box-shadow:var(--shadow-card);
  transition:transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.fb-keyword-cols > ul:hover{
  transform:translateY(-3px);
  box-shadow:var(--shadow-pop);
  border-color:transparent;
}
.fb-keyword-cols > ul > li{
  display:inline-block;
  font-family:var(--font-display);
  font-weight:800; font-size:16px; color:var(--green-900);
  margin:0 0 16px;
  padding-bottom:12px;
  border-bottom:2px solid var(--amber-500);
}
.fb-keyword-cols ul ul{
  margin:0; padding:0; list-style:none;
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:10px 14px;
}
.fb-keyword-cols ul ul li{
  font-family:var(--font-body); font-weight:400;
  font-size:14px; line-height:1.45; color:var(--ink-700);
  padding-left:14px; position:relative;
}
.fb-keyword-cols ul ul li::before{
  content:""; position:absolute; left:0; top:.5em;
  width:5px; height:5px; border-radius:50%;
  background:var(--amber-500);
}
.fb-keyword-cols a{ color:var(--green-700); font-weight:700; }
.fb-keyword-cols a:hover{ color:var(--amber-600); }

@media (max-width:399px){
  /* The narrowest phones: two 14px columns inside a card padded on
     both sides left ~110px per column, where "apertura porte
     bloccate" (23 characters) was wrapping to three cramped lines.
     Tightened size and padding match the established phone-size
     pattern already used for .fb-tag/.fb-service-card at this range. */
  .fb-keyword-cols ul ul{ gap:8px 10px; }
  .fb-keyword-cols ul ul li{ font-size:12.5px; padding-left:12px; }
  .fb-keyword-cols ul ul li::before{ top:.45em; }
}

/* 8d. The closing keyword band — twenty real <h5> elements (the old
   page's own markup, each with a decorative fa-check icon in front of
   it), grouped into four columns of five. Font Awesome is not loaded
   on the new site (hard rule 5 bans adding a third-party icon font),
   so the empty decorative <i> becomes the same inline check SVG the
   hero trust-list already uses elsewhere on this page — nothing about
   the icon was ever real content, only its presence. Two of the
   twenty headings carry the source's own real links; the rest are
   plain text, exactly as in the source. */
/* DOM order matches the source's own four columns exactly (five
   headings per group, in source order) — grid-auto-flow:column with a
   set row count places item 6 at the top of column 2 instead of beside
   item 2, so the visual columns match the source's grouping rather
   than an interleaved row-major reflow. */
/* The source sets this H4 orange via an inline style (CSS rule 3 bans
   that); the same amber the rest of the page's CTAs already use. */
.fb-h5-grid-title{
  margin:0 0 24px;
  font-family:var(--font-display);
  font-size:clamp(1.1rem,1rem + .4vw,1.35rem);
  font-weight:800; color:var(--amber-600);
}

/* Two columns from the base (mobile) up, not just from 700px — twenty
   short headings in one stacked column made for a long scroll on a
   phone. grid-auto-flow:column with a set row count keeps item 6 at
   the top of column 2, matching the source's own column grouping,
   the same reasoning as the 700px/1100px steps above it. */
.fb-h5-grid{
  display:grid; gap:8px 20px;
  grid-template-columns:repeat(2,minmax(0,1fr));
  grid-auto-flow:column;
  grid-template-rows:repeat(10,auto);
}
@media (min-width:700px){
  .fb-h5-grid{ gap:10px 32px; }
}
@media (min-width:1100px){
  .fb-h5-grid{
    grid-template-columns:repeat(4,minmax(0,1fr));
    grid-template-rows:repeat(5,auto);
  }
}
.fb-h5-grid h5{
  display:flex; align-items:center; gap:8px;
  margin:0; padding:9px 0;
  border-bottom:1px solid var(--line-200);
  font-family:var(--font-body); font-weight:600;
  font-size:14.5px; line-height:1.35; color:var(--green-900);
}
.fb-h5-grid h5 svg{ flex-shrink:0; color:var(--amber-500); }
.fb-h5-grid a{ color:inherit; text-decoration:none; }

@media (max-width:479px){
  /* The narrowest phones: two columns at 14.5px left entries like
     "Sostituzione Serrande Elettriche" pushing right up against the
     gap. Tightened size/gap/icon match the established phone-size
     pattern already used for .fb-tag and .fb-keyword-cols at this
     range, rather than a one-off number. */
  .fb-h5-grid{ gap:6px 12px; }
  .fb-h5-grid h5{
    gap:6px; padding:7px 0;
    font-size:12px; line-height:1.3;
  }
  .fb-h5-grid h5 svg{ width:13px; height:13px; }
}
.fb-h5-grid a:hover{ color:var(--amber-600); text-decoration:underline; }

/* ============================================================
   9. COVERAGE NOTE — Imperia only (so far).

   A real <h3> plus two body paragraphs sitting between the service
   cards and the closing band — the source's own "NECESSITI DI UN
   FABBRO VICINO A TE A SANREMO O IMPERIA?" section, explaining the
   business also covers Sanremo (same province, legitimate service-area
   copy, not a wrong-city fault). Centred heading reuses the existing
   .features__head--center look. Full container width, not a narrower
   centred column — the source's own row is col-sm-12, and a capped
   measure here would just be inventing a constraint the old page
   never had.
============================================================ */
.fb-note p{
  margin:0 0 16px; font-size:16.5px; line-height:1.75; color:var(--ink-700);
}
.fb-note p:last-child{ margin-bottom:0; }
.fb-note strong{ color:var(--green-900); font-weight:700; }

/* ============================================================
   10. APERTURA PORTE — hub page and its city pages

   The first taglist to hold real navigable links rather than
   plain-text keyword runs — fb_taglist() in _taglist.php has no
   anchor support, so the DOVE OPERIAMO city index on the hub page is
   hand-written <li class="fb-tag"><a>…</a></li> instead. The base
   .fb-tag styling (dot marker, hairline, spacing) still applies as-is;
   only the click target needs to fill the whole row.
============================================================ */
.fb-tag a{
  display:block; width:100%;
  color:inherit; text-decoration:none;
}
.fb-tag a:hover,
.fb-tag a:focus-visible{
  color:var(--amber-600); text-decoration:underline;
}

/* The source's "DOVE OPERIAMO" heading and rule sit above the whole
   row, not inside either column — same shape as .fb-services-inner's
   head, centred above its grid. */
.fb-coverage-head{
  text-align:center;
  margin-bottom:clamp(32px,4vw,48px);
}
.fb-coverage-cta{
  margin-top:clamp(32px,4vw,48px);
  text-align:center;
}

/* Apertura Porte's closing band reads mostly as a link directory, and
   the base .fb-emergency heading (up to 38px/800) and 16.5px body copy
   read heavy on top of it — owner's call, 24 Sep 2026. Trims both down
   a step. Scoped to this modifier only: the base component and every
   page already using it (the fabbro hub, Roma, Torino, Udine,
   Alessandria, Asti) are unaffected. */
.fb-emergency--modest h2:where(:not(.h1-look)){
  font-size:clamp(1.25rem,1.05rem + .8vw,1.6rem);
  font-weight:700;
}
.fb-emergency--modest p{
  font-size:15px;
}

/* Apertura Porte Milano's 4-tile strip labels are plain bold text on
   the old page (<p><img><strong>…</strong></p>), not a heading — unlike
   the hub's "I SERVIZI" cards, which use real <h4>s. Promoting these to
   <h4> would add heading structure the source never had (hard rule 9),
   so .fb-service-card__label carries the exact same look as
   .fb-service-card h4 on a <p> instead. */
.fb-service-card__label{
  margin:0;
  font-family:var(--font-display);
  font-size:16px; font-weight:800; letter-spacing:.01em;
  color:var(--green-900); line-height:1.35;
}

/* A little breathing room between the intro's last paragraph and its
   call button — .fb-story__head p:last-child clears its own margin,
   which otherwise left the button flush against the text.

   white-space:normal/max-width:100% guard against .cta-btn's default
   nowrap (fabbro.css §1) — fine for the short "CHIAMA SUBITO [number]"
   label every sibling page's .fb-story__head button uses, but
   Venezia's equivalent button reads "CONTATTACI AL NUMERO DI TELEFONO
   [number]", a full sentence that overflowed 320px by ~196px.
   white-space:normal only wraps when a line actually needs it, so the
   short siblings render identically — confirmed unchanged on Milano/
   Brescia/Monza/Bergamo/Roma/Verona/Padova after this. */
.fb-story__head .cta-btn{
  margin-top:8px;
  white-space:normal;
  max-width:100%;
}
/* .fb-story__head a{color:var(--green-700)} (§7d, above) is 0,1,1 —
   more specific than .cta-btn's own 0,1,0 color rule — so without this
   the button's white text rendered green-on-orange. Same collision
   already documented for .about__content a.btn--primary. */
.fb-story__head a.cta-btn,
.fb-story__head a.cta-btn:hover,
.fb-story__head a.cta-btn:focus-visible{ color:var(--paper-000); }

/* Apertura Porte Milano's "Servizi" row: five real photographs (not
   64px icons) each with their own <h4> and paragraph — the old page's
   vc_box_border_grey bordered rectangle, reproduced as a plain framed
   card since none of the icon-chip cards elsewhere (.fb-service-card,
   .feature-card) are built for a landscape photo.

   A fixed 3-column grid, not auto-fit — owner's call, 24 Sep 2026. Five
   cards means the second row only ever holds two; the sixth slot
   (.fb-photo-card--cta, below) is a real grid item now, sized down to
   sit beside them and complete the row, rather than a separate block
   floating under the whole grid. */
.fb-photo-cards{
  display:grid; gap:clamp(24px,3vw,36px);
  grid-template-columns:1fr;
  /* .fb-services-inner (the section this grid sits in) centres its own
     heading/rule; the cards' body copy reads as rivers of whitespace
     centred at this length, so it's set back to left here. */
  text-align:left;
}
@media (min-width:620px){
  .fb-photo-cards{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (min-width:900px){
  .fb-photo-cards{ grid-template-columns:repeat(3,minmax(0,1fr)); }

  /* Exactly five cells (Padova: four cards + the CTA/photo cell) — a
     plain 3-up grid left the second row as two cards and a gap where a
     third would be. A pure-CSS quantity query (Heydon Pickering), same
     technique already used for the even/six-card cases in
     .features__grid--rows: :has() lets the GRID react to its own child
     count at render time, so a page with a different card count is
     unaffected and nothing is hardcoded per page. Six columns split
     3+3+3 / 3+3 give the first row three equal thirds and the second
     row two equal halves. */
  .fb-photo-cards:has(> .fb-photo-card:nth-child(5):last-child){
    grid-template-columns:repeat(6,minmax(0,1fr));
  }
  .fb-photo-cards:has(> .fb-photo-card:nth-child(5):last-child) .fb-photo-card:nth-child(-n+3){
    grid-column:span 2;
  }
  .fb-photo-cards:has(> .fb-photo-card:nth-child(5):last-child) .fb-photo-card:nth-child(n+4){
    grid-column:span 3;
  }
}
.fb-photo-card__media{
  display:block;
  border-radius:var(--radius-m);
  border:1px solid var(--line-200);
  overflow:hidden;
  margin:0 0 18px;
}
.fb-photo-card__media img{ display:block; width:100%; height:auto; }
.fb-photo-card h4{
  margin:0 0 10px;
  font-family:var(--font-display);
  font-size:17px; font-weight:800; color:var(--green-900);
}
.fb-photo-card p{
  margin:0; font-size:15px; line-height:1.75; color:var(--ink-700);
}

/* The row's sixth slot is not a card on the old page — a call button
   and the coverage map, filling the cell exactly like an ordinary
   card's photo does rather than sitting in their own boxed-within-a-
   boxed-card frame (owner's call, 24 Sep 2026 — an earlier version's
   padding/background/border here read as a container inside the grid
   cell's own container). */
.fb-photo-card--cta{
  display:flex; flex-direction:column; align-items:stretch;
  justify-content:center;
  gap:16px;
  text-align:center;
}
.fb-photo-card--cta .cta-btn{
  justify-content:center;
}
.fb-photo-card--cta img{
  display:block; height:auto;
  width:100%;
  border-radius:var(--radius-m);
  border:1px solid var(--line-200);
}

/* ============================================================
   11. APERTURA PORTE VENEZIA — a text-only source page, laid out
   rather than transcribed.

   This page's source carries no photos at all (checked: one <img> on
   the whole document, the favicon), no tile strip, no service cards
   and no coverage map — just prose under H2/H3/H4/H5 headings. Run
   through .fb-story it came out as a blog post: one narrow column of
   grey text, every section looking like the last. Owner's call, 24
   Sep 2026 — same copy, same heading levels (hard rules 2 and 9),
   carried instead by a dark banner, a callout card, icon cards and a
   dark checklist panel, so the page has the same rhythm as its
   photo-led siblings without inventing any content to fill it.
============================================================ */

/* 11a. Intro band — the page's H2, its own <hr> and its lead line on
   §7e-quater's dark .fb-banner. That component draws an amber rule
   with h2::after; this page brings a real <hr> of its own, so the
   pseudo-element is switched off here rather than drawing two. */
.fb-banner--lead h2:where(:not(.h1-look))::after{ display:none; }
.fb-banner--lead h2:where(:not(.h1-look)) a{
  color:inherit; text-decoration:underline; text-underline-offset:3px;
}
.fb-banner--lead hr{
  width:96px; height:3px; border:0; border-radius:3px;
  background:var(--amber-500);
  margin:20px auto 22px;
}
.fb-banner--lead p{
  position:relative;
  max-width:62ch; margin:0 auto;
  font-size:clamp(1rem,.95rem + .3vw,1.15rem);
  line-height:1.7; color:var(--green-100);
}
/* .cta-btn is nowrap by design (§1); this page's banner button is a
   full sentence ("CONTATTACI AL NUMERO DI TELEFONO …"), so it wraps
   here rather than running off a phone screen. */
.fb-banner__actions .cta-btn{
  white-space:normal;
  max-width:100%;
}

/* 11b. Callout card — "Perché scegliere noi come fabbro locale a
   Venezia?" is one heading, one paragraph and one call button. As a
   plain centred column it read as filler between two sections; as a
   raised card with an amber edge it reads as the claim it is.

   Owner's call, 24 Sep 2026: the card sits in the middle of a
   three-column row, flanked by two photos. Those photos are NOT from
   this page's source — it has no images at all (see the page's own
   header comment) — they were chosen by the owner from the uploads
   the sibling Apertura Porte pages already use, so they carry empty
   alt text: they are decoration, and inventing alt copy for them
   would be putting words on the page that the old site never had. */
.fb-callout{ background:var(--paper-050); }
.fb-callout__grid{
  display:grid;
  gap:clamp(20px,3vw,34px);
  align-items:center;
  /* Below 1000px the card leads and the two photos share a row under
     it — a decorative image above the heading would push the actual
     claim off a phone screen. */
  grid-template-columns:repeat(2,minmax(0,1fr));
}
.fb-callout__grid > .fb-callout__card{
  grid-column:1 / -1;
  order:-1;
}
/* A grid item's automatic minimum is its min-content width, and
   .cta-btn is nowrap by design (§1) — so at 320px the button's own
   unbreakable width pushed the card ~5px past the track. min-width:0
   lets the item shrink to its column; white-space:normal only wraps
   when a line actually needs it, so the button is unchanged at every
   width where it already fitted. Same pair of fixes .fb-tag and
   .fb-emergency__copy already carry for the same reason. */
.fb-callout__grid > *{ min-width:0; }
.fb-callout__card .cta-btn{
  white-space:normal;
  max-width:100%;
}
@media (min-width:1000px){
  /* Side columns widened from .72fr at the owner's request, 24 Sep
     2026. Capped there rather than pushed further: the photos are
     350px natives, so anything past ~310px would upscale them, and
     the middle column still needs room for the paragraph. */
  .fb-callout__grid{
    grid-template-columns:minmax(0,.9fr) minmax(0,1.4fr) minmax(0,.9fr);
  }
  .fb-callout__grid > .fb-callout__media:first-child{ grid-column:1; }
  .fb-callout__grid > .fb-callout__card{ grid-column:2; order:0; }
  .fb-callout__grid > .fb-callout__media:last-child{ grid-column:3; }
}
.fb-callout__media img{
  display:block;
  width:100%; height:auto;
  border-radius:var(--radius-m);
  border:1px solid var(--line-200);
  box-shadow:var(--shadow-card);
}
.fb-callout__card{
  max-width:840px; margin-inline:auto;
  background:var(--paper-000);
  border:1px solid var(--line-200);
  border-top:4px solid var(--amber-500);
  border-radius:var(--radius-l);
  box-shadow:var(--shadow-card);
  padding:clamp(28px,4vw,48px);
  text-align:center;
}
.fb-callout__card h3{
  margin:0 0 18px;
  font-family:var(--font-display);
  font-size:clamp(1.35rem,1.1rem + 1vw,1.9rem);
  font-weight:800; line-height:1.25;
  color:var(--green-900); letter-spacing:-.01em;
  text-wrap:balance;
}
/* Left-aligned inside a centred card: the paragraph is long enough
   that centring it opens rivers, the same reason .about__content and
   .fb-photo-cards already set their copy left. */
.fb-callout__card p{
  margin:0 0 28px;
  font-size:16.5px; line-height:1.8; color:var(--ink-700);
  text-align:left;
}

/* 11c. Section lead — the two paragraphs that sit under "Servizi
   Fabbro a Venezia." and above the cards. */
.fb-section-lead{
  max-width:860px; margin:0 auto clamp(32px,4vw,52px);
}
.fb-section-lead p{
  margin:0 0 16px;
  font-size:16.5px; line-height:1.8; color:var(--ink-700);
}
.fb-section-lead p:last-child{ margin-bottom:0; }
.fb-section-lead a{ color:var(--green-700); font-weight:700; }
.fb-section-lead a:hover{ color:var(--amber-600); }

/* The old page's own em-dash divider ("—————–") opens several of
   these blocks. It is copy, so hard rule 7 keeps it in the DOM — but
   muted to the hairline it is standing in for, instead of reading as
   stray punctuation in the middle of a sentence. */
.fb-rule-dashes{
  color:var(--line-200);
  letter-spacing:-.05em;
}

/* 11d. The three H5 sub-sections as cards. global.css's own
   .feature-card :is(h2…h6) rule already styles an H5 in a card, so
   the heading LEVEL is untouched (hard rule 9) — only its setting.
   The icons are decorative and aria-hidden: this page's source has
   none of its own, and §8d already took the same licence when Font
   Awesome's empty <i> became an inline SVG. */
@media (max-width:859px){
  /* .features__grid--rows centres its cards below 860px, which suits
     an icon over a short label; these cards carry full paragraphs, so
     only the icon stays centred. */
  .fb-venezia-cards .feature-card{ text-align:left; }
  .fb-venezia-cards .feature-card__icon{ margin-inline:0; }
}

/* 11e. Closing panel — the six-item <ul> becomes .fb-checklist chips
   on §7e-quinquies' dark .fb-services__panel. That component's tick
   rule targets the check.png the Velletri/Tivoli pages reproduce from
   their own markup; this list has no icon of its own, so the tick is
   an inline decorative SVG and needs the same chip treatment.
   box-sizing is stated because the 35px box is padding-inclusive.

   >>> SPECIFICITY <<<
   Written as `.fb-services h3.…` (0,2,1), not as a bare class, because
   §4's `.fb-services h3` (0,1,1) already sets colour/size/weight on
   any h3 inside this section and beats a plain 0,1,0 class. The size
   and weight are restated here for the same reason — the same trap
   .mega-menu a/.mega-region__link and .fb-story__head a/.cta-btn hit
   earlier in this file.

   NOTE: that collision also means `.fb-services__title` itself loses
   to `.fb-services h3` on the Velletri/Tivoli/Anzio pages, where the
   section title has been rendering at §4's 19–24px subtitle size
   instead of its own 1.6–2.45rem. Left alone here — it changes how
   three already-approved pages look, so it is the owner's call, not
   a side-effect of this page's build. */
.fb-services h3.fb-services__title--accent{
  margin:0 0 20px;
  font-size:clamp(1.35rem,1.1rem + 1vw,1.9rem);
  font-weight:800;
  line-height:1.2;
  color:var(--amber-600);
}
.fb-services h3.fb-services__title--accent a{ color:inherit; }

/* The closing grid places the panel in a spanning right-hand column
   so the left one carries the heading, the lead-in AND the closing
   paragraph. Explicit placement rather than a wrapper div: it keeps
   the DOM in the old page's own reading order (heading, lead-in,
   list, closing line) while filling a column that was otherwise two
   thirds empty beside the panel. */
.fb-venezia-close{
  display:grid;
  gap:clamp(28px,3.5vw,54px);
  align-items:start;
}
@media (min-width:1000px){
  .fb-venezia-close{
    grid-template-columns:minmax(0,1.32fr) minmax(320px,.8fr);
  }
  .fb-venezia-close > .fb-services__title{ grid-column:1; grid-row:1; }
  .fb-venezia-close > .fb-venezia-close__lead{ grid-column:1; grid-row:2; }
  .fb-venezia-close > .fb-services__panel{ grid-column:2; grid-row:1 / span 3; }
  .fb-venezia-close > .fb-services__tail{ grid-column:1; grid-row:3; margin:0; }
}
.fb-venezia-close__lead{
  margin:0;
  font-size:16.5px; line-height:1.8; color:var(--ink-700);
}
.fb-services__panel .fb-checklist svg{
  box-sizing:border-box;
  flex-shrink:0;
  width:35px; height:35px; padding:6px;
  border-radius:10px;
  background:rgba(255,255,255,.12);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.10);
  color:var(--amber-400);
}
.fb-services__tail{
  margin:clamp(28px,3.4vw,44px) 0 0;
  font-size:16.5px; line-height:1.8; color:var(--ink-700);
}
.fb-services__tail a{ color:var(--green-700); font-weight:700; }
.fb-services__tail a:hover{ color:var(--amber-600); }

/* ============================================================
   RESPONSIVE
============================================================ */
@media (max-width:980px){
  .fb-service-grid{ grid-template-columns:repeat(2,1fr); }
}

@media (max-width:820px){
  .fb-step-grid{ grid-template-columns:1fr; }
}

@media (max-width:620px){
  /* Two columns on a phone, not one. The four cards were stacking into a
     single tall column below 620px — a lot of scrolling for four short
     labels. Kept at two, tightening the icon, the padding and the
     heading so a pair fits side by side without cramming; the labels
     ("MONTAGGIO PORTE BLINDATE", 24 characters) wrap to two lines at this
     width rather than one, same as they already do at the 980px/2-up
     tablet size above. */
  .fb-service-grid{ grid-template-columns:repeat(2,1fr); gap:14px; }
  .cta-group{ flex-direction:column; align-items:stretch; }
  .fb-service-card{ padding:20px 12px 18px; border-radius:18px; }
  .fb-service-media{
    width:64px; height:64px; margin:0 auto 14px;
    border-radius:16px;
  }
  .fb-service-media img{ width:36px; height:36px; }
  /* Same 12.5px the mobile .fb-tag below already uses — the established
     "tightened" size for this breakpoint, not a one-off. */
  .fb-service-card h4{ font-size:12.5px; line-height:1.3; }
  /* Two columns on a phone for both runs: the entries are short and
     repetitive, so a pair of narrow columns still scans cleanly and
     halves a list that would otherwise be 29 and 40 rows of scrolling.
     Entries that wrap keep their dot on the first line. */
  .fb-taglist{ grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:16px; }
  .fb-tag{
    align-items:flex-start;
    font-size:12.5px; gap:8px; padding:9px 0;
  }
  .fb-tag::before{ margin-top:5px; }
}


/* ============================================================
   12. NESTED SERVICE PAGES — .fb-svc

   The per-service pages that live under a city
   (/fabbro-genova/riparazione-serrature-genova/ and its siblings)
   are shaped differently from a city page: no tile strip, no
   pricing cards, no service-card artwork. What they have is a
   short benefit list, two or three long prose blocks and a
   keyword index — which, run through the city-page components
   alone, came out as correct but unfurnished walls of text.

   Everything below is scoped to .fb-svc on <main>, so none of the
   ninety-odd city pages can be reached by it.
============================================================ */

/* 12a. The hero.

   The old page opens on one band carrying three things: the
   heading, a five-item benefit list and the call button. Run
   through .fb-banner that had to be split in two — .fb-banner
   paints only h1/h2 white, so the five <h4> items (headings in the
   source, and headings they stay, hard rule 9) would have rendered
   near-black on navy and had to move to a light section below it.
   The result was a thin dark strip followed by a row of stranded
   cards: two weak sections where the source had one strong one.

   This band owns its own colour, so the items come home. Depth
   comes from three stacked layers rather than a flat fill — an
   amber glow high on one side, a cooler one low on the other, over
   a diagonal brand gradient — and the items sit on it as
   translucent chips that borrow the band's own light instead of
   punching white holes in it. */
.fb-svc-hero{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  padding:clamp(46px,6.5vw,88px) 5vw clamp(42px,5.5vw,76px);
  text-align:center;
  color:var(--paper-000);
  background:
    radial-gradient(1000px 460px at 80% -14%, rgba(255,81,0,.26) 0%, rgba(255,81,0,0) 60%),
    radial-gradient(720px 380px at 6% 124%, rgba(41,145,214,.14) 0%, rgba(41,145,214,0) 62%),
    linear-gradient(152deg,
      var(--green-950) 0%,
      var(--green-900) 58%,
      var(--green-800) 100%);
}

/* Two passes over the band, both decorative.

   A vignette first: without it the glows read as two bright patches
   on a flat field, and darkening the corners pulls them back into
   one lit surface, settling the eye on the heading and the button.

   Then a fine dot grid at roughly 5% white. On its own a gradient
   this large reads as a flat digital wash however it is tuned; the
   grid gives the surface a texture to catch, and at 22px it is felt
   rather than seen. */
.fb-svc-hero__veil{
  position:absolute;
  inset:0;
  z-index:0;
  pointer-events:none;
  background:
    radial-gradient(120% 92% at 50% 44%,
      rgba(0,0,0,0) 38%,
      rgba(0,0,0,.30) 100%),
    radial-gradient(rgba(255,255,255,.055) 1px, rgba(255,255,255,0) 1px);
  background-size:auto, 22px 22px;
}

/* Hairline top and bottom, so the band reads as a deliberate edge
   against the header above and the page below rather than a block
   that simply stops. */
.fb-svc-hero::before,
.fb-svc-hero::after{
  content:"";
  position:absolute; left:0; right:0; height:1px;
  background:linear-gradient(90deg,
    transparent, rgba(255,255,255,.20) 28%, rgba(255,255,255,.20) 72%, transparent);
}
.fb-svc-hero::before{ top:0; }
.fb-svc-hero::after{ bottom:0; }

.fb-svc-hero__inner{
  position:relative;
  z-index:1;
  max-width:980px;
  margin:0 auto;
}

.fb-svc-hero h1,
.fb-svc-hero h2:where(.h1-look){
  margin:0;
  color:var(--paper-000);
  font-family:var(--font-display);
  font-size:clamp(1.6rem,1.1rem + 2.3vw,2.85rem);
  font-weight:800;
  line-height:1.12;
  letter-spacing:-.01em;
  text-wrap:balance;
  /* Lifts the heading off the amber glow it crosses at the top
     right, where white-on-light-amber was the weakest contrast on
     the band. */
  text-shadow:0 2px 20px rgba(0,0,0,.38);
}

/* The five benefit items. Chips, not cards: each is two or three
   words, so a bordered box per item gave five tall rectangles
   carrying one short line each. Centred and wrapping, they read as
   one row of credentials under the heading — which is the job the
   source gives them. */
.fb-svc-hero__list{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:10px 12px;
  max-width:880px;
  margin:clamp(24px,3vw,34px) auto 0;
}

.fb-svc-hero__list h4{
  margin:0;
  display:inline-flex;
  align-items:center;
  padding:11px 20px;
  border-radius:999px;
  /* Lit from above rather than filled flat, with a hairline inner
     highlight on the top edge — the chips sit ON the band instead of
     looking like holes cut in it. */
  background:linear-gradient(180deg,
    rgba(255,255,255,.14) 0%,
    rgba(255,255,255,.05) 100%);
  border:1px solid rgba(255,255,255,.20);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.16),
    0 2px 10px rgba(0,0,0,.20);
  color:var(--paper-000);
  font-family:var(--font-body);
  font-size:clamp(.82rem,.78rem + .18vw,.95rem);
  font-weight:600;
  line-height:1.3;
  letter-spacing:.01em;
  transition:background .18s ease, border-color .18s ease, transform .18s ease;
}

.fb-svc-hero__list h4:hover{
  background:linear-gradient(180deg,
    rgba(255,255,255,.20) 0%,
    rgba(255,255,255,.09) 100%);
  border-color:var(--amber-500);
  transform:translateY(-2px);
}

.fb-svc-hero__actions{
  margin-top:clamp(26px,3vw,36px);
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:14px;
}

/* .cta-btn is nowrap by design; on a 320px screen this page's own
   label ("CHIAMA 0107766806") has to be allowed to wrap rather than
   push the band — the same fix §7e-sexies already applies to
   .fb-cta-plain. */
.fb-svc-hero__actions .cta-btn{
  white-space:normal;
  max-width:100%;
}


/* 12b. Prose columns as panels.

   The "serramenti / infissi" row is two paragraph blocks of 90-odd
   words each, side by side on the tinted band. Unpanelled they ran
   edge to edge as one undifferentiated field of justified text with
   nothing marking where the first ended and the second began.

   align-items:stretch on the row so the two panels match height —
   global.css §9 centres .about__grid, which left the shorter one
   floating against the taller one's middle. */
.fb-svc .about__grid--panels{ align-items:stretch; }

/* Tinted, not white: §12e turns the band around these white, so a
   white panel on it would have nothing to stand against. The tint
   also keeps the pair reading as one unit against the plain prose
   above and below. */
.fb-svc-panel{
  background:linear-gradient(168deg,
    var(--green-050) 0%,
    var(--paper-050) 100%);
  border:1px solid var(--line-200);
  border-radius:var(--radius-l);
  padding:clamp(24px,3vw,40px);
}

/* The section titles here are <h4> in the source — a level the page
   uses for section headings, not sub-points. At global.css's h4 size
   they read smaller than the body they introduce. Lifted, and given
   the same short amber rule the .fb-banner heading carries, so the
   two agree. */
.fb-svc-panel > h4:first-child,
.fb-svc-prose > h4:first-child{
  margin:0 0 18px;
  font-size:clamp(1.15rem,1.05rem + .45vw,1.4rem);
  line-height:1.25;
  color:var(--green-900);
  letter-spacing:.01em;
}

.fb-svc-panel > h4:first-child::after,
.fb-svc-prose > h4:first-child::after{
  content:"";
  display:block;
  width:52px; height:3px; border-radius:3px;
  margin-top:14px;
  background:var(--amber-500);
}


/* 12b-bis. The .about rows.

   global.css §9's .about__content is built for a short lead beside a
   photo. These pages run three and four paragraphs through it under
   headings two and three sizes larger, and the defaults gave a
   heading sitting flush on its own first line with no air between
   them — top-heavy, and the reason the rows read as unfinished.

   All of it is scoped to .fb-svc: .about__content is on ninety-odd
   city pages and none of them should move. */
.fb-svc .about__content > h2:where(:not(.h1-look)):first-child,
.fb-svc .about__content > h3:first-child{
  margin:0 0 20px;
  color:var(--green-900);
  line-height:1.15;
}

/* The same short amber rule the hero and the panels carry, so the
   page has one accent rather than three unrelated treatments. */
.fb-svc .about__content > h2:where(:not(.h1-look)):first-child::after,
.fb-svc .about__content > h3:first-child::after{
  content:"";
  display:block;
  width:52px; height:3px; border-radius:3px;
  margin-top:16px;
  background:var(--amber-500);
}

/* The opening line of each column, lifted out of the body colour. */
.fb-svc .about__content > h2:where(:not(.h1-look)):first-child + p,
.fb-svc .about__content > h3:first-child + p{
  font-size:17px;
  line-height:1.75;
  color:var(--ink-900);
}

/* .cta-group centres by default (fabbro.css §1), which left the
   button floating under a left-aligned column. */
.fb-svc .about__content .cta-group{
  justify-content:flex-start;
  margin-top:26px;
}

/* .cta-btn is nowrap by design; the tapparelle sibling's own label
   ("Chiama Adesso! 0107766806") is long enough to push past a 320px
   column otherwise — same fix §7e-sexies already applies elsewhere. */
.fb-svc .about__content .cta-group .cta-btn{
  white-space:normal;
  max-width:100%;
}

/* .about__content a{color:var(--green-500)} (global.css §9) outspecifies
   .cta-btn's own white text the same way it did .btn--primary/.btn--white
   before those got their own exception (global.css:1236, fabbro.css:585)
   — .cta-btn was never added to that list, and it shipped here as blue
   text on an orange button, unreadable. Same fix, same slot. */
.fb-svc .about__content a.cta-btn,
.fb-svc .about__content a.cta-btn:hover,
.fb-svc .about__content a.cta-btn:focus-visible{
  color:var(--paper-000);
}

.fb-svc .about__media img{
  border-radius:var(--radius-l);
  box-shadow:var(--shadow-card);
}

/* A short photo beside three long paragraphs made .about__grid's default
   align-items:center float the photo in the middle of a much taller row
   — on a tinted band that empty space above and below it read as a
   hole in the page rather than as breathing room. Anchoring both
   columns to the top removes the float; the row is simply as tall as
   its taller column now, with no dead space to explain. Scoped to rows
   that actually need it via a modifier rather than changing every
   .about__grid on the page. */
.fb-svc .about__grid--top{ align-items:start; }

/* The SOS Fabbro row's photo is a small portrait crop (225×300
   native) — .about__grid's default 50/50 split, or even
   --wide-text's 62/38, still hands it far more column than a photo
   that size can use without upscaling past its own resolution and
   going soft (global.css's .about__media already caps at 400px for
   exactly this reason, on a source built for a 724px original).
   Instead of splitting by ratio, the media column is fixed to just
   past the photo's own width and the text column takes whatever is
   left — the text gets the space the photo was never going to use,
   at any viewport width above 900px. */
@media (min-width:900px){
  .fb-svc .about__grid--media-narrow{
    grid-template-columns:minmax(0,1fr) minmax(0,320px);
  }
}

/* fabbro-39-225x300.jpg is the exact file this page serves (hard rule
   1 — no derivative swap), so 225 is its real, final rendered width.
   The track above is 290, not 225: the photo now sits inside
   .fb-svc-photo-card, whose own padding needs room too — capping the
   IMAGE at its true size while giving the CARD the extra 65px means
   the photo still renders at exactly its native resolution (never
   upscaled, never soft), and the padding around it is real padding,
   not more empty page background pretending to be breathing room. */
/* 225px would match the photo's native resolution exactly, but at
   that width the caption ("Riparazione Tapparelle Genova") spans the
   box edge to edge with zero margin either side — technically not
   overflowing, but visually pressed against the card's own padding,
   reading as cut off. 250px gives the caption breathing room; the
   photo itself upscales by 25px, a soft trade worth making since the
   alternative is text that looks clipped on every load.

   width:100% is required alongside max-width here: .fb-svc-photo-card
   is a column flexbox with align-items:center, so its non-stretched
   children shrink-wrap to their own content's intrinsic size — the
   image's native 225px — rather than growing to fill anything wider,
   no matter how high max-width is raised. width:100% gives the box a
   definite size to resolve against instead of shrinking to content,
   which is what actually lets it reach the new cap. */
.fb-svc .about__media--compact{ width:100%; max-width:250px; }

/* global.css §9 caps every .about__content p at max-width:70ch — a
   readability measure that's right for a 50/50 photo+text row, but
   it silently overrode every width change made to this row: the
   grid column kept getting wider while the paragraphs stayed capped
   at ~588px regardless, which is why widening .about__grid alone
   never shortened the text block. Lifted only in this row, where
   the column is deliberately much wider than a normal .about__content
   half specifically so the paragraphs can use it. */
.fb-svc .about__grid--media-narrow .about__content p{
  max-width:none;
}

/* 13f. The photo card — the source's photo, caption and call button
   as one self-contained unit, replacing a bare image floating beside
   three paragraphs of copy that ran on well past where the photo
   ended. Same tint-card language as the closing sidebar (§13e), so
   the two "shorter column beside longer prose" rows on this page
   read as one deliberate pattern rather than two different fixes. */
.fb-svc-photo-card{
  display:flex;
  flex-direction:column;
  align-items:center;
  background:linear-gradient(168deg,
    var(--green-050) 0%,
    var(--paper-050) 100%);
  border:1px solid var(--line-200);
  border-radius:var(--radius-l);
  padding:clamp(20px,2.6vw,28px);
}

.fb-svc-photo-card .cta-group{
  margin-top:20px;
  width:100%;
}

/* .cta-btn is nowrap by design; the card is far narrower than the
   button's own label ("Chiama Adesso! 0107766806") needs on one
   line — same wrap fix used everywhere else .cta-btn sits in a
   column narrower than its text. */
.fb-svc-photo-card .cta-btn{
  display:flex;
  white-space:normal;
  max-width:100%;
  text-align:center;
}


/* 13e. The closing sidebar — nine short entries under a <h2>-led
   prose block. First built inside a side-by-side grid
   (.about__grid--panels), which stretched the card to match the
   three-paragraph column's full height — a defined edge instead of
   plain page background, but still a card mostly empty below its own
   list. Owner's call (28 Sep 2026): stack instead of stretch. The
   card now sizes to exactly what the list needs — no forced height —
   and the prose runs the section's full width underneath it. See
   §13g for the stack itself. */
.fb-svc-sidebar{
  display:flex;
  flex-direction:column;
  background:linear-gradient(168deg,
    var(--green-050) 0%,
    var(--paper-050) 100%);
  border:1px solid var(--line-200);
  border-radius:var(--radius-l);
  padding:clamp(24px,3vw,36px);
}

.fb-svc-sidebar h3{
  margin:0 0 18px;
  color:var(--green-900);
  font-size:clamp(1.3rem,1.15rem + .5vw,1.6rem);
}

.fb-svc-sidebar h3::after{
  content:"";
  display:block;
  width:44px; height:3px; border-radius:3px;
  margin-top:14px;
  background:var(--amber-500);
}

.fb-svc-sidebar .fb-taglist{ margin:0; }


/* 13g. The stack — sidebar card, then full-width prose beneath it.
   Plain block flow: no grid, so nothing stretches the sidebar to
   match the prose, and the prose isn't confined to a column beside
   it either. The sidebar's own margin-bottom is the only thing doing
   the spacing a grid gap used to. */
.fb-svc-stack .fb-svc-sidebar{
  margin-bottom:clamp(28px,3.5vw,40px);
}

/* Same fix as the SOS Fabbro row above: global.css §9 caps
   .about__content p at max-width:70ch regardless of container width,
   sized for a column that shares its row with a photo. This prose no
   longer shares a row with anything — lifted so it actually reaches
   the section's full measure instead of stopping two-thirds across
   it. */
.fb-svc-stack .about__content p{
  max-width:none;
}


/* 12b-ter. The capability list.

   This is the page saying what it actually does, and .fb-checklist
   rendered it as bold text over hairlines — the least alive thing on
   a page that is mostly grey paragraphs already. Tiles, each with a
   real tick, in the brand's own colours.

   The tick is a mask rather than a background image, so its colour
   is still --amber-500 rather than a hex baked into a data URI. */
.fb-svc .fb-checklist{
  grid-template-columns:repeat(auto-fit,minmax(min(240px,100%),1fr));
  gap:10px;
  margin-top:22px;
}

.fb-svc .fb-checklist li{
  align-items:flex-start;
  gap:12px;
  padding:14px 16px;
  border-bottom:0;
  border-radius:var(--radius-s);
  background:var(--paper-000);
  border:1px solid var(--line-100);
  font-size:15px;
  font-weight:600;
  line-height:1.5;
  color:var(--green-900);
  transition:border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}

.fb-svc .fb-checklist li:hover{
  transform:translateY(-2px);
  border-color:var(--amber-400);
  box-shadow:var(--shadow-card);
}

.fb-svc .fb-checklist li::before{
  content:"";
  flex-shrink:0;
  width:19px; height:19px;
  margin-top:.12em;
  background:var(--amber-500);
  /* Where mask-image is unsupported the mask is simply ignored and
     the amber box would show as-is; the radius makes that fallback a
     dot rather than a square. The tick sits inside the inscribed
     circle, so it costs nothing where masks do work. */
  border-radius:50%;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.7l5.4 5.4L20 6.4'/%3E%3C/svg%3E") center / contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.7l5.4 5.4L20 6.4'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* 12c. The closing prose block.

   .about__content carries its own measure, which is right beside a
   photo and wrong on its own: this ran in a 620px column with the
   other half of the row empty.

   It is also the page's closing argument and its last call to
   action, and as bare paragraphs on white it was the flattest thing
   on the page. Given a panel of its own — a soft tint falling away
   to white, so it reads as a considered close rather than more of
   the same body copy. */
.fb-svc-prose{
  max-width:880px;
  margin-inline:auto;
}

/* The opening line carries the claim the rest of the block supports,
   so it is set as a lead rather than as the first of five identical
   grey paragraphs. */
.fb-svc-prose > p:first-of-type{
  font-size:clamp(1.02rem,.98rem + .3vw,1.18rem);
  line-height:1.7;
  color:var(--green-900);
  font-weight:500;
}

/* The line that introduces the list — short, and the hinge between
   the prose and the tiles under it. */
.fb-svc-prose > p:last-of-type{
  margin-top:26px;
  font-weight:700;
  color:var(--green-900);
}


/* 12d. The closing list.

   .fb-checklist tracks are minmax(220px,1fr), which suits a run of
   short like-sized labels. This list is four entries running from
   three words to a full closing paragraph (the source leaves that
   paragraph inside the <li> — see _PHASE-6-LOG.md C17), and across
   four tracks they came out wildly ragged. One column, so the long
   one simply reads as the long one. */
/* One column here, not the auto-fit tracks the capability list uses:
   these four entries run from three words to a whole closing
   paragraph (the source leaves it inside the <li> — see
   _PHASE-6-LOG.md C17), and across tracks they came out ragged. */
.fb-svc-prose .fb-checklist{
  grid-template-columns:1fr;
  gap:10px;
}

.fb-svc-prose .fb-checklist li{
  font-weight:500;
  line-height:1.65;
  color:var(--ink-700);
}

.fb-svc-prose .fb-checklist strong{ color:var(--green-900); }

/* The page's last phone number, sitting in body copy at the very end
   of the closing list. */
.fb-svc-prose .fb-checklist a[href^="tel:"]{
  font-weight:800;
  color:var(--amber-600);
  text-decoration:none;
  white-space:nowrap;
}

.fb-svc-prose .fb-checklist a[href^="tel:"]:hover{ text-decoration:underline; }


/* 12e. Section rhythm.

   Read end to end the page was one near-white field from the hero to
   the footer: every band the same tone, so nothing marked where one
   argument ended and the next began, and the whole middle read flat
   however the individual blocks were styled. Alternating the bands
   gives the page a pulse — tinted where the page lists what it does,
   white where it explains. */
.fb-svc-band{
  background:linear-gradient(180deg,
    var(--green-050) 0%,
    var(--paper-050) 100%);
}

.fb-svc-closing{
  background:
    radial-gradient(900px 420px at 88% 6%, rgba(41,145,214,.10) 0%, rgba(41,145,214,0) 60%),
    linear-gradient(180deg, var(--green-050) 0%, var(--paper-000) 100%);
  border-top:1px solid var(--line-200);
  border-bottom:1px solid var(--line-200);
}

/* Body copy across the whole page. 16.5px grey at 1.8 was legible
   and characterless; a little more size and a darker ink make the
   long blocks read as prose someone wrote rather than as filler. */
.fb-svc .about__content p,
.fb-svc-prose p{
  font-size:16.8px;
  line-height:1.78;
}

/* The page's last phone number, sitting in body copy at the very end
   of the closing list. */
.fb-svc-prose .fb-checklist a[href^="tel:"]{
  font-weight:700;
  color:var(--amber-600);
  text-decoration:none;
  white-space:nowrap;
}

.fb-svc-prose .fb-checklist a[href^="tel:"]:hover{
  text-decoration:underline;
}


/* ============================================================
   13. SECOND SERVICE PAGE — additions for
   /fabbro-genova/tapparelle-e-persiane-genova/ and its siblings.

   This page carries three shapes .fb-svc's first page (Riparazione
   Serrature) did not: a one-line call-out band, a short icon row,
   and a photo with its own caption. All scoped to .fb-svc so the
   ninety-odd city pages stay untouched.
============================================================ */

/* 13a. The call-out band — the source's own H2, wrapping a tel:
   link, sitting beside a lead heading in a light grey row (source:
   background-color #e5e5e5, which var(--line-200) already matches
   almost exactly — reused rather than a new near-identical hex). */
.fb-svc-callout{ background:var(--line-200); }

/* Unscoped, this <h2> inherits global.css's default h2 clamp — built
   for a full section heading, and it renders at 47px here, in a
   compact two-column banner sitting beside a call button. Way out of
   proportion for a supporting line, not a page-section moment. Sized
   down to something that reads as a strong lead-in instead. */
.fb-svc-callout .about__content > h2:where(:not(.h1-look)):first-child{
  margin:0;
  font-size:clamp(1.4rem,1.2rem + 1.1vw,1.85rem);
  line-height:1.3;
}
.fb-svc-callout .about__content > h2:where(:not(.h1-look)):first-child::after{ display:none; }

/* The right column's H2 IS the call-to-action in the source — a
   heading-level link, not a button demoted from one. Hard rule 9
   keeps it an <h2>; this makes it read as the obvious next thing to
   press without turning it into a <button> or dropping its level. */
.fb-svc-callout-cta{
  display:flex;
  align-items:center;
  justify-content:center;
  text-align:center;
}

.fb-svc-callout-cta h2:where(:not(.h1-look)){
  margin:0;
  width:100%;
}

.fb-svc-callout-cta h2:where(:not(.h1-look)) a{
  display:flex;
  align-items:center;
  justify-content:center;
  gap:12px;
  padding:22px 28px;
  background:var(--amber-500);
  color:var(--paper-000);
  border-radius:var(--radius-m);
  box-shadow:0 10px 24px rgba(243,90,0,.28);
  font-family:var(--font-display);
  font-size:clamp(1.15rem,1.05rem + .4vw,1.5rem);
  font-weight:800;
  letter-spacing:-.01em;
  text-decoration:none;
  transition:background .18s ease, transform .18s ease, box-shadow .18s ease;
}

.fb-svc-callout-cta h2:where(:not(.h1-look)) a:hover{
  background:var(--amber-600);
  transform:translateY(-2px);
  box-shadow:0 14px 30px rgba(243,90,0,.4);
}

.fb-svc-callout-cta h2:where(:not(.h1-look)) a::before{
  content:"";
  flex-shrink:0;
  width:22px; height:22px;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z'/%3E%3C/svg%3E") center / contain no-repeat;
}


/* 13b. The icon strip — a centred lead sentence over four short
   "icon + label" items. The source's icons are empty Font Awesome
   <i> tags (icon-tools, decorative, no text lost); replaced with one
   inline SVG reused four times, same practice as §8d elsewhere in
   this file. */
.fb-svc-icons-lead{
  max-width:760px;
  margin:0 auto clamp(28px,3.5vw,40px);
  text-align:center;
  color:var(--ink-900);
  font-weight:600;
}

.fb-svc-icons{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(min(180px,100%),1fr));
  gap:clamp(20px,2.6vw,32px);
  max-width:900px;
  margin:0 auto;
  text-align:center;
}

.fb-svc-icon{
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:12px;
}

.fb-svc-icon__glyph{
  display:grid;
  place-items:center;
  width:52px; height:52px;
  border-radius:50%;
  background:var(--green-050);
  color:var(--green-800);
}

.fb-svc-icon__glyph svg{ width:24px; height:24px; }

.fb-svc-icon strong{
  font-size:.95rem;
  color:var(--green-900);
}


/* 13c. Photo caption — the source's own <h5> under the intro photo.
   Kept at its source level; styled as a small centred caption line
   rather than a fourth heading tier competing with the prose beside
   it.

   global.css's shared h1-h6 rule sets line-height:1.08, tuned for
   large display headings where a tight line-box doesn't matter. At
   this caption's small size, 1.08 makes the line-box shorter than
   the glyphs actually painted — mostly invisible on its own, but
   .about__media has its own overflow:hidden (global.css §9, there to
   clip the PHOTO to its rounded corners), and that hard edge lands
   exactly at the tight line-box's boundary and slices the bottom off
   the caption's descenders. A real line-height here fixes it at the
   source rather than fighting the ancestor's clip. */
.fb-svc .about__media h5{
  margin:16px 0 0;
  text-align:center;
  font-size:.95rem;
  line-height:1.5;
  font-weight:700;
  color:var(--green-900);
}


/* 13d. Section divider — the source's own <hr>-equivalent between
   the photo row and the closing sidebar row.

   Both neighbouring sections are .about, which already carries its
   own padding-block:clamp(56px,8vw,108px) top AND bottom (global.css
   §9) — at a typical desktop width that's over 100px of whitespace
   on each side of this rule before its own margin adds anything. The
   first pass gave it a further clamp(32px,4vw,56px), which stacked on
   top of both sections' padding rather than replacing it, and the two
   .about sections ended up roughly 300px apart. The sections' own
   padding is already doing the separating; this only needs enough
   margin to keep the rule from touching either section's content. */
.fb-svc-divider{
  max-width:1000px;
  margin:0 auto;
  border:0;
  border-top:1px solid var(--line-200);
}


/* ============================================================
   14. PREVENTIVO FABBRO {CITY} — /preventivi/intervento-fabbro-{city}/

   Shared across the whole "Preventivo Fabbro" page family (first
   built for Monza, reused as-is for Parma and any city after it) —
   not page-specific despite the section name.

   global.css's .feature-card__icon is a fixed 48x48 box; §7c above
   already overrides that for the 128px photographic icon family
   (.feature-card__icon img{width:128px;height:128px}, plus
   .feature-card__icon:has(img){width:fit-content;padding:16px} to
   let the chip grow to fit it). This family's own "I Servizi" icons
   are the 64x64 flat-icon family the tile strips use, not that 128px
   family, so both of those rules fight a plain .fb-icon-64 override:
   the img rule forces the image itself back to 128px regardless of
   its own width/height attributes, and the :has(img) rule's
   specificity (0,2,0) beats a single .fb-icon-64 class. Both
   overridden here with matching or higher specificity, so these
   pages' cards render at their own real 64x64 without touching
   §7c or any other feature-card on the site. */
.feature-card__icon.fb-icon-64{
  width:64px;
  height:64px;
  padding:0;
}
.feature-card__icon.fb-icon-64 img{
  width:64px;
  height:64px;
}

/* global.css justifies .feature-card p at >=900px ("Justified text
   creates rivers on narrow screens" — its own comment, written for
   the usual 3-up grid). This family's grid is 4-up (--cols-max:4,
   narrower columns than that comment assumed), so the same rivers
   show up on desktop too. Owner's call (Monza, kept for every page in
   the family): left-align unconditionally on .fb-preventivo cards
   only; every other feature-card on the site keeps the
   justify-at-desktop behaviour untouched. */
.fb-preventivo .feature-card p{
  text-align:left;
}
/* ============================================================
   consent.css — cookie banner (assets/js/consent.js), every page.
   global.css supplies tokens and .btn; nothing here redefines them.

   The bar sits at the bottom of the viewport. On phones it sits
   ABOVE the green call bar (global.css §20) instead of covering it:
   the call button must stay tappable while the banner is open.
============================================================ */

.cc{ display:none; }
.cc.cc--open{ display:block; }

.cc-bar{
  position:fixed;
  left:50%; transform:translateX(-50%);
  bottom:16px;
  z-index:10001;
  width:min(100% - 32px, 980px);
  max-height:calc(100vh - 120px);
  overflow:auto;
  background:var(--paper-000);
  color:var(--ink-900);
  border:1px solid var(--line-200);
  border-radius:var(--radius-m);
  box-shadow:0 18px 50px rgba(14,57,94,.22);
  padding:22px 24px 20px;
  font-size:.92rem;
  line-height:1.5;
}

@media (max-width:768px){
  .cc-bar{
    bottom:calc(var(--callbar-h) + env(safe-area-inset-bottom) + 8px);
    width:calc(100% - 16px);
    max-height:calc(100vh - var(--callbar-h) - 90px);
    padding:18px 16px 16px;
  }
}

.cc-title{
  margin:0 32px 8px 0;
  font-family:var(--font-display);
  font-weight:800;
  font-size:1.05rem;
  color:var(--green-900);
}

.cc-desc p, .cc-intro, .cc-cat p{
  margin:0 0 8px;
  color:var(--ink-700);
  font-size:.88rem;
}
.cc-desc a, .cc-intro a{ color:var(--green-700); text-decoration:underline; }

.cc-x{
  position:absolute; top:10px; right:12px;
  width:36px; height:36px;
  border:0; border-radius:50%;
  background:transparent;
  color:var(--ink-700);
  font-size:26px; line-height:1;
  cursor:pointer;
}
.cc-x:hover{ background:var(--line-100); }

.cc-actions{
  display:flex; flex-wrap:wrap; justify-content:flex-end; align-items:center;
  gap:10px;
  margin-top:12px;
}
.cc-actions .btn{ padding:12px 22px; font-size:.92rem; }

.cc-links{ display:none; }

/* Phones: keep the bar short so the page's own CHIAMA button and the
   green call bar stay usable while the banner is open.
   Rifiuta and Accetta keep the same size side by side (Garante 2021:
   rejecting must be as easy as accepting); "Impostazioni cookie"
   drops to a text link underneath. */
@media (max-width:600px){
  .cc-bar{ padding:14px 14px 12px; }
  .cc-title{ font-size:.98rem; margin-bottom:6px; }
  .cc-desc .cc-more{ display:none; }
  .cc-desc p, .cc-links{ font-size:.82rem; line-height:1.4; margin-bottom:6px; }
  .cc-links{ display:block; }
  .cc-links a{ color:var(--green-700); text-decoration:underline; }
  .cc-bar .cc-actions{
    display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:8px;
  }
  .cc-bar .cc-actions .btn{
    width:100%; min-height:44px; padding:10px 8px;
    font-size:.82rem; white-space:normal; line-height:1.2;
  }
  .cc-bar .cc-actions [data-cc="reject"]{ grid-column:1; grid-row:1; }
  .cc-bar .cc-actions [data-cc="accept"]{ grid-column:2; grid-row:1; }
  .cc-bar .cc-actions [data-cc="settings"]{ grid-column:1 / -1; grid-row:2; min-height:36px; padding:4px; }
  .cc-panel .cc-actions{ flex-direction:column-reverse; align-items:stretch; }
  .cc-panel .cc-actions .btn{ width:100%; }
}

/* While the banner is open the green call bar never slides away
   (site.js §4 hides it when another CHIAMA is on screen — here that
   button may sit under the banner). */
.cc-visible .call-bar.call-bar--hidden{ transform:none; }

/* ---- settings modal ---- */
.cc-modal{
  position:fixed; inset:0;
  z-index:10002;
  background:rgba(26,27,39,.55);
  display:flex; align-items:center; justify-content:center;
  padding:16px;
}
.cc-modal[hidden]{ display:none; }

.cc-panel{
  position:relative;
  width:min(100%, 640px);
  max-height:calc(100vh - 32px);
  overflow:auto;
  background:var(--paper-000);
  border-radius:var(--radius-m);
  box-shadow:0 24px 60px rgba(0,0,0,.3);
  padding:24px;
}

.cc-cat{
  border-top:1px solid var(--line-200);
  padding:14px 0 6px;
}
.cc-cat-head{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  margin-bottom:4px;
  cursor:pointer;
}
.cc-cat-name{ font-weight:700; color:var(--ink-900); }
.cc-always{ font-size:.8rem; font-weight:700; color:var(--live-500); }

/* Toggle switch built on a real checkbox (keyboard + screen reader) */
.cc-switch{
  appearance:none; -webkit-appearance:none;
  position:relative; flex-shrink:0;
  width:44px; height:26px; margin:0;
  border-radius:999px;
  background:var(--ink-500);
  cursor:pointer;
  transition:background .15s ease;
}
.cc-switch::after{
  content:""; position:absolute; top:3px; left:3px;
  width:20px; height:20px; border-radius:50%;
  background:var(--paper-000);
  transition:transform .15s ease;
}
.cc-switch:checked{ background:var(--green-700); }
.cc-switch:checked::after{ transform:translateX(18px); }
.cc-switch:focus-visible{ outline:2px solid var(--amber-500); outline-offset:2px; }
