/*
Theme Name:  Albini e Castelli
Theme URI:   https://www.albiniecastelli.it/
Author:      Albini e Castelli
Description: Tema su misura per Impresa di Costruzioni Albini e Castelli S.r.l. Costruito su blocchi ACF, con markup e CSS derivati direttamente dal file Figma di progetto.
Version:     0.1.0
Requires at least: 6.5
Tested up to: 6.8
Requires PHP: 8.1
License:     GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: albini-aec
Tags:        custom-colors, custom-menu, translation-ready
*/

/* ==========================================================================
   ALBINI E CASTELLI — sitewide stylesheet

   Everything reusable lives here, in one file, loaded on every page: design
   tokens, the base layer, and every shared component. Per-block CSS does NOT
   belong here — it lives in blocks/<slug>/style.css, which WordPress enqueues
   only when that block is actually on the page.

   So there are exactly two tiers:

     style.css                 reusable, sitewide, always loaded (this file)
     blocks/<slug>/style.css   one block, loaded only when present

   ORDER IS LOAD-BEARING and is preserved from the split files this replaces:
   header → mega-bar → mobile-drawer, because mobile-drawer's max-width:1024px
   block overrides the other two; and wp.css after header.css, because its
   admin-bar rules override .site-header--over.

   Font and icon url()s are relative to this file at the theme root, i.e.
   assets/fonts/… and assets/icons/… — not the ../ paths the split files used
   from inside assets/css/.
   ========================================================================== */


/* ============================================================
   assets/css/tokens.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — Design tokens
   Source: Figma "ALBINI E CASTELLI AEC — DEV SHM" (z2Wh5FBwvgNmMv4ZY12iKf)
   Every value here is measured from the file. Do not invent values.
   ========================================================================== */

:root {

  /* --- Colour — "PALETTE AEC SITO", node 39:454 ------------------------- */
  --aec-rosso:        #AF1E2D;  /* signature: CTA band, links, social, arrows */
  --aec-rosso-light:  #E57A85;  /* "storia AEC" timeline wheel                */
  --aec-bianco:       #FFFFFF;  /* page background, negative text             */
  --aec-beige:        #E8E4E0;  /* card bg, mega-bar, graphic rules           */
  --aec-tortora:      #8C8279;  /* header nav, footer headings, hover state   */
  --aec-antracite:    #1E1E1E;  /* body text, footer, dark bands              */

  /* Semantic aliases — prefer these in component CSS */
  --c-text:           var(--aec-antracite);
  --c-text-invert:    var(--aec-bianco);
  --c-text-muted:     var(--aec-tortora);
  --c-accent:         var(--aec-rosso);
  --c-surface:        var(--aec-bianco);
  --c-surface-alt:    var(--aec-beige);
  --c-surface-dark:   var(--aec-antracite);
  --c-rule:           var(--aec-beige);
  /* Distinct from --c-rule: measured off the progetti tabs/cards (177:2449,
     177:2530) — a neutral gray, not the warm beige used everywhere else. */
  --c-border-light:   #DFDFDF;

  /* --- Typography ------------------------------------------------------- */
  --font-sans: "Roboto", "Helvetica Neue", Arial, sans-serif;

  /* Named Figma type tokens (get_variable_defs — exact).
     Each is weight / size / line-height. Letter-spacing is 0 throughout. */
  --fw-h1-hero: 500;        --fs-h1-hero: 56px;   --lh-h1-hero: 62px;
  --fw-cta-big: 500;        --fs-cta-big: 40px;   --lh-cta-big: 44px;
  --fw-h2-large: 400;       --fs-h2-large: 40px;  --lh-h2-large: 45px;
  --fw-h2-small: 400;       --fs-h2-small: 35px;  --lh-h2-small: 42px;
  --fw-h3: 400;             --fs-h3: 29px;        --lh-h3: 35px;
  --fw-titoletti: 500;      --fs-titoletti: 27px; --lh-titoletti: 38px;
  --fw-body-lg: 200;        --fs-body-lg: 22px;   --lh-body-lg: 30px;
  --fw-body-sm-light: 200;  --fs-body-sm-light: 17px; --lh-body-sm-light: 22px;
  --fw-body-sm-med: 500;    --fs-body-sm-med: 17px;   --lh-body-sm-med: 22px;
  --fw-micro: 600;          --fs-micro: 15px;     --lh-micro: 22px;
  /* NUMERI BIG — Chi Siamo storia timeline years (2001:2793/2794). Not in
     the original 10-token get_variable_defs set, but a real named Figma
     text style (get_design_context reports it by name), same tier as the
     others above. */
  --fw-numeri-big: 700;     --fs-numeri-big: 56px; --lh-numeri-big: 61px;
  /* Unnamed intro-copy style — appears identically on Servizi hub (104:184)
     and General Contractor's intro paragraph (180:2524), so promoted to a
     token/utility on the second occurrence rather than re-hardcoded again. */
  --fw-copy: 200;           --fs-copy: 24px;      --lh-copy: 29px;

  /* Component type NOT covered by a named Figma token — measured directly
     off the components, so it is still ground truth, just unnamed upstream. */
  --fw-nav: 400;            --fs-nav: 15px;       --lh-nav: 34px;  /* 88:304  */
  --fw-megabar: 400;        --fs-megabar: 16px;   --lh-megabar: 34px; /* 77:427 */
  --fw-foot-head: 600;      --fs-foot-head: 12px; --lh-foot-head: 19px; /* 177:2514 */
  --fw-foot-body: 300;      --fs-foot-body: 12px; --lh-foot-body: 18px; /* 177:2514 */
  --fw-breadcrumb: 600;     --fs-breadcrumb: 12px; --lh-breadcrumb: 34px; /* 2001:2826 */

  /* --- Layout ----------------------------------------------------------- */
  --canvas: 1440px;         /* Figma artboard width                          */
  --container: 1280px;      /* "Max width 1280 px / Centered layout"         */
  --gutter: 80px;           /* (1440 - 1280) / 2                             */
  /* Inner padding for every full-bleed band. 0 at the design width (the
     1280 column already sits inside a 1440 canvas); below that it becomes a
     real gutter. 25px matches the mobile frame 104:1380 (logo at x=25). */
  --pad-x: 0px;

  /* Grid columns, measured from the artboards */
  --col-3: 411px;           /* services/home 3-up, x = 80 / 514 / 949        */
  --gap-3: 23.5px;
  --col-proj: 413px;        /* project cards,  x = 78 / 513 / 948            */
  --gap-proj: 22px;
  --col-2: 628px;           /* 2-up split,     x = 80 / 732                  */
  --gap-2: 24px;
  --col-narrow: 413px;      /* left rail of the asymmetric text split        */

  /* --- Spacing — from the hidden spacer layers in 77:345 ----------------- */
  --space-14: 14px;         /* "testo spacing 40_01 SMALL"                   */
  --space-40: 40px;         /* "testo spacing 40_01 / _02"                   */
  --space-100: 100px;       /* "testo padding 100 top / bottom"              */
  --space-120: 120px;       /* "spacing 120"                                 */

  /* --- Radii — "FRAME IMMAGINI" notes in 39:454 -------------------------- */
  --radius-frame: 5px;      /* "general frame angoli smussati radius 5"      */
  --radius-chip: 2px;       /* "IT/EN menù a tendina angoli smussati radius 2"*/

  /* --- Fixed band heights ------------------------------------------------ */
  --h-header: 123px;        /* 88:305; becomes 78px below 1024, see --pad-x  */
  --h-header-stuck: 100px;  /* the same row once .is-stuck is on (desktop)   */
  --h-megabar: 60px;        /* 77:425  */
  --h-footer: 540px;        /* 177:2514 */
  --h-cta: 219px;           /* 177:2528 */
  --h-hero-home: 809px;     /* 177:2489 */
  --h-hero-inner: 686px;    /* inner-page hero image */

  /* --- Component metrics ------------------------------------------------- */
  --logo-w: 190px;          /* header logo (194px in the footer)             */
  --logo-w-stuck: 150px;    /* the same mark once the header is stuck        */
  --logo-ratio: 1576 / 450; /* intrinsic ratio of the logo PNG               */
  --arrow-w: 21px;          /* line length; the SVG is 21.75 incl. the head  */
  --arrow-gap: 13px;        /* label → arrow gap inside a PULSANTE (133 wide)*/

  --z-header: 100;
  --z-megabar: 90;
  --z-drawer: 200;
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur: 240ms;
  --dur-zoom: 600ms;        /* slower than UI feedback (--dur) — reads as a
                                deliberate, smooth image zoom, not a hover flick */

  /* Scroll reveal. Long and soft on purpose: this is scenery, not feedback,
     so it runs well past --dur and decelerates without any overshoot. */
  --dur-reveal: 620ms;
  --ease-reveal: cubic-bezier(0.22, 0.61, 0.36, 1);
  --reveal-shift: 16px;     /* travel; small enough not to disturb the grid   */
  --reveal-stagger: 70ms;   /* documents the STEP in assets/js/aec-reveal.js  */
}


/* ============================================================
   assets/css/base.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — Base: fonts, reset, type utilities, layout primitives
   ========================================================================== */

/* --- Roboto, self-hosted -------------------------------------------------
   Roboto v51 is a variable font: one file covers 100–900, so each subset
   needs a single @font-face with a weight *range*. Two files, 72 KB total. */
