44.6471° N, 10.9252° E059 391132

Studio R.B.

WordPress Handoff — Design & Dev Documentation

01 — Overview del Progetto

SitoStudio R.B. — Studio di ingegneria impiantistica
Framework origineReact 18 + Vite + Tailwind CSS 3
RouterReact Router DOM v6
AnimazioniFramer Motion v11
IconeLucide React v0.475
Target WPWordPress + tema custom (FSE o classico)
LinguaItaliano
ViewportMobile-first, breakpoint lg: 1024px

Struttura delle pagine

/

Home

/studio

Studio

/servizi

Servizi

/settori

Settori

/metodo

Metodo

/team

Team

/contatti

Contatti

02 — Design Tokens (Colori)

Tutti i colori usano variabili CSS HSL. Aggiungili nel :root del tema WordPress.

CSS Variables — :root (Light Mode)

css
:root {
  --background: 0 0% 99.2%;        /* #FDFDFD — sfondo pagina */
  --foreground: 0 0% 10.2%;        /* #1A1A1A — testo principale */
  --card: 0 0% 100%;               /* #FFFFFF — sfondo card */
  --card-foreground: 0 0% 10.2%;   /* #1A1A1A */
  --primary: 200 100% 18%;         /* #005C7A — blu petrolio (brand) */
  --primary-foreground: 0 0% 99.2%;/* #FDFDFD */
  --secondary: 240 5% 96%;         /* #F4F4F6 — sfondo secondario */
  --secondary-foreground: 0 0% 10.2%;
  --muted: 240 5% 96%;             /* #F4F4F6 */
  --muted-foreground: 0 0% 45%;    /* #737373 — testo secondario */
  --accent: 200 100% 18%;          /* = primary */
  --accent-foreground: 0 0% 99.2%;
  --border: 214 20% 90%;           /* #DDE3EC — bordi */
  --input: 214 20% 90%;
  --ring: 200 100% 18%;
  --radius: 0.25rem;               /* Border radius base = 4px */
}

Primary (Brand)

#005C7A — hsl(200,100%,18%)

Background

#FDFDFD — hsl(0,0%,99.2%)

Foreground / Text

#1A1A1A — hsl(0,0%,10.2%)

Secondary / Muted bg

#F4F4F6 — hsl(240,5%,96%)

Muted Foreground

#737373 — hsl(0,0%,45%)

Border

#DDE3EC — hsl(214,20%,90%)

Utilizzo Tailwind

html
<!-- Colore brand su testo -->
<p class="text-primary">Testo brand</p>

<!-- Sfondo secondario -->
<section class="bg-secondary">...</section>

<!-- Bordo -->
<div class="border border-border">...</div>

<!-- In WordPress puro (senza Tailwind): usa le variabili CSS -->
<style>
  .brand-text { color: hsl(var(--primary)); }
  .bg-secondary { background: hsl(var(--secondary)); }
</style>

03 — Tipografia

Google Fonts — da inserire nel <head>

html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">

Space Grotesk

Heading / Titoli

Variabile: --font-heading

Pesi: 300 400 500 600 700

Classe Tailwind: font-heading

Inter

Body / Corpo testo

Variabile: --font-body

Pesi: 300 400 500 600 700

Classe Tailwind: font-body

JetBrains Mono

Mono / Label tecnici

Variabile: --font-mono

Pesi: 400 500

Classe Tailwind: font-mono

CSS Variables font + regola base

css
:root {
  --font-heading: 'Space Grotesk', sans-serif;
  --font-body: 'Inter', sans-serif;
  --font-mono: 'JetBrains Mono', monospace;
}

body {
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
}

Scala tipografica usata nel sito

css
/* Hero H1 */
font-size: clamp(2.5rem, 6vw, 4.5rem); /* text-4xl → text-7xl */
font-weight: 700;
line-height: 1.05;
letter-spacing: -0.02em;

/* Page H1 */
font-size: clamp(2.25rem, 4vw, 3.75rem); /* text-4xl → text-6xl */
font-weight: 700;
line-height: 1.1;

