/* ============================================
   MameTech - Layer effetti
   ============================================
   Caricato DOPO site.css: contiene solo il livello "visivo" aggiuntivo
   (header cinematografici, riflessi, riveli allo scroll) e non ridefinisce
   la struttura delle pagine. Si puo' togliere dall'AppAsset e il sito torna
   esattamente com'era prima, senza rompere nulla.

   Regole seguite ovunque:
   - si animano solo transform e opacity, cosi' il lavoro resta sulla GPU;
   - ogni effetto e' additivo: senza JS, o con prefers-reduced-motion,
     il contenuto e' comunque visibile e leggibile;
   - i colori arrivano dai token gia' esistenti, niente palette parallele.
   ============================================ */

:root {
    --fx-gold: 214, 158, 46;
    --fx-blue: 110, 168, 254;
    --fx-ease: cubic-bezier(0.22, 1, 0.36, 1);
}


/* ============================================
   1. Barra di avanzamento lettura
   ============================================
   Filo sottile in cima alla pagina che cresce con lo scroll. La scala arriva
   da una variabile aggiornata in JS: senza JS resta a zero e la barra e'
   semplicemente invisibile. */

.fx-progress {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 1035; /* sopra la navbar fixed-top di Bootstrap (1030) */
    width: 100%;
    height: 3px;
    pointer-events: none;
    background: transparent;
}

.fx-progress::after {
    content: "";
    display: block;
    height: 100%;
    width: 100%;
    transform: scaleX(var(--fx-scroll, 0));
    transform-origin: 0 50%;
    background: linear-gradient(90deg,
        var(--brand-navy) 0%,
        rgba(var(--fx-blue), 0.9) 35%,
        var(--accent-color) 75%,
        var(--accent-light) 100%);
    box-shadow: 0 0 12px rgba(var(--fx-gold), 0.55);
}

[data-bs-theme="dark"] .fx-progress::after {
    background: linear-gradient(90deg,
        rgba(var(--fx-blue), 0.85) 0%,
        var(--accent-color) 60%,
        var(--accent-light) 100%);
}


/* ============================================
   2. Page header cinematografico
   ============================================
   E' l'intervento con piu' resa: lo stesso blocco apre tutte le pagine
   interne, quindi basta questo per togliere l'effetto "pagina di servizio".
   Tre livelli sovrapposti: aurora in movimento (::before), griglia tecnica
   sfumata (::after) e filo dorato sul bordo inferiore (layer di background
   sull'elemento stesso). */

