Files
ThothII/presentation/prototype/slide07-ontology.html
T

252 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<!-- PROTOTYPE (throwaway) — Slide 07 "The clinical ontology": three variants, switchable
via ?variant=A|B|C + floating bar (← → keys too).
Question: how to present 11+5 categories so the slide is more readable, livelier,
and with ENGLISH more prominent than Italian (audience mostly foreign).
A = three columns of 5-6 pills (user's idea) · B = editorial bands, EN-first pills
· C = split: ontology left, "why the order matters" panel right. -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>PROTOTYPE · Slide 07 "The clinical ontology" — 3 layout variants</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; }
.band .jump { font: 700 11px/1 var(--mono); letter-spacing: .1em; }
.sbody { flex: 1; min-height: 0; display: flex; flex-direction: column;
padding: 22px 48px 16px; text-align: left; }
.vwrap { margin: auto 0; width: 100%; }
.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 14px; }
/* ---- shared: EN-first pills (EN bold dark = primary, IT gloss = secondary) ---- */
.pill { display: inline-flex; align-items: baseline; gap: 7px; border: 1px solid var(--bordeaux);
border-radius: 9999px; padding: 6px 13px; background: #fff; white-space: nowrap; }
.pill .en { font: 700 13px/1 var(--sans); color: var(--ink); }
.pill .it { font: 400 11px/1 var(--sans); color: var(--ink-muted); }
.pill.fill { background: var(--bordeaux-tint); }
.col-h { display: flex; align-items: center; gap: 8px; font: 700 10px/1 var(--mono);
letter-spacing: .14em; text-transform: uppercase; color: var(--bordeaux-deep); margin-bottom: 9px; }
.col-h .n { margin-left: auto; font: 700 9px/1 var(--mono); color: var(--bordeaux);
border: 1px solid var(--bordeaux); border-radius: 9999px; padding: 2px 7px; letter-spacing: .08em; }
/* ---- shared: numbered points ---- */
.pt .num { flex: 0 0 22px; font: 700 11px/1.6 var(--mono); color: var(--bordeaux); }
.pt b { font: 700 13px/1.35 var(--sans); color: var(--ink); }
.pt span.d { font: 400 12.5px/1.45 var(--sans); color: var(--ink-muted); }
code { font: 700 11.5px/1 var(--mono); color: var(--bordeaux-deep); background: var(--bordeaux-tint);
padding: 2px 6px; border-radius: 4px; }
/* ================= VARIANT A — three columns (user's idea) ================= */
.va-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0 26px; align-items: start; }
.va-col + .va-col { border-left: 1px solid var(--line); padding-left: 26px; }
.va-col .stack { display: flex; flex-direction: column; gap: 7px; align-items: stretch; }
.va-col .pill { display: flex; justify-content: flex-start; }
.va-points { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 26px; margin-top: 20px;
padding-top: 14px; border-top: 1px solid var(--line); }
.va-points .pt { display: flex; gap: 10px; }
/* ================= VARIANT B — editorial bands ================= */
.vb-band { display: flex; gap: 20px; align-items: flex-start; padding: 13px 0 15px; border-bottom: 1px solid var(--line); }
.vb-band:first-of-type { padding-top: 4px; }
.vb-num { flex: 0 0 96px; }
.vb-num b { display: block; font: 800 30px/1 var(--sans); letter-spacing: -.02em; color: var(--bordeaux); }
.vb-num span { display: block; margin-top: 5px; font: 700 9px/1.4 var(--mono); letter-spacing: .12em;
text-transform: uppercase; color: var(--ink-muted); }
.vb-chips { display: flex; flex-wrap: wrap; gap: 8px; align-content: flex-start; }
.vb-points { margin-top: 16px; }
.vb-points .pt { display: flex; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.vb-points .pt:last-child { border-bottom: none; }
/* ================= VARIANT C — split: ontology / why order matters ================= */
.vc-split { display: grid; grid-template-columns: 1.42fr 1fr; gap: 26px; align-items: start; flex: 1; min-height: 0; }
.vc-tier { margin-bottom: 16px; }
.vc-tier .col-h { margin-bottom: 10px; }
.vc-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.vc-why { border: 1px solid var(--bordeaux); background: var(--bordeaux-tint); border-radius: 10px;
padding: 15px 18px 8px; }
.vc-why-h { font: 700 10px/1 var(--mono); letter-spacing: .14em; text-transform: uppercase;
color: var(--bordeaux-deep); margin-bottom: 4px; }
.vc-why .pt { display: flex; gap: 10px; padding: 10px 0; border-bottom: 1px solid rgba(143,18,4,.18); }
.vc-why .pt:last-child { border-bottom: none; }
.vc-why .pt .num { color: var(--bordeaux-deep); }
/* ---- floating switcher (not part of the design) ---- */
.switcher { position: fixed; left: 50%; bottom: 18px; transform: translateX(-50%); z-index: 99;
display: flex; align-items: center; gap: 10px; background: #1d1a1b; color: #fff;
border-radius: 9999px; padding: 8px 10px; box-shadow: 0 6px 22px rgba(0,0,0,.35); }
.switcher button { all: unset; cursor: pointer; width: 30px; height: 30px; border-radius: 9999px;
display: grid; place-items: center; background: rgba(255,255,255,.14); font: 700 14px/1 var(--sans); }
.switcher button:hover { background: rgba(255,255,255,.28); }
.switcher .lbl { font: 700 12px/1 var(--mono); letter-spacing: .06em; min-width: 240px; text-align: center; }
</style>
</head>
<body>
<div class="proto-head">
<b>PROTOTYPE · slide 07 — the clinical ontology</b>
<span>Three layout variants · EN primary (bold dark) over IT gloss (secondary) · A = three columns (your idea) · B = editorial bands · C = ontology + "why order matters" panel</span>
</div>
<div class="frame">
<header class="head">
<img src="/deck/logo.png" alt="">
<span class="head-org">AritmoLab · Policlinico San Donato</span>
</header>
<nav class="band"><b>Text analysis</b><span class="jump">07 · The clinical ontology</span></nav>
<div class="sbody" id="sbody"></div>
<footer 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>07 / 14</span>
</footer>
</div>
<div class="switcher">
<button id="prev" aria-label="previous variant">←</button>
<span class="lbl" id="lbl"></span>
<button id="next" aria-label="next variant">→</button>
</div>
<script>
// ---- data (EN-first: EN bold primary, IT gloss secondary) ----
const T1 = [
{ en: 'AF', it: 'FA' },
{ en: 'Brugada', it: '' },
{ en: 'Flutter', it: '' },
{ en: 'AT', it: 'TA' },
{ en: 'AVNRT', it: 'TRN' },
{ en: 'PSVT', it: 'WPW / TPSV' },
{ en: 'VT', it: 'TV' },
{ en: 'VF', it: 'FV' },
{ en: 'Ventricular ectopy', it: 'Extrasistolia V.' },
{ en: 'Syncope', it: 'Sincope' },
{ en: 'Long QT', it: 'QT lungo' },
];
const T2 = [
{ en: 'AV block', it: 'Blocco AV' },
{ en: 'Bundle branch block', it: 'Blocco di branca' },
{ en: 'Cardiomyopathy', it: 'Cardiomiopatia' },
{ en: 'Heart failure', it: 'Scompenso' },
{ en: 'Valvular disease', it: 'Valvulopatia' },
];
const pill = (c, fill) =>
`<span class="pill${fill ? ' fill' : ''}"><span class="en">${c.en}</span>${c.it ? `<span class="it">${c.it}</span>` : ''}</span>`;
const POINTS = [
{ n: '01', b: 'Order encodes clinical precedence', d: '“Brugada” is matched before “TV”, so “substrato per TV” <span style="color:var(--bordeaux-deep)">("substrate for VT")</span> can\'t mask a Brugada pattern' },
{ n: '02', b: 'Synonyms live inline', d: 'FA / f.a. / fib. atriale / atrial fibrillation → one canonical label' },
{ n: '03', b: 'Versioned like software', d: 'semver for the pattern library, <code>pattern_version</code> on every extracted row' },
];
// ---- variant A: three columns of pills (user's idea) ----
function variantA() {
const col = (h, count, items, fill) => `
<div class="va-col">
<div class="col-h">${h}<span class="n">${count}</span></div>
<div class="stack">${items.map(c => pill(c, fill)).join('')}</div>
</div>`;
return `
<div class="va-grid">
${col('Tier 1 · arrhythmic — 1/2', '6 of 11', T1.slice(0, 6), true)}
${col('Tier 1 · arrhythmic — 2/2', '5 of 11', T1.slice(6), true)}
${col('Tier 2 · structural', '5 of 5', T2, false)}
</div>
<div class="va-points">${POINTS.map(p => `
<div class="pt"><span class="num">${p.n}</span><div><b>${p.b}</b> <span class="d">— ${p.d}</span></div></div>`).join('')}
</div>`;
}
// ---- variant B: editorial bands with big numerals ----
function variantB() {
const band = (num, name, count, items, fill) => `
<div class="vb-band">
<div class="vb-num"><b>${num}</b><span>${name} · ${count} categories</span></div>
<div class="vb-chips">${items.map(c => pill(c, fill)).join('')}</div>
</div>`;
return `
${band('01', 'Arrhythmic', 11, T1, true)}
${band('02', 'Structural', 5, T2, false)}
<div class="vb-points">${POINTS.map(p => `
<div class="pt"><span class="num">${p.n}</span><div><b>${p.b}</b> <span class="d">— ${p.d}</span></div></div>`).join('')}
</div>`;
}
// ---- variant C: ontology left, "why the order matters" right ----
function variantC() {
return `
<div class="vc-split">
<div>
<div class="vc-tier">
<div class="col-h">Tier 1 · arrhythmic<span class="n">11</span></div>
<div class="vc-chips">${T1.map(c => pill(c, true)).join('')}</div>
</div>
<div class="vc-tier" style="margin-bottom:0">
<div class="col-h">Tier 2 · structural<span class="n">5</span></div>
<div class="vc-chips">${T2.map(c => pill(c, false)).join('')}</div>
</div>
</div>
<div class="vc-why">
<div class="vc-why-h">Why one clinical order matters</div>
${POINTS.map(p => `
<div class="pt"><span class="num">${p.n}</span><div><b>${p.b}</b> <span class="d">— ${p.d}</span></div></div>`).join('')}
</div>
</div>`;
}
// ---- switcher ----
const VARIANTS = [
{ key: 'A', name: 'Three columns (5-6 per column)', render: variantA },
{ key: 'B', name: 'Editorial bands, big numerals', render: variantB },
{ key: 'C', name: 'Ontology + why-order panel', render: variantC },
];
function current() {
const k = (location.search.match(/variant=([ABC])/) || [])[1] || 'A';
return Math.max(0, VARIANTS.findIndex(v => v.key === k));
}
function show(i) {
const v = VARIANTS[i];
document.getElementById('sbody').innerHTML =
'<div class="vwrap"><div class="kicker">The clinical ontology</div><h2>Two tiers, one clinical order</h2>' + v.render() + '</div>';
document.getElementById('lbl').textContent = `${v.key} · ${v.name}`;
history.replaceState(null, '', location.pathname + '?variant=' + v.key);
}
document.getElementById('prev').onclick = () => show((current() + VARIANTS.length - 1) % VARIANTS.length);
document.getElementById('next').onclick = () => show((current() + 1) % VARIANTS.length);
addEventListener('keydown', e => {
if (e.key === 'ArrowLeft') document.getElementById('prev').click();
if (e.key === 'ArrowRight') document.getElementById('next').click();
});
show(current());
</script>
</body>
</html>