@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("assets/fonts/roboto-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Roboto";
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("assets/fonts/roboto-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The header is sticky on every page, so anything scrolled to by id — a
     block's anchor, the skip link's #main — has to stop clear of it instead of
     landing underneath.

     This reserves the UNSTUCK row (123, 78 below 1024) even though the bar is
     only --h-header-stuck tall by the time the jump lands, and the 23px
     difference is not slack — it is spent. The destination is computed against
     the layout at click time, i.e. Y - 123 for a target at document offset Y;
     the page then leaves 0, the header sticks, and its 23px come out of the
     flow ABOVE the target, which drops to Y - 23. The target therefore arrives
     at 123 - 23 = 100 from the top: flush under the stuck bar. Reserving 100
     here would land it at 77 and bury its first 23px behind that bar. Below
     1024 the row never shrinks, so 78 is simply exact. */
  scroll-padding-top: var(--h-header);
  /* The home hero's caption band bleeds 87px past the left edge on purpose;
     Chrome counts that toward document scrollWidth. `clip` suppresses the
     phantom horizontal scroll without creating a scroll container the way
     `overflow: hidden` would (which breaks position: sticky). */
  overflow-x: clip;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-weight: var(--fw-body-sm-light);
  font-size: var(--fs-body-sm-light);
  line-height: var(--lh-body-sm-light);
  color: var(--c-text);
  background: var(--c-surface);
  font-variation-settings: "wdth" 100;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input, textarea, select { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* --- Layout primitives ----------------------------------------------------
   .container is the 1280px centred content column (80px gutter at 1440).
   .bleed is a full-width band whose *inner* content still respects it. */
.container,
.site-header__inner,
.cta-band__inner,
.site-footer__inner {
  width: 100%;
  max-width: calc(var(--container) + var(--pad-x) * 2);
  margin-inline: auto;
  padding-inline: var(--pad-x);
}

.bleed { width: 100%; }

/* Below the design width the gutter has to become real or bands go flush
   to the viewport edge. Set once here; every band above inherits it. */
@media (max-width: 1440px) { :root { --pad-x: 40px; } }
/* --h-header rides along so the 78px mobile row has ONE source: the row rule,
   html's anchor reserve and site.js's --over threshold all read the token. */
@media (max-width: 1024px) { :root { --pad-x: 25px; --h-header: 78px; } }

/* The block-rhythm scale (section padding, kicker/copy gaps — see tokens.css)
   is tuned for the 1440 design. Every section's mobile/tablet spacing reads
   as too loose if it's left at full size, so it's scaled down once here
   rather than overridden per section. Figma has no tablet frame and only a
   partial 402 mobile frame, so these ratios are a judgement call (~40%
   tighter at tablet, ~55% at mobile), not a measurement. */
@media (max-width: 1024px) {
  :root {
    --space-120: 72px;
    --space-100: 60px;
    --space-40: 30px;
    --space-14: 12px;
  }
}
@media (max-width: 768px) {
  :root {
    --space-120: 54px;
    --space-100: 46px;
    --space-40: 24px;
    --space-14: 10px;
  }
}

/* --- Grids ----------------------------------------------------------------
   Fixed track widths reproduce Figma exactly at >=1440; below that they
   become equal fractions so the columns stay flush with the container. */
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, var(--col-3));
  gap: var(--gap-3);
  justify-content: space-between;
}
.grid-projects {
  display: grid;
  grid-template-columns: repeat(3, var(--col-proj));
  gap: var(--gap-proj);
  justify-content: space-between;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, var(--col-2));
  gap: var(--gap-2);
  justify-content: space-between;
}
/* Asymmetric text split: 413px rail + 628px body, flush to container edges. */
.grid-split {
  display: grid;
  grid-template-columns: var(--col-narrow) var(--col-2);
  justify-content: space-between;
}

@media (max-width: 1440px) {
  .grid-3, .grid-projects { grid-template-columns: repeat(3, 1fr); }
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-split { grid-template-columns: 1fr 1.52fr; gap: var(--gap-2); }
}
@media (max-width: 1024px) {
  .grid-3, .grid-projects { grid-template-columns: repeat(2, 1fr); }
  .grid-2, .grid-split { grid-template-columns: 1fr; gap: var(--space-40); }
}
@media (max-width: 768px) {
  .grid-3, .grid-projects { grid-template-columns: 1fr; }
}

/* --- Type utilities -------------------------------------------------------
   One class per Figma token. Sizes use clamp() so they scale down cleanly
   but land on the exact Figma value at >= the design width. */
/* Floor is 40px, not an arbitrary small value: the mobile frame 104:1380 draws
   a 2-line hero title 94px tall, i.e. ~47px line-height → ~42px type. 40 keeps
   "Costruire Valore" inside the 402 gutter while staying true to that. */
.t-h1-hero {
  font-weight: var(--fw-h1-hero);
  font-size: clamp(40px, 3.89vw, var(--fs-h1-hero));
  line-height: 1.107;
}
.t-cta-big {
  font-weight: var(--fw-cta-big);
  font-size: clamp(28px, 2.78vw, var(--fs-cta-big));
  line-height: 1.1;
}
.t-h2-large {
  font-weight: var(--fw-h2-large);
  font-size: clamp(28px, 2.78vw, var(--fs-h2-large));
  line-height: 1.125;
}
.t-h2-small {
  font-weight: var(--fw-h2-small);
  font-size: clamp(26px, 2.43vw, var(--fs-h2-small));
  line-height: 1.2;
}
.t-h3 {
  font-weight: var(--fw-h3);
  font-size: clamp(22px, 2.01vw, var(--fs-h3));
  line-height: 1.207;
}
.t-titoletti {
  font-weight: var(--fw-titoletti);
  font-size: clamp(21px, 1.88vw, var(--fs-titoletti));
  line-height: 1.407;
}
.t-body-lg {
  font-weight: var(--fw-body-lg);
  font-size: clamp(18px, 1.53vw, var(--fs-body-lg));
  line-height: 1.364;
}
/* Distinct from Body Large (22/30) — a slightly larger unnamed intro-copy
   style, first seen on Servizi hub and reused verbatim on the General
   Contractor detail page's intro paragraph. */
.t-copy {
  font-weight: var(--fw-copy);
  font-size: clamp(18px, 1.67vw, var(--fs-copy));
  line-height: 1.208;
}
.t-body-sm {
  font-weight: var(--fw-body-sm-light);
  font-size: var(--fs-body-sm-light);
  line-height: var(--lh-body-sm-light);
}
.t-body-sm-med {
  font-weight: var(--fw-body-sm-med);
  font-size: var(--fs-body-sm-med);
  line-height: var(--lh-body-sm-med);
}
.t-micro {
  font-weight: var(--fw-micro);
  font-size: var(--fs-micro);
  line-height: var(--lh-micro);
  text-transform: uppercase;
}

@media (max-width: 768px) {
  .t-body-sm { font-size: 16px; }
  .t-titoletti { font-size: 20px; }
  .t-h2-small { font-size: 24px; }
}

/* --- Helpers -------------------------------------------------------------- */
.u-accent  { color: var(--c-accent); }
.u-muted   { color: var(--c-text-muted); }
.u-invert  { color: var(--c-text-invert); }
.u-upper   { text-transform: uppercase; }
.u-rule    { height: 1px; background: var(--c-rule); border: 0; margin: 0; }

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

/* Arrow glyph. One SVG, recoloured via mask + currentColor, so the same
   asset serves white-on-red, red-on-white and tortora-on-hover. */
.icon-arrow {
  display: inline-block;
  width: var(--arrow-w);
  height: 11px;
  flex: none;
  background-color: currentColor;
  -webkit-mask: url("assets/icons/arrow-right.svg") no-repeat center / contain;
          mask: url("assets/icons/arrow-right.svg") no-repeat center / contain;
}


/* ============================================================
   assets/css/common/buttons.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — Buttons
   ========================================================================== */

/* ==========================================================================
   PULSANTE — the "label + arrow" link. Figma 177:2542 / 177:2549 / 2001:2833
   Box is 133x22: label, 13px gap, 21px arrow. Default red, hover tortora.
   ========================================================================== */
.aec-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--arrow-gap);
  height: var(--lh-micro);
  font-weight: var(--fw-micro);
  font-size: var(--fs-micro);
  line-height: var(--lh-micro);
  text-transform: uppercase;
  color: var(--c-accent);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.aec-btn .icon-arrow { transition: transform var(--dur) var(--ease); }
.aec-btn:hover { color: var(--c-text-muted); }              /* = Variant2 */
.aec-btn:hover .icon-arrow { transform: translateX(4px); }

/* On dark or red bands the label is white and stays white. */
.aec-btn--invert { color: var(--c-text-invert); }
.aec-btn--invert:hover { color: var(--c-text-invert); opacity: .85; }


/* ============================================================
   assets/css/common/header.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — Header
   ========================================================================== */

/* ==========================================================================
   HEADER — Figma 88:305. 1440x123.
   Logo 190x54 @ (80,45); nav row 34px tall @ y=55 → both centre on y=72,
   which is why the inner row is padded 21px from the top rather than
   vertically centred (that would land on 61.5).
   ========================================================================== */
/* STICKY ON EVERY PAGE. `sticky`, not `fixed`, because the header keeps its
   box in the flow — no spacer element, no scroll listener to place it, and
   nothing below it jumps at the moment it pins. It also stays a containing
   block for .megabar, which is absolute at top:100% and would otherwise
   resolve against the viewport.

   This is safe here specifically because html sets overflow-x: CLIP rather
   than hidden (see base.css) — clip suppresses the home hero's phantom
   scrollbar without making html a scroll container, which is what would break
   sticky. The one place sticky genuinely cannot work is the open mobile
   drawer, where body.nav-open sets overflow:hidden; mobile-drawer.css pins
   .site-header__inner for that case instead, and still does.

   .site-header--over overrides both properties below: it is absolute over the
   home hero, then fixed once .is-stuck. */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  width: 100%;
  background: var(--c-surface);
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

