← back to Model Arena
data/artifacts/0066d3284995/qwen3-14b.html
352 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>The Ship of State Steered by Committee</title>
<style>
:root {
--bg-light: #f9f9f9;
--bg-dark: #1e1e1e;
--text-light: #222;
--text-dark: #ddd;
--accent: #4a90e2;
--error: #d9534f;
--success: #5cb85c;
}
body {
margin: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-light);
color: var(--text-light);
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
transition: background-color 0.3s, color 0.3s;
}
body.dark {
--bg-light: #1e1e1e;
--bg-dark: #0e0e0e;
--text-light: #ddd;
--text-dark: #222;
background-color: var(--bg-dark);
color: var(--text-dark);
}
.container {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
padding: 20px;
box-sizing: border-box;
}
svg {
width: 100%;
height: 100%;
max-height: 80vh;
max-width: 100%;
min-width: 390px;
min-height: 400px;
user-select: none;
}
.controls {
display: flex;
gap: 10px;
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
}
.control {
background-color: var(--accent);
padding: 8px 12px;
border: none;
color: white;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.2s;
}
.control:active {
background-color: #3a76c0;
}
.toggle {
position: absolute;
top: 10px;
right: 10px;
background-color: var(--accent);
color: white;
border: none;
border-radius: 50%;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
cursor: pointer;
user-select: none;
}
.caption {
margin-top: 20px;
font-size: 18px;
text-align: center;
max-width: 80%;
white-space: pre-wrap;
transition: color 0.3s;
}
.error {
color: var(--error);
}
.success {
color: var(--success);
}
.info {
color: var(--accent);
}
.ship {
transform: scale(1);
transition: transform 0.3s;
}
.ship.dragging {
transform: scale(1.1);
}
.handle {
cursor: move;
fill: var(--accent);
pointer-events: all;
}
.handle.dragging {
fill: #3a76c0;
}
.indicator {
position: absolute;
top: 10px;
left: 10px;
background-color: var(--accent);
color: white;
padding: 5px 10px;
border-radius: 6px;
font-size: 12px;
display: none;
}
.indicator.active {
display: block;
}
.empty {
display: none;
}
.empty.active {
display: block;
}
.error-state {
display: none;
}
.error-state.active {
display: block;
}
.success-state {
display: none;
}
.success-state.active {
display: block;
}
@media (prefers-reduced-motion: no-preference) {
.ship {
transition: transform 0.3s;
}
}
@media (max-width: 768px) {
.controls {
flex-direction: column;
}
}
</style>
</head>
<body>
<div class="container">
<svg viewBox="0 0 800 600">
<!-- Sea -->
<rect x="0" y="0" width="800" height="600" fill="#99ccff" />
<!-- Ship -->
<g id="ship" class="ship" transform="translate(400,300)">
<!-- Hull -->
<polygon points="0,-60 100,-20 150,0 140,60 0,60 -60,0" fill="#666" stroke="#333" stroke-width="3" />
<!-- Masts -->
<line x1="70" y1="-60" x2="70" y2="-140" stroke="#888" stroke-width="6" />
<line x1="130" y1="-60" x2="130" y2="-140" stroke="#888" stroke-width="6" />
<!-- Sails -->
<polygon points="70,-140 100,-160 130,-140 100,-130" fill="white" stroke="#888" stroke-width="2" />
<polygon points="70,-140 40,-180 130,-140 100,-160" fill="white" stroke="#888" stroke-width="2" />
<!-- Steering Wheel -->
<g class="handle" transform="translate(75,-70)">
<circle cx="0" cy="0" r="20" fill="#4a90e2" />
<line x1="0" y1="10" x2="0" y2="30" stroke="#333" stroke-width="3" />
</g>
<!-- Committee -->
<g id="committee">
<circle cx="100" cy="30" r="15" fill="#c93030" />
<text x="115" y="40" font-size="14" fill="white" text-anchor="start">Red</text>
<circle cx="200" cy="30" r="15" fill="#4caf50" />
<text x="215" y="40" font-size="14" fill="white" text-anchor="start">Green</text>
<circle cx="300" cy="30" r="15" fill="#ff9800" />
<text x="315" y="40" font-size="14" fill="white" text-anchor="start">Yellow</text>
<circle cx="400" cy="30" r="15" fill="#00bcd4" />
<text x="415" y="40" font-size="14" fill="white" text-anchor="start">Blue</text>
</g>
</g>
</svg>
<button class="toggle" aria-label="Toggle light/dark mode">
🌞
</button>
<div class="controls">
<button class="control" id="reset">Reset</button>
<button class="control" id="drift">Drift</button>
<button class="control" id="sink">Sink</button>
<button class="control" id="anchor">Anchor</button>
</div>
<div class="indicator" id="indicator">Dragging...</div>
<div class="empty" id="empty">No committee members present.</div>
<div class="error" id="error">Ship is sinking. Committee is disoriented.</div>
<div class="success" id="success">Course corrected! The ship is on track.</div>
<div class="caption" id="caption">The ship of state steered by a committed and balanced committee.</div>
</div>
<script>
const svg = document.querySelector('svg');
const shipGroup = document.getElementById('ship');
const handle = document.querySelector('.handle');
const committee = document.getElementById('committee');
const indicator = document.getElementById('indicator');
const caption = document.getElementById('caption');
const empty = document.getElementById('empty');
const error = document.getElementById('error');
const success = document.getElementById('success');
const resetBtn = document.getElementById('reset');
const driftBtn = document.getElementById('drift');
const sinkBtn = document.getElementById('sink');
const anchorBtn = document.getElementById('anchor');
const toggleBtn = document.querySelector('.toggle');
let isDragging = false;
let offsetX, offsetY;
// Toggle light/dark
toggleBtn.addEventListener('click', () => {
document.body.classList.toggle('dark');
});
// Dragging ship handle
handle.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - shipGroup.transform.baseVal.getItem(0).matrix.e;
offsetY = e.clientY - shipGroup.transform.baseVal.getItem(0).matrix.f;
indicator.classList.add('active');
handle.classList.add('dragging');
});
document.addEventListener('mousemove', (e) => {
if (isDragging) {
const x = e.clientX - offsetX;
const y = e.clientY - offsetY;
shipGroup.setAttribute('transform', `translate(${x},${y})`);
}
});
document.addEventListener('mouseup', () => {
if (isDragging) {
isDragging = false;
indicator.classList.remove('active');
handle.classList.remove('dragging');
}
});
// Reset all
resetBtn.addEventListener('click', () => {
shipGroup.setAttribute('transform', 'translate(400,300)');
committee.setAttribute('transform', 'translate(0,0)');
indicator.classList.remove('active');
handle.classList.remove('dragging');
empty.classList.remove('active');
error.classList.remove('active');
success.classList.remove('active');
caption.textContent = "The ship of state steered by a committed and balanced committee.";
});
// Drift (move committee)
driftBtn.addEventListener('click', () => {
const randomX = Math.random() * 200 - 100;
const randomY = Math.random() * 200 - 100;
committee.setAttribute('transform', `translate(${randomX},${randomY})`);
caption.textContent = "The ship of state is drifting. The committee is divided.";
});
// Sink (add error state)
sinkBtn.addEventListener('click', () => {
committee.setAttribute('transform', 'translate(0,100)');
caption.textContent = "The ship of state is sinking. The committee is at odds.";
error.classList.add('active');
});
// Anchor (add success state)
anchorBtn.addEventListener('click', () => {
committee.setAttribute('transform', 'translate(0,0)');
caption.textContent = "The ship of state is anchored. The committee is unified.";
success.classList.add('active');
});
// Keyboard access
document.addEventListener('keydown', (e) => {
if (e.key === 'r') resetBtn.click();
if (e.key === 'd') driftBtn.click();
if (e.key === 's') sinkBtn.click();
if (e.key === 'a') anchorBtn.click();
if (e.key === 't') toggleBtn.click();
});
// Focus styles
document.querySelectorAll('button, [role="button"]').forEach(el => {
el.setAttribute('tabindex', '0');
el.addEventListener('focus', () => {
el.style.outline = '2px solid var(--accent)';
});
el.addEventListener('blur', () => {
el.style.outline = 'none';
});
});
// Empty state (if committee is hidden)
if (!committee) {
empty.classList.add('active');
}
</script>
</body>
</html>