Initial commit

This commit is contained in:
2026-05-15 09:52:56 +02:00
commit 634c1822b0
19 changed files with 6927 additions and 0 deletions

32
.gitignore vendored Normal file
View File

@@ -0,0 +1,32 @@
# Dependencies
node_modules/
# Build output
dist/
.output/
# Astro cache
.astro/
# Environment variables
.env
.env.local
.env.*.local
# Editor
.vscode/
.idea/
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# OS
.DS_Store
Thumbs.db
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*

62
CLAUDE.md Normal file
View File

@@ -0,0 +1,62 @@
# context-mode — MANDATORY routing rules
You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
## BLOCKED commands — do NOT attempt these
### curl / wget — BLOCKED
Any Bash command containing `curl` or `wget` is intercepted and replaced with an error message. Do NOT retry.
Instead use:
- `ctx_fetch_and_index(url, source)` to fetch and index web pages
- `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
### Inline HTTP — BLOCKED
Any Bash command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` is intercepted and replaced with an error message. Do NOT retry with Bash.
Instead use:
- `ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
### WebFetch — BLOCKED
WebFetch calls are denied entirely. The URL is extracted and you are told to use `ctx_fetch_and_index` instead.
Instead use:
- `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` to query the indexed content
## REDIRECTED tools — use sandbox equivalents
### Bash (>20 lines output)
Bash is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
For everything else, use:
- `ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
- `ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
### Read (for analysis)
If you are reading a file to **Edit** it → Read is correct (Edit needs content in context).
If you are reading to **analyze, explore, or summarize** → use `ctx_execute_file(path, language, code)` instead. Only your printed summary enters context. The raw file content stays in the sandbox.
### Grep (large results)
Grep results can flood context. Use `ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
## Tool selection hierarchy
1. **GATHER**: `ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
2. **FOLLOW-UP**: `ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
3. **PROCESSING**: `ctx_execute(language, code)` | `ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
4. **WEB**: `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
5. **INDEX**: `ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
## Subagent routing
When spawning subagents (Agent/Task tool), the routing block is automatically injected into their prompt. Bash-type subagents are upgraded to general-purpose so they have access to MCP tools. You do NOT need to manually instruct subagents about context-mode.
## Output constraints
- Keep responses under 500 words.
- Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
- When indexing content, use descriptive source labels so others can `ctx_search(source: "label")` later.
## ctx commands
| Command | Action |
|---------|--------|
| `ctx stats` | Call the `ctx_stats` MCP tool and display the full output verbatim |
| `ctx doctor` | Call the `ctx_doctor` MCP tool, run the returned shell command, display as checklist |
| `ctx upgrade` | Call the `ctx_upgrade` MCP tool, run the returned shell command, display as checklist |

96
README.md Normal file
View File

@@ -0,0 +1,96 @@
# Smart Roots — Sito Web
Stack: **Astro 4** (static output) · CSS custom · Deploy su **IIS 10 / Windows Server 2016**
---
## Struttura del progetto
```
/
├── public/
│ ├── assets/ ← immagini, loghi (copiati as-is nel build)
│ └── web.config ← configurazione IIS (copiata as-is nel build)
├── src/
│ ├── components/
│ │ ├── Layout.astro ← head HTML, meta SEO, font
│ │ ├── Nav.astro ← navbar (variante full o back)
│ │ └── Footer.astro ← footer con dati societari
│ ├── pages/
│ │ ├── index.astro ← Home / Landing page
│ │ ├── contatti.astro ← Form contatti → WebAPI
│ │ ├── privacy.astro ← Privacy Policy (da completare)
│ │ └── termini.astro ← Termini (da completare)
│ └── styles/
│ └── global.css ← CSS variables, nav, footer, form, responsive
├── astro.config.mjs
└── package.json
```
---
## Setup locale
### Prerequisiti
- Node.js 18+ (solo per sviluppo/build, non necessario in produzione)
```bash
npm install
npm run dev # avvia dev server su http://localhost:4321
npm run build # genera cartella /dist pronta per il deploy
```
---
## Deploy su IIS 10
1. Eseguire il build: `npm run build`
2. La cartella `/dist` contiene il sito statico completo
3. Copiare il contenuto di `/dist` nella cartella del sito su IIS
- Il `web.config` è già incluso nel build (sta in `/public`)
4. In IIS Manager:
- Application Pool: **.NET CLR version = No Managed Code**
- Assicurarsi che il modulo **URL Rewrite** sia installato (necessario per il routing)
### Modulo URL Rewrite
Se non installato: scaricarlo da https://www.iis.net/downloads/microsoft/url-rewrite
---
## Form contatti — WebAPI
Il form invia a `https://api.smart-roots.net/api/contatti` via `fetch` POST JSON.
Payload inviato:
```json
{
"nome": "Mario Rossi",
"azienda": "Acme S.r.l.",
"email": "mario@azienda.it",
"ambito": "smartdb",
"messaggio": "..."
}
```
### Endpoint WebAPI da creare (.NET Framework 4.8)
Vedere documentazione separata per `ContattiController`.
Ricordarsi di abilitare CORS per `https://www.smart-roots.net` nella WebAPI.
---
## Aggiungere nuove pagine
1. Creare `src/pages/nuova-pagina.astro`
2. Usare il componente `Layout` con titolo e descrizione
3. `npm run build` e rideploy della cartella `/dist`
---
## TODO
- [ ] Aggiungere immagine `hero-dashboard.png` in `/public/assets/`
- [ ] Aggiungere immagine `og-image.jpg` in `/public/assets/` (1200×630px)
- [ ] Completare testo Privacy Policy in `src/pages/privacy.astro`
- [ ] Completare testo Termini in `src/pages/termini.astro`
- [ ] Creare endpoint `POST /api/contatti` nella WebAPI
- [ ] Abilitare CORS per `https://www.smart-roots.net` nella WebAPI

9
astro.config.mjs Normal file
View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'astro/config';
export default defineConfig({
output: 'static',
site: 'https://www.smart-roots.net',
build: {
format: 'directory' // genera /contatti/index.html invece di /contatti.html
}
});

5553
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

13
package.json Normal file
View File

@@ -0,0 +1,13 @@
{
"name": "smart-roots-website",
"type": "module",
"version": "1.0.0",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview"
},
"dependencies": {
"astro": "^4.15.0"
}
}

View File

