Sam20202's picture
Initial deploy
0533780
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>GLM-OCR</title>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;700&family=DM+Serif+Display:ital@0;1&family=DM+Sans:wght@400;500&display=swap" rel="stylesheet"/>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--ink: #0f0e0d;
--paper: #f5f0e8;
--warm: #ede8dc;
--border: #d4cfc3;
--muted: #8f8880;
--accent: #c94a1f;
--green: #1a6b4a;
--mono: 'IBM Plex Mono', monospace;
--serif: 'DM Serif Display', serif;
--sans: 'DM Sans', sans-serif;
}
body {
width: 300px;
background: var(--paper);
color: var(--ink);
font-family: var(--sans);
}
body::before {
content: '';
position: fixed; inset: 0;
background-image: radial-gradient(circle, rgba(0,0,0,0.05) 1px, transparent 1px);
background-size: 16px 16px;
pointer-events: none;
}
.inner { position: relative; }
/* Header */
.header {
padding: 16px 18px 14px;
border-bottom: 2px solid var(--ink);
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
font-family: var(--serif);
font-size: 1.1rem;
letter-spacing: -0.01em;
}
.logo em { font-style: italic; color: var(--accent); }
.server-badge {
display: flex;
align-items: center;
gap: 5px;
font-family: var(--mono);
font-size: 0.58rem;
color: var(--muted);
letter-spacing: 0.06em;
}
.dot {
width: 6px; height: 6px;
border-radius: 50%;
background: var(--muted);
}
.dot.ok { background: var(--green); }
.dot.err { background: var(--accent); }
.dot.pulse { animation: blink 1.2s ease-in-out infinite; }
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:0.3} }
/* Main CTA */
.cta-area {
padding: 20px 18px;
border-bottom: 1px solid var(--border);
}
.cta-label {
font-family: var(--mono);
font-size: 0.62rem;
color: var(--muted);
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 10px;
}
.select-btn {
width: 100%;
padding: 14px;
background: var(--accent);
color: white;
border: none;
border-radius: 2px;
font-family: var(--serif);
font-size: 1rem;
cursor: pointer;
transition: background 0.15s;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.select-btn:hover:not(:disabled) { background: #b53d15; }
.select-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.select-btn .shortcut {
font-family: var(--mono);
font-size: 0.6rem;
opacity: 0.7;
margin-left: auto;
}
.offline-msg {
display: none;
margin-top: 10px;
font-family: var(--mono);
font-size: 0.65rem;
color: var(--accent);
line-height: 1.6;
}
.offline-msg.show { display: block; }
.offline-msg a {
color: var(--accent);
text-decoration: underline;
}
/* How it works */
.how {
padding: 16px 18px;
border-bottom: 1px solid var(--border);
}
.how-title {
font-family: var(--mono);
font-size: 0.6rem;
color: var(--muted);
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 12px;
}
.step {
display: flex;
gap: 10px;
align-items: flex-start;
margin-bottom: 8px;
}
.step:last-child { margin-bottom: 0; }
.step-num {
font-family: var(--mono);
font-size: 0.6rem;
color: var(--accent);
font-weight: 700;
flex-shrink: 0;
margin-top: 2px;
}
.step-text {
font-size: 0.78rem;
line-height: 1.5;
color: var(--ink);
}
/* Settings */
.settings {
padding: 14px 18px;
}
.settings-title {
font-family: var(--mono);
font-size: 0.6rem;
color: var(--muted);
letter-spacing: 0.1em;
text-transform: uppercase;
margin-bottom: 10px;
}
.setting-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
}
.setting-label {
font-family: var(--mono);
font-size: 0.68rem;
color: var(--ink);
}
.mode-toggle {
display: flex;
gap: 4px;
}
.mode-opt {
font-family: var(--mono);
font-size: 0.58rem;
padding: 4px 8px;
border: 1px solid var(--border);
background: transparent;
color: var(--muted);
cursor: pointer;
border-radius: 2px;
transition: all 0.12s;
}
.mode-opt.active {
background: var(--ink);
border-color: var(--ink);
color: var(--paper);
}
/* Footer */
.footer {
padding: 10px 18px;
border-top: 1px solid var(--border);
font-family: var(--mono);
font-size: 0.58rem;
color: var(--muted);
display: flex;
justify-content: space-between;
}
</style>
</head>
<body>
<div class="inner">
<!-- Header -->
<div class="header">
<div class="logo">GLM-<em>OCR</em></div>
<div class="server-badge">
<div class="dot pulse" id="dot"></div>
<span id="server-label">checking…</span>
</div>
</div>
<!-- CTA -->
<div class="cta-area">
<div class="cta-label">Select region on screen</div>
<button class="select-btn" id="select-btn" disabled>
&nbsp;Select & Extract Text
</button>
<div class="offline-msg" id="offline-msg">
⚠ GLM-OCR server not running.<br>
Start it with <code>python main.py</code> at <a href="http://localhost:8000" target="_blank">localhost:8000</a>.
</div>
</div>
<!-- How it works -->
<div class="how">
<div class="how-title">How it works</div>
<div class="step">
<div class="step-num">01</div>
<div class="step-text">Click the button above — page dims</div>
</div>
<div class="step">
<div class="step-num">02</div>
<div class="step-text">Drag a box around the text you want</div>
</div>
<div class="step">
<div class="step-num">03</div>
<div class="step-text">GLM-OCR extracts text into a sidebar</div>
</div>
<div class="step">
<div class="step-num">04</div>
<div class="step-text">Copy or download the result</div>
</div>
</div>
<!-- Settings -->
<div class="settings">
<div class="settings-title">Settings</div>
<div class="setting-row">
<span class="setting-label">OCR Mode</span>
<div class="mode-toggle">
<button class="mode-opt active" data-mode="recognize">recognize</button>
<button class="mode-opt" data-mode="parse">parse</button>
</div>
</div>
</div>
<div class="footer">
<span>zai-org/GLM-OCR · 0.9B</span>
<span>self-hosted</span>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>