.page-header {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: clamp(3.5rem, 7vw, 6rem) 0 !important;
    background:
        /* filo dorato in basso: separa l'header dal contenuto */
        linear-gradient(90deg,
            transparent 0%,
            rgba(var(--fx-gold), 0.15) 15%,
            rgba(var(--fx-gold), 0.85) 50%,
            rgba(var(--fx-gold), 0.15) 85%,
            transparent 100%) bottom center / 100% 2px no-repeat,
        linear-gradient(135deg,
            var(--brand-navy-dark) 0%,
            var(--brand-navy) 45%,
            #22406e 100%);
}

/* In tema scuro site.css riscrive il fondo dell'header: lo riallineiamo qui,
   altrimenti perderebbe aurora e filo dorato. */
[data-bs-theme="dark"] .page-header {
    background:
        linear-gradient(90deg,
            transparent 0%,
            rgba(var(--fx-gold), 0.15) 15%,
            rgba(var(--fx-gold), 0.85) 50%,
            rgba(var(--fx-gold), 0.15) 85%,
            transparent 100%) bottom center / 100% 2px no-repeat,
        linear-gradient(135deg,
            #0e1c30 0%,
            var(--brand-navy-dark) 50%,
            #1d3557 100%);
}

.page-header::before {
    content: "";
    position: absolute;
    /* deborda: cosi' i bordi delle macchie non entrano mai in scena */
    inset: -45%;
    z-index: -2;
    pointer-events: none;
    background:
        radial-gradient(36% 40% at 20% 30%, rgba(var(--fx-gold), 0.30), transparent 62%),
        radial-gradient(32% 36% at 80% 22%, rgba(var(--fx-blue), 0.26), transparent 64%),
        radial-gradient(44% 48% at 62% 84%, rgba(255, 255, 255, 0.10), transparent 66%);
    animation: fxAurora 24s ease-in-out infinite alternate;
    will-change: transform;
}

.page-header::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image:
        linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
        linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
    background-size: 46px 46px;
    /* la griglia sfuma prima di arrivare al testo */
    -webkit-mask-image: radial-gradient(ellipse 75% 85% at 50% 0%, #000 5%, transparent 75%);
    mask-image: radial-gradient(ellipse 75% 85% at 50% 0%, #000 5%, transparent 75%);
}

@keyframes fxAurora {
    0%   { transform: translate3d(-3%, -2%, 0) scale(1); }
    50%  { transform: translate3d(3%, 2%, 0) scale(1.14); }
    100% { transform: translate3d(-2%, 3%, 0) scale(1.05); }
}

.page-header .container {
    position: relative;
    z-index: 1;
}

/* Occhiello in cima all'header: pillola di vetro con puntino dorato, stesso
   ruolo di .hero-eyebrow in home. Lo spazio sotto lo mette il <p> che lo
   avvolge, che e' anche l'elemento che l'animazione d'ingresso muove. */
.page-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 1rem;
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    color: rgba(255, 255, 255, 0.92);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    line-height: 1.4;
}

.page-eyebrow::before {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent-light);
    box-shadow: 0 0 0 0 rgba(var(--fx-gold), 0.7);
    animation: fxPulse 2.4s ease-out infinite;
}

@keyframes fxPulse {
    0%   { box-shadow: 0 0 0 0 rgba(var(--fx-gold), 0.7); }
    70%  { box-shadow: 0 0 0 9px rgba(var(--fx-gold), 0); }
    100% { box-shadow: 0 0 0 0 rgba(var(--fx-gold), 0); }
}

/* Parola evidenziata nel titolo dell'header */
.page-header .fx-accent {
    background: linear-gradient(120deg, var(--accent-light) 0%, var(--accent-color) 45%, var(--accent-light) 100%);
    background-size: 220% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: var(--accent-light); /* ripiego se background-clip non e' supportato */
    animation: fxShine 6s linear infinite;
}

@keyframes fxShine {
    0%   { background-position: 0% 50%; }
    100% { background-position: 220% 50%; }
}

/* Riga di riscontri sotto il sommario dell'header */
.page-header-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    justify-content: flex-start;
    margin: 1.25rem 0 0;
    padding: 0;
    list-style: none;
    color: rgba(255, 255, 255, 0.78);
    font-size: 0.9rem;
}

.page-header-meta li {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
}

.page-header-meta i {
    color: var(--accent-light);
}

/* Quasi tutti gli header sono centrati; la scheda progetto e' allineata a
   sinistra e resta tale. */
.page-header .text-center .page-header-meta {
    justify-content: center;
}


/* ============================================
   2-bis. Sezione CTA: stessa aurora dell'header
   ============================================
   Il blocco "Pronto a iniziare?" chiude quasi tutte le pagine interne. La
   griglia c'e' gia' (site.css usa ::before): qui si aggiunge solo l'aurora su
   ::after, ancora libero. */

.cta-section {
    isolation: isolate;
}

.cta-section::after {
    content: "";
    position: absolute;
    inset: -40%;
    z-index: -1;
    pointer-events: none;
    background:
        radial-gradient(34% 40% at 78% 26%, rgba(var(--fx-gold), 0.26), transparent 62%),
        radial-gradient(30% 34% at 18% 74%, rgba(var(--fx-blue), 0.22), transparent 64%);
    animation: fxAurora 26s ease-in-out infinite alternate-reverse;
    will-change: transform;
}

/* Il testo va portato sopra i due livelli decorativi. */
.cta-section > .container {
    position: relative;
    z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
    .cta-section::after {
        animation: none;
    }
}


/* ============================================
   3. Riflesso che segue il cursore sulle card
   ============================================
   Il JS aggiunge uno <span class="fx-glow"> come primo figlio e aggiorna
   --fx-x / --fx-y con la posizione del puntatore. Lo span sta a z-index -1
   dentro un contesto di impilamento isolato: resta sopra lo sfondo della
   card ma sotto il testo, quindi non tocca mai la leggibilita'. */

.fx-spotlight {
    position: relative;
    isolation: isolate;
}

.fx-glow {
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.35s ease;
    background: radial-gradient(
        260px circle at var(--fx-x, 50%) var(--fx-y, 0%),
        rgba(var(--fx-gold), 0.20),
        rgba(var(--fx-gold), 0.06) 40%,
        transparent 68%);
}