@@ -0,0 +1,167 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 400" width="600" height="400">
<defs>
<style>
.bg { fill: #1e2840; }
.panel { fill: #111829; stroke: rgba(100,140,200,0.18); stroke-width: 1; }
.panel-dark { fill: #0b0f1c; stroke: rgba(100,140,200,0.12); stroke-width: 1; }
.accent { fill: #4d8fd4; }
.accent-dim { fill: rgba(77,143,212,0.15); }
.bar-1 { fill: #4d8fd4; }
.bar-2 { fill: rgba(77,143,212,0.5); }
.bar-3 { fill: rgba(77,143,212,0.3); }
.line-color { stroke: #4d8fd4; stroke-width: 1.5; fill: none; }
.line-dim { stroke: rgba(77,143,212,0.35); stroke-width: 1; fill: none; }
.txt-primary { fill: #ddd8d0; font-family: IBM Plex Mono, monospace; }
.txt-secondary { fill: #8799bb; font-family: IBM Plex Mono, monospace; }
.txt-dim { fill: #5a6e90; font-family: IBM Plex Mono, monospace; }
.dot { fill: #4d8fd4; }
.dot-empty { fill: none; stroke: #4d8fd4; stroke-width: 1.5; }
.grid-line { stroke: rgba(100,140,200,0.08); stroke-width: 1; }
.badge { fill: rgba(77,143,212,0.15); }
.badge-border { fill: none; stroke: #2e5fa3; stroke-width: 1; }
.positive { fill: #1d9e75; }
.negative { fill: #e24b4a; }
</style>
</defs>
<!-- Background -->
<rect width="600" height="400" class="bg" rx="8"/>
<!-- Header bar -->
<rect x="0" y="0" width="600" height="44" fill="#0b0f1c" rx="8"/>
<rect x="0" y="36" width="600" height="8" fill="#0b0f1c"/>
<!-- Header dots -->
<circle cx="20" cy="22" r="4" fill="#2e5fa3" opacity="0.6"/>
<circle cx="34" cy="22" r="4" fill="#2e5fa3" opacity="0.4"/>
<circle cx="48" cy="22" r="4" fill="#2e5fa3" opacity="0.2"/>
<!-- Header label -->
<text x="72" y="27" class="txt-dim" font-size="10" letter-spacing="2">SMARTDB — ANALYTICS DASHBOARD</text>
<!-- Badge live -->
<rect x="510" y="13" width="70" height="18" class="badge" rx="9"/>
<rect x="510" y="13" width="70" height="18" class="badge-border" rx="9"/>
<circle cx="522" cy="22" r="3" fill="#1d9e75"/>
<text x="530" y="26" class="txt-secondary" font-size="9" letter-spacing="1">LIVE</text>
<!-- ===== KPI CARDS ROW ===== -->
<!-- Card 1 -->
<rect x="16" y="56" width="128" height="68" class="panel" rx="4"/>
<text x="26" y="74" class="txt-dim" font-size="8" letter-spacing="1.5">PE RATIO</text>
<text x="26" y="96" class="txt-primary" font-size="22" font-weight="300">14.32</text>
<text x="26" y="113" fill="#1d9e75" font-family="IBM Plex Mono,monospace" font-size="9">▲ +0.8%</text>
<!-- Card 2 -->
<rect x="156" y="56" width="128" height="68" class="panel" rx="4"/>
<text x="166" y="74" class="txt-dim" font-size="8" letter-spacing="1.5">DIV YIELD</text>
<text x="166" y="96" class="txt-primary" font-size="22" font-weight="300">3.87%</text>
<text x="166" y="113" fill="#1d9e75" font-family="IBM Plex Mono,monospace" font-size="9">▲ +0.2%</text>
<!-- Card 3 -->
<rect x="296" y="56" width="128" height="68" class="panel" rx="4"/>
<text x="306" y="74" class="txt-dim" font-size="8" letter-spacing="1.5">VOLATILITY 1Y</text>
<text x="306" y="96" class="txt-primary" font-size="22" font-weight="300">0.218</text>
<text x="306" y="113" fill="#e24b4a" font-family="IBM Plex Mono,monospace" font-size="9">▼ -0.012</text>
<!-- Card 4 -->
<rect x="436" y="56" width="148" height="68" class="panel" rx="4"/>
<text x="446" y="74" class="txt-dim" font-size="8" letter-spacing="1.5">ESG SCORE</text>
<text x="446" y="96" class="txt-primary" font-size="22" font-weight="300">72</text>
<text x="446" y="113" class="txt-dim" font-family="IBM Plex Mono,monospace" font-size="9">stable</text>
<!-- ===== CHART PANEL - LINE ===== -->
<rect x="16" y="136" width="348" height="160" class="panel-dark" rx="4"/>
<text x="26" y="153" class="txt-dim" font-size="8" letter-spacing="1.5">PRICE INDEX — 12M</text>
<!-- Grid lines -->
<line x1="26" y1="166" x2="354" y2="166" class="grid-line"/>
<line x1="26" y1="186" x2="354" y2="186" class="grid-line"/>
<line x1="26" y1="206" x2="354" y2="206" class="grid-line"/>
<line x1="26" y1="226" x2="354" y2="226" class="grid-line"/>
<line x1="26" y1="246" x2="354" y2="246" class="grid-line"/>
<line x1="26" y1="266" x2="354" y2="266" class="grid-line"/>
<line x1="26" y1="284" x2="354" y2="284" class="grid-line"/>
<!-- Y labels -->
<text x="20" y="169" class="txt-dim" font-size="8" text-anchor="end">120</text>
<text x="20" y="209" class="txt-dim" font-size="8" text-anchor="end">110</text>
<text x="20" y="249" class="txt-dim" font-size="8" text-anchor="end">100</text>
<text x="20" y="287" class="txt-dim" font-size="8" text-anchor="end">90</text>
<!-- Area fill -->
<path d="M30 260 L60 248 L90 238 L120 252 L150 240 L180 228 L210 218 L240 208 L270 196 L300 186 L330 174 L354 168 L354 284 L30 284 Z" fill="rgba(77,143,212,0.07)"/>
<!-- Line chart -->
<path d="M30 260 L60 248 L90 238 L120 252 L150 240 L180 228 L210 218 L240 208 L270 196 L300 186 L330 174 L354 168" class="line-color" stroke-linecap="round" stroke-linejoin="round"/>
<!-- Dot at end -->
<circle cx="354" cy="168" r="3.5" class="dot"/>
<!-- X labels -->
<text x="30" y="296" class="txt-dim" font-size="7" text-anchor="middle">Gen</text>
<text x="90" y="296" class="txt-dim" font-size="7" text-anchor="middle">Mar</text>
<text x="150" y="296" class="txt-dim" font-size="7" text-anchor="middle">Mag</text>
<text x="210" y="296" class="txt-dim" font-size="7" text-anchor="middle">Lug</text>
<text x="270" y="296" class="txt-dim" font-size="7" text-anchor="middle">Set</text>
<text x="330" y="296" class="txt-dim" font-size="7" text-anchor="middle">Nov</text>
<!-- ===== BAR CHART PANEL ===== -->
<rect x="376" y="136" width="208" height="160" class="panel-dark" rx="4"/>
<text x="386" y="153" class="txt-dim" font-size="8" letter-spacing="1.5">ASSET CLASS MIX</text>
<!-- Bars -->
<rect x="390" y="248" width="22" height="26" class="bar-1" rx="2"/>
<rect x="390" y="196" width="22" height="52" class="bar-1" opacity="0.85" rx="2"/>
<rect x="390" y="176" width="22" height="20" class="bar-1" opacity="0.6" rx="2"/>
<rect x="428" y="236" width="22" height="38" class="bar-2" rx="2"/>
<rect x="428" y="204" width="22" height="32" class="bar-2" opacity="0.85" rx="2"/>
<rect x="428" y="190" width="22" height="14" class="bar-2" opacity="0.7" rx="2"/>
<rect x="466" y="250" width="22" height="24" class="bar-3" rx="2"/>
<rect x="466" y="220" width="22" height="30" class="bar-3" opacity="0.85" rx="2"/>
<rect x="466" y="206" width="22" height="14" class="bar-3" opacity="0.7" rx="2"/>
<rect x="504" y="242" width="22" height="32" class="bar-1" opacity="0.4" rx="2"/>
<rect x="504" y="218" width="22" height="24" class="bar-1" opacity="0.3" rx="2"/>
<!-- X labels bar -->
<text x="401" y="290" class="txt-dim" font-size="7" text-anchor="middle">Equity</text>
<text x="439" y="290" class="txt-dim" font-size="7" text-anchor="middle">Bond</text>
<text x="477" y="290" class="txt-dim" font-size="7" text-anchor="middle">Fund</text>
<text x="515" y="290" class="txt-dim" font-size="7" text-anchor="middle">Deriv</text>
<!-- ===== INSTRUMENT TABLE ===== -->
<rect x="16" y="308" width="568" height="76" class="panel-dark" rx="4"/>
<text x="26" y="325" class="txt-dim" font-size="8" letter-spacing="1.5">INSTRUMENTS — ENRICHED DATA</text>
<!-- Table header -->
<rect x="16" y="329" width="568" height="1" fill="rgba(100,140,200,0.12)"/>
<text x="30" y="342" class="txt-dim" font-size="8">ISIN</text>
<text x="150" y="342" class="txt-dim" font-size="8">NAME</text>
<text x="300" y="342" class="txt-dim" font-size="8">CLASS</text>
<text x="380" y="342" class="txt-dim" font-size="8">P/E</text>
<text x="440" y="342" class="txt-dim" font-size="8">YIELD</text>
<text x="520" y="342" class="txt-dim" font-size="8">ESG</text>
<rect x="16" y="345" width="568" height="1" fill="rgba(100,140,200,0.08)"/>
<!-- Row 1 -->
<text x="30" y="358" class="txt-secondary" font-size="9" font-family="IBM Plex Mono,monospace">IT0005365165</text>
<text x="150" y="358" class="txt-primary" font-size="9">ENI S.p.A.</text>
<text x="300" y="358" class="accent" font-size="9" font-family="IBM Plex Mono,monospace" fill="#4d8fd4">equity</text>
<text x="380" y="358" class="txt-secondary" font-size="9">14.32</text>
<text x="440" y="358" class="txt-secondary" font-size="9">3.87%</text>
<text x="520" y="358" fill="#1d9e75" font-family="IBM Plex Mono,monospace" font-size="9">72</text>
<!-- Row 2 -->
<text x="30" y="374" class="txt-secondary" font-size="9" font-family="IBM Plex Mono,monospace">IT0004965148</text>
<text x="150" y="374" class="txt-primary" font-size="9">Intesa Sanpaolo</text>
<text x="300" y="374" class="accent" font-size="9" font-family="IBM Plex Mono,monospace" fill="#4d8fd4">equity</text>
<text x="380" y="374" class="txt-secondary" font-size="9">11.08</text>
<text x="440" y="374" class="txt-secondary" font-size="9">5.21%</text>
<text x="520" y="374" fill="#1d9e75" font-family="IBM Plex Mono,monospace" font-size="9">68</text>
<!-- Separator rows -->
<rect x="16" y="362" width="568" height="1" fill="rgba(100,140,200,0.05)"/>
</svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

BIN
public/assets/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

63
public/web.config Normal file
View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
web.config per IIS 10 — Smart Roots (sito statico Astro)
Da copiare nella cartella /dist dopo il build: astro build
-->
<configuration>
<system.webServer>
<!-- Routing: se il file non esiste fisicamente, serve index.html della directory -->
<rewrite>
<rules>
<!-- Forza HTTPS -->
<rule name="HTTP to HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
<!-- SPA/Static fallback: cartelle Astro con index.html -->
<rule name="Astro static routing" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/{R:1}/index.html" />
</rule>
</rules>
</rewrite>
<!-- MIME types aggiuntivi necessari per Astro -->
<staticContent>
<remove fileExtension=".webmanifest" />
<mimeMap fileExtension=".webmanifest" mimeType="application/manifest+json" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff2" mimeType="font/woff2" />
<remove fileExtension=".woff" />
<mimeMap fileExtension=".woff" mimeType="font/woff" />
</staticContent>
<!-- Cache control per asset statici -->
<httpProtocol>
<customHeaders>
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="X-XSS-Protection" value="1; mode=block" />
<add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
</customHeaders>
</httpProtocol>
<!-- Compressione gzip -->
<urlCompression doStaticCompression="true" doDynamicCompression="true" />
<!-- Errori personalizzati -->
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" path="/index.html" responseMode="ExecuteURL" />
</httpErrors>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,30 @@
---
const year = new Date().getFullYear();
---
<footer>
<div class="footer-inner">
<div style="display:flex;align-items:center;justify-content:space-between;width:100%;flex-wrap:wrap;gap:1rem">
<div class="footer-logo">Smart Roots</div>
<nav class="footer-links" aria-label="Link footer">
<a href="/privacy">Privacy</a>
<a href="/termini">Termini</a>
<a href="/contatti">Contatti</a>
</nav>
</div>
<div style="width:100%;height:1px;background:var(--border)" aria-hidden="true"></div>
<div style="display:flex;align-items:flex-start;justify-content:space-between;width:100%;flex-wrap:wrap;gap:1.5rem">
<address style="font-style:normal">
<div style="font-family:var(--mono);font-size:0.7rem;color:var(--txt3);letter-spacing:0.06em;margin-bottom:0.6rem;text-transform:uppercase">Dati societari</div>
<div style="font-size:0.78rem;color:var(--txt3);line-height:1.9">
<span style="color:var(--txt2);font-weight:500">SMART ROOTS S.R.L.</span><br />
Via Lombardia 40 — 00187 Roma (RM)<br />
P.IVA / C.F.: 17439811005 &nbsp;·&nbsp; VAT EU: IT17439811005
</div>
</address>
<div class="footer-copy" style="align-self:flex-end">
<small>© {year} Smart Roots S.r.l.</small>
</div>
</div>
</div>
</footer>

View File

@@ -0,0 +1,63 @@
---
import '../styles/global.css';
export interface Props {
title: string;
description: string;
canonical?: string;
noindex?: boolean;
ogImage?: string;
}
const {
title,
description,
canonical,
noindex = false,
ogImage = 'https://www.smart-roots.net/assets/og-image.jpg'
} = Astro.props;
const canonicalUrl = canonical ?? Astro.url.href;
---
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="robots" content={noindex ? 'noindex, follow' : 'index, follow'} />
<link rel="canonical" href={canonicalUrl} />
<title>{title}</title>
<meta name="description" content={description} />
<meta name="author" content="Smart Roots S.r.l." />
<!-- Open Graph -->
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:url" content={canonicalUrl} />
<meta property="og:image" content={ogImage} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:locale" content="it_IT" />
<meta property="og:site_name" content="Smart Roots" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={ogImage} />
<!-- Fonts -->
<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=IBM+Plex+Sans:wght@300;400;500&family=IBM+Plex+Mono:wght@300;400&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap" rel="stylesheet" />
<!-- Slot per head aggiuntivo per pagina -->
<slot name="head" />
</head>
<body>
<slot />
</body>
</html>

26
src/components/Nav.astro Normal file
View File

@@ -0,0 +1,26 @@
---
export interface Props {
variant?: 'full' | 'back'; // full = nav principale, back = solo logo + freccia home
}
const { variant = 'full' } = Astro.props;
---
<nav aria-label="Navigazione principale">
<a href="/" class="nav-logo" aria-label="Smart Roots — Home">
<img src="/assets/logo.png" alt="Smart Roots" width="32" height="32" />
<span class="nav-logo-text">Smart Roots</span>
</a>
{variant === 'full' && (
<div class="nav-links">
<a href="/#prodotto">Prodotto</a>
<a href="/#smartdb">SmartDB</a>
<a href="/#chi">Per chi</a>
<a href="/contatti" class="nav-cta">Conosciamoci</a>
</div>
)}
{variant === 'back' && (
<a href="/" class="nav-back">Home</a>
)}
</nav>

1
src/env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference path="../.astro/types.d.ts" />

166
src/pages/contatti.astro Normal file
View File

@@ -0,0 +1,166 @@
---
import Layout from '../components/Layout.astro';
import Nav from '../components/Nav.astro';
import Footer from '../components/Footer.astro';
---
<Layout
title="Contatti — Smart Roots | Conosciamoci"
description="Contatta Smart Roots per una presentazione del prodotto o per valutare come i nostri servizi di Financial Data Intelligence si adattano al tuo flusso di lavoro."
canonical="https://www.smart-roots.net/contatti"
noindex={true}
>
<Nav variant="back" />
<main>
<div class="page-tag">Contatti</div>
<h1>Conosciamoci.</h1>
<p>
Scrivici per una presentazione ad hoc, per approfondire il prodotto o semplicemente per capire se Smart Roots può essere utile al tuo flusso di lavoro.
Risponderemo entro 24 ore lavorative.
</p>
<form id="contact-form" novalidate style="margin-top:2.5rem" aria-label="Modulo di contatto Smart Roots">
<!-- Honeypot anti-spam -->
<input type="checkbox" name="botcheck" style="display:none" tabindex="-1" aria-hidden="true" />
<div class="form-row">
<div class="form-field">
<label class="form-label" for="nome">Nome <span aria-label="obbligatorio">*</span></label>
<input class="form-input" type="text" id="nome" name="nome" required placeholder="Mario Rossi" autocomplete="given-name" />
</div>
<div class="form-field">
<label class="form-label" for="azienda">Azienda</label>
<input class="form-input" type="text" id="azienda" name="azienda" placeholder="Acme S.r.l." autocomplete="organization" />
</div>
</div>
<div class="form-field">
<label class="form-label" for="email">Email <span aria-label="obbligatorio">*</span></label>
<input class="form-input" type="email" id="email" name="email" required placeholder="mario@azienda.it" autocomplete="email" />
</div>
<div class="form-field">
<label class="form-label" for="ambito">Ambito di interesse</label>
<select class="form-input" id="ambito" name="ambito">
<option value="">— seleziona —</option>
<option value="data-enrichment">Data Enrichment</option>
<option value="analytics">Advanced Analytics</option>
<option value="smartdb">SmartDB / API</option>
<option value="ai-workflow">AI Workflows</option>
<option value="altro">Altro</option>
</select>
</div>
<div class="form-field" style="margin-bottom:1.5rem">
<label class="form-label" for="messaggio">Messaggio <span aria-label="obbligatorio">*</span></label>
<textarea
class="form-input"
id="messaggio"
name="messaggio"
required
rows="5"
placeholder="Raccontaci brevemente il tuo contesto e cosa stai cercando..."
style="resize:vertical"
></textarea>
</div>
<button type="submit" class="btn-submit" id="submit-btn">
Invia messaggio
</button>
<div class="form-feedback ok" id="form-ok" role="alert" aria-live="polite">
✓ Messaggio inviato — ti risponderemo entro 24 ore lavorative.
</div>
<div class="form-feedback err" id="form-err" role="alert" aria-live="polite">
Errore nell'invio. Scrivi direttamente a
<a href="mailto:info@smart-roots.net">info@smart-roots.net</a>
</div>
<p class="form-note">
I dati forniti saranno utilizzati esclusivamente per rispondere alla tua richiesta.
Consulta la nostra <a href="/privacy">Privacy Policy</a> per maggiori informazioni.
</p>
</form>
<p style="margin-top:2.5rem;font-size:0.82rem;color:var(--txt3)">
Oppure scrivici direttamente a
<a href="mailto:info@smart-roots.net" style="color:var(--txt2)">info@smart-roots.net</a>
</p>
</main>
<Footer />
</Layout>
<script>
(function () {
'use strict';
// ⚠️ Sostituire con l'URL reale dell'endpoint nella WebAPI
const API_ENDPOINT = 'https://api.smart-roots.net/api/contatti';
const form = document.getElementById('contact-form') as HTMLFormElement;
const submitBtn = document.getElementById('submit-btn') as HTMLButtonElement;
const okMsg = document.getElementById('form-ok') as HTMLElement;
const errMsg = document.getElementById('form-err') as HTMLElement;
form.addEventListener('submit', async function (e) {
e.preventDefault();
// Honeypot check
const botcheck = form.querySelector('[name="botcheck"]') as HTMLInputElement;
if (botcheck && botcheck.checked) return;
// Validazione HTML5 nativa
if (!form.checkValidity()) {
form.reportValidity();
return;
}
// Stato loading
submitBtn.disabled = true;
submitBtn.textContent = 'Invio in corso…';
okMsg.style.display = 'none';
errMsg.style.display = 'none';
const payload = {
nome: (document.getElementById('nome') as HTMLInputElement).value.trim(),
azienda: (document.getElementById('azienda') as HTMLInputElement).value.trim(),
email: (document.getElementById('email') as HTMLInputElement).value.trim(),
ambito: (document.getElementById('ambito') as HTMLSelectElement).value,
messaggio:(document.getElementById('messaggio') as HTMLTextAreaElement).value.trim(),
};
try {
const response = await fetch(API_ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (response.ok) {
form.reset();
okMsg.style.display = 'block';
okMsg.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
} else {
throw new Error(`HTTP ${response.status}`);
}
} catch (err) {
console.error('Errore invio form:', err);
errMsg.style.display = 'block';
} finally {
submitBtn.disabled = false;
submitBtn.textContent = 'Invia messaggio';
}
});
})();
</script>
<style>
main { max-width: 760px; margin: 0 auto; padding: 120px 2.5rem 80px; }
.page-tag { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin-bottom: 1rem; }
h1 { font-family: var(--serif); font-size: clamp(1.8rem, 3.5vw, 2.4rem); font-weight: normal; color: var(--txt); line-height: 1.15; margin-bottom: 2rem; }
p { font-size: 0.95rem; color: var(--txt2); line-height: 1.8; margin-bottom: 1rem; }
</style>

467
src/pages/index.astro Normal file
View File

@@ -0,0 +1,467 @@
---
import Layout from '../components/Layout.astro';
import Nav from '../components/Nav.astro';
import Footer from '../components/Footer.astro';
const jsonLd = {
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://www.smart-roots.net/#organization",
"name": "Smart Roots S.r.l.",
"url": "https://www.smart-roots.net/",
"logo": "https://www.smart-roots.net/assets/logo.png",
"description": "Financial Data Intelligence per asset manager, advisory firm e operatori finanziari.",
"address": {
"@type": "PostalAddress",
"streetAddress": "Via Lombardia 40",
"addressLocality": "Roma",
"postalCode": "00187",
"addressCountry": "IT"
},
"vatID": "IT17439811005",
"contactPoint": {
"@type": "ContactPoint",
"contactType": "customer service",
"url": "https://www.smart-roots.net/contatti"
}
},
{
"@type": "WebSite",
"@id": "https://www.smart-roots.net/#website",
"url": "https://www.smart-roots.net/",
"name": "Smart Roots",
"publisher": { "@id": "https://www.smart-roots.net/#organization" },
"inLanguage": "it-IT"
}
]
};
---
<Layout
title="Smart Roots — Financial Data Intelligence | Dati finanziari rielaborati e analytics"
description="Smart Roots offre soluzioni di Financial Data Intelligence per asset manager, advisory firm e operatori finanziari. Trasformiamo dati finanziari complessi in analytics, workflow e decisioni operative tramite API e piattaforma dedicata."
canonical="https://www.smart-roots.net/"
>
<Fragment slot="head">
<meta name="keywords" content="financial data intelligence, data enrichment finanziario, analytics finanziari, API dati finanziari, asset management, SmartDB" />
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
</Fragment>
<Nav variant="full" />
<!-- HERO -->
<section class="hero" aria-labelledby="hero-heading">
<div class="hero-grid" aria-hidden="true"></div>
<div class="hero-glow" aria-hidden="true"></div>
<div class="hero-inner">
<div class="hero-left">
<div class="hero-tag">Financial Intelligence Platform</div>
<h1 id="hero-heading">
Dati finanziari rielaborati,<br /><em>analytics</em> e piattaforma<br />in un unico ambiente.
</h1>
<p class="hero-sub">
Smart Roots supporta asset manager, advisory firm e operatori finanziari a trasformare dati complessi in analisi, workflow e decisioni operative.
</p>
<div class="hero-actions">
<a href="/contatti" class="btn-primary">Conosciamoci</a>
</div>
<div class="hero-scroll" aria-hidden="true">
<div class="hero-scroll-line"></div>
Scorri
</div>
</div>
<div class="hero-right">
<div class="hero-image-wrap">
<!-- Sostituire con immagine dashboard reale -->
<img src="/assets/hero-dashboard.svg" alt="Dashboard Smart Roots" loading="lazy" width="600" height="400" />
</div>
<div class="hero-motto-block">
<div class="hero-motto-large"><em>smart roots</em> — solid ground</div>
<div class="hero-motto-rule" aria-hidden="true"></div>
<div class="hero-motto-sub">dati su misura, decisioni fondate</div>
</div>
</div>
</div>
</section>
<!-- THREE PILLARS -->
<section class="pillars" id="prodotto" aria-labelledby="pillars-heading">
<h2 id="pillars-heading" class="sr-only">I pilastri della piattaforma</h2>
<div class="pillars-inner">
<article class="pillar">
<div class="pillar-num" aria-hidden="true">01</div>
<h3 class="pillar-title">Data Enrichment</h3>
<p class="pillar-desc">Dati finanziari rielaborati, normalizzati e strutturati. Consegniamo dati pronti all'uso.</p>
</article>
<article class="pillar">
<div class="pillar-num" aria-hidden="true">02</div>
<h3 class="pillar-title">Advanced Analytics</h3>
<p class="pillar-desc">Motori di calcolo proprietari, metriche operative e logiche di analisi integrate direttamente nella piattaforma.</p>
</article>
<article class="pillar">
<div class="pillar-num" aria-hidden="true">03</div>
<h3 class="pillar-title">Interactive Delivery</h3>
<p class="pillar-desc">Piattaforma web per la consultazione, l'utilizzo e l'esportazione dei dati. Accesso riservato, orientato all'operatività.</p>
</article>
<article class="pillar">
<div class="pillar-num" aria-hidden="true">04</div>
<h3 class="pillar-title">AI Workflows</h3>
<p class="pillar-desc">Workflow AI su task specifici e misurabili. L'AI accelera l'esecuzione dei processi che padroneggiamo. Non deleghiamo ciò che non controlliamo.</p>
</article>
</div>
</section>
<!-- FOUNDERS -->
<section class="founders" id="chi-siamo" aria-labelledby="founders-heading">
<div class="founders-inner">
<div class="founders-left">
<div class="section-tag">Chi siamo</div>
<h2 id="founders-heading" class="sr-only">Chi siamo — Il team di Smart Roots</h2>
<div class="founders-stat">
<span class="founders-stat-num">30+</span>
<span class="founders-stat-label">anni di esperienza</span>
</div>
<blockquote class="founders-quote">«Sappiamo cosa vuol dire lavorare con dati finanziari nella pratica operativa, da operatori.»</blockquote>
<p class="founders-body">I fondatori di Smart Roots hanno maturato oltre trent'anni di esperienza diretta nei settori finanziario e informatico. Abbiamo vissuto dall'interno la frustrazione di ricevere dati grezzi, incompleti o non omogenei, e di dover costruire ogni volta, da zero, gli strumenti per renderli utilizzabili.</p>
<p class="founders-body" style="margin-top:1rem">Da questa esperienza nasce Smart Roots: un progetto costruito da chi conosce il problema dall'interno e conosce la finanza sul campo.</p>
</div>
<div class="founders-right">
<div class="section-tag" style="margin-bottom:1.5rem">Il dato «su misura»</div>
<blockquote class="founders-quote" style="font-size:1.1rem">Un dato ben rielaborato è più pulito e diventa uno strumento di decisione. La differenza tra un dato grezzo e un dato su misura è la stessa che passa tra un'informazione e una scelta operativa.</blockquote>
<p class="founders-body">Abbiamo imparato che il valore sta nella qualità della trasformazione dei dati, più che nel loro volume. Un dato normalizzato secondo la logica del business, e non della fonte, accorcia drasticamente il percorso tra analisi e azione.</p>
<div class="founders-expertise">
<div class="exp-item">
<div class="exp-label">Settore finanziario</div>
<p class="exp-text">Asset management, advisory, strutturazione di prodotti finanziari, risk e compliance.</p>
</div>
<div class="exp-item">
<div class="exp-label">Settore informatico</div>
<p class="exp-text">Architetture dati, sviluppo di piattaforme, integrazione di sistemi, infrastruttura cloud.</p>
</div>
</div>
</div>
</div>
</section>
<!-- PER CHI È -->
<section class="audience" id="chi" aria-labelledby="audience-heading">
<div class="section-inner">
<div class="section-tag">Posizionamento</div>
<h2 id="audience-heading" class="section-title">Per chi lavora con dati finanziari complessi</h2>
<p class="section-sub">Smart Roots è costruita per operatori che non possono permettersi di perdere tempo tra dato grezzo e decisione.</p>
<div class="audience-grid">
<article class="aud-card">
<div class="aud-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" focusable="false"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
</div>
<h3 class="aud-title">Asset &amp; Wealth Management</h3>
<p class="aud-problem">Il dato arriva grezzo, il processo di pulizia è lungo e manuale.</p>
<p class="aud-result">Riduci il tempo tra dato grezzo e decisione di investimento.</p>
</article>
<article class="aud-card">
<div class="aud-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" focusable="false"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
</div>
<h3 class="aud-title">Advisory &amp; Private Banking</h3>
<p class="aud-problem">I consulenti hanno bisogno di analytics pronti, non di dataset da assemblare.</p>
<p class="aud-result">Analisi e metriche operative disponibili nel flusso di lavoro quotidiano.</p>
</article>
<article class="aud-card">
<div class="aud-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" focusable="false"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
</div>
<h3 class="aud-title">Fintech / Data-Driven Operations</h3>
<p class="aud-problem">Integrare più fonti di dati finanziari ha un costo tecnico elevato.</p>
<p class="aud-result">API strutturate e dataset normalizzati, pronti per l'integrazione.</p>
</article>
</div>
</div>
</section>
<!-- PIPELINE -->
<section class="pipeline" aria-labelledby="pipeline-heading">
<div class="section-inner">
<div class="section-tag">Come funziona</div>
<h2 id="pipeline-heading" class="section-title">Dal dato grezzo all'analisi operativa</h2>
<p class="section-sub">Smart Roots copre l'intero ciclo: acquisizione, elaborazione e distribuzione. Ogni fase è progettata per ridurre la distanza tra informazione e decisione.</p>
<div class="pipeline-flow">
<div class="pipe-block">
<div class="pipe-label">Input</div>
<h3 class="pipe-title">Fonti &amp; Dataset</h3>
<ul class="pipe-items">
<li>Fonti dati strutturate e non</li>
<li>Dataset di mercato e fondamentali</li>
<li>Regole di calcolo e logiche operative</li>
<li>Integrazioni esterne su misura</li>
</ul>
</div>
<div class="pipe-arrow" aria-hidden="true">
<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
</div>
<div class="pipe-block">
<div class="pipe-label">Processing</div>
<h3 class="pipe-title">Motori di analisi</h3>
<ul class="pipe-items">
<li>Normalizzazione e validazione</li>
<li>Librerie di calcolo proprietarie</li>
<li>Pipeline di enrichment automatizzate</li>
<li>Metriche e indicatori operativi</li>
</ul>
</div>
<div class="pipe-arrow" aria-hidden="true">
<svg viewBox="0 0 24 24"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
</div>
<div class="pipe-block">
<div class="pipe-label">Output</div>
<h3 class="pipe-title">Delivery operativa</h3>
<ul class="pipe-items">
<li>Dashboard e viste operative</li>
<li>Dataset pronti all'uso</li>
<li>Accesso API via SmartDB</li>
<li>Export strutturati su richiesta</li>
</ul>
</div>
</div>
</div>
</section>
<!-- SMARTDB -->
<section class="smartdb" id="smartdb" aria-labelledby="smartdb-heading">
<div class="section-inner smartdb-inner">
<div>
<div class="smartdb-badge">SmartDB</div>
<div class="section-tag">Accesso ai dati</div>
<h2 id="smartdb-heading" class="section-title">L'ambiente operativo<br />di accesso ai dati.</h2>
<p style="font-size:1rem;color:var(--txt2);line-height:1.75;margin-bottom:2rem">SmartDB è il layer di esposizione dei dati rielaborati di Smart Roots. Fornisce accesso strutturato via API a dataset normalizzati, metriche calcolate e viste operative, senza la complessità di costruire e mantenere un'infrastruttura dati proprietaria.</p>
<ul style="list-style:none;display:flex;flex-direction:column;gap:0.6rem;margin-bottom:2rem">
<li style="font-size:0.875rem;color:var(--txt2);display:flex;align-items:center;gap:10px"><span style="color:var(--accent);font-family:var(--mono)" aria-hidden="true">→</span> Accesso riservato a operatori professionali</li>
<li style="font-size:0.875rem;color:var(--txt2);display:flex;align-items:center;gap:10px"><span style="color:var(--accent);font-family:var(--mono)" aria-hidden="true">→</span> Endpoint API documentati e stabili</li>
<li style="font-size:0.875rem;color:var(--txt2);display:flex;align-items:center;gap:10px"><span style="color:var(--accent);font-family:var(--mono)" aria-hidden="true">→</span> Dati già processati, non raw feed</li>
<li style="font-size:0.875rem;color:var(--txt2);display:flex;align-items:center;gap:10px"><span style="color:var(--accent);font-family:var(--mono)" aria-hidden="true">→</span> Integrazione semplificata nel tuo stack</li>
</ul>
</div>
<div class="smartdb-visual" aria-label="Esempio di risposta API SmartDB">
<div class="line-dim">// SmartDB API — esempio di risposta</div>
<br />
<div>GET /v1/instruments/<span class="line-accent">ISIN</span>/analytics</div>
<br />
<div>{"{"}</div>
<div>&nbsp;&nbsp;"isin": <span class="line-accent">"IT0005365165"</span>,</div>
<div>&nbsp;&nbsp;"asset_class": <span class="line-accent">"equity"</span>,</div>
<div>&nbsp;&nbsp;"metrics": {"{"}</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;"pe_ratio": <span class="line-accent">14.32</span>,</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;"dividend_yield": <span class="line-accent">3.87</span>,</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;"volatility_1y": <span class="line-accent">0.218</span>,</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;"score_esg": <span class="line-accent">72</span></div>
<div>&nbsp;&nbsp;{"}"},</div>
<div>&nbsp;&nbsp;"updated_at": <span class="line-dim">"2026-03-14T18:00:00Z"</span></div>
<div>{"}"}</div>
</div>
</div>
</section>
<!-- AI SECTION -->
<section style="background:var(--bg1);border-top:1px solid var(--border);padding:100px 2.5rem" aria-labelledby="ai-heading">
<div class="section-inner">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:5rem;align-items:start">
<div>
<div class="section-tag">Intelligenza artificiale</div>
<h2 id="ai-heading" class="section-title">AI come strumento,<br />non come oracolo.</h2>
<p style="font-size:1rem;color:var(--txt2);line-height:1.75;margin-bottom:1.5rem">Usiamo l'AI in modo deliberato e circoscritto: automatizza l'esecuzione di task che sappiamo già come svolgere, senza usarla per scoprire cosa fare.</p>
<p style="font-size:1rem;color:var(--txt2);line-height:1.75">La differenza è sostanziale. Chi delega all'AI un problema che non sa risolvere entra in un territorio opaco, perde tempo e perde controllo sul risultato. Noi usiamo l'AI perché conosciamo il processo e possiamo governarla con precisione.</p>
<div style="margin-top:1rem;padding:1.75rem;border:1px solid var(--accent2);border-radius:var(--r);background:var(--accent-dim)">
<div style="font-family:var(--serif);font-size:1.2rem;color:var(--txt);margin-bottom:0.6rem">Non siamo una fint-tech.</div>
<p style="font-family:var(--mono);font-size:0.75rem;color:var(--txt3);line-height:1.7;letter-spacing:0.03em">Finta tecnologia: usare l'AI per sembrare innovativi senza sapere cosa si sta facendo.</p>
</div>
</div>
<div style="display:flex;flex-direction:column;gap:1.5rem;padding-top:0.5rem">
{[
{ label: 'Il nostro approccio', text: 'Costruiamo workflow AI su task specifici e misurabili. Ogni automazione nasce da una competenza consolidata. L\'AI ne accelera l\'esecuzione, senza prendere il posto della competenza.' },
{ label: 'Cosa evita questo', text: 'Nessun risultato casuale. Nessuna dipendenza da output che non sappiamo verificare. Il controllo del processo resta dove deve stare: nelle mani di chi conosce il dominio.' },
{ label: 'Il risultato', text: 'Workflow più rapidi, output verificabili e competenza umana amplificata. L\'AI fa più veloce quello che noi sappiamo già fare bene.' }
].map(item => (
<div style="padding:1.75rem;border:1px solid var(--border);border-radius:var(--r);background:var(--bg)">
<div style="font-family:var(--mono);font-size:0.68rem;letter-spacing:0.1em;text-transform:uppercase;color:var(--accent);margin-bottom:0.75rem">{item.label}</div>
<p style="font-size:0.9rem;color:var(--txt2);line-height:1.7">{item.text}</p>
</div>
))}
</div>
</div>
</div>
</section>
<!-- DIFF -->
<section class="diff" aria-labelledby="diff-heading">
<div class="section-inner">
<div class="section-tag">Perché Smart Roots</div>
<h2 id="diff-heading" class="section-title">Tra vendor di dati<br />e software house.</h2>
<p class="section-sub">Smart Roots occupa uno spazio preciso: tra chi distribuisce dati grezzi e chi costruisce software su misura. Un approccio più agile, più integrato, più operativo.</p>
<div class="diff-grid">
{[
{ n:'01', t:'Dati rielaborati e pronti all\'uso', b:'Il valore sta nella logica di elaborazione che trasforma il dato grezzo in informazione operativa.' },
{ n:'02', t:'Logica di calcolo integrata', b:'Le metriche sono incorporate nell\'infrastruttura di Smart Roots e disponibili via API.' },
{ n:'03', t:'Esperienza orientata all\'uso', b:'La piattaforma è progettata per flussi di lavoro finanziari professionali specifici. Non nasce come strumento di analisi generico.' },
{ n:'04', t:'Approccio modulare e adattabile', b:'I componenti sono configurabili. L\'ambiente si adatta al flusso di lavoro del cliente.' }
].map(item => (
<article class="diff-item">
<div class="diff-num" aria-hidden="true">{item.n}</div>
<h3 class="diff-title">{item.t}</h3>
<p class="diff-body">{item.b}</p>
</article>
))}
</div>
</div>
</section>
<!-- TRUST -->
<section class="trust" aria-labelledby="trust-heading">
<div class="section-inner">
<div class="section-tag">Infrastruttura</div>
<h2 id="trust-heading" class="section-title">Progettato per operatori professionali</h2>
<div class="trust-grid">
<article class="trust-item">
<div class="trust-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg></div>
<h3 class="trust-label">Accesso riservato</h3>
<p class="trust-desc">Infrastruttura ad accesso controllato. Ambienti dedicati per ogni cliente.</p>
</article>
<article class="trust-item">
<div class="trust-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 4.93a10 10 0 0 0 0 14.14"/></svg></div>
<h3 class="trust-label">Supporto tecnico dedicato</h3>
<p class="trust-desc">Interlocutore tecnico diretto. Nessun ticket anonimo, nessuna coda.</p>
</article>
<article class="trust-item">
<div class="trust-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/><line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/></svg></div>
<h3 class="trust-label">Ambiti coperti</h3>
<p class="trust-desc">Equity, fixed income, derivati, fondi. Coverage su mercati europei e internazionali.</p>
</article>
<article class="trust-item">
<div class="trust-icon" aria-hidden="true"><svg viewBox="0 0 24 24"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg></div>
<h3 class="trust-label">Use case operativi</h3>
<p class="trust-desc">Screening, portfolio analytics, reporting, data enrichment per modelli interni.</p>
</article>
</div>
</div>
</section>
<!-- CTA FINALE -->
<section class="cta-final" id="contatti" aria-labelledby="cta-heading">
<div class="cta-glow" aria-hidden="true"></div>
<div class="section-inner" style="position:relative;text-align:center">
<div class="section-tag" style="justify-content:center;display:flex">Inizia</div>
<h2 id="cta-heading">Vuoi valutare come Smart Roots può adattarsi al tuo flusso di lavoro?</h2>
<p>Mostriamo come funziona nell'ambiente operativo che usi già. Nessuna demo generica: una conversazione sul tuo caso specifico.</p>
<div class="cta-buttons">
<a href="/contatti" class="btn-primary">Conosciamoci</a>
</div>
</div>
</section>
<Footer />
</Layout>
<style>
/* HERO */
.hero { min-height: 100vh; display: flex; flex-direction: column; justify-content: center; padding: 120px 2.5rem 80px; position: relative; overflow: hidden; }
.hero-grid { position: absolute; inset: 0; background-image: linear-gradient(var(--border) 1px, transparent 1px), linear-gradient(90deg, var(--border) 1px, transparent 1px); background-size: 80px 80px; opacity: 0.4; pointer-events: none; }
.hero-glow { position: absolute; top: -100px; right: -100px; width: 700px; height: 700px; background: radial-gradient(ellipse, rgba(45,90,163,0.18) 0%, transparent 65%); pointer-events: none; }
.hero-inner { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: center; max-width: var(--max); width: 100%; margin: 0 auto; position: relative; }
.hero-tag { font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin-bottom: 1.8rem; display: flex; align-items: center; gap: 10px; }
.hero-tag::before { content: ''; width: 28px; height: 1px; background: var(--accent); display: inline-block; }
.hero h1 { font-family: var(--serif); font-size: clamp(2.6rem, 5.5vw, 4.2rem); font-weight: normal; line-height: 1.12; letter-spacing: -0.01em; color: var(--txt); max-width: 760px; margin-bottom: 0.6rem; }
.hero h1 em { font-style: italic; color: var(--accent); opacity: 0.9; }
.hero-sub { font-size: 1.08rem; font-weight: 300; color: var(--txt2); max-width: 560px; line-height: 1.75; margin-bottom: 3rem; }
.hero-actions { display: flex; gap: 1rem; flex-wrap: wrap; }
.hero-scroll { margin-top: 5rem; display: flex; align-items: center; gap: 10px; color: var(--txt3); font-size: 0.75rem; letter-spacing: 0.08em; text-transform: uppercase; font-family: var(--mono); }
.hero-scroll-line { width: 1px; height: 40px; background: linear-gradient(to bottom, transparent, var(--txt3)); }
.hero-right { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1.8rem; }
.hero-image-wrap { position: relative; width: 340px; height: 340px; display: flex; align-items: center; justify-content: center; }
.hero-image-wrap::before { content: ''; position: absolute; inset: -24px; border-radius: 50%; border: 1px solid rgba(77,143,212,0.15); }
.hero-image-wrap::after { content: ''; position: absolute; inset: -48px; border-radius: 50%; border: 1px solid rgba(77,143,212,0.07); }
.hero-image-wrap img { width: 300px; height: 300px; object-fit: contain; position: relative; z-index: 1; filter: drop-shadow(0 0 40px rgba(77,143,212,0.25)); }
.hero-motto-block { text-align: center; }
.hero-motto-large { font-family: var(--serif); font-size: clamp(1.3rem, 2vw, 1.8rem); font-weight: normal; font-style: italic; color: var(--txt2); letter-spacing: 0.02em; line-height: 1.3; margin-bottom: 0.4rem; }
.hero-motto-large em { font-style: normal; color: var(--accent); }
.hero-motto-rule { width: 60px; height: 1px; background: var(--accent); margin: 0.8rem auto; opacity: 0.4; }
.hero-motto-sub { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.14em; text-transform: lowercase; color: var(--txt3); }
/* PILLARS */
.pillars { padding: 80px 2.5rem; border-top: 1px solid var(--border); }
.pillars-inner { max-width: var(--max); margin: 0 auto; display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px; background: var(--border); }
.pillar { background: var(--bg); padding: 2.5rem 2rem; transition: background 0.3s; }
.pillar:hover { background: var(--bg1); }
.pillar-num { font-family: var(--mono); font-size: 0.7rem; color: var(--accent); letter-spacing: 0.1em; margin-bottom: 1.2rem; }
.pillar-title { font-family: var(--serif); font-size: 1.55rem; font-weight: normal; color: var(--txt); margin-bottom: 0.75rem; line-height: 1.2; }
.pillar-desc { font-size: 0.9rem; color: var(--txt2); line-height: 1.7; }
/* FOUNDERS */
.founders { background: var(--bg2); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 100px 2.5rem; }
.founders-inner { display: grid; grid-template-columns: 1fr 1fr; gap: 5rem; align-items: start; max-width: var(--max); margin: 0 auto; }
.founders-stat { display: flex; align-items: baseline; gap: 0.5rem; margin-bottom: 1.5rem; }
.founders-stat-num { font-family: var(--serif); font-size: clamp(3.5rem, 6vw, 5rem); font-weight: normal; color: var(--accent); line-height: 1; }
.founders-stat-label { font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--txt3); }
.founders-quote { font-family: var(--serif); font-size: clamp(1.2rem, 2vw, 1.55rem); font-weight: normal; font-style: italic; color: var(--txt); line-height: 1.5; margin-bottom: 2rem; padding-left: 1.5rem; border-left: 2px solid var(--accent); }
.founders-body { font-size: 0.95rem; color: var(--txt2); line-height: 1.75; }
.founders-expertise { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 2.5rem; }
.exp-item { padding: 1.5rem 1.25rem; border: 1px solid var(--border); border-radius: var(--r); background: var(--bg); }
.exp-label { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent); margin-bottom: 0.5rem; }
.exp-text { font-size: 0.85rem; color: var(--txt2); line-height: 1.6; }
/* AUDIENCE */
.audience { background: var(--bg1); }
.audience-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; margin-top: 3rem; }
.aud-card { border: 1px solid var(--border); padding: 2.2rem 1.8rem; border-radius: var(--r); background: var(--bg); transition: border-color 0.3s, background 0.3s; }
.aud-card:hover { border-color: var(--border2); background: var(--bg2); }
.aud-icon { width: 40px; height: 40px; border: 1px solid var(--border2); border-radius: var(--r); display: flex; align-items: center; justify-content: center; margin-bottom: 1.5rem; }
.aud-icon svg { width: 18px; height: 18px; stroke: var(--accent); fill: none; stroke-width: 1.5; }
.aud-title { font-family: var(--serif); font-size: 1.3rem; font-weight: normal; color: var(--txt); margin-bottom: 0.5rem; }
.aud-problem { font-size: 0.85rem; color: var(--txt3); margin-bottom: 0.5rem; font-style: italic; }
.aud-result { font-size: 0.9rem; color: var(--txt2); line-height: 1.6; }
/* PIPELINE */
.pipeline { background: var(--bg); }
.pipeline-flow { display: grid; grid-template-columns: 1fr 40px 1fr 40px 1fr; align-items: center; gap: 0; margin-top: 3.5rem; }
.pipe-block { border: 1px solid var(--border); border-radius: var(--r); padding: 2rem 1.75rem; background: var(--bg1); }
.pipe-label { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin-bottom: 1rem; }
.pipe-title { font-family: var(--serif); font-size: 1.2rem; font-weight: normal; color: var(--txt); margin-bottom: 1rem; }
.pipe-items { list-style: none; display: flex; flex-direction: column; gap: 0.4rem; }
.pipe-items li { font-size: 0.83rem; color: var(--txt2); display: flex; align-items: center; gap: 8px; }
.pipe-items li::before { content: ''; width: 4px; height: 4px; border-radius: 50%; background: var(--accent); flex-shrink: 0; }
.pipe-arrow { display: flex; align-items: center; justify-content: center; color: var(--txt3); }
.pipe-arrow svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.5; }
/* SMARTDB */
.smartdb { background: var(--bg2); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); position: relative; overflow: hidden; }
.smartdb-inner { display: grid; grid-template-columns: 1fr 1fr; gap: 5rem; align-items: center; }
.smartdb-visual { background: var(--bg3); border: 1px solid var(--border2); border-radius: var(--r); padding: 1.75rem; font-family: var(--mono); font-size: 0.78rem; color: var(--txt2); line-height: 1.9; }
.smartdb-visual .line-accent { color: var(--accent); }
.smartdb-visual .line-dim { color: var(--txt3); }
.smartdb-badge { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; background: var(--accent-dim); border: 1px solid var(--accent2); border-radius: 20px; font-family: var(--mono); font-size: 0.68rem; color: var(--accent); letter-spacing: 0.08em; margin-bottom: 1rem; }
.smartdb-badge::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
/* DIFF */
.diff { background: var(--bg); }
.diff-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2px; background: var(--border); margin-top: 3rem; border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.diff-item { background: var(--bg); padding: 2.2rem 2rem; transition: background 0.25s; }
.diff-item:hover { background: var(--bg1); }
.diff-num { font-family: var(--mono); font-size: 0.7rem; color: var(--txt3); margin-bottom: 0.75rem; }
.diff-title { font-size: 1rem; font-weight: 500; color: var(--txt); margin-bottom: 0.5rem; }
.diff-body { font-size: 0.875rem; color: var(--txt2); line-height: 1.65; }
/* TRUST */
.trust { background: var(--bg1); border-top: 1px solid var(--border); }
.trust-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; margin-top: 3rem; }
.trust-item { padding: 1.75rem 1.5rem; border: 1px solid var(--border); border-radius: var(--r); }
.trust-icon { margin-bottom: 1rem; color: var(--accent); }
.trust-icon svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.5; }
.trust-label { font-size: 0.82rem; font-weight: 500; color: var(--txt); margin-bottom: 0.3rem; }
.trust-desc { font-size: 0.8rem; color: var(--txt2); line-height: 1.6; }
/* CTA FINALE */
.cta-final { background: var(--bg); border-top: 1px solid var(--border); text-align: center; position: relative; overflow: hidden; }
.cta-glow { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 600px; height: 300px; background: radial-gradient(ellipse, rgba(45,90,163,0.15) 0%, transparent 70%); pointer-events: none; }
.cta-final h2 { font-family: var(--serif); font-size: clamp(1.8rem, 3vw, 2.6rem); font-weight: normal; color: var(--txt); max-width: 620px; margin: 0 auto 1.2rem; line-height: 1.2; }
.cta-final p { font-size: 0.98rem; color: var(--txt2); max-width: 440px; margin: 0 auto 2.5rem; line-height: 1.7; }
.cta-buttons { display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }
</style>

39
src/pages/privacy.astro Normal file
View File

@@ -0,0 +1,39 @@
---
import Layout from '../components/Layout.astro';
import Nav from '../components/Nav.astro';
import Footer from '../components/Footer.astro';
---
<Layout
title="Privacy Policy — Smart Roots"
description="Informativa sul trattamento dei dati personali di Smart Roots S.r.l. ai sensi del GDPR."
canonical="https://www.smart-roots.net/privacy"
noindex={true}
>
<Nav variant="back" />
<main>
<div class="page-tag">Legal</div>
<h1>Privacy Policy</h1>
<p class="intro">
Informativa sul trattamento dei dati personali ai sensi dell'art. 13 del Regolamento (UE) 2016/679 (GDPR).
</p>
<!-- TODO: inserire testo completo della privacy policy -->
<div class="placeholder-notice">
<span>⚠</span> Testo completo da completare
</div>
</main>
<Footer />
</Layout>
<style>
main { max-width: 760px; margin: 0 auto; padding: 120px 2.5rem 80px; }
.page-tag { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin-bottom: 1rem; }
h1 { font-family: var(--serif); font-size: clamp(1.8rem, 3.5vw, 2.4rem); font-weight: normal; color: var(--txt); line-height: 1.15; margin-bottom: 2rem; }
h2 { font-family: var(--serif); font-size: 1.1rem; font-weight: normal; color: var(--txt); margin: 2.5rem 0 0.75rem; }
p { font-size: 0.95rem; color: var(--txt2); line-height: 1.8; margin-bottom: 1rem; }
.intro { font-size: 1rem; color: var(--txt2); }
.placeholder-notice { margin-top: 2rem; padding: 1.25rem 1.5rem; border: 1px dashed var(--border2); border-radius: var(--r); font-family: var(--mono); font-size: 0.8rem; color: var(--txt3); display: flex; align-items: center; gap: 0.75rem; }
</style>

39
src/pages/termini.astro Normal file
View File

@@ -0,0 +1,39 @@
---
import Layout from '../components/Layout.astro';
import Nav from '../components/Nav.astro';
import Footer from '../components/Footer.astro';
---
<Layout
title="Termini e Condizioni — Smart Roots"
description="Termini e condizioni d'uso dei servizi Smart Roots S.r.l."
canonical="https://www.smart-roots.net/termini"
noindex={true}
>
<Nav variant="back" />
<main>
<div class="page-tag">Legal</div>
<h1>Termini e Condizioni</h1>
<p class="intro">
Termini e condizioni d'uso dei servizi offerti da Smart Roots S.r.l.
</p>
<!-- TODO: inserire testo completo dei termini -->
<div class="placeholder-notice">
<span>⚠</span> Testo completo da completare
</div>
</main>
<Footer />
</Layout>
<style>
main { max-width: 760px; margin: 0 auto; padding: 120px 2.5rem 80px; }
.page-tag { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin-bottom: 1rem; }
h1 { font-family: var(--serif); font-size: clamp(1.8rem, 3.5vw, 2.4rem); font-weight: normal; color: var(--txt); line-height: 1.15; margin-bottom: 2rem; }
h2 { font-family: var(--serif); font-size: 1.1rem; font-weight: normal; color: var(--txt); margin: 2.5rem 0 0.75rem; }
p { font-size: 0.95rem; color: var(--txt2); line-height: 1.8; margin-bottom: 1rem; }
.intro { font-size: 1rem; color: var(--txt2); }
.placeholder-notice { margin-top: 2rem; padding: 1.25rem 1.5rem; border: 1px dashed var(--border2); border-radius: var(--r); font-family: var(--mono); font-size: 0.8rem; color: var(--txt3); display: flex; align-items: center; gap: 0.75rem; }
</style>

101
src/styles/global.css Normal file
View File

@@ -0,0 +1,101 @@
/* ============================================================
SMART ROOTS — global.css
Font: Cormorant Garamond (display/serif) + IBM Plex Sans + IBM Plex Mono
============================================================ */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500&family=IBM+Plex+Mono:wght@300;400&family=Cormorant+Garamond:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap');
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #0b0f1c;
--bg1: #111829;
--bg2: #171f35;
--bg3: #1e2840;
--txt: #ddd8d0;
--txt2: #8799bb;
--txt3: #5a6e90;
--accent: #4d8fd4;
--accent2: #2e5fa3;
--accent-dim: rgba(77,143,212,0.12);
--border: rgba(100,140,200,0.10);
--border2: rgba(100,140,200,0.18);
--mono: 'IBM Plex Mono', monospace;
--sans: 'IBM Plex Sans', sans-serif;
--serif: 'Cormorant Garamond', Georgia, serif;
--max: 1180px;
--r: 6px;
}
html { scroll-behavior: smooth; }
body { background: var(--bg); color: var(--txt); font-family: var(--sans); font-size: 16px; line-height: 1.7; -webkit-font-smoothing: antialiased; }
a { color: inherit; text-decoration: none; }
img { display: block; }
/* ── Utility ── */
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
/* ── Sezioni comuni ── */
section { padding: 100px 2.5rem; }
.section-inner { max-width: var(--max); margin: 0 auto; }
.section-tag { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent); margin-bottom: 1rem; }
.section-title { font-family: var(--serif); font-size: clamp(2rem, 3.5vw, 2.8rem); font-weight: normal; line-height: 1.15; color: var(--txt); margin-bottom: 1.2rem; }
.section-sub { font-size: 1rem; color: var(--txt2); max-width: 520px; line-height: 1.75; margin-bottom: 3.5rem; }
/* ── Bottoni ── */
.btn-primary { font-size: 0.85rem; font-weight: 500; letter-spacing: 0.04em; padding: 14px 28px; background: var(--accent); color: #06101f; border-radius: var(--r); transition: opacity 0.2s; border: none; cursor: pointer; display: inline-block; }
.btn-primary:hover { opacity: 0.85; }
.btn-ghost { font-size: 0.85rem; font-weight: 400; letter-spacing: 0.04em; padding: 14px 28px; border: 1px solid var(--border2); color: var(--txt2); border-radius: var(--r); transition: all 0.2s; cursor: pointer; display: inline-block; }
.btn-ghost:hover { border-color: var(--txt2); color: var(--txt); }
/* ── NAV ── */
nav { position: fixed; top: 0; left: 0; right: 0; z-index: 100; display: flex; align-items: center; justify-content: space-between; padding: 0 2.5rem; height: 68px; background: rgba(11,15,28,0.88); backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); }
.nav-logo { display: flex; align-items: center; gap: 10px; }
.nav-logo img { width: 32px; height: 32px; object-fit: contain; }
.nav-logo-text { font-family: var(--serif); font-size: 1.4rem; font-weight: normal; letter-spacing: 0.04em; color: var(--txt); }
.nav-links { display: flex; gap: 2rem; align-items: center; }
.nav-links a { font-size: 0.82rem; font-weight: 400; letter-spacing: 0.05em; text-transform: uppercase; color: var(--txt2); transition: color 0.2s; }
.nav-links a:hover { color: var(--txt); }
.nav-cta { font-size: 0.8rem !important; font-weight: 500 !important; letter-spacing: 0.04em !important; padding: 8px 18px; border: 1px solid var(--accent2); color: var(--accent) !important; border-radius: var(--r); transition: all 0.2s; }
.nav-cta:hover { background: var(--accent-dim) !important; }
.nav-back { font-size: 0.8rem; color: var(--txt2); letter-spacing: 0.04em; display: flex; align-items: center; gap: 6px; transition: color 0.2s; }
.nav-back:hover { color: var(--txt); }
.nav-back::before { content: '←'; }
/* ── FOOTER ── */
footer { border-top: 1px solid var(--border); padding: 2rem 2.5rem; }
.footer-inner { max-width: var(--max); margin: 0 auto; width: 100%; display: flex; flex-direction: column; gap: 1.5rem; align-items: flex-start; }
.footer-logo { font-family: var(--serif); font-weight: normal; font-size: 1.3rem; color: var(--txt2); }
.footer-copy { font-family: var(--mono); font-size: 0.7rem; color: var(--txt3); letter-spacing: 0.06em; }
.footer-links { display: flex; gap: 1.5rem; }
.footer-links a { font-size: 0.78rem; color: var(--txt3); transition: color 0.2s; }
.footer-links a:hover { color: var(--txt2); }
/* ── FORM CONTATTI ── */
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
.form-field { margin-bottom: 1rem; }
.form-label { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--txt3); display: block; margin-bottom: 0.4rem; }
.form-input { width: 100%; background: var(--bg1); border: 1px solid var(--border2); border-radius: var(--r); padding: 12px 14px; color: var(--txt); font-family: var(--sans); font-size: 0.9rem; outline: none; transition: border-color 0.2s; }
.form-input:focus { border-color: var(--accent); }
.form-input:invalid:not(:placeholder-shown) { border-color: #e24b4a; }
.btn-submit { font-family: var(--serif); font-size: 0.9rem; font-weight: normal; padding: 14px 32px; background: var(--accent); color: #06101f; border: none; border-radius: var(--r); cursor: pointer; letter-spacing: 0.04em; transition: opacity 0.2s; }
.btn-submit:hover { opacity: 0.85; }
.btn-submit:disabled { opacity: 0.5; cursor: not-allowed; }
.form-feedback { display: none; margin-top: 1.5rem; font-family: var(--mono); font-size: 0.8rem; line-height: 1.5; padding: 1rem 1.25rem; border-radius: var(--r); }
.form-feedback.ok { color: var(--accent); background: var(--accent-dim); border: 1px solid var(--accent2); }
.form-feedback.err { color: #e24b4a; background: rgba(226,75,74,0.08); border: 1px solid rgba(226,75,74,0.3); }
.form-note { font-family: var(--mono); font-size: 0.72rem; color: var(--txt3); line-height: 1.6; margin-top: 1rem; }
/* ── RESPONSIVE ── */
@media (max-width: 900px) {
.pillars-inner, .audience-grid, .pipeline-flow,
.smartdb-inner, .diff-grid, .trust-grid,
.founders-inner { grid-template-columns: 1fr !important; }
.pipe-arrow { transform: rotate(90deg); }
nav .nav-links { display: none; }
.pipeline-flow { grid-template-columns: 1fr !important; }
.hero-inner { grid-template-columns: 1fr !important; gap: 3rem; }
.hero-right { order: -1; }
.founders-expertise { grid-template-columns: 1fr !important; }
.form-row { grid-template-columns: 1fr; }
}