/* A hairline once the page has moved under it — on an inner page the header is
   white on white, so without this there is no edge where content passes
   beneath. Same value the --over variant already solidifies to. */
.site-header.is-stuck { box-shadow: 0 1px 0 rgba(30, 30, 30, .06); }
/* Width/gutter come from the shared band rule in base.css. */
.site-header__inner {
  display: flex;
  align-items: center;
  height: var(--h-header);
  padding-top: 21px;                 /* puts the optical centre on y=72 */
  transition: height var(--dur) var(--ease), padding-top var(--dur) var(--ease);
}

/* Stuck: the row gives up its 21px top pad and 2px more, so the bottom edge
   rises 23px (123 → 100) and the content line re-centres 22px up (y=72 → y=50),
   closing around a mark that has already stepped to --logo-w-stuck. All of it
   runs on the same --dur/--ease as the background and the cross-fade, so it
   reads as one movement.

   The media query is load-bearing, not cosmetic: this selector is (0,2,1) and
   would otherwise beat the (0,1,0) mobile row rule below wherever it sat in
   the file, leaving a 100px row inside the drawer's 78px header box. Mobile is
   already a compact 78px and keeps it — the hamburger's -5px centring is
   measured off that bar.

   .site-header is in flow (sticky, not fixed — see above), so on an inner page
   those 23px come off the document itself. Where they show up is the engine's
   call: Chrome and Firefox absorb them into the scroll offset (scroll
   anchoring, so the content appears to hold still), Safari lets everything
   below rise by them. Both are accepted — it is what a shrink-on-scroll header
   does, and the transition makes it a --dur glide rather than a jump. The
   alternative, keeping the flow box and fixing the row, would strand .megabar,
   which is absolute at top:100% of .site-header and follows the shorter row
   for free as things stand. */
@media (min-width: 1025px) {
  .site-header.is-stuck .site-header__inner {
    height: var(--h-header-stuck);
    padding-top: 0;
  }
}

/* Logo — two files, cross-faded so the variant swap needs no JS re-render. */
.site-header__logo {
  position: relative;
  width: var(--logo-w);
  aspect-ratio: var(--logo-ratio);
  flex: none;
  transition: width var(--dur) var(--ease);
}
.site-header__logo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: opacity var(--dur) var(--ease);
}
.site-header__logo .logo--negative { opacity: 0; }
.site-header__logo .logo--color    { opacity: 1; }

/* Stuck, both variants: the mark steps down to --logo-w-stuck. Only the width
   is animated — aspect-ratio carries the height with it, and the row is
   align-items:center, so the logo shrinks about its own optical line instead
   of hanging from the top. Nothing beside it moves either: the nav is
   right-anchored with margin-left:auto, so the width the logo gives up is
   absorbed by the free space between them. */
.site-header.is-stuck .site-header__logo { width: var(--logo-w-stuck); }

/* --- Nav ---------------------------------------------------------------
   Figma x: 623 / 749 / 855 / 977 / 1056 / 1227 / 1348 → a uniform 51px gap. */
/* The nav is right-anchored. Figma's IT chip spans 1343–1365, i.e. it
   deliberately overhangs the 1280 container's right edge (1360) by 5px, so
   the whole row is pulled 5px past the gutter to match. */