.fx-spotlight:hover > .fx-glow,
.fx-spotlight:focus-within > .fx-glow {
    opacity: 1;
}

[data-bs-theme="dark"] .fx-glow {
    background: radial-gradient(
        260px circle at var(--fx-x, 50%) var(--fx-y, 0%),
        rgba(var(--fx-gold), 0.26),
        rgba(var(--fx-blue), 0.10) 42%,
        transparent 70%);
}


/* ============================================
   4. Riveli allo scroll con direzione
   ============================================
   .animate-on-scroll resta com'e' (salita verticale). Qui si aggiungono le
   varianti, scelte in pagina con data-fx. Valgono solo sotto .js-anim, quindi
   senza JavaScript il contenuto non sparisce mai. */

.js-anim .animate-on-scroll[data-fx] {
    transition-duration: 0.75s;
    transition-timing-function: var(--fx-ease);
}

.js-anim .animate-on-scroll[data-fx="left"]  { transform: translate3d(-40px, 0, 0); }
.js-anim .animate-on-scroll[data-fx="right"] { transform: translate3d(40px, 0, 0); }
.js-anim .animate-on-scroll[data-fx="zoom"]  { transform: scale(0.92); }
.js-anim .animate-on-scroll[data-fx="rise"]  { transform: translate3d(0, 46px, 0) scale(0.97); }

.js-anim .animate-on-scroll[data-fx="blur"] {
    transform: translate3d(0, 18px, 0);
    filter: blur(8px);
    transition-property: opacity, transform, filter;
}

.js-anim .animate-on-scroll[data-fx].animate-in {
    transform: none;
    filter: none;
}


/* ============================================
   5. Titoli di sezione con sottolineatura animata
   ============================================
   Da usare insieme ad .animate-on-scroll: la barretta si disegna quando il
   titolo entra in viewport. Senza JS non c'e' .js-anim e la barretta e' gia'
   al suo posto. */

.fx-underline {
    position: relative;
    padding-bottom: 0.85rem;
}

.fx-underline::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 0;
    width: 72px;
    height: 4px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--primary-color), var(--accent-color));
    transform: scaleX(1);
    transform-origin: 0 50%;
    transition: transform 0.8s var(--fx-ease) 0.15s;
}

.fx-underline.text-center::after {
    left: 50%;
    margin-left: -36px;
}

.js-anim .fx-underline.animate-on-scroll::after {
    transform: scaleX(0);
}

.js-anim .fx-underline.animate-on-scroll.animate-in::after {
    transform: scaleX(1);
}


/* ============================================
   6. Riflesso sui bottoni pieni
   ============================================
   Stessa lama di luce gia' usata da .btn-hero-primary in home, estesa ai
   bottoni delle pagine interne. */

.btn-primary,
.btn-dark,
.btn-light,
.btn-service-cta {
    position: relative;
    overflow: hidden;
    z-index: 1;
}

.btn-primary::after,
.btn-dark::after,
.btn-light::after,
.btn-service-cta::after {
    content: "";
    position: absolute;
    top: 0;
    left: -120%;
    z-index: -1;
    width: 60%;
    height: 100%;
    transform: skewX(-20deg);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.35), transparent);
    transition: left 0.6s ease;
}

.btn-light::after {
    background: linear-gradient(90deg, transparent, rgba(var(--fx-gold), 0.35), transparent);
}

.btn-primary:hover::after,
.btn-dark:hover::after,
.btn-light:hover::after,
.btn-service-cta:hover::after {
    left: 140%;
}


/* ============================================
   7. Portfolio: anteprime piu' vive
   ============================================ */

.portfolio-image-wrapper {
    position: relative;
}

/* Lama di luce che attraversa l'anteprima al passaggio del mouse */
.portfolio-image-wrapper::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.38) 50%, transparent 62%);
    transform: translateX(-130%);
    transition: transform 0.8s var(--fx-ease);
}

.portfolio-card:hover .portfolio-image-wrapper::before {
    transform: translateX(130%);
}

/* Pastiglia con freccia in alto a destra. La freccia e' un SVG inline: non
   dipende da Font Awesome, che si carica in modo non bloccante e potrebbe
   non essere ancora arrivato. */
.portfolio-image-wrapper::after {
    content: "";
    position: absolute;
    top: 12px;
    right: 12px;
    z-index: 3;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background-color: var(--brand-navy);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='7' y1='17' x2='17' y2='7'/%3E%3Cpolyline points='7 7 17 7 17 17'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 16px 16px;
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
    opacity: 0;
    transform: translateY(-8px) scale(0.7);
    transition: opacity 0.35s var(--fx-ease), transform 0.35s var(--fx-ease);
    pointer-events: none;
}

