Reveal.js deck + prototypes + speaker scripts for the talk 'Role of AI in the Analysis of Unstructured Clinical Databases' (AritmoLab — Policlinico San Donato, 2-3 October 2026). Lives on its own branch while in progress; not for main until ready.
406 lines
25 KiB
HTML
406 lines
25 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>PROTOTYPE · Icon variants — legacy systems (slides 02 & 03)</title>
|
||
<link rel="stylesheet" href="../deck/fonts.css">
|
||
<style>
|
||
:root {
|
||
--bordeaux: #cb333b; --bordeaux-deep: #8f1204; --bordeaux-tint: #f4dfe1;
|
||
--surface: #fdfcfc; --surface-alt: #f6f5f5; --surface-sunken: #ecebeb;
|
||
--ink: #2a2426; --ink-muted: #6b6568;
|
||
--line: #e3e0e1; --line-strong: #c9c5c6;
|
||
--sans: 'Source Sans 3', system-ui, sans-serif;
|
||
--mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
|
||
}
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body { background: var(--surface-sunken); font-family: var(--sans); padding: 36px 0 90px; color: var(--ink); }
|
||
|
||
.note { width: 1280px; margin: 0 auto 18px; padding: 12px 18px; background: #fff8e6; border: 1px solid #e8d9a8;
|
||
border-radius: 8px; font: 400 13px/1.5 var(--sans); color: #6b5d2a; }
|
||
.note b { font-weight: 700; }
|
||
|
||
.switcher { position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
|
||
display: flex; align-items: center; gap: 6px; padding: 8px 10px; background: #2a2426;
|
||
border-radius: 9999px; box-shadow: 0 6px 24px rgba(0,0,0,.25); z-index: 10; white-space: nowrap; }
|
||
.switcher .tag { font: 700 10px/1 var(--mono); letter-spacing: .1em; color: #9c9598; padding: 0 10px; }
|
||
.switcher a { display: inline-flex; height: 30px; align-items: center; padding: 0 14px; border-radius: 9999px;
|
||
font: 700 12px/1 var(--sans); color: #fdfcfc; text-decoration: none; opacity: .75; }
|
||
.switcher a.active { background: var(--bordeaux); opacity: 1; }
|
||
.switcher .who { font: 400 11px/1 var(--sans); color: #9c9598; padding: 0 12px 0 8px; max-width: 430px; white-space: normal; }
|
||
|
||
.slide { position: relative; width: 1280px; margin: 0 auto 34px; display: flex; flex-direction: column;
|
||
overflow: hidden; background: var(--surface); color: var(--ink); border: 1px solid var(--line);
|
||
border-radius: 8px; height: 720px; }
|
||
.head { flex: 0 0 104px; display: flex; align-items: center; justify-content: space-between;
|
||
padding: 0 40px; background: var(--surface); border-bottom: 1px solid var(--line); }
|
||
.head img { height: 80px; display: block; }
|
||
.head-org { font: 700 11.5px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-muted); }
|
||
.band { flex: 0 0 46px; display: flex; align-items: center; justify-content: space-between;
|
||
padding: 0 40px; background: var(--bordeaux); color: var(--surface); }
|
||
.band-section { font: 700 13px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; }
|
||
.jump { background: transparent; color: #fff; border: none; padding: 6px 12px;
|
||
font: 700 11.5px/1.2 var(--sans); letter-spacing: .04em; }
|
||
.foot { flex: 0 0 34px; display: flex; align-items: center; justify-content: space-between; gap: 24px;
|
||
padding: 0 40px; border-top: 1px solid var(--line); font: 600 10px/1.4 var(--sans);
|
||
letter-spacing: .03em; color: var(--ink-muted); }
|
||
.foot span { white-space: nowrap; }
|
||
.foot span:first-child { overflow: hidden; text-overflow: ellipsis; }
|
||
.sbody { flex: 1; display: flex; flex-direction: column; padding: 30px 48px 22px; }
|
||
.kicker { font: 700 12px/1 var(--sans); letter-spacing: .16em; text-transform: uppercase;
|
||
color: var(--bordeaux); margin-bottom: 14px; }
|
||
h2 { font: 700 30px/1.15 var(--sans); color: var(--ink); margin: 0 0 8px; }
|
||
.hint { margin-top: 12px; font: italic 400 12px/1.4 var(--sans); color: var(--ink-muted); }
|
||
.lead { font: 400 15px/1.5 var(--sans); color: var(--ink-muted); margin: 4px 0 14px; }
|
||
|
||
/* ---------- SLIDE 02 · system map ---------- */
|
||
.sysmap { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; flex: 1; align-content: center; }
|
||
.syscard { position: relative; display: flex; flex-direction: column; align-items: center; width: 100%;
|
||
border: 1.5px solid var(--line-strong); border-radius: 10px; background: var(--surface-alt);
|
||
padding: 18px 16px 14px; text-align: center; cursor: pointer; font-family: var(--sans);
|
||
transition: transform .15s ease, box-shadow .15s ease; }
|
||
.syscard:hover, .syscard:focus-visible { transform: translateY(-3px); box-shadow: 0 6px 18px rgba(42,36,38,.14); outline: none; }
|
||
.syscard b { display: block; font: 700 17px/1.3 var(--sans); color: var(--ink); margin: 10px 0 5px; }
|
||
.syscard .d { display: block; font: 400 12.5px/1.45 var(--sans); color: var(--ink-muted); }
|
||
.syscard .tag { position: absolute; top: -10px; right: 12px; background: var(--bordeaux); color: #fff;
|
||
border-radius: 9999px; padding: 3px 10px; font: 700 9.5px/1 var(--sans); letter-spacing: .08em; }
|
||
.syscard.ghost { border: 1.5px dashed var(--bordeaux); background: #fff; cursor: default; }
|
||
.syscard.ghost b { color: var(--bordeaux-deep); }
|
||
.syscard.ghost .tag { background: var(--bordeaux-deep); }
|
||
|
||
/* ---------- SLIDE 03 · flow with iconized sources ---------- */
|
||
.flow { display: flex; align-items: stretch; gap: 14px; flex: 1; min-height: 0; margin-top: 6px; }
|
||
.zone { border-radius: 8px; padding: 28px 14px 12px; position: relative; }
|
||
.zone > .zlabel { position: absolute; top: 8px; left: 14px; font: 700 10px/1 var(--mono);
|
||
letter-spacing: .14em; text-transform: uppercase; }
|
||
.zone.existed { flex: 0 0 210px; background: var(--surface-alt); border: 1px dashed var(--line-strong); }
|
||
.zone.existed > .zlabel { color: var(--ink-muted); }
|
||
.zone.built { flex: 1; background: #faf4f5; border: 1px solid #e7c3c6; }
|
||
.zone.built > .zlabel { color: var(--bordeaux); }
|
||
.zone.built .row { display: flex; align-items: center; gap: 10px; height: 100%; }
|
||
.fcol { flex: 1; display: flex; flex-direction: column; gap: 8px; min-width: 0; }
|
||
.fbox { background: #fff; border: 1px solid var(--line-strong); border-radius: 6px; padding: 9px 8px; text-align: center; }
|
||
.fbox b { display: block; font: 700 12.5px/1.25 var(--sans); }
|
||
.fbox span { display: block; margin-top: 2px; font: 400 10.5px/1.3 var(--sans); color: var(--ink-muted); }
|
||
.fbox.end { background: var(--bordeaux); border-color: var(--bordeaux); color: #fff; }
|
||
.fbox.end span { color: rgba(255,255,255,.85); }
|
||
.farrow { align-self: center; color: var(--bordeaux); font: 700 14px/1 var(--sans); }
|
||
.fcol.src-icons { flex: 0 0 190px; justify-content: space-evenly; }
|
||
.src-item { display: flex; flex-direction: column; align-items: center; gap: 2px; }
|
||
.src-item b { font: 700 12px/1.2 var(--sans); }
|
||
</style>
|
||
</head>
|
||
<body class="i1">
|
||
|
||
<div class="note"><b>EVALUATION</b> — tre ipotesi di iconografia disegnata per i 4 sistemi di partenza (+ 2 "missing"),
|
||
applicate a slide 02 e 03. Nel file finale il set vincitore verrà <b>incorporato come SVG inline</b> (nessuna dipendenza, scalabile, colorabile col brand).</div>
|
||
|
||
<main id="deck"></main>
|
||
|
||
<nav class="switcher">
|
||
<span class="tag">PROTOTYPE</span>
|
||
<a href="?i=1" data-v="1">1 · App badges</a>
|
||
<a href="?i=2" data-v="2">2 · Era artifacts</a>
|
||
<a href="?i=3" data-v="3">3 · Emblems</a>
|
||
<span class="who" id="who"></span>
|
||
</nav>
|
||
|
||
<script>
|
||
/* ================================================================
|
||
ICONS — hand-drawn SVG, three styles
|
||
================================================================ */
|
||
const S = (inner, vb = '0 0 48 48', cls = '') =>
|
||
`<svg class="ico ${cls}" viewBox="${vb}" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round">${inner}</svg>`;
|
||
|
||
const MONO = {
|
||
cardioref: S(`<rect x="8" y="6" width="32" height="36" rx="3"/>
|
||
<path d="M8 14 H40"/><path d="M31 10 h6"/><path d="M34 7 v6"/>
|
||
<path d="M13 22 H28"/><path d="M13 28 H34"/><path d="M13 34 H22"/>
|
||
<path d="M29 36 c0-2.2 3-3.2 4.2-1.2 1.2-2 4.2-1 4.2 1.2 0 2.4-4.2 4.4-4.2 4.4 s-4.2-2-4.2-4.4z"/>`),
|
||
genetic: S(`<path d="M18 4 C30 11 30 19 18 26 C10 31 10 37 18 44"/>
|
||
<path d="M30 4 C18 11 18 19 30 26 C38 31 38 37 30 44"/>
|
||
<path d="M17 9 H31"/><path d="M15 16 H33"/><path d="M17 23 H31"/><path d="M14 32 H26"/>
|
||
<rect x="30" y="31" width="13" height="13" rx="1.5" stroke-width="2"/>
|
||
<path d="M30 36 H43"/><path d="M36 31 V44"/>`),
|
||
omics: S(`<rect x="7" y="11" width="34" height="29" rx="3"/>
|
||
<path d="M7 17 H41"/><circle cx="11" cy="14" r="0.8" fill="currentColor"/><circle cx="15" cy="14" r="0.8" fill="currentColor"/>
|
||
<path d="M24 30 c0-2.4 3.2-3.4 4.4-1.3 1.2-2.1 4.4-1.1 4.4 1.3 0 2.6-4.4 4.8-4.4 4.8 s-4.4-2.2-4.4-4.8z"/>
|
||
<path d="M12 26 h5"/><path d="M36 26 h-5"/><path d="M17 26 h2"/><path d="M34 26 h-2"/>`),
|
||
ecg: S(`<rect x="8" y="10" width="32" height="28" rx="2"/>
|
||
<path d="M12 15 h4"/><path d="M20 15 h4"/><path d="M28 15 h4"/><path d="M36 15 h-1"/>
|
||
<path d="M11 30 h6 l3-9 4 15 3-7 h10"/>
|
||
<rect x="28" y="33" width="10" height="4" rx="1" stroke-width="1.8"/>`),
|
||
};
|
||
const FLAT = {
|
||
cardioref: S(`<rect x="5" y="7" width="38" height="27" rx="2" fill="#efece7" stroke-width="2.2"/>
|
||
<rect x="8" y="10" width="32" height="21" rx="1" fill="#dfe9f4" stroke-width="1.8"/>
|
||
<rect x="8" y="10" width="32" height="4" fill="#c9d7e8" stroke="none"/>
|
||
<path d="M11 20 H26" stroke-width="1.8"/><path d="M11 24 H30" stroke-width="1.8"/>
|
||
<path d="M11 28 H20" stroke-width="1.8"/>
|
||
<path d="M30 26 c0-2 2.8-3 4-1.2 1.2-1.8 4-0.8 4 1.2 0 2.2-4 4-4 4 s-4-1.8-4-4z" fill="#cb333b" stroke="none"/>
|
||
<rect x="19" y="34" width="10" height="3" fill="#efece7" stroke-width="1.8"/>
|
||
<rect x="13" y="37" width="22" height="3" rx="1" fill="#efece7" stroke-width="1.8"/>`, '0 0 48 44'),
|
||
genetic: S(`<rect x="5" y="8" width="15" height="32" rx="2" fill="#f0f0f0" stroke-width="2.2"/>
|
||
<rect x="8" y="12" width="9" height="3" rx="1" fill="#fff" stroke-width="1.6"/>
|
||
<circle cx="10" cy="22" r="1.6" fill="#cb333b" stroke="none"/><circle cx="15" cy="22" r="1.6" fill="#cb333b" stroke="none"/>
|
||
<rect x="8" y="27" width="9" height="6" rx="1" fill="#fff" stroke-width="1.6"/>
|
||
<rect x="26" y="5" width="17" height="36" rx="1" fill="#fff" stroke-width="2.2"/>
|
||
<path d="M26 11 H43" stroke-width="1.6"/><path d="M31.5 5 V41" stroke-width="1.2"/><path d="M37.5 5 V41" stroke-width="1.2"/>
|
||
<path d="M26 17 H43" stroke-width="1.2"/><path d="M26 23 H43" stroke-width="1.2"/><path d="M26 29 H43" stroke-width="1.2"/>
|
||
<path d="M35 30 l8 8 -2.5 1 -1.5 2.5 -4-9z" fill="#cb333b" stroke="none"/>
|
||
<path d="M24 24 C24 18 24 16 24 14" stroke-width="1.6" stroke-dasharray="3 3"/>`),
|
||
omics: S(`<rect x="8" y="14" width="32" height="26" rx="2" fill="#fff" stroke-width="2.2"/>
|
||
<path d="M8 20 H40" stroke-width="1.8"/><circle cx="12" cy="17" r="1" fill="#cb333b" stroke="none"/>
|
||
<circle cx="16" cy="17" r="1" fill="#cb333b" stroke="none"/>
|
||
<path d="M24 34 c0-2.4 3.2-3.4 4.4-1.3 1.2-2.1 4.4-1.1 4.4 1.3 0 2.6-4.4 4.8-4.4 4.8 s-4.4-2.2-4.4-4.8z" fill="#cb333b" stroke="none"/>
|
||
<path d="M24 14 C24 10 20 9 18 6" stroke-width="1.8" stroke-dasharray="3 3"/>
|
||
<path d="M24 14 C24 10 28 9 30 6" stroke-width="1.8" stroke-dasharray="3 3"/>
|
||
<path d="M18 6 c0 0 3-1 4 2" stroke-width="1.8"/><path d="M30 6 c0 0 -3-1 -4 2" stroke-width="1.8"/>
|
||
<path d="M13 27 h5 l2-3 2 5" stroke-width="1.6"/><path d="M33 27 h5" stroke-width="1.6"/>`),
|
||
ecg: S(`<rect x="6" y="16" width="22" height="22" rx="2" fill="#f0f0f0" stroke-width="2.2"/>
|
||
<rect x="9" y="20" width="16" height="9" rx="1" fill="#fff" stroke-width="1.6"/>
|
||
<path d="M10.5 24.5 h3 l1.5-3 2 5 1.5-2 h5" stroke-width="1.4"/>
|
||
<circle cx="11" cy="33" r="1.8" fill="#cb333b" stroke="none"/><circle cx="16" cy="33" r="1.8" fill="#cb333b" stroke="none"/>
|
||
<rect x="31" y="6" width="11" height="32" rx="1" fill="#fff" stroke-width="2.2"/>
|
||
<path d="M34 10 h5 M34 13 h5 M34 38 h5" stroke-width="1.2"/>
|
||
<path d="M33 16 l6 2 -4 4 6 2" stroke-width="1.6"/>
|
||
<rect x="30" y="40" width="13" height="5" rx="1" fill="#cb333b" stroke="none"/>
|
||
<text x="36.5" y="44" font-family="monospace" font-size="3.6" fill="#fff" stroke="none" text-anchor="middle">CSV</text>`),
|
||
};
|
||
const EMB = {
|
||
cardioref: S(`<circle cx="24" cy="24" r="20" stroke-width="2.6"/>
|
||
<path d="M24 33 c-6-3.5-9-7-9-10.5 0-3 4-5.5 7-3 1 .8 1.6 1.8 2 3 .4-1.2 1-2.2 2-3 3-2.5 7 0 7 3 0 3.5-3 7-9 10.5z" fill="currentColor" stroke="none"/>
|
||
<path d="M22.5 21 h3 v3 h3 v3 h-3 v3 h-3 v-3 h-3 v-3 h3 z" fill="#fff" stroke="none"/>`),
|
||
genetic: S(`<circle cx="24" cy="24" r="20" stroke-width="2.6"/>
|
||
<path d="M18 8 C28 14 28 20 18 26 C12 30 12 35 18 40"/>
|
||
<path d="M30 8 C20 14 20 20 30 26 C36 30 36 35 30 40"/>
|
||
<path d="M17 12 H31"/><path d="M15.5 18 H32.5"/><path d="M17 24 H31"/><path d="M14.5 31 H22"/>
|
||
<rect x="25" y="29" width="12" height="12" rx="1.5" stroke-width="2"/>
|
||
<path d="M25 34 H37"/><path d="M30.5 29 V41"/>`),
|
||
omics: S(`<circle cx="24" cy="24" r="20" stroke-width="2.6"/>
|
||
<circle cx="24" cy="24" r="4" fill="currentColor" stroke="none"/>
|
||
<circle cx="24" cy="10" r="3.4"/><circle cx="11.5" cy="31" r="3.4"/><circle cx="36.5" cy="31" r="3.4"/>
|
||
<path d="M24 20.5 V13.5"/><path d="M21 26.5 L14 29.5"/><path d="M27 26.5 L34 29.5"/>`),
|
||
ecg: S(`<circle cx="24" cy="24" r="20" stroke-width="2.6"/>
|
||
<path d="M9 24 h6 l3-9 5 16 3-7 h14" stroke-width="2.4"/>
|
||
<circle cx="24" cy="24" r="1.8" fill="currentColor" stroke="none"/>`),
|
||
};
|
||
const MISSING = {
|
||
1: S(`<rect x="8" y="8" width="32" height="32" rx="4" stroke-dasharray="5 4" stroke-width="2.2"/>
|
||
<path d="M18 18 L30 30" stroke-width="2.4"/><path d="M30 18 L18 30" stroke-width="2.4"/>`),
|
||
2: S(`<ellipse cx="24" cy="38" rx="14" ry="4" stroke-dasharray="4 4" stroke-width="2"/>
|
||
<path d="M24 34 V16" stroke-dasharray="4 4" stroke-width="2.2"/>
|
||
<path d="M13 16 h22" stroke-width="2.2"/><path d="M24 8 v4" stroke-width="2"/>`),
|
||
3: S(`<circle cx="24" cy="24" r="20" stroke-dasharray="5 4" stroke-width="2.4"/>
|
||
<path d="M15 33 L33 15" stroke-width="2.4"/><circle cx="17" cy="17" r="2.4" fill="currentColor" stroke="none"/>`),
|
||
};
|
||
|
||
const STYLE_ICON = (style, sys) => {
|
||
const dict = { 1: MONO, 2: FLAT, 3: EMB }[style];
|
||
return dict[sys];
|
||
};
|
||
const ICON_CLS = { 1: 'i-mono', 2: 'i-flat', 3: 'i-emb' };
|
||
|
||
/* ================================================================
|
||
SLIDES
|
||
================================================================ */
|
||
const SYS = [
|
||
{ id: 'cardioref', name: 'Cardioref', scope: 'hospital procedures: visits, operations, reports — on relational forms' },
|
||
{ id: 'genetic', name: 'Genetic data', scope: 'DNA instruments — but the data is typed into Excel by hand' },
|
||
{ id: 'omics', name: 'Omics Portal', scope: 'meant to host Cardioref + genetics — still immature' },
|
||
{ id: 'ecg', name: 'ECG', scope: 'classic devices: paper strip + a CSV you can view on request' },
|
||
];
|
||
const GHOSTS = [
|
||
{ name: 'No Health Intelligence', scope: 'nothing usable to analyse historical data' },
|
||
{ name: 'No ML-ready datamarts', scope: 'nothing for predictive statistics or machine learning' },
|
||
];
|
||
|
||
const CONTRIBS = {
|
||
cardioref: { kicker: 'The starting point · 20 years ago', title: 'Cardioref — the daily workhorse',
|
||
body: `<p class="lead">A traditional relational application: classic forms for the typical hospital procedures.</p>
|
||
<ul class="pop-list">
|
||
<li><b>Used for</b> — visits, operations, reports: the daily management of the Arrhythmology Unit</li>
|
||
<li><b>Good at it</b> — twenty years of patient management on structured records</li>
|
||
<li><b>The catch</b> — the clinical story is told in free-text fields, not in the boxes designed for it</li>
|
||
</ul>
|
||
<div class="roi"><b class="k">Problem</b>Almost unusable for research: the knowledge is there — locked in prose.</div>` },
|
||
genetic: { kicker: 'The starting point · 20 years ago', title: 'Genetic data — sophisticated in, Excel out',
|
||
body: `<p class="lead">The DNA instruments are state-of-the-art. What happens after them is not.</p>
|
||
<ul class="pop-list">
|
||
<li><b>Used for</b> — running the genetic analyses that the Unit prescribes</li>
|
||
<li><b>The catch</b> — results are transcribed by hand into Excel files</li>
|
||
<li><b>Never connected</b> — Cardioref has no idea genetics exists</li>
|
||
</ul>
|
||
<div class="roi"><b class="k">Problem</b>Two parallel worlds: genotypes on one side, clinical records on the other.</div>` },
|
||
omics: { kicker: 'The starting point · 20 years ago', title: 'Omics Portal — the right idea, too soon',
|
||
body: `<p class="lead">A portal meant to host both Cardioref and the genetic data — the seed of AritmoLab.</p>
|
||
<ul class="pop-list">
|
||
<li><b>Used for</b> — the first 360° patient-management features</li>
|
||
<li><b>The catch</b> — functionality still immature</li>
|
||
<li><b>Never connected</b> — it could not see the data it was meant to host</li>
|
||
</ul>
|
||
<div class="roi"><b class="k">Problem</b>A promising idea without a bridge: too young to carry the data.</div>` },
|
||
ecg: { kicker: 'The starting point · 20 years ago', title: 'ECG — paper, and a CSV if you ask',
|
||
body: `<p class="lead">Classic ECG devices: they print the strip, and they can export a file.</p>
|
||
<ul class="pop-list">
|
||
<li><b>Used for</b> — acquiring and viewing ECG traces</li>
|
||
<li><b>The catch</b> — no machine-to-machine communication</li>
|
||
<li><b>The only door out</b> — a CSV file, produced on request</li>
|
||
</ul>
|
||
<div class="roi"><b class="k">Problem</b>Every ECG meant a manual download — automation was impossible by design.</div>` },
|
||
};
|
||
|
||
const chrome = (band) => `
|
||
<header class="head"><img src="logo.png" alt=""><span class="head-org">AritmoLab · Policlinico San Donato</span></header>
|
||
<nav class="band"><span class="band-section">${band}</span><span class="jump">0X · …</span></nav>`;
|
||
|
||
const foot = `<footer class="foot"><span>Role of AI in the Analysis of Unstructured Clinical Databases · Dr. Marco Pancotti - MultiPhysixLab · Dr. Sara Paratico - Gruppo San Donato · San Donato Milanese, Milan, Italy · 2–3 October 2026</span><span>0X / 15</span></footer>`;
|
||
|
||
function iconBox(sys, style, size) {
|
||
return `<span class="icon-wrap ${ICON_CLS[style]}" style="--icon:${size}px">${STYLE_ICON(style, sys.id)}</span>`;
|
||
}
|
||
|
||
function slide02(style) {
|
||
const cards = SYS.map(s => `
|
||
<button class="syscard" data-start="${s.id}">
|
||
${iconBox(s, style, style === '3' ? 104 : 96)}
|
||
<b>${s.name}</b><span class="d">${s.scope}</span>
|
||
</button>`).join('');
|
||
const ghosts = GHOSTS.map(g => `
|
||
<div class="syscard ghost">
|
||
<span class="icon-wrap">${S(MISSING[String(style)], '0 0 48 48')}</span>
|
||
<b>${g.name}</b><span class="d">${g.scope}</span>
|
||
</div>`).join('');
|
||
return `
|
||
<section class="slide">
|
||
${chrome('Where we started')}
|
||
<div class="sbody">
|
||
<div class="kicker">Twenty years ago</div>
|
||
<h2>Four islands and two missing pieces</h2>
|
||
<div class="sysmap">${cards}${ghosts}</div>
|
||
<p class="hint">▸ click a system: how it was used — and what held it back</p>
|
||
</div>
|
||
${foot}
|
||
<aside class="notes">[icon evaluation — content as in the deck]</aside>
|
||
</section>`;
|
||
}
|
||
|
||
function slide03(style) {
|
||
const srcIcons = SYS.map(s => `
|
||
<div class="src-item">${iconBox(s, style, style === '3' ? 64 : 58)}<b>${s.name}</b></div>`).join('');
|
||
const ghostIcon = (style) => S(MISSING[String(style)], '0 0 48 48');
|
||
return `
|
||
<section class="slide">
|
||
${chrome('The plan')}
|
||
<div class="sbody">
|
||
<div class="kicker">The plan · what we wanted to build</div>
|
||
<h2>One platform, two destinations</h2>
|
||
<div class="flow">
|
||
<div class="zone existed">
|
||
<span class="zlabel">What existed — to connect</span>
|
||
<div class="fcol src-icons">
|
||
${srcIcons}
|
||
<div class="src-item"><span class="icon-wrap" style="width:56px;height:56px;color:var(--bordeaux);opacity:.45">${ghostIcon(style)}</span><b style="color:var(--bordeaux-deep)">missing</b></div>
|
||
</div>
|
||
</div>
|
||
<div class="farrow">→</div>
|
||
<div class="zone built">
|
||
<span class="zlabel">What we wanted to build</span>
|
||
<div class="row">
|
||
<div class="fcol"><div class="fbox"><b>Staging</b><span>raw replica</span></div></div>
|
||
<div class="farrow">→</div>
|
||
<div class="fcol"><div class="fbox"><b>Integration</b><span>clean · text mining</span></div></div>
|
||
<div class="farrow">→</div>
|
||
<div class="fcol"><div class="fbox"><b>Star schema</b><span>warehouse</span></div></div>
|
||
<div class="farrow">→</div>
|
||
<div class="fcol"><div class="fbox"><b>Datamarts</b><span>for research</span></div></div>
|
||
<div class="farrow">→</div>
|
||
<div class="fcol"><div class="fbox end"><b>AritmoLab</b><span>portal + warehouse</span></div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
${foot}
|
||
<aside class="notes">[icon evaluation — content as in the deck]</aside>
|
||
</section>`;
|
||
}
|
||
|
||
/* ================================================================ */
|
||
const VARIANTS = {
|
||
1: { desc: 'App badges in monoline: pictogrammi a tratto disegnati ad hoc in badge arrotondati (come icone di app). Puliti, moderni, professionali.' },
|
||
2: { desc: 'Era artifacts: mini-illustrazioni flat che raccontano l\u2019epoca — il vecchio monitor con le form, lo strumento genetico col foglio Excel e la matita, il portale germoglio, l\u2019ECG con lo strip e il tag CSV.' },
|
||
3: { desc: 'Emblems: medaglioni circolari istituzionali (stile stemma di reparto) — cuore+croce, elica, rete del portale, tracciato ECG. Sobri, molto brand GSD.' },
|
||
};
|
||
const q = new URLSearchParams(location.search);
|
||
const v = ['1','2','3'].includes(q.get('i')) ? q.get('i') : '1';
|
||
document.body.className = 'i' + v;
|
||
document.querySelectorAll('.switcher a').forEach(a => a.classList.toggle('active', a.dataset.v === v));
|
||
document.getElementById('who').textContent = VARIANTS[v].desc;
|
||
document.getElementById('deck').innerHTML = slide02(v) + slide03(v);
|
||
|
||
const pop = document.createElement('div');
|
||
pop.className = 'ai-pop';
|
||
pop.innerHTML = `<div class="ai-pop-card" role="dialog"><button class="ai-pop-x">✕</button>
|
||
<div class="ai-pop-kicker" id="kick"></div><div class="ai-pop-title" id="ttl"></div><div id="bdy"></div></div>`;
|
||
document.body.appendChild(pop);
|
||
const closePop = () => pop.classList.remove('open');
|
||
document.addEventListener('click', (e) => {
|
||
const s = e.target.closest('[data-start]');
|
||
if (s) {
|
||
const c = CONTRIBS[s.dataset.start];
|
||
document.getElementById('kick').textContent = c.kicker;
|
||
document.getElementById('ttl').textContent = c.title;
|
||
document.getElementById('bdy').innerHTML = c.body;
|
||
pop.classList.add('open');
|
||
return;
|
||
}
|
||
if (e.target.closest('.ai-pop-x') || e.target === pop) closePop();
|
||
});
|
||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closePop(); });
|
||
</script>
|
||
<style>
|
||
/* popup styles (same language as deck) */
|
||
.ai-pop { position: fixed; inset: 0; z-index: 100; background: rgba(42,36,38,.45);
|
||
display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity .2s; }
|
||
.ai-pop.open { opacity: 1; pointer-events: auto; }
|
||
.ai-pop-card { position: relative; width: min(560px, 92%); background: #fff; border: 1px solid var(--line);
|
||
border-radius: 12px; box-shadow: 0 18px 50px rgba(42,36,38,.28); padding: 24px 28px 22px;
|
||
transform: translateY(14px) scale(.95); transition: transform .24s cubic-bezier(.2,.9,.3,1.15); }
|
||
.ai-pop.open .ai-pop-card { transform: none; }
|
||
.ai-pop-kicker { font: 700 10.5px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--bordeaux); margin-bottom: 10px; }
|
||
.ai-pop-title { font: 700 18px/1.3 var(--sans); color: var(--ink); margin-bottom: 12px; }
|
||
.ai-pop-card p { font: 400 14px/1.65 var(--sans); color: var(--ink); margin: 0 0 12px; }
|
||
.pop-list { list-style: none; display: flex; flex-direction: column; gap: 9px; }
|
||
.pop-list li { position: relative; padding-left: 20px; font: 400 13.5px/1.5 var(--sans); }
|
||
.pop-list li::before { content: ''; position: absolute; left: 0; top: 7px; width: 8px; height: 8px; border-radius: 9999px; background: var(--bordeaux); }
|
||
.pop-list b { font-weight: 700; }
|
||
.roi { margin-top: 14px; border: 1.5px solid var(--bordeaux); background: #faf4f5; border-radius: 8px; padding: 10px 14px; font: 400 13.5px/1.55 var(--sans); }
|
||
.roi .k { display: block; margin-bottom: 4px; font: 800 10.5px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--bordeaux-deep); }
|
||
.ai-pop-x { position: absolute; top: 12px; right: 14px; width: 30px; height: 30px; border: none; border-radius: 9999px;
|
||
background: var(--surface-alt); font: 700 15px/1 var(--sans); color: var(--ink-muted); cursor: pointer; }
|
||
|
||
/* icon sizing */
|
||
.icon-wrap { display: flex; align-items: center; justify-content: center; width: var(--icon, 96px); height: var(--icon, 96px); }
|
||
.icon-wrap .ico { width: 100%; height: 100%; }
|
||
|
||
/* style 1 — monoline app badges */
|
||
.i1 .syscard .icon-wrap { background: #fff; border: 2.4px solid var(--bordeaux); border-radius: 22px;
|
||
color: var(--bordeaux-deep); }
|
||
.i1 .syscard.ghost .icon-wrap { border: 2px dashed var(--line-strong); border-radius: 22px; color: var(--ink-muted); }
|
||
.i1 .src-icons .icon-wrap { color: var(--bordeaux-deep); }
|
||
.i1 .flow .fcol.src-icons b { color: var(--ink); }
|
||
|
||
/* style 2 — flat era artifacts (no frame, illustration speaks) */
|
||
.i2 .syscard .icon-wrap { color: var(--ink); }
|
||
.i2 .syscard.ghost .icon-wrap { opacity: .55; }
|
||
.i2 .src-icons .icon-wrap { color: var(--ink); }
|
||
|
||
/* style 3 — institutional emblems */
|
||
.i3 .syscard .icon-wrap { color: var(--bordeaux); }
|
||
.i3 .syscard.ghost .icon-wrap { color: var(--ink-muted); }
|
||
.i3 .src-icons .icon-wrap { color: var(--bordeaux); }
|
||
</style>
|
||
</body>
|
||
</html>
|