.site-nav { margin-left: auto; margin-right: -5px; }
.site-nav__list {
  display: flex;
  align-items: center;
  gap: 51px;
}
.site-nav__link {
  display: block;
  font-weight: var(--fw-nav);
  font-size: var(--fs-nav);
  line-height: var(--lh-nav);
  text-transform: uppercase;
  color: var(--c-text-muted);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.site-nav__link:hover,
.site-nav__item.is-open > .site-nav__link,
.site-nav__item.is-current > .site-nav__link { color: var(--c-accent); }
/* The current item is Medium as well as red — confirmed on three independent
   header instances (`77:345` SERVIZI, `77:430` PROGETTI, `104:1142` ESG), all
   Roboto Medium + #af1e2d. Only the colour was being applied. The slot
   min-widths below already carry the extra width this adds. */
.site-nav__item.is-current > .site-nav__link { font-weight: 500; }

/* Figma stores each label's box at a whole pixel; the browser renders Roboto
   0.3–1px narrower per label, which compounds to ~5px of drift by the right
   edge. Pinning min-width per slot reproduces the Figma x-positions exactly
   without clipping — a longer label simply grows past its minimum.
   Desktop only; the drawer stacks and needs no pinning. */
@media (min-width: 1025px) {
  .site-nav__list > .site-nav__item:nth-child(1) .site-nav__link { min-width: 75px; }
  .site-nav__list > .site-nav__item:nth-child(2) .site-nav__link { min-width: 54px; }
  .site-nav__list > .site-nav__item:nth-child(3) .site-nav__link { min-width: 71px; }
  /* Figma's Servizi→Progetti gap is 52px where every other gap is 51px. */
  .site-nav__list > .site-nav__item:nth-child(3) { margin-left: 1px; }
  .site-nav__list > .site-nav__item:nth-child(4) .site-nav__link { min-width: 28px; }
  .site-nav__list > .site-nav__item:nth-child(5) .site-nav__link { min-width: 120px; }
  .site-nav__list > .site-nav__item:nth-child(6) .site-nav__link { min-width: 70px; }
}

/* --- IT/EN switcher — 22x22 chip, 0.4px border, radius 2 ----------------
   -5px margin absorbs the chip's own padding so the "IT" glyph still
   lands on x=1348 inside the 51px rhythm. .lang-switch is the wrapper and
   contributes no box of its own: the li is sized by the chip inside it, so
   the header row measures exactly as it did when .lang-switch WAS the chip.
   Figma draws only that closed chip; tokens.css records the design note that
   it is a "menù a tendina", so the other languages sit in a panel below. */
.lang-switch {
  position: relative;
  margin-left: -5px;
}
.lang-switch__chip {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border: 0.4px solid rgba(140, 130, 121, .9);
  border-radius: var(--radius-chip);
  font-weight: var(--fw-nav);
  font-size: var(--fs-nav);
  line-height: 1;
  color: var(--c-text-muted);
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.lang-switch__chip:hover,
.lang-switch__chip:focus-visible { color: var(--c-accent); border-color: var(--c-accent); }

/* The dropdown. A panel rather than bare chips because it has to stay legible
   over the hero, where the header's own chip is white-on-image. */
.lang-switch__menu {
  position: absolute;
  top: calc(100% + 5px);
  right: -4px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px;
  border-radius: var(--radius-chip);
  background: var(--c-surface);
  box-shadow: 0 2px 10px rgba(30, 30, 30, .14);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.lang-switch.is-open .lang-switch__menu { visibility: visible; opacity: 1; }
/* Inside the panel the chips are on --c-surface whatever the header variant
   is doing, so they never take the --over inversion below. */
.lang-switch__menu .lang-switch__chip,
.site-header--over .lang-switch__menu .lang-switch__chip {
  color: var(--c-text-muted);
  border-color: rgba(140, 130, 121, .9);
}
.lang-switch__menu .lang-switch__chip:hover,
.lang-switch__menu .lang-switch__chip:focus-visible,
.site-header--over .lang-switch__menu .lang-switch__chip:hover,
.site-header--over .lang-switch__menu .lang-switch__chip:focus-visible {
  color: var(--c-accent);
  border-color: var(--c-accent);
}

/* --- Variant: transparent over the hero (Figma "Default", 88:304) ------- */
.site-header--over {
  position: absolute;
  top: 0; left: 0; right: 0;
  background: transparent;
}
.site-header--over .logo--negative { opacity: 1; }
.site-header--over .logo--color    { opacity: 0; }
.site-header--over .site-nav__link,
.site-header--over .lang-switch__chip { color: var(--c-text-invert); }
.site-header--over .lang-switch__chip { border-color: rgba(255, 255, 255, .9); }
.site-header--over .site-nav__link:hover,
.site-header--over .site-nav__item.is-open > .site-nav__link { color: var(--c-accent); }

/* Once scrolled past the hero it solidifies back to Variant2. */
.site-header--over.is-stuck {
  position: fixed;
  background: var(--c-surface);
  box-shadow: 0 1px 0 rgba(30, 30, 30, .06);
}
.site-header--over.is-stuck .logo--negative { opacity: 0; }
.site-header--over.is-stuck .logo--color    { opacity: 1; }
.site-header--over.is-stuck .site-nav__link,
.site-header--over.is-stuck .lang-switch__chip { color: var(--c-text-muted); }
.site-header--over.is-stuck .lang-switch__chip { border-color: rgba(140, 130, 121, .9); }
/* Last, so hover/focus beats both variants above. The panel's own chips are
   a selector deeper and keep the rule they were given. */
.site-header--over .lang-switch__chip:hover,
.site-header--over .lang-switch__chip:focus-visible,
.site-header--over.is-stuck .lang-switch__chip:hover,
.site-header--over.is-stuck .lang-switch__chip:focus-visible {
  color: var(--c-accent);
  border-color: var(--c-accent);
}

/* ==========================================================================
   HEADER — mobile metrics (Figma 104:1380: logo 109px @ x=25, y=23)
   ========================================================================== */
@media (max-width: 1024px) {
  /* The row height and html's anchor reserve both come from --h-header, which
     is 78px at this breakpoint (the override sits with --pad-x's), so the two
     rules that used to repeat the number are gone rather than rewritten. */
  .site-header__inner { padding-top: 0; }
  .site-header__logo { width: 109px; }   /* Figma 104:1380 */
  /* The same step down, proportional to the 109px mobile mark rather than
     reusing the desktop token — 150px is wider than mobile even starts. The
     row itself does not step here: 78px has no 21px pad to give up, and the
     hamburger's -5px centring is measured off that bar. */
  .site-header.is-stuck .site-header__logo { width: 88px; }
}


/* ============================================================
   assets/css/common/mega-bar.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — Mega-bar
   Figma 77:345 (Servizi) / 77:430 (Progetti). 1440x60, beige.

   Both bars are a *centred* row of content-width labels inside the 1280
   container — not a slot grid. Figma's text boxes hug their labels and the
   group centres on the canvas (Servizi spans 297–1142, centre 719.5;
   Progetti spans 83–1365, centre 720).

   Implemented as `space-between` inside a list capped at the group's exact
   width, so at >=1440 the slack resolves to the Figma gap and the labels land
   on their drawn positions, while below 1440 the same rule simply tightens
   the gaps instead of overflowing. The cap reuses the container's --pad-x so
   the row keeps the page gutter at every width.

   The group widths below bake in the rendered width of the current Italian
   labels; if the WP menu changes them, re-measure (same caveat as the header
   nav — see FIGMA-MAP.md).

   Mobile override (accordion) lives in mobile-drawer.css and must load
   after this file.
   ========================================================================== */
.megabar {
  position: absolute;
  left: 0; right: 0;
  top: 100%;
  z-index: var(--z-megabar);
  height: var(--h-megabar);
  background: var(--c-surface-alt);
  overflow: hidden;
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), visibility var(--dur) var(--ease);
}
.site-nav__item.is-open .megabar { visibility: visible; opacity: 1; }

.megabar__list {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--pad-x);
  /* 3 labels (563.6px of text) + 2 gaps of 135.2 */
  max-width: calc(834px + var(--pad-x) * 2);
}
.megabar__item { flex: 0 0 auto; }
.megabar__link {
  font-weight: var(--fw-megabar);
  font-size: var(--fs-megabar);
  line-height: var(--lh-megabar);
  text-transform: uppercase;
  color: var(--c-text-muted);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.megabar__link:hover { color: var(--c-accent); }

/* The Progetti bar carries 5 labels, so its group is wider and its gap
   narrower — 5 labels (930.8px of text) + 4 gaps of 75.05. */
.megabar--projects .megabar__list { max-width: calc(1231px + var(--pad-x) * 2); }


/* ============================================================
   assets/css/common/mobile-drawer.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — Mobile drawer
   Figma 190:3080 "iPhone 17 - menu aperto" (402 wide).

   A 580px TOP SHEET, not a full-screen overlay: Rectangle 13 is 402x580 at
   (0,0), 90% white over the hero — sampled against the closed frame
   (104:1380) the blend is a flat 0.90 on every channel even next to the
   hero's hard edges, so there is no backdrop blur to reproduce.

   The header rides ON TOP of the sheet: Figma shows the colour logo and a red
   hamburger over the panel, so the header band goes transparent, the logo and
   the toggle are lifted past --z-drawer, and the logo flips to the colour file
   even on the front page where --over normally shows the negative one.

   Geometry, all from 190:3080:
     logo      109x31 @ (25,23)      — already set in header.css
     hamburger  7x10  @ (370,29)     — centre y=34 in a 78px bar, hence -5px
     labels     22px boxes @ x=25, y=137 then every 48px  → 26px gaps
     IT/EN      22x22 chips @ (24,487) and (53,487)       → 7px gap
     sheet      bottom edge at y=580

   Overrides .site-nav__link (header.css) and .megabar (mega-bar.css) for
   mobile, so this file must load after both.
   ========================================================================== */
/* 7x10 in Figma both open and closed — the icon never becomes an X, it just
   turns red. ::before restores a 44px tap target the 7px glyph cannot give. */
.nav-toggle {
  display: none;
  width: 7px;
  height: 10px;
  margin-left: auto;
  position: relative;
  flex: none;
}
.nav-toggle::before {
  content: "";
  position: absolute;
  inset: -17px -19px;
}
.nav-toggle span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: var(--c-text-muted);
  transition: background var(--dur) var(--ease);
}
.nav-toggle span:nth-child(1) { top: 0; }
.nav-toggle span:nth-child(2) { top: 50%; transform: translateY(-50%); }
.nav-toggle span:nth-child(3) { bottom: 0; }
.site-header--over:not(.is-stuck) .nav-toggle span { background: var(--c-text-invert); }

/* Second selector is not redundant: the --over rule above is (0,3,1) and a
   plain `body.nav-open .nav-toggle span` is only (0,2,2), so on the front page
   the open hamburger stayed white-on-white and vanished. */
body.nav-open .nav-toggle span,
body.nav-open .site-header--over:not(.is-stuck) .nav-toggle span { background: var(--c-accent); }

@media (max-width: 1024px) {
  .nav-toggle {
    display: block;
    transform: translateY(-5px);      /* icon centre y=34, bar centre y=39 */
  }

  /* --- Header over the sheet ------------------------------------------
     The logo and the hamburger have to stay at the top of the sheet however
     far the page was scrolled, so the header row is pinned while the drawer
     is open. It is the INNER row that goes fixed, not .site-header: the
     header then keeps an empty 78px box in the flow and nothing below it
     jumps. (`sticky` cannot do this job — body.nav-open sets overflow:hidden,
     which makes body a scroll container of its own, and the header would
     stick to the top of the document rather than the top of the screen. See
     the note on html{overflow-x:clip} in base.css.) */
  body.nav-open .site-header {
    height: 78px;
    background: transparent;
    box-shadow: none;
  }
  body.nav-open .site-header__inner {
    position: fixed;
    top: 0; left: 0; right: 0;
  }
  /* The drawer is a DESCENDANT of the header (see header.php), so --z-drawer
     stacks inside the header's own context and paints over its siblings —
     the logo and the hamburger included. Figma has both on top of the panel,
     and the hamburger has to stay clickable to close it, so each is lifted
     past the sheet here rather than by raising the header as a whole. */
  body.nav-open .site-header__logo,
  body.nav-open .nav-toggle { z-index: calc(var(--z-drawer) + 1); }

  /* Figma 190:3101 is AeC_Logo_rgb — the colour mark, even on the front page. */
  body.nav-open .logo--color    { opacity: 1; }
  body.nav-open .logo--negative { opacity: 0; }
  /* …and at full size: 190:3101 is the closed-menu header row, so the drawer
     opens on the whole mark however far the page had scrolled under it. */
  body.nav-open .site-header.is-stuck .site-header__logo { width: 109px; }

  /* 190:3080 keeps the hero video behind the 90% panel but drops the caption
     band and the slider UI that 104:1380 (same frame, menu closed) carries —
     a red band ghosting through the sheet sits right on top of LAVORA CON NOI
     and CONTATTI. Hidden rather than deleted so the hero is intact on close. */
  body.nav-open .hero__caption,
  body.nav-open .hero__ui { opacity: 0; }

  /* --- The sheet ------------------------------------------------------- */
  .site-nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    margin: 0;                        /* header.css pulls it -5px right */
    height: 580px;                    /* Figma 190:3082 */
    max-height: 100dvh;
    z-index: var(--z-drawer);
    background: rgba(255, 255, 255, .9);
    padding: 137px 25px 40px;         /* first label box starts at y=137 */
    overflow-y: auto;
    transform: translateY(-100%);
    visibility: hidden;
    transition: transform var(--dur) var(--ease), visibility var(--dur) var(--ease);
  }
  body.nav-open { overflow: hidden; }
  body.nav-open .site-nav { transform: none; visibility: visible; }

  .site-nav__list {
    flex-direction: column;
    align-items: flex-start;
    gap: 26px;                        /* 48px pitch − the 22px line box */
  }
  /* Roboto Medium 14/22. The six Figma label widths (71/51/67/26/113/67) are
     each 1.3% wider than Regular at the same size — that margin is Medium,
     and it is what pins the size to 14 rather than the header's 15. */
  .site-nav__link,
  .site-header--over .site-nav__link {
    color: var(--c-accent);
    font-size: 14px;
    font-weight: 500;
    line-height: 22px;
  }

  /* Parent items get a chevron and expand in place. */
  .site-nav__item--parent > .site-nav__link::after {
    content: "";
    display: inline-block;
    width: 7px; height: 7px;
    margin-left: 10px;
    border-right: 1px solid currentColor;
    border-bottom: 1px solid currentColor;
    transform: translateY(-3px) rotate(45deg);
    transition: transform var(--dur) var(--ease);
  }
  .site-nav__item--parent.is-open > .site-nav__link::after {
    transform: translateY(1px) rotate(-135deg);
  }

  /* Mega-bar degrades to an inline accordion. */
  .megabar {
    position: static;
    height: auto;
    background: transparent;
    visibility: visible;
    opacity: 1;
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows var(--dur) var(--ease);
  }
  .site-nav__item.is-open .megabar { grid-template-rows: 1fr; }
  .megabar__list {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 14px;
    height: auto;
    max-width: none;
    padding: 0 0 0 16px;
    min-height: 0;
    overflow: hidden;
  }
  .site-nav__item.is-open .megabar__list { padding-top: 16px; }
  .megabar--projects .megabar__list { max-width: none; padding-left: 16px; }
  .megabar__item,
  .megabar--projects .megabar__item { width: auto; margin-right: 0; }
  .megabar__link { font-size: 14px; line-height: 1.4; }

  /* --- IT / EN --------------------------------------------------------
     190:3080 shows both chips in a row, so the header's dropdown flattens:
     the panel loses its positioning and chrome and becomes the rest of the
     row. CONTATTI's box ends at y=399 and the chips start at y=487; 26px of
     that is the list gap. site.js keeps the toggle's aria in step — with
     every chip already on screen there is nothing left for it to expand. */
  .site-nav__item--lang { margin-top: 62px; }
  .lang-switch {
    display: flex;
    gap: 7px;                         /* 46 → 53 */
    /* The chips are centred on their glyphs, not flush with the labels: the
       IT box starts at x=24 where every label starts at 25. */
    margin-left: -1px;
  }
  .lang-switch__menu {
    position: static;
    flex-direction: row;
    gap: 7px;
    padding: 0;
    background: none;
    box-shadow: none;
    visibility: visible;
    opacity: 1;
  }
  .lang-switch__menu .lang-switch__chip,
  .site-header--over .lang-switch__menu .lang-switch__chip {
    color: var(--c-text-muted);
    border-color: rgba(140, 130, 121, .9);
  }
  .lang-switch__toggle,
  .site-header--over .lang-switch__toggle {
    color: var(--c-accent);
    border-color: var(--c-accent);
  }
}