.portfolio-card:hover .portfolio-image-wrapper::after {
    opacity: 1;
    transform: none;
}

.portfolio-card:hover .portfolio-image {
    transform: scale(1.08);
}

.portfolio-card {
    transition: transform 0.45s var(--fx-ease), box-shadow 0.45s ease, border-color 0.45s ease;
}

.portfolio-card:hover {
    transform: translateY(-10px);
    box-shadow: 0 22px 45px -18px rgba(var(--bs-primary-rgb), 0.45), var(--shadow-lg);
}


/* ============================================
   8. Ingresso di pagina
   ============================================
   Dissolvenza breve del contenuto principale: rende il passaggio da una
   pagina all'altra meno secco. Solo opacita', nessuno spostamento, cosi' non
   interferisce con le animazioni dell'header. */

.js-anim main {
    /* backwards e non both: serve solo lo stato iniziale (invisibile) prima
       che l'animazione parta. Con both l'animazione continua ad applicarsi
       anche a fine corsa, e un'animazione che riempie tiene vivo il contesto
       di impilamento di <main>: i toast, che stavano dentro, finivano sotto
       la navbar fissa nonostante uno z-index altissimo. */
    animation: fxPageEnter 0.5s ease-out backwards;
}

@keyframes fxPageEnter {
    from { opacity: 0; }
    to   { opacity: 1; }
}


/* ============================================
   9. Trama decorativa per le sezioni chiare
   ============================================
   Utility opzionale: puntini appena percettibili dietro una sezione, per
   spezzare i blocchi di fondo pieno. */

.fx-dotted {
    position: relative;
    isolation: isolate;
}

.fx-dotted::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image: radial-gradient(circle at center, rgba(var(--bs-primary-rgb), 0.14) 1px, transparent 1px);
    background-size: 26px 26px;
    -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 0%, transparent 72%);
    mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 0%, transparent 72%);
}


/* ============================================
   10. Rispetto delle preferenze di movimento
   ============================================
   Chi ha chiesto meno animazioni al sistema operativo vede lo stesso layout,
   senza nulla che si muova da solo. */

@media (prefers-reduced-motion: reduce) {
    .page-header::before,
    .page-eyebrow::before,
    .page-header .fx-accent {
        animation: none !important;
    }

    .js-anim main {
        animation: none;
    }

    .fx-glow,
    .portfolio-image-wrapper::before,
    .portfolio-image-wrapper::after,
    .btn-primary::after,
    .btn-dark::after,
    .btn-light::after,
    .btn-service-cta::after {
        display: none;
    }

    .js-anim .fx-underline.animate-on-scroll::after,
    .js-anim .fx-underline.animate-on-scroll.animate-in::after {
        transform: scaleX(1);
        transition: none;
    }

    .js-anim .animate-on-scroll[data-fx],
    .js-anim .animate-on-scroll[data-fx="blur"] {
        transition-duration: 0.01ms;
        filter: none;
    }
}

/* Su schermi tattili il riflesso che segue il cursore non ha senso e i :hover
   restano "appiccicati" dopo il tocco. */
@media (hover: none) {
    .fx-glow {
        display: none;
    }
}


/* ============================================
   11. Copertine generate degli articoli
   ============================================
   Il widget ArticleCover stampa un SVG con viewBox fisso e
   preserveAspectRatio="slice": riempie il contenitore ritagliando, come farebbe
   object-fit: cover su una foto. Qui si definisce solo il contenitore. */

.article-cover {
    position: relative;
    overflow: hidden;
    width: 100%;
    height: 100%;
    min-height: 200px;
    background: var(--brand-navy-dark); /* copre il tempo fra layout e paint dell'SVG */
}

.article-cover-svg {
    display: block;
    width: 100%;
    height: 100%;
    transition: transform 0.6s var(--fx-ease);
}

.blog-post-card:hover .article-cover-svg,
.correlato-card:hover .article-cover-svg {
    transform: scale(1.06);
}

/* Velo dorato al passaggio del mouse: lega la copertina al resto del sito
   senza dover rigenerare l'SVG. */
.article-cover::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    background: linear-gradient(135deg, rgba(var(--fx-gold), 0.30), transparent 65%);
    transition: opacity 0.4s ease;
}