/* Section H2 */
font-size: clamp(1.875rem, 3vw, 2.5rem); /* text-3xl → text-4xl */
font-weight: 700;

/* Card H3 */
font-size: 1.25rem; /* text-xl */
font-weight: 700;

/* Body large */
font-size: 1.125rem; /* text-lg */
line-height: 1.75;

/* Body base */
font-size: 1rem;
line-height: 1.75;
color: hsl(var(--muted-foreground));

/* Label tecnico (SectionLabel) */
font-family: var(--font-mono);
font-size: 0.75rem; /* text-xs */
text-transform: uppercase;
letter-spacing: 0.25em;
color: hsl(var(--primary));

/* Numero decorativo (01, 02...) */
font-family: var(--font-mono);
font-size: 0.75rem;
color: hsl(var(--muted-foreground));

04 — Spacing & Layout

Container principale

css
/* Tutti i contenuti usano questo wrapper */
.container {
  max-width: 80rem; /* max-w-7xl = 1280px */
  margin-left: auto;
  margin-right: auto;
  padding-left: 1.5rem;   /* px-6 mobile */
  padding-right: 1.5rem;
}

@media (min-width: 1024px) { /* lg */
  .container {
    padding-left: 2rem;   /* px-8 desktop */
    padding-right: 2rem;
  }
}

Padding verticale sezioni

css
/* Sezione standard */
.section { padding-top: 6rem; padding-bottom: 6rem; }        /* py-24 */

/* Sezione grande */
.section-lg { padding-top: 6rem; padding-bottom: 6rem; }
@media (min-width: 1024px) {
  .section-lg { padding-top: 10rem; padding-bottom: 10rem; } /* lg:py-40 */
}

/* Page header (primo blocco sotto navbar) */
.page-header {
  padding-top: 8rem;   /* pt-32 */
  padding-bottom: 4rem; /* pb-16 */
}
@media (min-width: 1024px) {
  .page-header {
    padding-top: 11rem;  /* lg:pt-44 */
    padding-bottom: 6rem; /* lg:pb-24 */
  }
}

Grid system

css
/* Grid 12 colonne usata ovunque */
.grid-12 {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: 1rem;
}
@media (min-width: 1024px) {
  .grid-12 { gap: 3rem; }
}

/* Grid 2 colonne standard */
.grid-2 {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4rem;
}
@media (min-width: 1024px) {
  .grid-2 {
    grid-template-columns: 1fr 1fr;
    gap: 6rem;
  }
}

/* Gap usati */
/* gap-4  = 1rem   | gap-6  = 1.5rem */
/* gap-8  = 2rem   | gap-10 = 2.5rem */
/* gap-12 = 3rem   | gap-16 = 4rem   */

05 — Componenti UI Riutilizzabili

SectionLabel — etichetta di sezione

html
<!-- Struttura HTML -->
<span class="section-label">
  <span class="section-label__line"></span>
  Servizi
</span>

<style>
.section-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.25em;
  color: hsl(var(--primary));
}
.section-label__line {
  display: inline-block;
  width: 2rem;
  height: 1px;
  background-color: hsl(var(--primary));
}
</style>

Bottone primario

html
<a href="/contatti" class="btn-primary">
  Richiedi un preventivo
  <svg><!-- ArrowRight --></svg>
</a>

<style>
.btn-primary {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  padding: 1rem 2.5rem;
  font-family: var(--font-heading);
  font-size: 0.875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border-radius: var(--radius);
  transition: background 0.2s;
  text-decoration: none;
}
.btn-primary:hover { background: hsl(200 100% 15%); }
.btn-primary svg { transition: transform 0.2s; }
.btn-primary:hover svg { transform: translateX(4px); }
</style>

Bottone outline (su dark bg)

html
<a href="/servizi" class="btn-outline-white">I Nostri Servizi</a>

<style>
.btn-outline-white {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  border: 1px solid rgba(255,255,255,0.3);
  color: white;
  padding: 1rem 2rem;
  font-family: var(--font-heading);
  font-size: 0.875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  transition: background 0.2s;
  text-decoration: none;
  border-radius: var(--radius);
}
.btn-outline-white:hover { background: rgba(255,255,255,0.1); }
</style>