/* ============================================================
   assets/css/common/footer.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — Footer
   Figma 177:2514. 1440x540, #1e1e1e.
   Logo 194px @ (80,100). Columns @ x = 488 / 814 / 1031 / 1249.
   Headings SemiBold 12/19 tortora · body Light 12/18 white · legal @ y=405.
   ========================================================================== */
.site-footer {
  background: var(--c-surface-dark);
  color: var(--c-text-invert);
}
.site-footer__inner {
  height: var(--h-footer);
  padding-top: 100px;
  display: flex;
  flex-direction: column;
}
.site-footer__cols {
  display: grid;
  /* 80→488 = 408 | 488→814 = 326 | 814→1031 = 217 | 1031→1249 = 218 | rest */
  grid-template-columns: 408px 326px 217px 218px 1fr;
  align-content: start;
}
.site-footer__brand { grid-column: 1; }
.site-footer__logo { width: 194px; aspect-ratio: var(--logo-ratio); }

.site-footer__col-head {
  font-weight: var(--fw-foot-head);
  font-size: var(--fs-foot-head);
  line-height: var(--lh-foot-head);
  text-transform: uppercase;
  color: var(--c-text-muted);
  margin-bottom: 9px;          /* heading y=100, body y=128 → 100+19+9 */
}
.site-footer__body,
.site-footer__list {
  font-weight: var(--fw-foot-body);
  font-size: var(--fs-foot-body);
  line-height: var(--lh-foot-body);
}
.site-footer__list--head {
  font-weight: var(--fw-foot-head);
  line-height: var(--lh-foot-head);
  color: var(--c-text-muted);
  text-transform: uppercase;
}
.site-footer a { transition: color var(--dur) var(--ease); }
.site-footer__body a { text-decoration: underline; text-underline-position: from-font; }
.site-footer a:hover { color: var(--aec-rosso-light); }

.site-footer__social {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 11px;            /* head y=100 (+19) → icons y=130 */
}
.site-footer__social img { height: 11px; width: auto; }

/* Legal row sits on y=405 in a 540px footer: pushed to the bottom, then
   held 117px clear of it (540 - 405 - 18px line = 117). */
.site-footer__legal {
  display: grid;
  grid-template-columns: 408px 326px 217px 1fr;
  margin-top: auto;
  margin-bottom: 117px;
  font-weight: var(--fw-foot-body);
  font-size: var(--fs-foot-body);
  line-height: var(--lh-foot-body);
}
.site-footer__legal > :first-child { grid-column: 2; }

@media (max-width: 1024px) {
  .site-footer__inner { height: auto; padding-block: 64px; }
  .site-footer__cols {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-40);
  }
  .site-footer__brand { grid-column: 1 / -1; }
  .site-footer__legal {
    grid-template-columns: 1fr;
    gap: 8px;
    margin-top: var(--space-40);
    margin-bottom: 0;
  }
  .site-footer__legal > :first-child { grid-column: 1; }
}
@media (max-width: 768px) {
  .site-footer__cols { grid-template-columns: 1fr; }
}


/* ============================================================
   assets/css/common/wp.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — WordPress-only additions

   Everything else under assets/css is a verbatim copy of the static build, so
   that a diff between the two trees stays meaningful. This file is the one
   place for rules the static build had no need for, because they exist to
   support WordPress chrome rather than the Figma design.
   ========================================================================== */

/* --- Skip link -----------------------------------------------------------
   The static build had no skip link; a keyboard user landing on a WordPress
   site expects one. Hidden using the same technique as .visually-hidden in
   base.css, but it must become visible when focused — that is the entire
   point of it. */
.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: calc(var(--z-drawer) + 10);
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link:focus {
  width: auto;
  height: auto;
  margin: 0;
  padding: 12px 20px;
  overflow: visible;
  clip-path: none;
  background: var(--c-surface);
  color: var(--c-accent);
  font-weight: var(--fw-body-sm-med);
  font-size: var(--fs-body-sm-med);
  line-height: var(--lh-body-sm-med);
  outline: 2px solid var(--c-accent);
  outline-offset: -2px;
}

/* --- Admin bar -----------------------------------------------------------
   The bar is position:fixed for logged-in users, and every variant of the
   header now resolves against top:0 — sticky on an inner page, absolute over
   the home hero, fixed once stuck — so all three have to clear it or they sit
   under the bar. Front-end only; never applies to a logged-out visitor or a
   screenshot taken by the pixel-diff run. */
body.admin-bar .site-header { top: 32px; }

@media screen and (max-width: 782px) {
  body.admin-bar .site-header { top: 46px; }
}

/* --- Block editor canvas --------------------------------------------------
   Editor-only: these selectors never occur on the front end. Without them the
   post title falls back to Gutenberg's generic bold UI font instead of the
   Figma h1-hero style, and the canvas spans the full iframe width instead of
   the 1280px design container — classic (non-block) themes never get core's
   automatic "constrained root" treatment for Post Content regardless of
   theme.json's contentSize/wideSize (wp_get_post_content_block_attributes()
   bails out unless wp_is_block_theme() is true), so it's replicated by hand
   here. */
.editor-post-title__input {
  max-width: var(--container);
  margin-inline: auto;
  font-weight: var(--fw-h1-hero);
  font-size: clamp(40px, 3.89vw, var(--fs-h1-hero));
  line-height: 1.107;
}

/* Classic themes never get the block-theme "constrained root" treatment core
   gives Post Content (wp_get_post_content_block_attributes() bails out for
   non-block themes), so a plain paragraph/heading dropped straight into the
   page spans the full iframe instead of the 1280px column. ACF section
   blocks are excluded — they're deliberately full-bleed (align:false in
   their block.json) and manage their own width via the .bleed primitive. */
.is-root-container > *:not([class*="wp-block-acf-"]) {
  max-width: var(--container);
  margin-inline: auto;
}


/* ============================================================
   assets/css/common/media-zoom.css
   ============================================================ */
/* ==========================================================================
   MEDIA ZOOM — reusable hover-zoom for card/showcase imagery.

   Apply `.media-zoom` to whichever element's :hover should trigger the
   zoom — the whole card link (servizi/progetti: hovering anywhere on the
   card zooms its photo) or just the image wrapper itself (ESG: only the
   image is hoverable, there's no surrounding link). The class carries its
   own `overflow: hidden`, so it clips correctly either way without
   depending on a parent already having it.
   ========================================================================== */
.media-zoom { overflow: hidden; }

.media-zoom img {
  display: block;
  transition: transform var(--dur-zoom) var(--ease);
}

.media-zoom:hover img { transform: scale(1.06); }

@media (prefers-reduced-motion: reduce) {
  .media-zoom img { transition: none; }
}


/* ============================================================
   assets/css/common/cta-band.css
   ============================================================ */
/* ==========================================================================
   ALBINI E CASTELLI — CTA band
   Figma 177:2528. 1440x219, #af1e2d.
   Title @ (80,64) 406 wide · link @ (1199,122) · arrow @ (1339,133)
   ========================================================================== */
.cta-band { background: var(--c-accent); color: var(--c-text-invert); }
.cta-band__inner {
  position: relative;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  height: var(--h-cta);
  padding-top: 64px;
}
.cta-band__title { max-width: 406px; }
/* The CTA link sets its label→arrow gap to 19px (Figma: text ends 1320,
   arrow starts 1339), wider than the 13px used inside a PULSANTE. */
.cta-band__link { margin-top: 58px; gap: 19px; }   /* 122 - 64 */

@media (max-width: 1024px) {
  .cta-band__inner {
    height: auto;
    flex-direction: column;
    gap: var(--space-40);
    padding-block: 56px;
  }
  .cta-band__link { margin-top: 0; }
}

@media (max-width: 768px) {
  /* Fixed 24px, not a lower clamp() floor — .t-cta-big is a shared utility
     used elsewhere too, so this overrides just the CTA band's own title
     rather than changing what every future use of the token clamps to. */
  .cta-band__title { font-size: 24px; line-height: 1.2; }
}