.blog-post-card:hover .article-cover::after,
.correlato-card:hover .article-cover::after {
    opacity: 1;
}


/* ============================================
   12. Articoli correlati a fine lettura
   ============================================ */

.articoli-correlati {
    background: var(--bg-light);
    border-top: 1px solid var(--border-color);
}

.correlato-card {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--bg-white);
    box-shadow: var(--shadow-sm);
    transition: transform 0.4s var(--fx-ease), box-shadow 0.4s ease, border-color 0.4s ease;
}

.correlato-card:hover {
    transform: translateY(-6px);
    border-color: var(--primary-color);
    box-shadow: var(--shadow-lg);
}

.correlato-media {
    display: block;
    height: 150px;
    flex: 0 0 auto;
}

.correlato-media .article-cover {
    min-height: 150px;
}

.correlato-body {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    /* Spinge la data in fondo: con titoli di lunghezza diversa le tre card
       restano allineate sull'ultima riga. */
    flex: 1 1 auto;
    padding: 1.1rem 1.25rem 1.25rem;
}

.correlato-title {
    margin: 0;
    font-size: 1.05rem;
    line-height: 1.45;
    font-weight: 700;
}

.correlato-title a {
    color: var(--text-dark);
    text-decoration: none;
    transition: color 0.25s ease;
}

.correlato-title a:hover {
    color: var(--primary-color);
}

.correlato-meta {
    margin: auto 0 0;
    color: var(--text-light);
    font-size: 0.85rem;
}

.correlato-body .blog-category {
    align-self: flex-start;
}


/* ============================================
   13. Trama animata dell'hero
   ============================================
   Il canvas riempie l'hero e sta sotto a tutto il resto. L'hero ha gia' due
   pseudo-elementi decorativi (i due aloni radiali di site.css) e un contenitore
   a z-index 1: qui basta restare al livello zero per finire fra lo sfondo e il
   testo, senza toccare nulla di quello che c'era. */

.hero-canvas {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: 100%;
    height: 100%;
    display: block;
    pointer-events: none;
    /* Il JS puo' decidere di non partire (moto ridotto, canvas assente): in quel
       caso l'elemento resta trasparente e non si nota. */
    opacity: 0.9;
}

@media (prefers-reduced-motion: reduce) {
    .hero-canvas {
        display: none;
    }
}


/* ============================================
   14. Marchio: nome piu' mestiere
   ============================================
   Il nome resta grande, sotto compare il mestiere in maiuscoletto spaziato.
   L'altezza della navbar cambia, ma il margine di <main> la misura a runtime
   (--navbar-height in app.js), quindi non serve toccare nient'altro. */

.custom-navbar .navbar-brand {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.15rem;
    line-height: 1.05;
}

.custom-navbar .navbar-brand .brand-name {
    font-size: 1.4rem;
    font-weight: 800;
    letter-spacing: -0.5px;
}

.custom-navbar .navbar-brand .brand-role {
    color: var(--text-light);
    font-size: 0.5rem;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    transition: color 0.3s ease;
}

.custom-navbar .navbar-brand:hover .brand-role {
    color: var(--accent-color);
}

/* Sotto i 360px la riga del mestiere manderebbe a capo il nome */
@media (max-width: 359px) {
    .custom-navbar .navbar-brand .brand-role {
        display: none;
    }
}


/* ============================================
   15. Glifo del menu su mobile
   ============================================
   Sostituisce navbar-toggler-icon di Bootstrap: due parentesi angolari, come
   nel logo, che racchiudono tre barre. Aprendo il menu le barre diventano una
   croce e le parentesi si allargano.

   Lo stato lo detta Bootstrap con aria-expanded sul bottone: nessun JS nostro. */

.custom-navbar .navbar-toggler {
    padding: 0.3rem 0.45rem;
    border-color: var(--border-color);
    border-radius: var(--radius-sm);
}

/* display va toccato solo sotto il breakpoint: sopra e' Bootstrap a nascondere
   il bottone con .navbar-expand-lg .navbar-toggler { display: none }, e una
   regola nostra senza media query lo rimetterebbe in scena sul desktop. */