Link testuale con freccia

html
<a href="/servizi" class="link-arrow">
  Tutti i servizi
  <svg><!-- ArrowRight --></svg>
</a>

<style>
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-heading);
  font-size: 0.875rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: hsl(var(--primary));
  text-decoration: none;
  transition: gap 0.2s;
}
.link-arrow:hover { gap: 0.75rem; }
</style>

Card con bordo + hover lift

html
<div class="card-bordered">
  <div class="card-icon">
    <!-- Icona SVG 20×20 -->
  </div>
  <h3>Titolo</h3>
  <p>Descrizione</p>
</div>

<style>
.card-bordered {
  background: hsl(var(--card));
  padding: 2.5rem 3.5rem;
  height: 100%;
  transition: transform 0.3s;
}
.card-bordered:hover { transform: translateY(-2px); }
.card-icon {
  width: 3rem;
  height: 3rem;
  border: 1px solid hsl(var(--border));
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.5rem;
  transition: border-color 0.3s;
}
.card-bordered:hover .card-icon {
  border-color: hsl(var(--primary) / 0.3);
}
</style>

Accordion (Servizi) — HTML + CSS + JS

html
<div class="accordion">
  <div class="accordion-item">
    <button class="accordion-trigger" aria-expanded="false">
      <span class="accordion-num">01</span>
      <span class="accordion-title">Progettazione</span>
      <span class="accordion-short">Preliminare, definitiva ed esecutiva...</span>
      <span class="accordion-icon">
        <!-- Plus SVG -->
        <svg class="icon-plus" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
        <!-- Minus SVG (hidden by default) -->
        <svg class="icon-minus" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display:none"><line x1="5" y1="12" x2="19" y2="12"/></svg>
      </span>
    </button>
    <div class="accordion-body" style="height:0;overflow:hidden">
      <div class="accordion-content">
        <div class="accordion-text">
          <p class="accordion-subtitle">Preliminare, definitiva ed esecutiva</p>
          <p>Descrizione lunga del servizio...</p>
          <a href="/contatti" class="link-arrow">Richiedi informazioni →</a>
        </div>
        <div class="accordion-image">
          <img src="img/progettazione.jpg" alt="Progettazione">
        </div>
      </div>
    </div>
  </div>
</div>

<style>
.accordion-item { border-top: 1px solid hsl(var(--border)); }
.accordion-item:last-child { border-bottom: 1px solid hsl(var(--border)); }

.accordion-trigger {
  width: 100%;
  text-align: left;
  display: grid;
  grid-template-columns: 2rem 1fr 1fr 2rem;
  align-items: center;
  gap: 3rem;
  padding: 2rem 0;
  background: none;
  border: none;
  cursor: pointer;
}
@media (max-width: 1023px) {
  .accordion-trigger {
    grid-template-columns: 2rem 1fr 2rem;
    gap: 1rem;
  }
  .accordion-short { display: none; }
}

.accordion-num {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  color: hsl(var(--muted-foreground));
}
.accordion-title {
  font-family: var(--font-heading);
  font-size: 1.5rem;
  font-weight: 700;
  color: hsl(var(--foreground));
  transition: color 0.3s;
}
.accordion-trigger:hover .accordion-title,
.accordion-trigger[aria-expanded="true"] .accordion-title {
  color: hsl(var(--primary));
}
.accordion-short {
  font-size: 1rem;
  color: hsl(var(--muted-foreground));
}
.accordion-trigger[aria-expanded="true"] .accordion-short { opacity: 0; }
.accordion-icon { display: flex; justify-content: flex-end; color: hsl(var(--muted-foreground)); }
.accordion-trigger[aria-expanded="true"] .accordion-icon { color: hsl(var(--primary)); }
.accordion-trigger[aria-expanded="true"] .icon-plus { display: none; }
.accordion-trigger[aria-expanded="true"] .icon-minus { display: block !important; }

