290 lines
17 KiB
HTML
290 lines
17 KiB
HTML
<!doctype html>
|
||
<!-- PROTOTYPE (throwaway) — Three variants of the "outputs from the datamarts" zone
|
||
for deck slide "The problem". Switchable via ?variant=A|B|C, floating switcher.
|
||
Question: how should Dashboards / Machine Learning / Predictive Statistics
|
||
be represented as the three outputs of the Marts stage? -->
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>PROTOTYPE · Slide “The problem” — outputs from the datamarts (3 options)</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;
|
||
--display: 'Source Serif 4', Georgia, serif;
|
||
--mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
|
||
}
|
||
* { box-sizing: border-box; }
|
||
body { margin: 0; background: #e9e7e7; font-family: var(--sans); padding: 26px 0 90px; }
|
||
.proto-head { text-align: center; margin: 0 0 14px; }
|
||
.proto-head b { font: 700 12px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase; color: var(--bordeaux); }
|
||
.proto-head span { display: block; margin-top: 6px; font: 400 13px/1.4 var(--sans); color: var(--ink-muted); }
|
||
|
||
/* ---- slide frame (deck-like, 1200×690) ---- */
|
||
.frame { width: 1200px; height: 690px; margin: 0 auto; background: var(--surface);
|
||
display: flex; flex-direction: column; box-shadow: 0 8px 30px rgba(42,36,38,.18); overflow: hidden; }
|
||
.head { flex: 0 0 74px; display: flex; align-items: center; justify-content: space-between;
|
||
padding: 0 40px; border-bottom: 1px solid var(--line); }
|
||
.head img { height: 54px; display: block; }
|
||
.head-org { font: 700 11px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--ink-muted); }
|
||
.band { flex: 0 0 42px; display: flex; align-items: center; justify-content: space-between;
|
||
padding: 0 40px; background: var(--bordeaux); color: var(--surface); }
|
||
.band b { font: 700 12.5px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; }
|
||
.sbody { flex: 1; min-height: 0; display: flex; flex-direction: column;
|
||
padding: 20px 48px 14px; text-align: left; }
|
||
.foot { flex: 0 0 30px; display: flex; align-items: center; justify-content: space-between; gap: 24px;
|
||
padding: 0 40px; border-top: 1px solid var(--line);
|
||
font: 600 9.5px/1.4 var(--sans); letter-spacing: .03em; color: var(--ink-muted); }
|
||
.kicker { font: 700 11.5px/1 var(--sans); letter-spacing: .16em; text-transform: uppercase; color: var(--bordeaux); margin-bottom: 10px; }
|
||
h2 { font: 700 27px/1.15 var(--sans); letter-spacing: -.01em; color: var(--ink); margin: 0 0 10px; }
|
||
|
||
.quote { position: relative; margin: 0 0 14px; padding: 14px 22px 11px 64px; border: 1px solid var(--line);
|
||
background: var(--surface-alt); border-radius: 8px;
|
||
font: italic 400 16.5px/1.5 var(--display); color: var(--ink); }
|
||
.quote::before { content: '\201C'; position: absolute; left: 18px; top: 6px;
|
||
font: 700 44px/1 var(--display); color: var(--bordeaux); }
|
||
.tr-grid { display: grid; grid-template-columns: 1.12fr 1fr; gap: 22px; align-items: center; }
|
||
.tr-grid .it, .tr-grid .en { margin: 0; }
|
||
.tr-grid .en { padding-left: 18px; border-left: 1px solid var(--line-strong);
|
||
font: 400 12.5px/1.55 var(--sans); color: var(--bordeaux-deep); }
|
||
.en-tag { display: inline-block; margin-right: 7px; padding: 2px 7px; border-radius: 4px;
|
||
background: var(--bordeaux); color: #fdfcfc; font: 700 9px/1 var(--sans); letter-spacing: .12em; vertical-align: 1px; }
|
||
.quote small { display: block; margin-top: 5px; font: 600 9.5px/1.4 var(--sans); font-style: normal;
|
||
letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted); }
|
||
|
||
.pipeline { display: flex; align-items: stretch; gap: 10px; }
|
||
.stage { flex: 1; padding: 10px 8px; text-align: center; border: 1px solid var(--line); border-radius: 8px; background: var(--surface-alt); }
|
||
.stage b { display: block; font: 700 12.5px/1.2 var(--sans); margin-bottom: 3px; }
|
||
.stage span { display: block; font: 400 10.5px/1.35 var(--sans); color: var(--ink-muted); }
|
||
.stage .tag { display: inline-block; margin-top: 4px; padding: 2px 9px; border-radius: 9999px;
|
||
background: var(--bordeaux); color: #fdfcfc; font: 700 8.5px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; }
|
||
.stage.ai { background: var(--bordeaux-tint); border-color: var(--bordeaux); }
|
||
.arrow { align-self: center; color: var(--line-strong); font: 700 17px/1 var(--sans); }
|
||
.stage.hot { background: #fdf1f2; border-color: var(--bordeaux); }
|
||
|
||
.thoth-wrap { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||
.thoth-wrap.left { justify-content: flex-start; }
|
||
.thoth-col { width: 500px; text-align: center; }
|
||
.thoth-arrow { color: var(--line-strong); font: 700 15px/1 var(--sans); margin: 1px 0; }
|
||
.thoth-box { border: 1px solid var(--bordeaux); border-radius: 8px; padding: 9px 14px;
|
||
background: var(--surface-alt); font: 600 11.5px/1.4 var(--sans); }
|
||
.thoth-box .tag { display: inline-block; margin-right: 7px; padding: 2px 9px; border-radius: 9999px;
|
||
background: var(--bordeaux); color: #fdfcfc; font: 700 8.5px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; }
|
||
|
||
/* ---- outputs icons ---- */
|
||
.oicon { width: 34px; height: 34px; color: var(--bordeaux); display: block; }
|
||
.oicon * { vector-effect: non-scaling-stroke; }
|
||
|
||
/* ---- variant A: branch tree from Marts ---- */
|
||
.fanwrap { display: flex; justify-content: flex-end; margin-top: 0; }
|
||
.fan { width: 58%; position: relative; padding-top: 16px; }
|
||
.fan .drop { position: absolute; top: -6px; right: 128px; width: 2px; height: 22px; background: var(--bordeaux); }
|
||
.fan .rail { height: 2px; background: var(--bordeaux); margin: 0 60px 0 40px; position: relative; }
|
||
.fan .nodes { display: flex; margin-top: 0; }
|
||
.fan .node { flex: 1; text-align: center; position: relative; padding-top: 14px; }
|
||
.fan .node::before { content: ''; position: absolute; top: 0; left: 50%; width: 2px; height: 14px;
|
||
background: var(--bordeaux); transform: translateX(-50%); }
|
||
.fan .node .oicon { margin: 0 auto 5px; }
|
||
.fan .node b { display: block; font: 700 13px/1.2 var(--sans); color: var(--ink); }
|
||
.fan .node span { display: block; font: 400 10.5px/1.35 var(--sans); color: var(--ink-muted); margin-top: 2px; }
|
||
|
||
/* ---- variant B: outputs band ---- */
|
||
.oband { margin-top: 12px; }
|
||
.oband .lbl { font: 700 10px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase;
|
||
color: var(--bordeaux); text-align: center; margin-bottom: 8px; }
|
||
.oband .tiles { display: flex; gap: 12px; }
|
||
.oband .tile { flex: 1; display: flex; align-items: center; gap: 12px; padding: 11px 14px;
|
||
border: 1px solid var(--line); border-radius: 8px; background: var(--surface-alt); }
|
||
.oband .tile .ic { flex: 0 0 44px; height: 44px; border-radius: 9999px; background: var(--bordeaux-tint);
|
||
display: flex; align-items: center; justify-content: center; }
|
||
.oband .tile .ic .oicon { width: 26px; height: 26px; }
|
||
.oband .tile b { display: block; font: 700 13.5px/1.2 var(--sans); color: var(--ink); }
|
||
.oband .tile span { display: block; margin-top: 2px; font: 400 11px/1.35 var(--sans); color: var(--ink-muted); }
|
||
|
||
/* ---- variant C: maturity rail ---- */
|
||
.railwrap { display: flex; justify-content: flex-end; margin-top: 10px; }
|
||
.rail { width: 560px; border-left: 2px solid var(--bordeaux); padding: 2px 0 2px 0; }
|
||
.rail .row { display: flex; align-items: center; gap: 12px; padding: 7px 14px 7px 16px; position: relative; }
|
||
.rail .row::before { content: ''; position: absolute; left: 0; top: 50%; width: 14px; height: 2px; background: var(--bordeaux); }
|
||
.rail .row .oicon { flex: 0 0 26px; width: 26px; height: 26px; }
|
||
.rail .row b { font: 700 13.5px/1.2 var(--sans); color: var(--ink); }
|
||
.rail .row span.d { font: 400 11px/1.3 var(--sans); color: var(--ink-muted); }
|
||
.rail .row .st { margin-left: auto; font: 700 9px/1 var(--mono); letter-spacing: .12em; text-transform: uppercase;
|
||
padding: 3px 9px; border-radius: 9999px; }
|
||
.rail .row.today .st { background: var(--bordeaux); color: #fdfcfc; }
|
||
.rail .row.next { border: 1px dashed var(--line-strong); border-radius: 8px; background: transparent; }
|
||
.rail .row.next .oicon { opacity: .55; }
|
||
.rail .row.next .st { border: 1px solid var(--line-strong); color: var(--ink-muted); }
|
||
.rail .lbl { font: 700 10px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase;
|
||
color: var(--bordeaux); margin: 0 0 6px 16px; }
|
||
|
||
/* ---- variant switcher (prototype chrome) ---- */
|
||
.switch { position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 50;
|
||
display: flex; align-items: center; gap: 10px; background: #2a2426; color: #fdfcfc;
|
||
padding: 8px 12px; border-radius: 9999px; box-shadow: 0 6px 22px rgba(0,0,0,.35);
|
||
font: 600 12.5px/1 var(--sans); }
|
||
.switch button { border: none; background: #4a4345; color: #fdfcfc; width: 28px; height: 28px;
|
||
border-radius: 9999px; font: 700 14px/1 var(--sans); cursor: pointer; }
|
||
.switch button:hover { background: var(--bordeaux); }
|
||
.caption { max-width: 1200px; margin: 12px auto 0; text-align: center;
|
||
font: 400 12.5px/1.5 var(--sans); color: var(--ink-muted); }
|
||
.caption b { color: var(--ink); }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="proto-head">
|
||
<b>Prototype — slide “The problem” · outputs from the datamarts</b>
|
||
<span>Three structural options for Dashboards / Machine Learning / Predictive Statistics. Use the bar below or the arrow keys.</span>
|
||
</div>
|
||
|
||
<div class="frame">
|
||
<div class="head">
|
||
<img src="/deck/logo.png" alt="">
|
||
<span class="head-org">AritmoLab · Policlinico San Donato</span>
|
||
</div>
|
||
<div class="band"><b>The problem</b><span style="font:700 11px/1 var(--sans)">04 · The problem</span></div>
|
||
<div class="sbody">
|
||
<div class="kicker">From free text to a research platform</div>
|
||
<h2>The clinical truth lives in unstructured columns</h2>
|
||
<div class="quote">
|
||
<div class="tr-grid">
|
||
<p class="it">“Il paziente riferisce sincope ricorrente; ECG basale con sopraslivellamento ST in V1–V3; test provocativo con flecainide positivo per pattern Brugada.”</p>
|
||
<p class="en"><span class="en-tag">EN</span>“The patient reports recurrent syncope; baseline ECG with ST-segment elevation in V1–V3; flecainide provocation test positive for a Brugada pattern.”</p>
|
||
</div>
|
||
</div>
|
||
<div class="pipeline" id="pipeline">
|
||
<div class="stage"><b>Sources</b><span>Cardioref · Genetic data<br>Omics Portal · ECG</span></div>
|
||
<div class="arrow">→</div>
|
||
<div class="stage"><b>Staging</b><span>raw replica</span></div>
|
||
<div class="arrow">→</div>
|
||
<div class="stage ai"><b>Integration</b><span>3NF · text mining</span><span class="tag">AI</span></div>
|
||
<div class="arrow">→</div>
|
||
<div class="stage"><b>Data Warehouse</b><span>star schema</span></div>
|
||
<div class="arrow">→</div>
|
||
<div class="stage hot" id="marts"><b>Marts</b><span>dbt · Superset</span></div>
|
||
</div>
|
||
<div class="variant-zone"></div>
|
||
<div class="thoth-wrap" id="thothwrap">
|
||
<div class="thoth-col">
|
||
<div class="thoth-arrow">↑</div>
|
||
<div class="thoth-box"><span class="tag">AI</span>ThothII — natural-language → SQL over the DWH, builds the final datamarts</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="foot"><span>Role of AI in the Analysis of Unstructured Clinical Databases</span><span>Dr. Marco Pancotti - MultiPhysixLab</span><span>Dr. Sara Paratico - Gruppo San Donato</span><span>San Donato Milanese, Milan, Italy · 2–3 October 2026</span><span>04 / 14</span></div>
|
||
</div>
|
||
|
||
<p class="caption" id="caption"></p>
|
||
|
||
<div class="switch">
|
||
<button id="prev" aria-label="previous variant">←</button>
|
||
<span id="label"></span>
|
||
<button id="next" aria-label="next variant">→</button>
|
||
</div>
|
||
|
||
<svg width="0" height="0" style="position:absolute">
|
||
<defs>
|
||
<g id="i-dash">
|
||
<svg class="oicon" viewBox="0 0 34 34" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
|
||
<path d="M4 29 h26"/><rect x="7" y="17" width="5" height="12" rx="1"/><rect x="15" y="9" width="5" height="20" rx="1"/><rect x="23" y="13" width="5" height="16" rx="1"/>
|
||
</svg>
|
||
</g>
|
||
<g id="i-ml">
|
||
<svg class="oicon" viewBox="0 0 34 34" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||
<circle cx="7" cy="7" r="2.6"/><circle cx="7" cy="27" r="2.6"/><circle cx="17" cy="17" r="3.4"/><circle cx="27" cy="7" r="2.6"/><circle cx="27" cy="27" r="2.6"/>
|
||
<path d="M9.3 8.8 L14.6 14.6"/><path d="M9.3 25.2 L14.6 19.4"/><path d="M19.4 14.6 L24.7 8.8"/><path d="M19.4 19.4 L24.7 25.2"/>
|
||
</svg>
|
||
</g>
|
||
<g id="i-pred">
|
||
<svg class="oicon" viewBox="0 0 34 34" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round">
|
||
<path d="M3 27 L11 19 L17 22 L23 13"/><path d="M23 13 L30 6" stroke-dasharray="3 3.4"/><circle cx="30" cy="6" r="2.2" fill="currentColor" stroke="none"/><path d="M3 31 h28" opacity=".35"/>
|
||
</svg>
|
||
</g>
|
||
</defs>
|
||
</svg>
|
||
|
||
<script>
|
||
const ICON = {
|
||
dash: document.getElementById('i-dash').innerHTML,
|
||
ml: document.getElementById('i-ml').innerHTML,
|
||
pred: document.getElementById('i-pred').innerHTML
|
||
};
|
||
const VARIANTS = {
|
||
A: {
|
||
name: 'A — Branch from Marts',
|
||
caption: '<b>A · Branch from Marts.</b> The three outputs fan out of the Marts stage as icon nodes on a connector tree: lightest visual weight, reads as “the pipeline flows on”. ThothII moves bottom-left, so left = AI reads the DWH, right = research outputs.',
|
||
html: `
|
||
<div class="fanwrap">
|
||
<div class="fan">
|
||
<div class="drop"></div>
|
||
<div class="rail"></div>
|
||
<div class="nodes">
|
||
<div class="node">${ICON.dash}<b>Dashboards</b><span>clinical review on Superset</span></div>
|
||
<div class="node">${ICON.ml}<b>Machine Learning</b><span>cohort tables for model training</span></div>
|
||
<div class="node">${ICON.pred}<b>Predictive Statistics</b><span>outcomes & risk analysis</span></div>
|
||
</div>
|
||
</div>
|
||
</div>`
|
||
},
|
||
B: {
|
||
name: 'B — Products band',
|
||
caption: '<b>B · Products band.</b> A labelled full-width band under the pipeline: three equal tiles, icon in a tinted disc + name + one-liner. Reads as “the three products of the platform” — most explicit, heaviest.',
|
||
html: `
|
||
<div class="oband">
|
||
<div class="lbl">what the datamarts enable</div>
|
||
<div class="tiles">
|
||
<div class="tile"><span class="ic">${ICON.dash}</span><span><b>Dashboards</b><span>clinical review on Superset dashboards</span></span></div>
|
||
<div class="tile"><span class="ic">${ICON.ml}</span><span><b>Machine Learning</b><span>cohort tables, ready for model training</span></span></div>
|
||
<div class="tile"><span class="ic">${ICON.pred}</span><span><b>Predictive Statistics</b><span>outcomes, risk and survival analysis</span></span></div>
|
||
</div>
|
||
</div>`
|
||
},
|
||
C: {
|
||
name: 'C — Maturity rail',
|
||
caption: '<b>C · Maturity rail.</b> A rail drops from Marts into three rows that encode the roadmap: Dashboards is live today (solid), Machine Learning and Predictive Statistics are the next steps (dashed). Sets up the “what is still missing” beat later in the talk.',
|
||
html: `
|
||
<div class="railwrap">
|
||
<div class="rail">
|
||
<div class="lbl">outputs of the datamarts</div>
|
||
<div class="row today">${ICON.dash}<b>Dashboards</b><span class="d">clinical review on Superset</span><span class="st">live today</span></div>
|
||
<div class="row next">${ICON.ml}<b>Machine Learning</b><span class="d">cohort tables for model training</span><span class="st">next</span></div>
|
||
<div class="row next">${ICON.pred}<b>Predictive Statistics</b><span class="d">outcomes & risk analysis</span><span class="st">next</span></div>
|
||
</div>
|
||
</div>`
|
||
}
|
||
};
|
||
const keys = Object.keys(VARIANTS);
|
||
const cur = () => {
|
||
const v = (new URLSearchParams(location.search).get('variant') || 'A').toUpperCase();
|
||
return keys.includes(v) ? v : 'A';
|
||
};
|
||
function render() {
|
||
const v = cur();
|
||
document.querySelector('.variant-zone').innerHTML = VARIANTS[v].html;
|
||
document.getElementById('label').textContent = VARIANTS[v].name;
|
||
document.getElementById('caption').innerHTML = VARIANTS[v].caption;
|
||
// ThothII placement: A and C put the outputs on the right → ThothII moves bottom-left
|
||
document.getElementById('thothwrap').classList.toggle('left', v !== 'B');
|
||
}
|
||
function cycle(dir) {
|
||
const i = keys.indexOf(cur());
|
||
const v = keys[(i + dir + keys.length) % keys.length];
|
||
const u = new URL(location);
|
||
u.searchParams.set('variant', v);
|
||
location.replace(u);
|
||
}
|
||
document.getElementById('prev').onclick = () => cycle(-1);
|
||
document.getElementById('next').onclick = () => cycle(1);
|
||
addEventListener('keydown', e => {
|
||
if (e.key === 'ArrowLeft') cycle(-1);
|
||
if (e.key === 'ArrowRight') cycle(1);
|
||
});
|
||
render();
|
||
</script>
|
||
</body>
|
||
</html>
|