Piattaforme riservate: ruolo dedicato e port della dashboard Stress Index

Il ruolo `campus` diventa `piattaforme` e non apre più solo la sezione
Biohacking: copre tutte le aree riservate, con migrazione guardata sugli
utenti esistenti. Nell'header la vecchia voce Biohacking lascia il posto a
un menu Piattaforme con i due link, visibile solo a chi ha il ruolo, e
/piattaforme diventa la pagina di atterraggio.

Stress Index è portata dentro il sito: le nove viste dell'area
professionisti diventano pagine Astro sotto /piattaforme/stress-index,
con lo stile del sito al posto del design system del prototipo. React
resta solo dove serve davvero — grafici recharts e scheda cliente — il
resto è Astro con un filo di JS. I dati sono ancora quelli dimostrativi,
raccolti in lib/stress-index/data.ts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 15:49:47 +02:00
parent e8e24e086b
commit c4eb598a3a
32 changed files with 2908 additions and 74 deletions
+287
View File
@@ -0,0 +1,287 @@
/* Stile della piattaforma Stress Index.
Vive in un foglio globale, non in <style> scoped, perché le stesse classi servono sia
ai componenti Astro sia alle isole React (grafici e viste interattive), che lo scope
di Astro non raggiungerebbe. Tutto è prefissato `.si` e usa i token del sito. */
.si {
--si-line: #e4dfd7;
--si-surface: #ffffff;
--si-ok: #6f8f6a;
--si-warn: #c08a3e;
--si-bad: #b05a4e;
display: flex;
align-items: flex-start;
background: var(--c-bg-alt);
}
/* --- sidebar --- */
.si-side {
width: 250px; flex: 0 0 250px; height: 100vh; position: sticky; top: 0; overflow-y: auto;
background: var(--c-dark); color: #cfc6bd; padding: 28px 20px 40px;
display: flex; flex-direction: column;
}
.si-brand {
display: block; font-family: var(--font-heading); font-size: 1.35rem; font-weight: 600;
letter-spacing: .1em; text-transform: uppercase; color: #fff; text-decoration: none; line-height: 1.1;
}
.si-brand .eyebrow { display: block; font-size: .7rem; letter-spacing: .18em; color: var(--c-accent); margin-bottom: 5px; }
.si-home {
display: inline-block; margin: 16px 0 22px; font-family: var(--font-heading); font-size: .68rem;
font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--c-accent);
text-decoration: none; border-bottom: 1px solid transparent;
}
.si-home:hover { border-bottom-color: var(--c-accent); }
.si-nav { display: flex; flex-direction: column; gap: 2px; border-top: 1px solid rgba(255,255,255,.12); padding-top: 16px; }
.si-nav__link {
display: flex; align-items: center; gap: 8px; padding: 9px 12px; text-decoration: none;
font-family: var(--font-heading); font-size: .74rem; font-weight: 600; letter-spacing: .12em;
text-transform: uppercase; color: #b6ada3; border-left: 3px solid transparent;
}
.si-nav__link:hover { color: #fff; background: rgba(255,255,255,.06); }
.si-nav__link.is-active { color: #fff; background: rgba(184,169,140,.22); border-left-color: var(--c-accent); }
.si-nav__badge {
margin-left: auto; background: var(--c-accent); color: var(--c-dark); border-radius: 999px;
padding: 1px 7px; font-size: .58rem; letter-spacing: .1em;
}
.si-foot {
display: flex; flex-direction: column; gap: 9px; margin-top: auto; padding-top: 20px;
border-top: 1px solid rgba(255,255,255,.12);
}
.si-foot__role { font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: var(--c-accent); }
.si-foot a { font-size: .74rem; letter-spacing: .1em; text-transform: uppercase; color: #8d8379; text-decoration: none; }
.si-foot a:hover { color: #fff; }
/* --- shell contenuto --- */
.si-body { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }
.si-top {
display: flex; align-items: baseline; justify-content: space-between; gap: 20px;
background: var(--si-surface); border-bottom: 1px solid var(--si-line); padding: 16px 32px;
position: sticky; top: 0; z-index: 10;
}
.si-top p { margin: 0; }
.si-top__crumbs { font-family: var(--font-heading); font-size: .74rem; letter-spacing: .14em; text-transform: uppercase; color: var(--c-text-light); }
.si-top__crumbs strong { color: var(--c-heading); font-weight: 600; }
.si-top__studio { font-size: .8rem; color: var(--c-text-light); }
.si-main { padding: 34px 32px 70px; }
/* --- intestazione di pagina --- */
.si-head { margin-bottom: 28px; }
.si-head h1 { font-size: clamp(1.6rem, 3vw, 2.1rem); text-transform: none; letter-spacing: .02em; margin-bottom: .25em; }
.si-head p { margin: 0; color: var(--c-text-light); font-size: .9rem; }
/* --- griglie --- */
.si-grid { display: grid; gap: 20px; }
.si-grid--kpi { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.si-grid--2 { grid-template-columns: 2fr 1fr; align-items: start; }
.si-grid--halves { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.si-stack { display: flex; flex-direction: column; gap: 20px; }
.si-mt { margin-top: 20px; }
/* --- card --- */
.si-card { background: var(--si-surface); border: 1px solid var(--si-line); padding: 20px 22px; }
.si-card__head { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 16px; }
.si-card__title {
margin: 0; font-family: var(--font-heading); font-size: .78rem; font-weight: 600;
letter-spacing: .16em; text-transform: uppercase; color: var(--c-heading);
}
.si-card__action { font-family: var(--font-heading); font-size: .68rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: var(--c-accent-dark); text-decoration: none; }
.si-card__action:hover { text-decoration: underline; }
/* --- kpi --- */
.si-kpi__label { font-size: .78rem; color: var(--c-text-light); letter-spacing: .04em; }
.si-kpi__value { font-family: var(--font-heading); font-size: 2rem; font-weight: 500; color: var(--c-heading); margin: 6px 0 4px; }
.si-kpi__delta { font-size: .78rem; font-weight: 600; }
.si-kpi__delta--up { color: var(--si-ok); }
.si-kpi__delta--down { color: var(--si-bad); }
/* --- liste e tabelle --- */
.si-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.si-list--rows > li { display: flex; align-items: center; justify-content: space-between; gap: 14px; font-size: .88rem; }
.si-list--defs .si-list__row { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; font-size: .88rem; }
.si-list--defs dd { margin: 0; color: var(--c-heading); }
.si-muted { color: var(--c-text-light); }
.si-small { font-size: .78rem; }
.si-note p { margin: 0; font-size: .84rem; }
.si-note__meta { margin-top: 2px; font-size: .76rem; color: var(--c-text-light); }
.si-table { width: 100%; border-collapse: collapse; font-size: .88rem; }
.si-table th, .si-table td { border-bottom: 1px solid var(--si-line); padding: 11px 10px; text-align: left; vertical-align: middle; }
.si-table th {
font-family: var(--font-heading); font-size: .68rem; font-weight: 600; letter-spacing: .14em;
text-transform: uppercase; color: var(--c-text-light);
}
.si-table tbody tr:hover { background: var(--c-bg-alt); }
.si-table a { color: var(--c-accent-dark); font-weight: 600; text-decoration: none; }
.si-table a:hover { text-decoration: underline; }
.si-table__num { font-family: var(--font-heading); }
/* --- elementi --- */
.si-avatar {
display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
border-radius: 50%; background: var(--c-accent); color: #fff; font-family: var(--font-heading);
font-size: .74rem; font-weight: 600; letter-spacing: .04em; flex: 0 0 34px;
}
.si-tag {
display: inline-block; border: 1px solid var(--si-line); padding: 2px 9px; margin-right: 5px;
font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; color: var(--c-text-light);
}
.si-badge { display: inline-block; padding: 2px 9px; font-size: .68rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.si-badge--ok { background: rgba(111,143,106,.16); color: var(--si-ok); }
.si-badge--warn { background: rgba(192,138,62,.16); color: var(--si-warn); }
.si-badge--bad { background: rgba(176,90,78,.16); color: var(--si-bad); }
.si-alert { display: flex; gap: 12px; align-items: flex-start; padding: 12px 0; border-bottom: 1px solid var(--si-line); }
.si-alert:last-child { border-bottom: 0; }
.si-alert__mark { width: 7px; height: 7px; border-radius: 50%; margin-top: 7px; flex: 0 0 7px; background: var(--si-warn); }
.si-alert--error .si-alert__mark { background: var(--si-bad); }
.si-alert__text { font-size: .88rem; font-weight: 600; color: var(--c-heading); }
.si-alert__meta { font-size: .76rem; color: var(--c-text-light); }
.si-btn {
display: inline-block; border: 1px solid var(--si-line); background: none; cursor: pointer;
padding: 6px 14px; font-family: var(--font-heading); font-size: .66rem; font-weight: 600;
letter-spacing: .14em; text-transform: uppercase; color: var(--c-heading); text-decoration: none;
}
.si-btn:hover { border-color: var(--c-accent); color: var(--c-accent-dark); }
.si-btn--solid { background: var(--c-dark); border-color: var(--c-dark); color: #fff; }
.si-btn--solid:hover { background: var(--c-dark-2); color: #fff; }
.si-field { display: flex; flex-direction: column; gap: 6px; font-size: .82rem; color: var(--c-text-light); }
.si-field input, .si-field select, .si-field textarea {
border: 1px solid var(--si-line); background: #fff; padding: 9px 11px; font: inherit;
font-size: .88rem; color: var(--c-text); border-radius: 0;
}
.si-field input:focus, .si-field select:focus, .si-field textarea:focus { outline: 2px solid var(--c-accent); outline-offset: -2px; }
/* --- misura, barre --- */
.si-bar { height: 6px; background: var(--c-bg-alt); overflow: hidden; }
.si-bar__fill { height: 100%; background: var(--c-accent); }
.si-bar__fill--ok { background: var(--si-ok); }
.si-bar__fill--warn { background: var(--si-warn); }
.si-bar__fill--bad { background: var(--si-bad); }
.si-score { display: flex; align-items: baseline; gap: 8px; }
.si-score__value { font-family: var(--font-heading); font-size: 1.9rem; font-weight: 500; color: var(--c-heading); }
.si-score__max { font-size: .82rem; color: var(--c-text-light); }
/* --- tab (isole React) --- */
.si-tabs { display: flex; gap: 26px; border-bottom: 1px solid var(--si-line); margin-bottom: 22px; }
.si-tabs__btn {
background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer; padding: 10px 2px;
font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .14em;
text-transform: uppercase; color: var(--c-text-light);
}
.si-tabs__btn[aria-selected='true'] { color: var(--c-heading); border-bottom-color: var(--c-accent); }
.si-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 16px; }
.si-chip {
background: none; border: 1px solid var(--si-line); cursor: pointer; padding: 5px 12px;
font-family: var(--font-heading); font-size: .66rem; font-weight: 600; letter-spacing: .12em;
text-transform: uppercase; color: var(--c-text-light);
}
.si-chip[aria-pressed='true'] { border-color: var(--c-accent); background: var(--c-bg-alt); color: var(--c-accent-dark); }
.si-chart { width: 100%; }
.si-chart__empty { font-size: .85rem; color: var(--c-text-light); }
/* --- mobile --- */
.si-menu-btn { display: none; }
@media (max-width: 900px) {
.si { display: block; }
.si-menu-btn {
display: block; position: sticky; top: 0; z-index: 20; background: var(--c-dark); color: #fff;
font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em;
text-transform: uppercase; padding: 14px 20px; cursor: pointer;
}
.si-side { display: none; width: auto; flex: none; height: auto; position: static; }
.si-menu-toggle:checked ~ .si-side { display: flex; }
.si-top { padding: 14px 20px; flex-direction: column; gap: 4px; }
.si-main { padding: 24px 20px 60px; }
.si-grid--2 { grid-template-columns: 1fr; }
}
/* --- elenco clienti --- */
.si-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 16px; }
.si-toolbar p { margin: 0; }
.si-field--inline { flex-direction: row; align-items: center; }
.si-field--inline input { min-width: 260px; }
.si-visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.si-client { display: flex; align-items: center; gap: 10px; text-decoration: none; }
.si-client__name { display: block; font-weight: 600; color: var(--c-heading); }
.si-client__mail { display: block; font-size: .76rem; color: var(--c-text-light); font-weight: 400; }
.si-client:hover .si-client__name { color: var(--c-accent-dark); }
.si-meter { display: flex; align-items: center; gap: 10px; }
.si-meter .si-bar { width: 74px; flex: 0 0 74px; }
.si-empty { margin: 16px 0 0; }
/* --- scheda cliente --- */
.si-client-head { display: flex; align-items: center; gap: 16px; }
.si-client-head h1 { margin: 0 0 2px; font-size: clamp(1.5rem, 2.6vw, 1.9rem); text-transform: none; letter-spacing: .02em; }
.si-client-head p { margin: 0; }
.si-avatar--lg { width: 52px; height: 52px; flex: 0 0 52px; font-size: .95rem; }
.si-gauges { display: flex; flex-wrap: wrap; gap: 20px; justify-content: space-around; }
.si-gauge { width: 150px; text-align: center; }
.si-gauge__svg { width: 100%; height: auto; }
.si-gauge__value { margin: 2px 0 0; font-family: var(--font-heading); font-size: 1.6rem; font-weight: 500; color: var(--c-heading); }
.si-gauge__max { font-size: .78rem; color: var(--c-text-light); }
.si-gauge__label { margin: 0; font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: var(--c-text-light); }
.si-insight { background: var(--c-dark); color: #cfc6bd; padding: 22px 24px; }
.si-insight p { margin: 0; font-size: .9rem; }
.si-insight__title {
font-family: var(--font-heading); font-size: .7rem; font-weight: 600; letter-spacing: .18em;
text-transform: uppercase; color: var(--c-accent); margin-bottom: 8px !important;
}
.si-scroll-x { overflow-x: auto; }
.si-note-card { border: 1px solid var(--si-line); padding: 12px 14px; }
.si-note-card p { margin: 0; font-size: .86rem; }
.si-chat { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.si-chat__row { display: flex; }
.si-chat__row--professionista { justify-content: flex-end; }
.si-chat__bubble { max-width: 70%; padding: 10px 14px; background: var(--c-bg-alt); border: 1px solid var(--si-line); }
.si-chat__row--professionista .si-chat__bubble { background: var(--c-dark); border-color: var(--c-dark); color: #efe9e1; }
.si-chat__bubble p { margin: 0; font-size: .86rem; }
.si-chat__when { margin-top: 4px !important; font-size: .7rem; opacity: .7; }
.si-chat__compose { display: flex; align-items: center; gap: 10px; }
.si-chat__compose .si-field { flex: 1; }
.si-chat__compose input { width: 100%; }
.si-tag-list { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.si-tag--removable { display: inline-flex; align-items: center; gap: 7px; margin-right: 0; }
.si-tag--removable button { background: none; border: 0; cursor: pointer; color: inherit; font-size: .7rem; padding: 0; }
/* --- analytics, sport, impostazioni --- */
.si-head--row { display: flex; align-items: flex-end; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.si-segment { border: 1px solid var(--si-line); padding: 16px 18px; }
.si-segment__label { margin: 0; font-weight: 600; color: var(--c-heading); font-size: .9rem; }
.si-segment p { margin: 0; }
.si-segment .si-kpi__value { margin: 6px 0 2px; }
.si-form-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px; }
.si-prefs > li { align-items: flex-start; }
.si-prefs strong { display: block; font-size: .88rem; color: var(--c-heading); }
.si-prefs .si-small { display: block; }
/* --- team live --- */
.si-live { text-align: center; padding: 54px 26px; }
.si-live__title { font-family: var(--font-heading); font-size: 1.05rem; color: var(--c-heading); margin: 0 0 6px; }
.si-live__how { max-width: 560px; margin: 32px auto 0; border: 1px solid var(--si-line); padding: 20px 22px; text-align: left; background: var(--c-bg-alt); }
.si-steps { list-style: none; margin: 14px 0 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.si-steps li { display: flex; gap: 12px; align-items: flex-start; font-size: .86rem; color: var(--c-text); }
.si-steps__num {
flex: 0 0 24px; width: 24px; height: 24px; border-radius: 50%; background: var(--c-accent); color: #fff;
display: inline-flex; align-items: center; justify-content: center; font-family: var(--font-heading);
font-size: .72rem; font-weight: 600;
}
/* --- organizzazione --- */
.si-center { display: flex; justify-content: center; padding: 40px 0; }
.si-org { width: 100%; max-width: 460px; text-align: center; padding: 34px 32px; }
.si-org h1 { font-size: 1.4rem; text-transform: none; letter-spacing: .02em; margin-bottom: .4em; }
.si-org p { margin: 0; }
.si-org .si-field { text-align: left; }
.si-org__cta:disabled { opacity: .45; cursor: not-allowed; }