.accordion-body { transition: height 0.45s cubic-bezier(0.25, 0.46, 0.45, 0.94); }
.accordion-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4rem;
  padding-bottom: 4rem;
  align-items: center;
}
@media (max-width: 1023px) {
  .accordion-content { grid-template-columns: 1fr; gap: 2rem; }
}
.accordion-subtitle {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: hsl(var(--primary));
  margin-bottom: 1rem;
}
.accordion-image img { width: 100%; aspect-ratio: 4/3; object-fit: cover; }
</style>

<script>
document.querySelectorAll('.accordion-trigger').forEach(btn => {
  btn.addEventListener('click', () => {
    const body = btn.nextElementSibling;
    const isOpen = btn.getAttribute('aria-expanded') === 'true';
    // Close all
    document.querySelectorAll('.accordion-trigger').forEach(b => {
      b.setAttribute('aria-expanded', 'false');
      b.nextElementSibling.style.height = '0';
    });
    // Open clicked
    if (!isOpen) {
      btn.setAttribute('aria-expanded', 'true');
      body.style.height = body.scrollHeight + 'px';
    }
  });
});
</script>

08 — Hero Section (Homepage)

• Full-screen: min-height: 100vh

• Background image: copre tutto il viewport, con animazione scale 1.1→1 all'entrata (12s)

• Overlay gradiente: from-foreground/90 via-foreground/50 to-foreground/20 (basso→alto)

• Grid overlay: pattern a griglia 80×80px, opacity 3%

• Contenuto: allineato in basso su mobile, al centro su desktop

• Animazioni entrata: label (delay 0.3s), H1 (delay 0.5s), sottotitolo (0.7s), CTA (0.9s), stat (1.2s)

• Immagine hero: vedere sezione Assets

CSS Hero

css
.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}
@media (min-width: 1024px) { .hero { align-items: center; } }

.hero-bg {
  position: absolute;
  inset: 0;
}
.hero-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: heroScale 12s ease-out forwards;
}
@keyframes heroScale {
  from { transform: scale(1.1); }
  to { transform: scale(1); }
}

.hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to top,
    rgba(26,26,26,0.9) 0%,
    rgba(26,26,26,0.5) 50%,
    rgba(26,26,26,0.2) 100%
  );
}

