Files
portfolio/designs/07-contextual-workspace.html
T
2026-02-13 16:42:45 +00:00

1756 lines
44 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clinical Record — Contextual Workspace</title>
<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=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<style>
/* ========================================
CONTEXTUAL WORKSPACE
Adaptive clinical record with narrative summary
======================================== */
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--sidebar-collapsed: 56px;
--sidebar-expanded: 208px;
--banner-height: 100px;
--sidebar-bg: #1E293B;
--sidebar-hover: #273548;
--sidebar-active: rgba(0, 94, 184, 0.15);
--sidebar-border: rgba(255, 255, 255, 0.06);
--banner-bg: #0F172A;
--banner-border: rgba(255, 255, 255, 0.08);
--content-bg: #F8F9FA;
--surface: #FFFFFF;
--accent: #005EB8;
--accent-hover: #004C93;
--accent-light: #EBF3FC;
--accent-pale: rgba(0, 94, 184, 0.06);
--text-primary: #111827;
--text-secondary: #4B5563;
--text-muted: #9CA3AF;
--text-faint: #D1D5DB;
--text-light: #F1F5F9;
--text-light-secondary: #94A3B8;
--text-light-muted: #64748B;
--green: #22C55E;
--green-text: #16A34A;
--green-bg: rgba(34, 197, 94, 0.08);
--amber: #F59E0B;
--amber-text: #D97706;
--amber-bg: rgba(245, 158, 11, 0.08);
--red: #EF4444;
--border: #E5E7EB;
--border-light: #F3F4F6;
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.04);
--shadow-md: 0 1px 2px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(0, 0, 0, 0.03);
--shadow-lg: 0 1px 3px rgba(0, 0, 0, 0.04), 0 8px 24px rgba(0, 0, 0, 0.06);
--font-sans: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}
html {
font-size: 14px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
font-family: var(--font-sans);
color: var(--text-primary);
background: var(--content-bg);
line-height: 1.5;
overflow: hidden;
height: 100vh;
}
/* ----------------------------------------
Layout Shell
---------------------------------------- */
.layout {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: var(--banner-height) 1fr;
height: 100vh;
margin-left: var(--sidebar-collapsed);
}
/* ----------------------------------------
Sidebar — Collapsed by default
---------------------------------------- */
.sidebar {
position: fixed;
top: 0;
left: 0;
bottom: 0;
background: var(--sidebar-bg);
display: flex;
flex-direction: column;
z-index: 20;
width: var(--sidebar-collapsed);
overflow: hidden;
transition: width 0.35s var(--ease-out), box-shadow 0.35s ease;
}
.sidebar::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 1px;
background: linear-gradient(
to bottom,
rgba(0, 94, 184, 0.2) 0%,
rgba(0, 94, 184, 0.05) 50%,
transparent 100%
);
}
.sidebar:hover {
width: var(--sidebar-expanded);
box-shadow: 8px 0 32px rgba(0, 0, 0, 0.15);
}
/* Sidebar Brand */
.sidebar-brand {
height: var(--banner-height);
display: flex;
align-items: center;
padding: 0 14px;
border-bottom: 1px solid var(--sidebar-border);
flex-shrink: 0;
gap: 12px;
overflow: hidden;
}
.sidebar-brand-icon {
width: 28px;
height: 28px;
border-radius: 7px;
background: var(--accent);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.sidebar-brand-icon svg {
width: 16px;
height: 16px;
color: white;
}
.sidebar-brand-text {
opacity: 0;
white-space: nowrap;
transition: opacity 0.2s ease 0.1s;
}
.sidebar:hover .sidebar-brand-text {
opacity: 1;
}
.sidebar-brand-title {
font-size: 13px;
font-weight: 600;
color: var(--text-light);
letter-spacing: 0.01em;
}
.sidebar-brand-sub {
font-size: 10px;
font-weight: 400;
color: var(--text-light-muted);
letter-spacing: 0.04em;
text-transform: uppercase;
margin-top: 1px;
}
/* Sidebar Navigation */
.sidebar-nav {
flex: 1;
padding: 12px 0;
display: flex;
flex-direction: column;
gap: 2px;
}
.nav-section-label {
font-size: 9px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--text-light-muted);
padding: 16px 18px 6px;
opacity: 0;
transition: opacity 0.2s ease 0.1s;
white-space: nowrap;
}
.sidebar:hover .nav-section-label {
opacity: 1;
}
.nav-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
color: var(--text-light-secondary);
cursor: pointer;
transition: all 0.15s ease;
text-decoration: none;
position: relative;
margin: 0 4px;
border-radius: 6px;
min-height: 40px;
}
.nav-item:hover {
background: var(--sidebar-hover);
color: var(--text-light);
}
.nav-item.active {
background: var(--sidebar-active);
color: white;
}
.nav-item.active::before {
content: '';
position: absolute;
left: -4px;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 20px;
background: var(--accent);
border-radius: 0 2px 2px 0;
}
.nav-item svg {
width: 18px;
height: 18px;
stroke-width: 1.6;
flex-shrink: 0;
}
.nav-item-label {
font-size: 13px;
font-weight: 400;
white-space: nowrap;
opacity: 0;
transition: opacity 0.2s ease 0.1s;
}
.nav-item.active .nav-item-label {
font-weight: 500;
}
.sidebar:hover .nav-item-label {
opacity: 1;
}
.nav-item .nav-key {
margin-left: auto;
font-family: var(--font-mono);
font-size: 10px;
color: var(--text-light-muted);
opacity: 0;
transition: opacity 0.2s ease 0.1s;
white-space: nowrap;
background: rgba(255, 255, 255, 0.05);
padding: 1px 6px;
border-radius: 3px;
}
.sidebar:hover .nav-key {
opacity: 1;
}
.nav-item.active .nav-key {
color: rgba(255, 255, 255, 0.4);
}
/* Sidebar Footer */
.sidebar-footer {
padding: 14px 16px;
border-top: 1px solid var(--sidebar-border);
display: flex;
align-items: center;
gap: 10px;
overflow: hidden;
}
.sidebar-footer-avatar {
width: 28px;
height: 28px;
border-radius: 50%;
background: linear-gradient(135deg, #334155, #475569);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 11px;
font-weight: 600;
color: var(--text-light);
}
.sidebar-footer-info {
opacity: 0;
transition: opacity 0.2s ease 0.1s;
white-space: nowrap;
}
.sidebar:hover .sidebar-footer-info {
opacity: 1;
}
.sidebar-footer-name {
font-size: 12px;
font-weight: 500;
color: var(--text-light);
display: flex;
align-items: center;
gap: 6px;
}
.sidebar-footer-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--green);
flex-shrink: 0;
}
.sidebar-footer-time {
font-size: 11px;
font-family: var(--font-mono);
color: var(--text-light-muted);
margin-top: 1px;
}
/* ----------------------------------------
Patient Banner
---------------------------------------- */
.banner {
grid-row: 1;
grid-column: 1;
background: var(--banner-bg);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 40px;
z-index: 10;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
position: relative;
}
.banner::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(
to right,
var(--accent) 0%,
rgba(0, 94, 184, 0.3) 30%,
transparent 100%
);
}
.banner-left {
display: flex;
align-items: center;
gap: 28px;
}
.banner-identity {
display: flex;
flex-direction: column;
gap: 6px;
}
.banner-name-row {
display: flex;
align-items: baseline;
gap: 12px;
}
.banner-name {
font-size: 24px;
font-weight: 700;
color: var(--text-light);
letter-spacing: -0.02em;
line-height: 1;
}
.banner-honorific {
font-size: 13px;
font-weight: 400;
color: var(--text-light-muted);
}
.banner-subtitle-row {
display: flex;
align-items: center;
gap: 12px;
}
.banner-role {
font-size: 12px;
font-weight: 400;
color: var(--text-light-secondary);
}
.banner-status {
display: inline-flex;
align-items: center;
gap: 5px;
font-size: 11px;
font-weight: 500;
color: #4ADE80;
}
.banner-status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--green);
animation: pulse-dot 2s ease-in-out infinite;
}
@keyframes pulse-dot {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
.banner-badge {
font-size: 10px;
font-weight: 500;
color: var(--accent);
padding: 3px 10px;
border: 1px solid rgba(0, 94, 184, 0.4);
border-radius: 100px;
background: rgba(0, 94, 184, 0.08);
letter-spacing: 0.02em;
}
.banner-divider {
width: 1px;
height: 48px;
background: rgba(255, 255, 255, 0.08);
}
.banner-meta {
display: flex;
align-items: center;
gap: 24px;
}
.banner-meta-item {
display: flex;
flex-direction: column;
gap: 3px;
}
.banner-meta-label {
font-size: 9px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--text-light-muted);
}
.banner-meta-value {
font-size: 12px;
font-weight: 500;
color: var(--text-light-secondary);
font-family: var(--font-mono);
}
.banner-right {
display: flex;
align-items: center;
gap: 8px;
}
.banner-action {
display: flex;
align-items: center;
gap: 6px;
padding: 7px 14px;
font-size: 12px;
font-weight: 500;
color: var(--text-light-secondary);
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.12);
border-radius: 6px;
cursor: pointer;
transition: all 0.15s ease;
font-family: var(--font-sans);
}
.banner-action:hover {
border-color: rgba(255, 255, 255, 0.25);
color: var(--text-light);
background: rgba(255, 255, 255, 0.04);
}
.banner-action.primary {
background: var(--accent);
color: white;
border-color: var(--accent);
}
.banner-action.primary:hover {
background: var(--accent-hover);
border-color: var(--accent-hover);
}
.banner-action svg {
width: 14px;
height: 14px;
stroke-width: 1.5;
}
/* ----------------------------------------
Content Area
---------------------------------------- */
.content {
grid-row: 2;
grid-column: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 36px 48px 80px;
background: var(--content-bg);
}
.content::-webkit-scrollbar {
width: 6px;
}
.content::-webkit-scrollbar-track {
background: transparent;
}
.content::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 3px;
}
.content::-webkit-scrollbar-thumb:hover {
background: var(--text-muted);
}
.content-inner {
max-width: 960px;
}
/* ----------------------------------------
Section: Narrative Header
---------------------------------------- */
.narrative-block {
margin-bottom: 48px;
position: relative;
}
.narrative-label {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--accent);
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.narrative-label::after {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(to right, var(--border), transparent);
max-width: 120px;
}
.narrative-headline {
font-size: 28px;
font-weight: 300;
color: var(--text-primary);
letter-spacing: -0.02em;
line-height: 1.35;
max-width: 720px;
margin-bottom: 8px;
}
.narrative-headline strong {
font-weight: 600;
color: var(--accent);
}
.narrative-body {
font-size: 14px;
font-weight: 400;
color: var(--text-secondary);
line-height: 1.7;
max-width: 640px;
}
/* ----------------------------------------
Section: KPI Metrics Strip
---------------------------------------- */
.kpi-strip {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1px;
background: var(--border);
border-radius: 8px;
overflow: hidden;
margin-bottom: 48px;
box-shadow: var(--shadow-md);
}
.kpi-item {
background: var(--surface);
padding: 24px 28px;
display: flex;
flex-direction: column;
gap: 4px;
position: relative;
}
.kpi-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: transparent;
}
.kpi-item:first-child::before {
background: var(--accent);
}
.kpi-label {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--text-muted);
}
.kpi-value {
font-size: 32px;
font-weight: 700;
color: var(--text-primary);
letter-spacing: -0.03em;
line-height: 1.1;
font-family: var(--font-sans);
}
.kpi-value .kpi-unit {
font-size: 16px;
font-weight: 400;
color: var(--text-muted);
letter-spacing: 0;
}
.kpi-context {
font-size: 11px;
color: var(--text-muted);
font-family: var(--font-mono);
margin-top: 2px;
}
/* ----------------------------------------
Section Headers
---------------------------------------- */
.section {
margin-bottom: 44px;
}
.section-header {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.16em;
color: var(--text-muted);
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
}
.section-header-left {
display: flex;
align-items: center;
gap: 8px;
}
.section-header svg {
width: 14px;
height: 14px;
stroke-width: 1.5;
color: var(--text-faint);
}
.section-count {
font-family: var(--font-mono);
font-size: 10px;
font-weight: 400;
color: var(--text-faint);
background: var(--border-light);
padding: 2px 8px;
border-radius: 10px;
}
/* ----------------------------------------
Career Timeline
---------------------------------------- */
.timeline {
position: relative;
padding-left: 28px;
}
.timeline::before {
content: '';
position: absolute;
left: 5px;
top: 8px;
bottom: 8px;
width: 1px;
background: linear-gradient(
to bottom,
var(--accent),
var(--border) 40%,
var(--border)
);
}
.timeline-entry {
position: relative;
padding: 0 0 28px 0;
cursor: pointer;
transition: all 0.15s ease;
}
.timeline-entry:last-child {
padding-bottom: 0;
}
.timeline-entry::before {
content: '';
position: absolute;
left: -28px;
top: 7px;
width: 11px;
height: 11px;
border-radius: 50%;
border: 2px solid var(--border);
background: var(--content-bg);
transition: all 0.15s ease;
z-index: 1;
}
.timeline-entry.current::before {
border-color: var(--accent);
background: var(--accent);
box-shadow: 0 0 0 3px rgba(0, 94, 184, 0.15);
}
.timeline-entry:hover::before {
border-color: var(--accent);
transform: scale(1.15);
}
.timeline-entry-header {
display: flex;
align-items: baseline;
gap: 12px;
margin-bottom: 4px;
}
.timeline-role {
font-size: 14px;
font-weight: 600;
color: var(--text-primary);
line-height: 1.3;
}
.timeline-entry.current .timeline-role {
color: var(--accent);
}
.timeline-current-badge {
font-size: 9px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.08em;
color: var(--accent);
background: var(--accent-pale);
padding: 2px 8px;
border-radius: 3px;
}
.timeline-meta {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 6px;
}
.timeline-org {
font-size: 12px;
font-weight: 500;
color: var(--text-secondary);
}
.timeline-org-dot {
display: inline-block;
width: 6px;
height: 6px;
border-radius: 50%;
margin-right: 6px;
vertical-align: middle;
}
.timeline-date {
font-size: 11px;
font-family: var(--font-mono);
color: var(--text-muted);
}
.timeline-summary {
font-size: 13px;
color: var(--text-secondary);
line-height: 1.6;
max-width: 600px;
}
.timeline-entry:hover .timeline-summary {
color: var(--text-primary);
}
.timeline-expand-hint {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 11px;
font-weight: 500;
color: var(--accent);
margin-top: 6px;
opacity: 0;
transform: translateX(-4px);
transition: all 0.15s ease;
}
.timeline-expand-hint svg {
width: 12px;
height: 12px;
stroke-width: 2;
}
.timeline-entry:hover .timeline-expand-hint {
opacity: 1;
transform: translateX(0);
}
/* ----------------------------------------
Active Problems
---------------------------------------- */
.problems-list {
display: flex;
flex-direction: column;
gap: 0;
}
.problem-item {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 12px 0;
border-bottom: 1px solid var(--border-light);
transition: background 0.1s ease;
}
.problem-item:last-child {
border-bottom: none;
}
.problem-indicator {
margin-top: 4px;
flex-shrink: 0;
}
.problem-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.problem-dot.active {
background: var(--green);
}
.problem-dot.in-progress {
background: var(--amber);
}
.problem-dot.resolved {
background: var(--text-faint);
}
.problem-body {
flex: 1;
min-width: 0;
}
.problem-description {
font-size: 13px;
font-weight: 500;
color: var(--text-primary);
line-height: 1.4;
}
.problem-detail-row {
display: flex;
align-items: center;
gap: 12px;
margin-top: 3px;
}
.problem-status-label {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.06em;
}
.problem-status-label.active {
color: var(--green-text);
}
.problem-status-label.in-progress {
color: var(--amber-text);
}
.problem-status-label.resolved {
color: var(--text-muted);
}
.problem-since {
font-size: 11px;
font-family: var(--font-mono);
color: var(--text-muted);
}
.problem-code {
font-size: 10px;
font-family: var(--font-mono);
color: var(--text-faint);
background: var(--border-light);
padding: 1px 6px;
border-radius: 3px;
}
.problem-outcome {
font-size: 12px;
color: var(--text-secondary);
margin-top: 2px;
font-style: italic;
}
/* ----------------------------------------
Skills — Horizontal Bar Chart
---------------------------------------- */
.skills-chart {
display: flex;
flex-direction: column;
gap: 10px;
}
.skill-row {
display: grid;
grid-template-columns: 120px 1fr 36px;
align-items: center;
gap: 12px;
}
.skill-name {
font-size: 12px;
font-weight: 500;
color: var(--text-primary);
font-family: var(--font-mono);
text-align: right;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.skill-bar-track {
height: 6px;
background: var(--border-light);
border-radius: 3px;
overflow: hidden;
position: relative;
}
.skill-bar-fill {
height: 100%;
border-radius: 3px;
background: var(--accent);
transition: width 0.8s var(--ease-out);
position: relative;
}
.skill-bar-fill.clinical {
background: linear-gradient(90deg, #0E7490, #06B6D4);
}
.skill-bar-fill.technical {
background: linear-gradient(90deg, var(--accent), #3B82F6);
}
.skill-bar-fill.leadership {
background: linear-gradient(90deg, #7C3AED, #A78BFA);
}
.skill-value {
font-size: 11px;
font-family: var(--font-mono);
color: var(--text-muted);
text-align: right;
}
/* Skill category labels */
.skill-category-label {
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--text-faint);
padding: 12px 0 4px;
}
.skill-category-label:first-child {
padding-top: 0;
}
/* ----------------------------------------
Two-column layout for bottom sections
---------------------------------------- */
.split-sections {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 48px;
}
/* ----------------------------------------
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;
}
/* Subtle divider */
.section-divider {
height: 1px;
background: linear-gradient(to right, var(--border), transparent 80%);
margin: 0 0 44px;
}
/* Alert Bar */
.alert-bar {
background: var(--surface);
border-left: 3px solid var(--accent);
padding: 12px 20px;
margin-bottom: 32px;
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 0 6px 6px 0;
box-shadow: var(--shadow-sm);
}
.alert-bar-content {
display: flex;
align-items: center;
gap: 12px;
}
.alert-bar-tag {
font-size: 9px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.1em;
color: var(--accent);
background: var(--accent-pale);
padding: 3px 8px;
border-radius: 3px;
}
.alert-bar-text {
font-size: 13px;
color: var(--text-secondary);
}
.alert-bar-text strong {
font-weight: 600;
color: var(--accent);
}
.alert-bar-dismiss {
background: none;
border: none;
cursor: pointer;
color: var(--text-faint);
padding: 4px;
display: flex;
align-items: center;
justify-content: center;
transition: color 0.15s ease;
border-radius: 4px;
}
.alert-bar-dismiss:hover {
color: var(--text-secondary);
background: var(--border-light);
}
.alert-bar-dismiss svg {
width: 14px;
height: 14px;
stroke-width: 2;
}
/* ----------------------------------------
Recent Achievements (resolved problems)
---------------------------------------- */
.achievements-compact {
display: flex;
flex-direction: column;
gap: 0;
}
.achievement-item {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 10px 0;
border-bottom: 1px solid var(--border-light);
}
.achievement-item:last-child {
border-bottom: none;
}
.achievement-icon {
margin-top: 2px;
color: var(--text-faint);
flex-shrink: 0;
}
.achievement-icon svg {
width: 14px;
height: 14px;
stroke-width: 1.5;
}
.achievement-text {
font-size: 13px;
color: var(--text-primary);
font-weight: 400;
line-height: 1.4;
}
.achievement-outcome {
font-size: 11px;
font-weight: 600;
color: var(--accent);
font-family: var(--font-mono);
margin-top: 2px;
}
</style>
</head>
<body>
<!-- ====================================
SIDEBAR — Collapsed, expands on hover
==================================== -->
<aside class="sidebar" role="navigation" aria-label="Clinical record navigation">
<div class="sidebar-brand">
<div class="sidebar-brand-icon">
<i data-lucide="heart-pulse"></i>
</div>
<div class="sidebar-brand-text">
<div class="sidebar-brand-title">ClinicalRecord</div>
<div class="sidebar-brand-sub">Patient System</div>
</div>
</div>
<nav class="sidebar-nav">
<div class="nav-section-label">Record</div>
<a class="nav-item active" href="#summary">
<i data-lucide="layout-dashboard"></i>
<span class="nav-item-label">Summary</span>
<span class="nav-key">Alt+1</span>
</a>
<a class="nav-item" href="#experience">
<i data-lucide="briefcase"></i>
<span class="nav-item-label">Experience</span>
<span class="nav-key">Alt+2</span>
</a>
<a class="nav-item" href="#skills">
<i data-lucide="cpu"></i>
<span class="nav-item-label">Skills</span>
<span class="nav-key">Alt+3</span>
</a>
<a class="nav-item" href="#achievements">
<i data-lucide="award"></i>
<span class="nav-item-label">Achievements</span>
<span class="nav-key">Alt+4</span>
</a>
<a class="nav-item" href="#projects">
<i data-lucide="folder-open"></i>
<span class="nav-item-label">Projects</span>
<span class="nav-key">Alt+5</span>
</a>
<a class="nav-item" href="#education">
<i data-lucide="graduation-cap"></i>
<span class="nav-item-label">Education</span>
<span class="nav-key">Alt+6</span>
</a>
<a class="nav-item" href="#contact">
<i data-lucide="mail"></i>
<span class="nav-item-label">Contact</span>
<span class="nav-key">Alt+7</span>
</a>
</nav>
<div class="sidebar-footer">
<div class="sidebar-footer-avatar">AC</div>
<div class="sidebar-footer-info">
<div class="sidebar-footer-name">
<span class="sidebar-footer-dot"></span>
A.CHARLWOOD
</div>
<div class="sidebar-footer-time" id="session-time">00:00:00</div>
</div>
</div>
</aside>
<div class="layout">
<!-- ====================================
PATIENT BANNER
==================================== -->
<header class="banner" role="banner">
<div class="banner-left">
<div class="banner-identity">
<div class="banner-name-row">
<span class="banner-name">CHARLWOOD, Andrew</span>
<span class="banner-honorific">(Mr)</span>
</div>
<div class="banner-subtitle-row">
<span class="banner-role">Deputy Head, Population Health & Data Analysis</span>
<span class="banner-status">
<span class="banner-status-dot"></span>
Active
</span>
<span class="banner-badge">Open to opportunities</span>
</div>
</div>
<div class="banner-divider"></div>
<div class="banner-meta">
<div class="banner-meta-item">
<span class="banner-meta-label">GPhC Reg</span>
<span class="banner-meta-value">221 181 0</span>
</div>
<div class="banner-meta-item">
<span class="banner-meta-label">DOB</span>
<span class="banner-meta-value">14/02/1993</span>
</div>
<div class="banner-meta-item">
<span class="banner-meta-label">Location</span>
<span class="banner-meta-value">Norwich, NR1</span>
</div>
<div class="banner-meta-item">
<span class="banner-meta-label">Email</span>
<span class="banner-meta-value">andy@charlwood.xyz</span>
</div>
</div>
</div>
<div class="banner-right">
<button class="banner-action primary">
<i data-lucide="download"></i>
Download CV
</button>
<button class="banner-action">
<i data-lucide="linkedin"></i>
LinkedIn
</button>
<button class="banner-action">
<i data-lucide="mail"></i>
Contact
</button>
</div>
</header>
<!-- ====================================
CONTENT — Summary View (Narrative)
==================================== -->
<main class="content" role="main">
<div class="content-inner">
<!-- Clinical Alert -->
<div class="alert-bar" role="alert" id="clinical-alert">
<div class="alert-bar-content">
<span class="alert-bar-tag">Alert</span>
<span class="alert-bar-text">This patient has identified <strong>&pound;14.6M in prescribing efficiency savings</strong> across Norfolk &amp; Waveney ICS.</span>
</div>
<button class="alert-bar-dismiss" aria-label="Dismiss alert" onclick="document.getElementById('clinical-alert').style.display='none'">
<i data-lucide="x"></i>
</button>
</div>
<!-- Narrative Header -->
<div class="narrative-block">
<div class="narrative-label">Clinical Summary</div>
<h1 class="narrative-headline">
NHS pharmacist turned <strong>data leader</strong>. 8+ years transforming healthcare delivery through analytics and prescribing optimisation.
</h1>
<p class="narrative-body">
Driving population health strategy for a 1M+ patient integrated care system. Combining deep clinical knowledge with advanced technical skills in Python, SQL, and Power BI to build the analytical infrastructure that identifies efficiency opportunities and addresses health inequalities at scale.
</p>
</div>
<!-- KPI Metrics Strip -->
<div class="kpi-strip">
<div class="kpi-item">
<span class="kpi-label">Savings Identified</span>
<span class="kpi-value">&pound;14.6<span class="kpi-unit">M</span></span>
<span class="kpi-context">efficiency programme</span>
</div>
<div class="kpi-item">
<span class="kpi-label">Budget Oversight</span>
<span class="kpi-value">&pound;220<span class="kpi-unit">M</span></span>
<span class="kpi-context">prescribing budget</span>
</div>
<div class="kpi-item">
<span class="kpi-label">Patients Identified</span>
<span class="kpi-value">14<span class="kpi-unit">K</span></span>
<span class="kpi-context">switching algorithm</span>
</div>
<div class="kpi-item">
<span class="kpi-label">Experience</span>
<span class="kpi-value">8<span class="kpi-unit">+ yrs</span></span>
<span class="kpi-context">since GPhC reg. 2016</span>
</div>
</div>
<!-- Career Timeline -->
<div class="section">
<div class="section-header">
<div class="section-header-left">
<i data-lucide="git-branch"></i>
Career Timeline
</div>
<span class="section-count">5 entries</span>
</div>
<div class="timeline">
<div class="timeline-entry current">
<div class="timeline-entry-header">
<span class="timeline-role">Deputy Head, Population Health & Data Analysis</span>
<span class="timeline-current-badge">Current</span>
</div>
<div class="timeline-meta">
<span class="timeline-org"><span class="timeline-org-dot" style="background: #005EB8;"></span>NHS Norfolk & Waveney ICB</span>
<span class="timeline-date">Jul 2024 &mdash; Present</span>
</div>
<p class="timeline-summary">Driving data analytics strategy for medicines optimisation. Managed &pound;220M prescribing budget. Created comprehensive medicines data infrastructure with dm+d integration.</p>
<div class="timeline-expand-hint">
<i data-lucide="chevron-right"></i>
View full record
</div>
</div>
<div class="timeline-entry">
<div class="timeline-entry-header">
<span class="timeline-role">Interim Head, Population Health & Data Analysis</span>
</div>
<div class="timeline-meta">
<span class="timeline-org"><span class="timeline-org-dot" style="background: #005EB8;"></span>NHS Norfolk & Waveney ICB</span>
<span class="timeline-date">May 2025 &mdash; Nov 2025</span>
</div>
<p class="timeline-summary">Led strategic delivery of population health initiatives. Identified &pound;14.6M efficiency programme. Built Python switching algorithm for 14,000 patients.</p>
<div class="timeline-expand-hint">
<i data-lucide="chevron-right"></i>
View full record
</div>
</div>
<div class="timeline-entry">
<div class="timeline-entry-header">
<span class="timeline-role">High-Cost Drugs & Interface Pharmacist</span>
</div>
<div class="timeline-meta">
<span class="timeline-org"><span class="timeline-org-dot" style="background: #005EB8;"></span>NHS Norfolk & Waveney ICB</span>
<span class="timeline-date">May 2022 &mdash; Jul 2024</span>
</div>
<p class="timeline-summary">Led NICE technology appraisal implementation. Developed Blueteq automation achieving 70% form reduction and 200 hours savings.</p>
<div class="timeline-expand-hint">
<i data-lucide="chevron-right"></i>
View full record
</div>
</div>
<div class="timeline-entry">
<div class="timeline-entry-header">
<span class="timeline-role">Pharmacy Manager</span>
</div>
<div class="timeline-meta">
<span class="timeline-org"><span class="timeline-org-dot" style="background: #00897B;"></span>Tesco PLC</span>
<span class="timeline-date">Nov 2017 &mdash; May 2022</span>
</div>
<p class="timeline-summary">Managed pharmacy operations across a 100-hour contract. Asthma screening process adopted nationally across ~300 branches, enabling ~&pound;1M revenue.</p>
<div class="timeline-expand-hint">
<i data-lucide="chevron-right"></i>
View full record
</div>
</div>
<div class="timeline-entry">
<div class="timeline-entry-header">
<span class="timeline-role">Duty Pharmacy Manager</span>
</div>
<div class="timeline-meta">
<span class="timeline-org"><span class="timeline-org-dot" style="background: #00897B;"></span>Tesco PLC</span>
<span class="timeline-date">Aug 2016 &mdash; Nov 2017</span>
</div>
<p class="timeline-summary">Commenced professional career following GPhC registration. Developed foundational clinical and operational competencies in community pharmacy.</p>
<div class="timeline-expand-hint">
<i data-lucide="chevron-right"></i>
View full record
</div>
</div>
</div>
</div>
<div class="section-divider"></div>
<!-- Split: Active Problems + Top Skills -->
<div class="split-sections">
<!-- Active Problems -->
<div class="section" style="margin-bottom: 0;">
<div class="section-header">
<div class="section-header-left">
<i data-lucide="alert-circle"></i>
Active Problems
</div>
<span class="section-count">3 active &middot; 7 resolved</span>
</div>
<div class="problems-list">
<div class="problem-item">
<div class="problem-indicator">
<div class="problem-dot active"></div>
</div>
<div class="problem-body">
<div class="problem-description">&pound;220M prescribing budget oversight and management</div>
<div class="problem-detail-row">
<span class="problem-status-label active">Active</span>
<span class="problem-since">Jul 2024</span>
<span class="problem-code">MGT001</span>
</div>
</div>
</div>
<div class="problem-item">
<div class="problem-indicator">
<div class="problem-dot in-progress"></div>
</div>
<div class="problem-body">
<div class="problem-description">Patient-level SQL analytics transformation</div>
<div class="problem-detail-row">
<span class="problem-status-label in-progress">In Progress</span>
<span class="problem-since">2025</span>
<span class="problem-code">TRN001</span>
</div>
</div>
</div>
<div class="problem-item">
<div class="problem-indicator">
<div class="problem-dot in-progress"></div>
</div>
<div class="problem-body">
<div class="problem-description">Team data literacy programme</div>
<div class="problem-detail-row">
<span class="problem-status-label in-progress">In Progress</span>
<span class="problem-since">Jul 2024</span>
<span class="problem-code">LEA001</span>
</div>
</div>
</div>
</div>
<!-- Recent Resolved -->
<div style="margin-top: 24px;">
<div style="font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-faint); margin-bottom: 12px;">Recently Resolved</div>
<div class="achievements-compact">
<div class="achievement-item">
<div class="achievement-icon"><i data-lucide="check-circle-2"></i></div>
<div>
<div class="achievement-text">Manual prescribing analysis inefficiency</div>
<div class="achievement-outcome">Python algorithm: 14,000 pts, &pound;2.6M/yr</div>
</div>
</div>
<div class="achievement-item">
<div class="achievement-icon"><i data-lucide="check-circle-2"></i></div>
<div>
<div class="achievement-text">&pound;14.6M efficiency target identification</div>
<div class="achievement-outcome">Over-target performance achieved</div>
</div>
</div>
<div class="achievement-item">
<div class="achievement-icon"><i data-lucide="check-circle-2"></i></div>
<div>
<div class="achievement-text">Blueteq form creation backlog</div>
<div class="achievement-outcome">70% reduction, 200hrs saved</div>
</div>
</div>
</div>
</div>
</div>
<!-- Top Skills -->
<div class="section" style="margin-bottom: 0;">
<div class="section-header">
<div class="section-header-left">
<i data-lucide="bar-chart-3"></i>
Top Skills
</div>
<span class="section-count">18 total</span>
</div>
<div class="skills-chart">
<div class="skill-category-label">Technical</div>
<div class="skill-row">
<span class="skill-name">Data Analysis</span>
<div class="skill-bar-track">
<div class="skill-bar-fill technical" style="width: 0%;" data-target="95"></div>
</div>
<span class="skill-value">95%</span>
</div>
<div class="skill-row">
<span class="skill-name">Power BI</span>
<div class="skill-bar-track">
<div class="skill-bar-fill technical" style="width: 0%;" data-target="92"></div>
</div>
<span class="skill-value">92%</span>
</div>
<div class="skill-row">
<span class="skill-name">Python</span>
<div class="skill-bar-track">
<div class="skill-bar-fill technical" style="width: 0%;" data-target="90"></div>
</div>
<span class="skill-value">90%</span>
</div>
<div class="skill-row">
<span class="skill-name">SQL</span>
<div class="skill-bar-track">
<div class="skill-bar-fill technical" style="width: 0%;" data-target="88"></div>
</div>
<span class="skill-value">88%</span>
</div>
<div class="skill-row">
<span class="skill-name">Dashboard Dev</span>
<div class="skill-bar-track">
<div class="skill-bar-fill technical" style="width: 0%;" data-target="88"></div>
</div>
<span class="skill-value">88%</span>
</div>
<div class="skill-category-label">Clinical</div>
<div class="skill-row">
<span class="skill-name">Medicines Opt.</span>
<div class="skill-bar-track">
<div class="skill-bar-fill clinical" style="width: 0%;" data-target="95"></div>
</div>
<span class="skill-value">95%</span>
</div>
<div class="skill-row">
<span class="skill-name">Pop. Health</span>
<div class="skill-bar-track">
<div class="skill-bar-fill clinical" style="width: 0%;" data-target="90"></div>
</div>
<span class="skill-value">90%</span>
</div>
<div class="skill-row">
<span class="skill-name">CD Assurance</span>
<div class="skill-bar-track">
<div class="skill-bar-fill clinical" style="width: 0%;" data-target="88"></div>
</div>
<span class="skill-value">88%</span>
</div>
<div class="skill-row">
<span class="skill-name">NICE TAs</span>
<div class="skill-bar-track">
<div class="skill-bar-fill clinical" style="width: 0%;" data-target="85"></div>
</div>
<span class="skill-value">85%</span>
</div>
<div class="skill-category-label">Leadership</div>
<div class="skill-row">
<span class="skill-name">Budget Mgmt</span>
<div class="skill-bar-track">
<div class="skill-bar-fill leadership" style="width: 0%;" data-target="90"></div>
</div>
<span class="skill-value">90%</span>
</div>
<div class="skill-row">
<span class="skill-name">Stakeholders</span>
<div class="skill-bar-track">
<div class="skill-bar-fill leadership" style="width: 0%;" data-target="88"></div>
</div>
<span class="skill-value">88%</span>
</div>
<div class="skill-row">
<span class="skill-name">Negotiation</span>
<div class="skill-bar-track">
<div class="skill-bar-fill leadership" style="width: 0%;" data-target="85"></div>
</div>
<span class="skill-value">85%</span>
</div>
</div>
</div>
</div><!-- /split-sections -->
</div><!-- /content-inner -->
</main>
</div><!-- /layout -->
<script>
// Initialize Lucide icons
lucide.createIcons();
// Session clock
function updateTime() {
const now = new Date();
const h = String(now.getHours()).padStart(2, '0');
const m = String(now.getMinutes()).padStart(2, '0');
const s = String(now.getSeconds()).padStart(2, '0');
const el = document.getElementById('session-time');
if (el) el.textContent = h + ':' + m + ':' + s;
}
updateTime();
setInterval(updateTime, 1000);
// Animate skill bars on page load
function animateSkillBars() {
const bars = document.querySelectorAll('.skill-bar-fill');
bars.forEach(function(bar, index) {
const target = bar.getAttribute('data-target');
setTimeout(function() {
bar.style.width = target + '%';
}, 200 + (index * 60));
});
}
// Run after a short delay to feel intentional
setTimeout(animateSkillBars, 400);
// Sidebar is position: fixed in CSS, expanding as overlay on hover.
// No JS needed for the sidebar behavior.
</script>
</body>
</html>