/* ============================================================
   assets/css/common/page-hero.css
   ============================================================ */
/* ==========================================================================
   PAGE HERO + BREADCRUMB + KICKER — shared inner-page opener.
   Figma Chi Siamo 2001:2758 (686h photo) + 2001:2826 (breadcrumb); Servizi
   hub 77:578 (686h photo) + 77:579 (wash) + 104:188 (caption title).
   `--h-hero-inner` (686px) was reserved in tokens.css back when only the
   homepage existed, anticipating exactly this reuse across every inner page
   (Servizi, Progetti, ESG, Lavora con noi, Contatti…) — built once here
   instead of per page. Only the photo band + breadcrumb + kicker type are
   common; each page's own heading/copy content is still page-specific CSS.

   Two hero variants confirmed so far: Chi Siamo's is a plain photo, Servizi
   hub's adds a dark wash + white H1 caption pinned near the bottom — so the
   wash/caption/title rules below are opt-in (add the elements only if a
   given page's Figma frame has them), not baked into the base `.page-hero`.
   ========================================================================== */
.page-hero {
  position: relative;
  height: var(--h-hero-inner);
  overflow: hidden;
  background: var(--aec-antracite);   /* shows while the photo loads */
}
.page-hero picture { display: contents; }
.page-hero__media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- Caption variant (Servizi hub 77:579/104:188) --------------------------
   Flat dark wash over the whole photo (not the homepage hero's boxed rosso
   band) with the H1 bottom-anchored on top — get_design_context on 77:579
   returned a plain rgba(36,36,36,.2) fill, no separate caption box. */
.page-hero__wash {
  position: absolute;
  inset: 0;
  background: rgba(36, 36, 36, .2);
  pointer-events: none;
}
.page-hero__caption {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-end;
  padding-bottom: 108px;   /* measured: title bottom (701) → hero bottom (809) */
  pointer-events: none;
}
.page-hero__title {
  max-width: 575px;
  margin: 0;
  color: var(--c-text-invert);
}

/* --- Title entrance, on load ----------------------------------------------
   The opener's H1 arrives with the page rather than on scroll. .page-hero is
   in aec-reveal.js's SKIP list precisely because an above-the-fold element
   must not wait for a scroll that has already happened, so the reveal
   utility is the wrong tool and a keyframe animation is the right one: it
   fires the moment the element first renders, with no class to toggle and no
   JS. A transition cannot do that — on a fresh paint there is no prior
   computed style to transition away from.

   It opens from the left, matching the hero-slider caption. `both` fill mode
   holds the from-state through the delay; without it the title would paint
   at full opacity for 120ms and only then jump back to the start.

   SITEWIDE ON PURPOSE. This rule is not block-scoped, so the eleven
   template-parts/sections/page-hero.php call sites open exactly like the
   block does — the MARKUP PARITY contract blocks/page-hero/render.php
   documents. Those two files are the only emitters of the class; the plate
   variant on single-progetto reuses .page-hero__caption but not the title,
   so it is untouched. The title exists only in the `wash` variant, so plain
   heroes have nothing to animate. */
@keyframes aec-page-hero-title-in {
  from { opacity: 0; transform: translate3d(var(--page-hero-title-shift), 0, 0); }
  to   { opacity: 1; transform: none; }
}
.page-hero__title {
  --page-hero-title-shift: -64px;
  animation: aec-page-hero-title-in var(--dur-reveal) var(--ease-reveal) 120ms both;
}

/* The global clamp near the top of this file kills animation-duration but
   resets neither animation-delay nor fill-mode, so `both` would otherwise
   hold the from-state — an invisible title — for the full 120ms. Kill the
   animation outright. This is also what keeps tools/verify.sh, which
   captures with --force-prefers-reduced-motion, matching its baselines. */
@media (prefers-reduced-motion: reduce) {
  .page-hero__title { animation: none; }
}

/* --- Short variant (General Contractor 180:2530, and presumably the other
   two Servizi detail pages) — a plain photo like Chi Siamo's, just shorter
   because it sits below the persistent sub-nav tab bar (.subnav)
   instead of directly under the header. Falls back to the same 360/240
   tablet/mobile heights as the base .page-hero — 371 is already close
   enough to 360 that a dedicated short-variant step wasn't worth adding. */
.page-hero--short { height: 371px; }

/* --- Breadcrumb band ------------------------------------------------------
   The crumb is its own <section> now: blocks/page-breadcrumb, plus
   template-parts/sections/page-breadcrumb.php for the two field-driven
   templates that have no post content to hold a block. It used to be drawn
   inside each page's opening section — the static build does it that way and
   the port copied it — which welded a breadcrumb into four different blocks.

   BOTH GAPS AROUND THE CRUMB LIVE HERE. The one above was each opener's own
   padding-top; the one below was .breadcrumb's margin-bottom. An opener no
   longer has to know a breadcrumb exists, and .breadcrumb is now pure type.

   PADDING, NOT MARGIN, ON PURPOSE — the same seam blocks/hub-intro/style.css
   documents. .container has padding-inline only, so a margin on the crumb
   would have to collapse through two box boundaries to draw the lower gap.

   THE MOBILE SPLIT IS INHERITED, NOT DESIGNED. Six of the eleven openers got a
   <=768px pass that took the 64px top gap down to 40; the other five never
   did. Figma has no mobile frame for any of them, so neither number is more
   correct than the other — but the static build renders both, and reproducing
   it is the whole point. --mobile-40 marks the six. Do not harmonise them
   without re-measuring the static build at 402 first.
   ========================================================================== */
.page-breadcrumb {
  padding-top: 64px;      /* measured: hero bottom -> crumb top, all eleven pages */
  padding-bottom: 64px;   /* measured: crumb bottom -> the opener's first line */
}

/* Contatti runs 61px from the crumb down to its heading, not 64. This was
   `.contatti .breadcrumb { margin-bottom: 61px }` in that block's stylesheet,
   which stopped matching anything the moment the crumb left .contatti — no
   error, no warning, just three pixels. Ties with .page-breadcrumb at 0,1,0,
   so it has to stay below it. */
.page-breadcrumb--contatti-61 { padding-bottom: 61px; }

/* Also 0,1,0 against the base, so also below it on purpose. */
@media (max-width: 768px) {
  .page-breadcrumb--mobile-40,
  .page-breadcrumb--contatti-61 { padding-top: 40px; }
}

/* --- Breadcrumb -----------------------------------------------------------
   Pure type now — both gaps around it belong to .page-breadcrumb above, so
   this rule no longer has an opinion about where it sits. It used to carry
   `margin: 0 0 64px` for the gap down to the page kicker, with the gap above
   left to whichever section happened to contain it. Figma spaces the words
   wider than the source text's own whitespace collapses to (get_design_context
   returns literal "HOME   >   CHI SIAMO"); reproduced with a margined
   separator instead of relying on multiple spaces. */
.breadcrumb {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  font-weight: var(--fw-breadcrumb);
  font-size: var(--fs-breadcrumb);
  line-height: var(--lh-breadcrumb);
  letter-spacing: .02em;
  text-transform: uppercase;
  color: var(--c-text-muted);
}
.breadcrumb a:hover { color: var(--c-accent); }
.breadcrumb__sep { opacity: .6; }

/* --- Page kicker ------------------------------------------------------------
   "TITOLETTI SEZIONI" bold-700 override, uppercase, red — identical on both
   Chi Siamo ("chi siamo", 2001:2825) and Servizi ("I NOSTRI SERVIZI",
   104:177), so promoted here instead of staying a per-page rule. Margin
   below it isn't shared (24px on Chi Siamo, 16px on Servizi), so that stays
   with the caller same as the breadcrumb's top gap. */
.page-kicker {
  margin: 0;
  font-weight: 700;
  font-size: var(--fs-titoletti);
  line-height: var(--lh-titoletti);
  text-transform: uppercase;
  color: var(--c-accent);
}

@media (max-width: 1024px) {
  /* No tablet/mobile frame for this band — derived, same 360/240 stepping
     used elsewhere for full-bleed photo bands without a mobile reference. */
  .page-hero { height: 360px; }
  .page-hero__caption { padding-bottom: 40px; }
  .page-hero__title { --page-hero-title-shift: -40px; }
}
@media (max-width: 768px) {
  .page-hero { height: 240px; }
}
@media (max-width: 768px) {
  .page-kicker { font-size: 24px; line-height: 1.407; }
}


/* ============================================================
   assets/css/common/section-heading.css
   ============================================================ */
/* ==========================================================================
   SECTION HEADING + RULED ITEM — two units that turned up on a third page.

   `.section-heading` is the TITOLETTI pairing at Medium rather than
   .page-kicker's bold override: 27px red uppercase. Figma draws it on a 44px
   line everywhere except ESG's "COSTRUIAMO VALORE SOSTENIBILE" (38), so 44 is
   the base and that one instance overrides.
     · 82:1158  INTERVENTO                 (progetto detail)
     · 86:409   LE NOSTRE INNOVAZIONI      (ESG)
     · 87:665   I NOSTRI CONTATTI          (Contatti)
     · 104:1170 COSTRUIAMO VALORE SOSTENIBILE (ESG, the 38 case)

   `.ruled-item` is a 21/50 label with a 193px rule under it and body copy
   below — identical on ESG's innovation items and Contatti's address/email
   blocks, down to the 193px rule width and the 8px gap beneath it. The label
   is fixed-width + nowrap because Figma sizes each label box to its own text
   (194/183/227 on ESG) so none of them wrap, while the rule stays 193.
     · 86:425/427/431 + lines 86:371/372/374  (ESG)
     · 87:667/669     + lines 87:661/662      (Contatti)
   ========================================================================== */