.hero-grid {
  position: absolute;
  inset: 0;
  opacity: 0.03;
  background-image:
    linear-gradient(#FDFDFD 1px, transparent 1px),
    linear-gradient(90deg, #FDFDFD 1px, transparent 1px);
  background-size: 80px 80px;
}

.hero-content {
  position: relative;
  z-index: 10;
  padding: 8rem 0 5rem;
}
@media (min-width: 1024px) { .hero-content { padding: 2rem 0; } }

.hero-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.25em;
  color: rgba(255,255,255,0.5);
  margin-bottom: 1.5rem;
  animation: fadeUp 0.6s 0.3s both;
}
.hero-label::before {
  content: '';
  display: inline-block;
  width: 2rem;
  height: 1px;
  background: rgba(255,255,255,0.5);
}

.hero h1 {
  font-size: clamp(2.5rem, 6vw, 4.5rem);
  font-weight: 700;
  color: white;
  line-height: 1.05;
  letter-spacing: -0.02em;
  animation: fadeUp 0.8s 0.5s both;
}

.hero-sub {
  margin-top: 1.5rem;
  font-size: 1.125rem;
  color: rgba(255,255,255,0.7);
  max-width: 36rem;
  line-height: 1.75;
  animation: fadeUp 0.7s 0.7s both;
}

.hero-cta {
  margin-top: 2.5rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  animation: fadeUp 0.6s 0.9s both;
}

.hero-stats {
  margin-top: 4rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  max-width: 32rem;
  animation: fadeIn 0.8s 1.2s both;
}
.hero-stat { border-top: 1px solid rgba(255,255,255,0.2); padding-top: 1rem; }
.hero-stat-value { font-size: 1.75rem; font-weight: 700; color: white; }
.hero-stat-label {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: rgba(255,255,255,0.5);
  margin-top: 0.25rem;
}

@keyframes fadeUp {
  from { opacity: 0; transform: translateY(20px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

09 — Struttura Pagine

Home

  • —HeroSection — Full-screen hero con immagine, headline, CTA e stats
  • —AboutPreview — 2 colonne: testo + immagine con badge overlay
  • —PortfolioSection — Grid clienti su sfondo scuro
  • —SectorsPreview — Grid 4 colonne con card settori animabili
  • —ServicesPreview — Lista accordion espandibile con foto
  • —MethodPreview — Immagine + lista fasi metodologia
  • —TechSection — Dark full-width con feature grid
  • —CTASection — Call to action centrata su sfondo scuro

Studio (/studio)

  • —Page header: SectionLabel + H1
  • —Full-width image 21:9
  • —2 colonne: titolo | testo lungo
  • —Grid 2×2 valori aziendali (su bg-secondary)
  • —CTA finale

Servizi (/servizi)

  • —Page header: SectionLabel + H1 + sottotitolo
  • —Accordion: 7 servizi espandibili con descrizione + immagine 4:3
  • —CTA finale su bg-secondary

Settori (/settori)

  • —Page header
  • —Grid 2 colonne: 8 card settori (icon + titolo + desc), hover lift -2px
  • —CTA finale su bg-secondary

Metodo (/metodo)

  • —Page header
  • —Full-width image 21:9
  • —5 fasi in lista verticale: numero grande (ghosted) | titolo + desc | dettagli
  • —Sezione chiavi-in-mano: 2 colonne testo + immagine (su bg-secondary)

Team (/team)

  • —Page header
  • —Grid 2×2 schede team: avatar monogramma + nome + ruolo + bio
  • —Sezione Lavora con noi: 2 colonne testo + form candidatura con upload CV

Contatti (/contatti)

  • —Page header
  • —2 colonne: info contatto (icon + label + valore) | form contatto
  • —Mappa Google iframe 2:1 + pannello info laterale (bg-secondary)

10 — Animazioni & Transizioni

AnimatedSection — scroll-triggered fade-up

css
/* Da replicare con Intersection Observer */
.animated-section {
  opacity: 0;
  transform: translateY(40px);
  transition: opacity 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94),
              transform 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.animated-section.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Delay per elementi in sequenza */
.animated-section:nth-child(2) { transition-delay: 0.05s; }
.animated-section:nth-child(3) { transition-delay: 0.1s; }
.animated-section:nth-child(4) { transition-delay: 0.15s; }

JS — Intersection Observer per scroll animations

javascript
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('is-visible');
      observer.unobserve(entry.target);
    }
  });
}, {
  threshold: 0,
  rootMargin: '-80px 0px 0px 0px'
});

document.querySelectorAll('.animated-section').forEach(el => {
  observer.observe(el);
});

Hover effects usati

css
/* Card lift */
.card:hover { transform: translateY(-2px); }

/* Link arrow shift */
.link-arrow { gap: 0.5rem; transition: gap 0.2s; }
.link-arrow:hover { gap: 0.75rem; }

/* Color transition */
.nav-link { transition: color 0.3s; }

/* Button arrow */
.btn svg { transition: transform 0.2s; }
.btn:hover svg { transform: translateX(4px); }

/* Team underline grow */
.team-underline {
  width: 2rem;
  height: 1px;
  background: hsl(var(--primary) / 0.3);
  transition: width 0.5s;
}
.team-card:hover .team-underline { width: 4rem; }

/* Scroll progress bar (top of page) */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  background: hsl(var(--primary));
  z-index: 100;
  transition: width 0.1s;
}

JS — Scroll progress bar

javascript
const progressBar = document.querySelector('.scroll-progress');
window.addEventListener('scroll', () => {
  const scrollTop = window.scrollY;
  const docHeight = document.documentElement.scrollHeight - window.innerHeight;
  const pct = (scrollTop / docHeight) * 100;
  progressBar.style.width = pct + '%';
});

11 — Assets (Immagini & Icone)

Logo bianco (navbar trasparente)