@media (max-width: 991.98px) {
    .custom-navbar .navbar-toggler {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}

.custom-navbar .navbar-toggler:focus {
    box-shadow: 0 0 0 3px rgba(var(--fx-gold), 0.35);
}

.brand-toggler {
    width: 28px;
    height: 28px;
    display: block;
    overflow: visible;
    fill: none;
    stroke: var(--primary-color);
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.brand-toggler-chevron,
.brand-toggler-bar {
    /* Le trasformazioni ruotano attorno al centro del disegno, non all'origine
       del sistema di coordinate SVG, che sta in alto a sinistra. */
    transform-origin: 12px 12px;
    transition: transform 0.35s var(--fx-ease), opacity 0.25s ease;
}

.custom-navbar .navbar-toggler[aria-expanded="true"] .brand-toggler-chevron {
    transform: scaleX(1.18);
}

.custom-navbar .navbar-toggler[aria-expanded="true"] .brand-toggler-bar-1 {
    transform: translateY(2.5px) rotate(45deg);
}

.custom-navbar .navbar-toggler[aria-expanded="true"] .brand-toggler-bar-2 {
    opacity: 0;
}

.custom-navbar .navbar-toggler[aria-expanded="true"] .brand-toggler-bar-3 {
    transform: translateY(-2.5px) rotate(-45deg);
}

[data-bs-theme="dark"] .brand-toggler {
    stroke: var(--primary-color);
}

@media (prefers-reduced-motion: reduce) {
    .brand-toggler-chevron,
    .brand-toggler-bar {
        transition: none;
    }
}


/* ============================================
   16. Note legali nel footer
   ============================================ */

.footer-legal {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1.5rem;
    font-size: 0.8rem;
}

.footer-legal a {
    color: rgba(255, 255, 255, 0.6);
    text-decoration: none;
    transition: color 0.25s ease;
}

.footer-legal a:hover,
.footer-legal a:focus-visible {
    color: var(--accent-light);
    text-decoration: underline;
}


/* ============================================
   17. Selettore di lingua
   ============================================
   Due sigle affiancate invece di un menu a tendina: le lingue sono due, e un
   menu costerebbe un clic in piu' per dire la stessa cosa. Le bandierine no,
   di proposito: una bandiera indica un paese, non una lingua, e l'inglese qui
   serve a chi scrive dall'Olanda quanto a chi scrive da Londra. */

.lang-switch {
    display: inline-flex;
    align-items: center;
    margin-left: 0.75rem;
    padding: 2px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: transparent;
}

.lang-switch-opt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    padding: 0.2rem 0.5rem;
    border-radius: 999px;
    color: var(--text-light);
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-decoration: none;
    transition: color 0.25s ease, background-color 0.25s ease;
}

.lang-switch-opt:hover {
    color: var(--accent-color);
}

.lang-switch-opt.is-active {
    background: var(--primary-color);
    color: #fff;
}

[data-bs-theme="dark"] .lang-switch-opt.is-active {
    background: var(--primary-color);
    color: #0d1117;
}

.lang-switch-opt:focus-visible {
    outline: 2px solid var(--accent-color);
    outline-offset: 2px;
}

/* Nel menu a scomparsa il selettore sta su una riga sua, allineato al resto */
@media (max-width: 991.98px) {
    .lang-switch {
        margin: 0.5rem 0 0;
    }
}


/* ============================================
   18. Carattere da display
   ============================================
   Space Grotesk per i titoli, Inter resta per il testo. E' la stessa coppia che
   usa il sito preso a riferimento, e funziona per il motivo per cui funziona
   li': un grottesco geometrico con dettagli spigolosi accanto a un neo-grottesco
   neutro. Il primo da' carattere dove si guarda, il secondo resta invisibile
   dove si legge.

   Arriva dalla stessa richiesta a Google Fonts di Inter: una famiglia in piu'
   nella stessa URL, non una seconda richiesta di rete.

   Non si applica al testo corrente di proposito: Space Grotesk ha una x-height
   generosa e un disegno marcato, che su un paragrafo lungo stanca. */

:root {
    --font-display: 'Space Grotesk', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

h1, h2, h3, h4, h5, h6,
.display-1, .display-2, .display-3, .display-4, .display-5, .display-6,
.hero-title,
.custom-navbar .navbar-brand .brand-name,
.counter-value,
.about-stat-number,
.stat-number,
.pricing-teaser-amount {
    font-family: var(--font-display);
}

/* Le etichette in maiuscoletto spaziato: e' li' che il carattere si riconosce,
   perche' le lettere restano isolate e si vede il disegno di ognuna. */
.page-eyebrow,
.section-eyebrow,
.hero-eyebrow,
.custom-navbar .navbar-brand .brand-role,
.tech-group-title {
    font-family: var(--font-display);
}

/* Space Grotesk e' piu' largo di Inter: senza questa correzione i titoli
   grandi crescono di qualche punto percentuale e mandano a capo righe che
   prima stavano su una sola. */
.hero-title,
.display-4,
.display-5 {
    letter-spacing: -0.035em;
}


/* ============================================
   19. Ricerca nel blog
   ============================================
   Un campo solo, con la lente dentro invece che accanto: nella colonna stretta
   della sidebar un pulsante affiancato lascerebbe al testo lo spazio di quattro
   parole. Il bordo si accende sul focus perche' la ricerca e' l'unico punto
   della pagina in cui si scrive, e deve essere ovvio dove.
   ============================================ */

.blog-search {
    position: relative;
    display: flex;
    align-items: center;
}

.blog-search input[type="search"] {
    width: 100%;
    padding: 0.6rem 2.6rem 0.6rem 0.9rem;
    font-size: 0.9rem;
    color: var(--text-dark);
    background: var(--bg-light);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    transition: border-color 0.25s ease, box-shadow 0.25s ease, background 0.25s ease;
}

.blog-search input[type="search"]::placeholder {
    color: var(--text-light);
}

.blog-search input[type="search"]:focus {
    outline: none;
    background: var(--bg-white);
    border-color: var(--accent-color);
    box-shadow: 0 0 0 3px rgba(214, 158, 46, 0.18);
}

/* La crocetta di serie di Chrome ha un grigio suo che non c'entra con la
   palette, ma toglierla priverebbe chi usa il mouse dell'unico modo rapido di
   svuotare il campo: si lascia, smorzata. */
.blog-search input[type="search"]::-webkit-search-cancel-button {
    opacity: 0.45;
    cursor: pointer;
}

.blog-search button {
    position: absolute;
    right: 0.35rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    padding: 0;
    color: var(--text-light);
    background: transparent;
    border: none;
    border-radius: 50%;
    cursor: pointer;
    transition: color 0.25s ease, background 0.25s ease;
}

.blog-search button:hover,
.blog-search button:focus-visible {
    color: var(--primary-color);
    background: var(--primary-light);
}

.blog-search-reset {
    display: inline-block;
    margin-top: 0.7rem;
    font-size: 0.8rem;
    color: var(--text-light);
    text-decoration: none;
    transition: color 0.25s ease;
}

.blog-search-reset:hover,
.blog-search-reset:focus-visible {
    color: var(--primary-color);
}

/* Il termine trovato dentro i risultati. Il giallo di serie del browser e' una
   pennellata da evidenziatore su una pagina che non ne ha altre: qui e' un
   fondo appena accennato nel gold del sito, con il testo che resta leggibile. */
.blog-posts mark {
    padding: 0.05em 0.15em;
    color: inherit;
    background: var(--accent-bg);
    border-bottom: 2px solid var(--accent-light);
    border-radius: 3px;
}

/* Ricerca senza risultati: non un vicolo cieco ma un bivio. */
.blog-vuoto {
    padding: 3rem 2rem;
    margin-bottom: 2rem;
    text-align: center;
    background: var(--bg-white);
    border: 1px dashed var(--border-color);
    border-radius: var(--radius-lg);
}

.blog-vuoto > i {
    font-size: 2rem;
    color: var(--border-color);
}

.blog-vuoto h2 {
    margin: 1rem 0 0.75rem;
    font-size: 1.3rem;
    font-weight: 600;
    font-family: var(--font-display);
    color: var(--text-dark);
}

.blog-vuoto p {
    margin-bottom: 0;
    color: var(--text-medium);
}

.blog-vuoto-suggerimenti {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
    margin-top: 1.25rem !important;
}

.blog-vuoto-suggerimenti a {
    padding: 0.35rem 0.9rem;
    font-size: 0.85rem;
    color: var(--primary-color);
    text-decoration: none;
    background: var(--primary-light);
    border-radius: 999px;
    transition: color 0.25s ease, background 0.25s ease;
}

.blog-vuoto-suggerimenti a:hover,
.blog-vuoto-suggerimenti a:focus-visible {
    color: #fff;
    background: var(--primary-color);
}

[data-bs-theme="dark"] .blog-search input[type="search"] {
    color: #e2e8f0;
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.12);
}

[data-bs-theme="dark"] .blog-search input[type="search"]:focus {
    background: rgba(255, 255, 255, 0.07);
    border-color: var(--accent-color);
}

[data-bs-theme="dark"] .blog-search button:hover,
[data-bs-theme="dark"] .blog-search button:focus-visible {
    color: var(--accent-light);
    background: rgba(255, 255, 255, 0.08);
}

/* Al buio il fondo chiaro dell'evidenziazione accecherebbe: si rovescia in un
   velo dorato sul fondo scuro, stessa funzione e stesso colore. */
[data-bs-theme="dark"] .blog-posts mark {
    color: #f7fafc;
    background: rgba(214, 158, 46, 0.25);
    border-bottom-color: rgba(236, 201, 75, 0.7);
}

[data-bs-theme="dark"] .blog-vuoto {
    background: rgba(255, 255, 255, 0.03);
    border-color: rgba(255, 255, 255, 0.12);
}

[data-bs-theme="dark"] .blog-vuoto h2 {
    color: #f7fafc;
}

[data-bs-theme="dark"] .blog-vuoto-suggerimenti a {
    color: var(--accent-light);
    background: rgba(214, 158, 46, 0.15);
}

[data-bs-theme="dark"] .blog-vuoto-suggerimenti a:hover,
[data-bs-theme="dark"] .blog-vuoto-suggerimenti a:focus-visible {
    color: #1a202c;
    background: var(--accent-light);
}


/* ============================================
   20. Progetti correlati a fine scheda
   ============================================
   Riusa la scheda degli articoli correlati: stessa forma, stesso sollevamento
   al passaggio del mouse. Cambia solo il riquadro dell'immagine, perche' qui
   non c'e' una copertina che riempie lo spazio ma un marchio, che va lasciato
   respirare sul fondo scelto per lui e mai deformato.
   ============================================ */

.progetti-correlati {
    background: var(--bg-light);
    border-top: 1px solid var(--border-color);
}

.correlato-logo {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.25rem;
    border-bottom: 1px solid var(--border-color);
}

.correlato-logo img {
    max-width: 100%;
    max-height: 100%;
    /* contain e non cover: un logo tagliato per riempire il riquadro non e'
       piu' quel logo, ed e' il marchio di un cliente. */
    object-fit: contain;
}

.correlato-testo {
    margin: 0;
    color: var(--text-medium);
    font-size: 0.9rem;
    line-height: 1.6;
}

[data-bs-theme="dark"] .progetti-correlati {
    background: transparent;
    border-top-color: rgba(255, 255, 255, 0.1);
}

[data-bs-theme="dark"] .correlato-logo {
    border-bottom-color: rgba(255, 255, 255, 0.1);
}


/* ============================================
   21. Respiro nelle intestazioni
   ============================================ */

/* Il pulsante non deve toccare la riga che lo precede.
   site.css azzera il margine di .hero-buttons per l'hero della home, dove lo
   spazio arriva da altro: qui dentro serve invece uno stacco netto, perche'
   sopra ci sono i dati commerciali e sotto c'e' l'invito ad agire — due cose
   che il lettore deve poter separare senza sforzo. */
.page-header .hero-buttons {
    margin-top: 2rem;
}

/* La riga di sommario correva per tutta la larghezza del contenitore: oltre i
   novanta caratteri l'occhio fatica a ritrovare l'inizio della riga dopo, e su
   schermo largo le due frasi si spezzavano lasciando una parola orfana in
   fondo. Con la misura limitata vanno a capo dove ha senso.
   Solo nelle intestazioni centrate: sulle schede progetto il testo e'
   allineato a sinistra e centrare il blocco lo scollerebbe dal titolo. */
.page-header .text-center .lead {
    max-width: 46rem;
    margin-inline: auto;
}

/* Righe di lunghezza pari invece di una riga piena e una con due parole.
   I browser che non conoscono la proprieta' la ignorano e vanno a capo come
   hanno sempre fatto: e' rifinitura, non struttura. */
.page-header h1,
.page-header .text-center .lead {
    text-wrap: balance;
}

/* I sottotitoli dentro il racconto del progetto separano tre blocchi di
   ragionamento: hanno bisogno di piu' aria sopra che sotto, o il lettore
   li legge come la prima riga del paragrafo precedente invece che come
   l'inizio del successivo. */
.project-body h3 {
    margin-top: 2.25rem;
    margin-bottom: 0.75rem;
    font-size: 1.35rem;
}

.project-body > :first-child {
    margin-top: 0;
}