.section-heading {
  margin: 0;
  font-weight: 500;
  font-size: var(--fs-titoletti);
  line-height: 44px;
  text-transform: uppercase;
  color: var(--c-accent);
}

.ruled-item__label {
  width: 193px;
  margin: 0;
  font-weight: 400;
  font-size: 21px;
  line-height: 50px;
  white-space: nowrap;
  border-bottom: 1px solid var(--c-rule);
}
.ruled-item__body { margin: 8px 0 0; }

@media (max-width: 768px) {
  /* The fixed label width is only there to pin the rule at the drawn 193px;
     once a column is narrower than that it has to give way. */
  .ruled-item__label { width: 100%; }
}


/* ============================================================
   assets/css/common/subnav.css
   ============================================================ */
/* ==========================================================================
   SUB-NAV — persistent category tab strip baked into a page.
   Figma: Servizi detail pages 180:2519–2522 · Progetti archives 79:796–801.
   Distinct from .megabar: that's a hover/tap dropdown hanging off the header
   nav, this is a static bar in the page itself, always visible, marking which
   sibling you're on. Confirmed on both via get_design_context — the current
   label renders Medium/red while the rest stay Regular/tortora.

   Generalised from the original .servizi-subnav when the Progetti archives
   turned out to need a bar with identical type, colours and states and only a
   different row of labels. The two variants differ purely in how that row is
   laid out, so everything else lives on the base class.
   ========================================================================== */
.subnav {
  background: var(--aec-beige);
  height: 60px;
}
.subnav__list {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
}
/* Figma types these labels in caps — get_design_context returns the literal
   "GENERAL CONTRACTOR" / "RESIDENZIALE", not a cased string with a transform.
   They were previously rendered mixed-case, which also made every label too
   narrow to land on its drawn x. */
.subnav__link {
  font-weight: 400;
  font-size: 16px;
  line-height: 34px;
  text-transform: uppercase;
  color: var(--c-text-muted);
  white-space: nowrap;
  transition: color var(--dur) var(--ease);
}
.subnav__link:hover,
.subnav__item.is-current .subnav__link {
  font-weight: 500;
  color: var(--c-accent);
}

/* Servizi: 3 labels, spaced 144px then 109px — Figma centres each on a fixed
   x rather than on an even gap. Reproduced with per-item margins now that the
   labels render at their real (uppercase) widths; a single averaged gap was
   only ever needed while they were rendering too narrow to place accurately. */
.subnav--servizi .subnav__list { gap: 0; }
.subnav--servizi .subnav__item:nth-child(1) { margin-right: 144px; }
.subnav--servizi .subnav__item:nth-child(2) { margin-right: 109px; }

/* Progetti: 5 labels, drawn at exactly the same x/width as the Progetti
   mega-bar (83/149, 256/263, 543/249, 816/233, 1071/294 — centre 720), so it
   reuses that component's geometry verbatim: a group capped at its own width
   and spaced out, which lands the labels on their Figma centres at >=1440 and
   simply tightens the gaps below it. See the mega-bar note in FIGMA-MAP §6. */
.subnav--progetti .subnav__list {
  justify-content: space-between;
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--pad-x);
  max-width: calc(1231px + var(--pad-x) * 2);
}

@media (max-width: 1024px) {
  .subnav__list {
    justify-content: flex-start;
    gap: 32px;
    padding-inline: var(--pad-x);
    overflow-x: auto;
    scrollbar-width: none;
  }
  .subnav__list::-webkit-scrollbar { display: none; }
  /* Both variants collapse to the same scrolling row, so the desktop spacing
     has to come off or the labels spread apart. */
  .subnav--progetti .subnav__list { max-width: none; justify-content: flex-start; }
  .subnav--servizi .subnav__list { gap: 32px; }
  .subnav--servizi .subnav__item:nth-child(1),
  .subnav--servizi .subnav__item:nth-child(2) { margin-right: 0; }
}


/* ============================================================
   assets/css/sections/esg.css  (showcase component only)
   ============================================================ */
/* ==========================================================================
   SHOWCASE PANEL — beige band with a photo and N icon/text rows.
   Figma homepage 177:2448, y=3993–4604.

   Promoted from sections/esg.css into the sitewide sheet when Soluzioni per
   Investitori's "processo integrato" became its own block: the panel is now
   drawn by two blocks (home-esg and si-process) through one shared partial,
   template-parts/sections/esg-showcase.php, and shared rules belong here
   rather than being duplicated into each block's stylesheet. The rest of
   sections/esg.css — the .esg wrapper the home page puts around it — moved
   the other way, into blocks/home-esg/style.css.

   Photo on the left, icon+text rows on the right, each row vertically
   centered against its own text block.
   ========================================================================== */
.esg-showcase {
  display: flex;
  margin-top: var(--space-40);   /* measured: link bottom (3953) → panel top (3993) = 40 exact */
  background: rgba(232, 228, 224, .5);  /* --aec-beige at 50% */
  border-radius: var(--radius-frame);
  overflow: hidden;
}
.esg-showcase__media {
  flex: 0 0 624px;
  align-self: stretch;
}
.esg-showcase__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.esg-showcase__features {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 40px;                  /* measured: identical 40px gap between all 3 rows */
  padding: 40px 40px 40px 88px;   /* measured: 88 image→icon, 40 elsewhere (space-40) */
}

.esg-feature {
  display: flex;
  align-items: center;        /* icon is vertically centered against the text block */
  gap: 64px;
}
/* Fixed-width column, not a fixed gap after the icon — the three icons are
   74/95/88px wide but the text column still starts at the same x in Figma,
   so the icon must be left-aligned inside a shared 95px (max-icon-width)
   slot rather than the gap absorbing the size difference. */
.esg-feature__icon-wrap { flex: 0 0 95px; }
/* Every curated icon in aec_feature_icons() is ≤96×88, so this cap is a no-op
   for them — width/height attributes still draw them at their exact size.
   It exists for a custom-uploaded icon, whose real dimensions are unknown at
   author time and could otherwise be anything: caps it to the slot instead of
   letting an oversized upload blow out the row. */
.esg-feature__icon-wrap img {
  display: block;
  max-width: 95px;
  max-height: 88px;
  width: auto;
  height: auto;
}

.esg-feature__title { margin: 0 0 24px; }
.esg-feature__desc { margin: 0; }

/* No tablet/mobile frame exists for this section — derived, same reasoning
   as featured-project: the overlay/side-by-side layout doesn't have room,
   so it stacks instead. */
@media (max-width: 1024px) {
  .esg-showcase { flex-direction: column; }
  .esg-showcase__media { flex: none; height: 280px; }
  .esg-showcase__features { padding: var(--space-40) var(--pad-x); }
}
@media (max-width: 768px) {
  .esg-feature { gap: 24px; }
}


/* ============================================================
   Reveal on scroll
   ============================================================ */
/* ==========================================================================
   Sections fade up once as they enter the viewport; see assets/js/aec-reveal.js.

   EVERY RULE HERE IS SCOPED UNDER .aec-reveal, and that class is added to
   <html> by the inline gate in inc/enqueue.php only when the animation is
   genuinely going to run. Without it nothing below matches and the page is
   simply visible — which is what no-JS, unsupported browsers,
   prefers-reduced-motion and tools/verify.sh's --force-prefers-reduced-motion
   captures all get. Do not lift the hidden state out of this scope: the global
   reduced-motion rule near the top of this file clamps transition-duration to
   .01ms but never resets opacity, so anything hidden outside the gate would
   stay hidden for good.
   ========================================================================== */
.aec-reveal [data-reveal] {
  opacity: 0;
  transform: translate3d(0, var(--reveal-shift), 0);
  transition:
    opacity var(--dur-reveal) var(--ease-reveal),
    transform var(--dur-reveal) var(--ease-reveal);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}

/* A section that holds a stagger group fades in place and lets its children
   do the rising — otherwise the two translates land on the same pixels and
   double the travel. Its children keep the default lift above, so a run of
   list items comes up from below one after another. */
.aec-reveal [data-reveal="parent"] { transform: none; }

.aec-reveal [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Belt and braces. The gate already means this can never match, but it keeps
   the resting state correct for anyone who reaches these rules another way. */
@media (prefers-reduced-motion: reduce) {
  .aec-reveal [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* --- SHM 08/09/2026 - BugSmash #10 e #44 (richiesta cliente) ---------------
   #10 "IT-EN: al passaggio del mouse scenda la tendina": la tendina si apre
   anche in hover/focus, oltre al click gia' gestito dal JS (che resta per il
   touch). Lo pseudo-elemento ::after copre i 5px di vuoto fra chip e pannello,
   altrimenti spostando il mouse verso EN la tendina si richiude.
   #44 "segnalare IT come selezionato (rosso)": il chip della lingua corrente
   e' rosso, in entrambe le varianti di header (anche sopra l'immagine). */
.lang-switch::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 8px;
}
.lang-switch:hover .lang-switch__menu,
.lang-switch:focus-within .lang-switch__menu { visibility: visible; opacity: 1; }

.lang-switch .lang-switch__toggle,
.site-header--over .lang-switch .lang-switch__toggle {
  color: var(--c-accent);
  border-color: var(--c-accent);
}