https://media.base44.com/images/public/6a032bf3cdf7b182b07ecf27/a95b8c8e4_Progettosenzatitolo4.png

Logo colorato (navbar scroll)

https://media.base44.com/images/public/6a032bf3cdf7b182b07ecf27/6498f3ff1_Progettosenzatitolo3.png

Hero background image

https://media.base44.com/images/public/6a032bf3cdf7b182b07ecf27/4cd69c7c0_generated_ce38fecf.png

Studio / About image

https://media.base44.com/images/public/6a032bf3cdf7b182b07ecf27/4be432b3f_generated_de151705.png

Metodo image (header)

https://media.base44.com/images/public/6a032bf3cdf7b182b07ecf27/c3edebe14_generated_dc5c8923.png

Metodo image (chiavi in mano)

https://media.base44.com/images/public/6a032bf3cdf7b182b07ecf27/fec37c339_generated_ee7ef68c.png

Immagini servizi (Unsplash)

text
01 Progettazione:        https://images.unsplash.com/photo-1503387762-592deb58ef4e?w=800&q=80
02 Direzione Lavori:     https://images.unsplash.com/photo-1581094794329-c8112a89af12?w=800&q=80
03 Coordinamento:        https://images.unsplash.com/photo-1558618666-fcd25c85cd64?w=800&q=80
04 Efficientamento:      https://images.unsplash.com/photo-1509391366360-2e959784a276?w=800&q=80
05 Sistemi di Controllo: https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=800&q=80
06 Consulenza Tecnica:   https://images.unsplash.com/photo-1521791136064-7986c2920216?w=800&q=80
07 Project Financing:    https://images.unsplash.com/photo-1554224155-6726b3ff858f?w=800&q=80

Icone — Lucide React (SVG inline)

Tutte le icone provengono da Lucide Icons. Su WordPress, scaricare da lucide.dev come SVG o usare il CDN:

html
<!-- CDN Lucide per WordPress -->
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<script>lucide.createIcons();</script>

<!-- Utilizzo -->
<i data-lucide="arrow-right"></i>
<i data-lucide="phone"></i>
<i data-lucide="map-pin"></i>
<i data-lucide="mail"></i>
<i data-lucide="clock"></i>
<i data-lucide="plus"></i>
<i data-lucide="minus"></i>

<!-- Stile icone -->
<style>
  [data-lucide] { width: 1rem; height: 1rem; stroke: currentColor;
    stroke-width: 1.5; fill: none; }
</style>

12 — Librerie & Dipendenze

Framer Motion

v11

Usato per: Animazioni (accordions, fade, scale)

WP: Sostituire con CSS transitions + Intersection Observer JS

Lucide React

v0.475

Usato per: Icone SVG

WP: lucide.dev CDN o SVG inline

Inter

Google Fonts

Usato per: Font corpo testo

WP: Aggiungere nel functions.php o @import in style.css

Space Grotesk

Google Fonts

Usato per: Font titoli

WP: Aggiungere nel functions.php o @import in style.css

JetBrains Mono

Google Fonts

Usato per: Label tecnici / mono

WP: Aggiungere nel functions.php o @import in style.css

Tailwind CSS

v3

Usato per: Utility CSS framework

WP: Non necessario — usare CSS custom con le variabili documentate

React Router

v6

Usato per: Routing SPA

WP: Sostituito dal routing nativo WordPress

Sonner / Toaster

-

Usato per: Notifiche toast (form)

WP: Piccola libreria JS toast, o nativa WP admin notices

13 — Note per WordPress

Struttura tema raccomandata

text
rbtecnica/
├── style.css          ← Header tema
├── functions.php      ← Enqueue scripts/fonts, CPTs
├── index.php
├── header.php         ← Navbar (trasparente/scroll)
├── footer.php         ← Footer dark
├── front-page.php     ← Homepage
├── page-studio.php
├── page-servizi.php
├── page-settori.php
├── page-metodo.php
├── page-team.php
├── page-contatti.php
├── assets/
│   ├── css/
│   │   ├── variables.css    ← Tutti i token CSS
│   │   ├── typography.css
│   │   ├── components.css   ← Bottoni, cards, accordion
│   │   ├── navbar.css
│   │   ├── footer.css
│   │   ├── hero.css
│   │   └── animations.css
│   ├── js/
│   │   ├── main.js          ← Scroll handler, mobile menu
│   │   ├── accordion.js     ← Servizi accordion
│   │   └── animations.js    ← Intersection Observer
│   └── images/
│       ├── logo-white.png
│       ├── logo-color.png
│       └── hero.jpg

functions.php — Enqueue fonts

php
<?php
function rbtecnica_enqueue() {
  // Google Fonts
  wp_enqueue_style(
    'rbtecnica-fonts',
    'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap',
    [], null
  );

  // Lucide Icons
  wp_enqueue_script(
    'lucide',
    'https://unpkg.com/lucide@0.475.0/dist/umd/lucide.js',
    [], '0.475.0', true
  );

  // Tema CSS
  wp_enqueue_style('rbtecnica', get_stylesheet_uri(), ['rbtecnica-fonts']);

  // JS principale
  wp_enqueue_script('rbtecnica-main', get_template_directory_uri() . '/assets/js/main.js', ['lucide'], '1.0', true);
  wp_enqueue_script('rbtecnica-accordion', get_template_directory_uri() . '/assets/js/accordion.js', [], '1.0', true);
  wp_enqueue_script('rbtecnica-animations', get_template_directory_uri() . '/assets/js/animations.js', [], '1.0', true);
}
add_action('wp_enqueue_scripts', 'rbtecnica_enqueue');
?>

Navbar JS (main.js)

javascript
// Scroll handler navbar
const header = document.querySelector('.site-header');
const isHome = document.body.classList.contains('home');

function updateNavbar() {
  if (isHome && window.scrollY <= 40) {
    header.classList.add('transparent');
    header.classList.remove('scrolled');
  } else {
    header.classList.remove('transparent');
    header.classList.add('scrolled');
  }
}

// Init
if (isHome) header.classList.add('transparent');
window.addEventListener('scroll', updateNavbar, { passive: true });

// Mobile menu
const menuBtn = document.querySelector('.menu-toggle');
const mobileMenu = document.querySelector('.mobile-menu');
menuBtn.addEventListener('click', () => {
  mobileMenu.classList.toggle('is-open');
  document.body.style.overflow = mobileMenu.classList.contains('is-open') ? 'hidden' : '';
});

// Lucide icons init
if (window.lucide) lucide.createIcons();

// Scroll progress
const progress = document.querySelector('.scroll-progress');
if (progress) {
  window.addEventListener('scroll', () => {
    const pct = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight) * 100;
    progress.style.width = pct + '%';
  }, { passive: true });
}

⚠ Punti di attenzione

  • • La navbar trasparente funziona solo sulla homepage — usare body.home come selettore
  • • Il form Contatti richiede un plugin WP (Contact Form 7 o WPForms) o gestione PHP custom
  • • Il form candidatura Team richiede upload file — usare plugin dedicato o AJAX PHP
  • • La mappa Google è un semplice iframe — nessuna API key necessaria
  • • L'accordion usa scrollHeight per l'animazione — testare su tutti i browser
  • • Le immagini Unsplash sono free per uso commerciale (licenza Unsplash)
  • • Le immagini custom (hero, studio, metodo) vanno scaricate dai link in sezione Assets

Studio R.B. — WordPress Handoff Documentation — v1.0 — Maggio 2026

Noi e terze parti selezionate utilizziamo cookie o tecnologie simili per finalità tecniche e, con il tuo consenso, anche per le finalità di funzionalità, esperienza, misurazione e “marketing (con annunci personalizzati)” come specificato nella cookie policy.

Puoi liberamente prestare, rifiutare o revocare il tuo consenso, in qualsiasi momento, accedendo al pannello delle preferenze. Il rifiuto del consenso può rendere non disponibili le relative funzioni.

Usa il pulsante “Accetta” per acconsentire. Usa il pulsante “Rifiuta” per continuare senza accettare.