/* --- SHM 08/09/2026 - BugSmash #11 (richiesta cliente) ---------------------
   Blocco ESG: "allineare [l'icona] al testo bold di fianco, non alla casella
   ma al testo (alle O)". L'icona era centrata in verticale sull'intera voce
   (titolo + paragrafo); ora parte dall'alto e il suo bordo superiore coincide
   con l'occhio delle lettere del titolo, non con la scatola del testo: il
   margine e' meta' dell'interlinea in eccesso del titolo (22-17 = 5px / 2)
   piu' i ~2px fra il bordo del box e la cima delle tonde. */
.esg-feature { align-items: flex-start; }
.esg-feature__icon-wrap {
  margin-top: calc((var(--lh-body-sm-med) - var(--fs-body-sm-med)) / 2 + 2px);
}

/* --- SHM 08/09/2026 - BugSmash #9 (richiesta cliente) ----------------------
   "Quando full screen 16:9 l'header si deve comportare come da mock up Figma,
   allineato a margine". Sul frame Figma (1440) header e contenuto coincidono:
   80px di gutter. Su uno schermo 1920 il container resta centrato a 1280 e
   l'header, che ne condivideva la regola, si ritrovava con 320px di vuoto per
   lato. Ora l'header segue i margini dello schermo (solo il gutter --pad-x),
   il contenuto sotto resta centrato come prima. Fino a 1440 nulla cambia. */
@media (min-width: 1441px) {
  .site-header__inner { max-width: none; padding-inline: 80px; }
}

/* --- SHM 08/09/2026 - BugSmash #18 / #25 / #26 / #41 (richiesta cliente) ---
   "sistemare allineamento di questi tre testi... check su Figma" (SI, valori),
   "controllare allineamento (piu' a dx)" (SI, processo), "check allineamento
   testi" (SVI), "allineare correttamente questi testi, vedi Figma" (chi siamo).
   Fino a 1440px il fallback di .grid-split (1fr 1.52fr + 24px) portava la
   colonna testo a x=602 invece dei 732 del mockup (rail 413 + corpo 628,
   flush ai bordi del container da 1280, come nella regola base sopra i 1440).
   Qui le due tracce restano in proporzione al design a qualsiasi larghezza:
   32.27% / 49.06% con space-between (413/628 nel container da 1280).
   Sotto i 1024px resta la colonna singola del dev. */
@media (min-width: 1025px) and (max-width: 1440px) {
  .grid-split { grid-template-columns: 32.27% 49.06%; column-gap: 0; row-gap: var(--gap-2); justify-content: space-between; }
}

/* --- SHM 08/09/2026 - BugSmash #42 / #43 / #49 (richiesta cliente, mobile) --
   #42 "icona menu piu' grande": hamburger 22x16 con barre da 2px (era il 7x10
   del mockup), area tap sempre 44px. #43 "meno trasparenza": tendina bianca al
   97% invece del 90%. #49 "Servizi e Progetti devono essere cliccabili come per
   desktop": il link ora naviga e l'accordion si apre dal pulsante freccia
   .site-nav__more che site.js inserisce accanto al link (nascosto su desktop,
   dove resta l'hover del dev). */
.site-nav__more { display: none; }
@media (max-width: 1024px) {
  .nav-toggle { width: 22px; height: 16px; transform: none; } /* centrata sul logo, non piu' 5px sopra */
  .nav-toggle::before { inset: -14px -11px; }
  .nav-toggle span { height: 2px; }
  .site-nav { background: rgba(255, 255, 255, .97); }
  .site-nav__item--parent { display: flex; flex-wrap: wrap; align-items: center; }
  .site-nav__item--parent > .site-nav__link::after { display: none; }
  .site-nav__item--parent > .megabar { flex-basis: 100%; }
  .site-nav__more {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin: 0 0 0 -8px; padding: 0; border: 0;
    background: none; color: var(--c-accent); cursor: pointer;
  }
  .site-nav__more::before {
    content: ""; display: block; width: 7px; height: 7px;
    border-right: 1px solid currentColor; border-bottom: 1px solid currentColor;
    transform: translateY(-3px) rotate(45deg); transition: transform var(--dur) var(--ease);
  }
  .site-nav__item--parent.is-open > .site-nav__more::before { transform: translateY(1px) rotate(-135deg); }
}

/* --- SHM 08/09/2026 - BugSmash #50 (richiesta cliente, decisione Davide) ------
   "su mobile la toglierei": sotto i 768px la barra secondaria dei servizi
   (General Contractor / Soluzioni per Investitori / Sviluppo Immobiliare) e'
   nascosta: le tre voci sono gia' nel menu a tendina sotto "Servizi" e la barra
   toglieva spazio alla testata. La barra delle categorie progetti resta. */
@media (max-width: 768px) { .subnav--servizi { display: none; } }

/* --- SHM 16/09/2026 - BugSmash #11 / #61 (richiesta cliente) ----------------------
   "possiamo allineare a testo bold di fianco? non alla casella ma al testo (alle O)"
   e "abbassare di 3 px tutti i paragrafi di questo tipo": nei blocchi a due colonne
   con titolo grande a sinistra e testo a destra, il testo partiva dal bordo del box
   (stessa y del titolo) e la cima delle sue lettere risultava ~2.5px piu alta di
   quella del titolo (interlinea 45 su 40px contro 30 su 22px). Da 1025px in su il
   testo scende di 3px, cosi le maiuscole dei due blocchi sono allineate. Sotto i
   1024px le colonne sono impilate e non serve.
   ------------------------------------------------------------------------------- */
@media (min-width: 1025px) {
  .home-about__copy, .esg__copy, .si-process-intro__copy,
  .chi-siamo-intro__copy, .gc-intro__copy, .si-intro__copy, .svi-intro__copy { position: relative; top: 3px; }
}

/* --- SHM 16/09/2026 - BugSmash #60 (richiesta cliente, mobile e desktop) ----------
   "Allineare le icone al paragrafo come altezza e diminuire di un 20% la grandezza":
   nel blocco ESG della home l'icona ora parte dalla cima del paragrafo (non piu dal
   titolo) e misura l'80% dell'originale (74->59, 95->76, 88->70px). Fatto con una
   griglia a due righe (titolo / paragrafo) al posto del flex; supera la regola SHM
   del 08/09 qui sopra che allineava l'icona al titolo. Solo dentro .esg-showcase:
   lo stesso componente in Soluzioni per Investitori non e stato toccato.
   ------------------------------------------------------------------------------- */
.esg-showcase .esg-feature { display: grid; grid-template-columns: 95px minmax(0, 1fr); grid-template-rows: auto auto; column-gap: 64px; row-gap: 0; align-items: start; }
.esg-showcase .esg-feature__icon-wrap { grid-column: 1; grid-row: 2; margin-top: 0; }
.esg-showcase .esg-feature__icon-wrap img[width="74"] { width: 59px; }
.esg-showcase .esg-feature__icon-wrap img[width="95"] { width: 76px; }
.esg-showcase .esg-feature__icon-wrap img[width="88"] { width: 70px; }
.esg-showcase .esg-feature__text { display: contents; }
.esg-showcase .esg-feature__title { grid-column: 2; grid-row: 1; }
.esg-showcase .esg-feature__desc { grid-column: 2; grid-row: 2; }
@media (max-width: 768px) { .esg-showcase .esg-feature { column-gap: 24px; } }

/* --- SHM 24/09/2026 - Pagine legali (Privacy Policy / Cookie Policy): testi in blocchi core dentro .page-intro.
   Il tema azzera margini e puntini delle liste: qui ridiamo spaziatura e leggibilita'. --- */
.page-intro .container > .wp-block-heading { margin: 2.4em 0 .6em; max-width: 34em; }
.page-intro .container > h1.wp-block-heading { margin: 0 0 1.2em; }
.page-intro .container > h2.wp-block-heading + h3.wp-block-heading { margin-top: .9em; }
.page-intro .container > h4.wp-block-heading { margin-top: 1.6em; font-weight: 600; }
.page-intro .container > p { margin: 0 0 1em; max-width: 72ch; }
.page-intro .container > ul.wp-block-list { list-style: disc; padding-left: 1.4em; margin: 0 0 1.4em; max-width: 72ch; }
.page-intro .container > ul.wp-block-list li { margin-bottom: .55em; }
.page-intro .container > p a, .page-intro .container > ul a { text-decoration: underline; }
/* SHM 24/09/2026 - ancora al form Contatti (link "Candidatura spontanea" da Lavora con noi): compensa l'header fisso */
.wpcf7 { scroll-margin-top: 140px; }
/* --- SHM 24/09/2026 - Cursore personalizzato con il marchio Albini e Castelli (richiesta Bea 22/09).
   PNG 20px (+40px retina) in Media, ID 728/729 - era 32px, ridotto su richiesta Davide 24/09. --- */
html, body, a, button, [role="button"], .splide__arrow, .splide__pagination__page, label, summary {
  cursor: url("https://albini.shmhosting.com/wp-content/uploads/2026/09/aec-cursor-20.png") 1 1, auto;
  cursor: -webkit-image-set(url("https://albini.shmhosting.com/wp-content/uploads/2026/09/aec-cursor-20.png") 1x, url("https://albini.shmhosting.com/wp-content/uploads/2026/09/aec-cursor-40.png") 2x) 1 1, auto;
  cursor: image-set(url("https://albini.shmhosting.com/wp-content/uploads/2026/09/aec-cursor-20.png") 1x, url("https://albini.shmhosting.com/wp-content/uploads/2026/09/aec-cursor-40.png") 2x) 1 1, auto;
}
