Web app: new entities (Image, RenderedAsset, SharedImage, Token, DeviceImageHistory), enums, repositories, controllers, message handlers, migrations, tests, frontend upload/library/sticker UI, Vue components. Firmware: EPD background screen binaries + gen scripts, setup_bg header. Infra: ddev config, test bundle, gitignore coverage dir. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,820 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=800">
|
||||
<title>AP Provisioning Screen — pictureFrame mockup</title>
|
||||
<style>
|
||||
/*
|
||||
HARDWARE CONSTRAINTS: 800×480px. Six colors only.
|
||||
#1a1a1a BLACK
|
||||
#f5f5f0 WHITE
|
||||
#f0d000 YELLOW
|
||||
#c03020 RED
|
||||
#1840c0 BLUE
|
||||
#10a040 GREEN
|
||||
|
||||
No gradients. No drop shadows. No anti-aliasing. No other colors.
|
||||
No fonts below ~16px.
|
||||
This file is a design mockup — open at 100% zoom in browser.
|
||||
*/
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #888;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
/* Outer frame — the physical bezel of the device */
|
||||
.device-bezel {
|
||||
width: 840px;
|
||||
height: 520px;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* The e-ink display surface — exactly 800×480 */
|
||||
.display {
|
||||
width: 800px;
|
||||
height: 480px;
|
||||
background: #f5f5f0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
YELLOW STATUS BAR — signals AP mode / action required
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
|
||||
.status-bar {
|
||||
width: 800px;
|
||||
height: 52px;
|
||||
background: #f0d000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-bar-label {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.status-bar-network {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
/* Monospaced network name chip */
|
||||
.network-chip {
|
||||
display: inline-block;
|
||||
background: #1a1a1a;
|
||||
color: #f0d000;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
MAIN BODY — three-column layout
|
||||
LEFT: header + instructions
|
||||
CENTER: orientation diagrams
|
||||
RIGHT: QR code
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
|
||||
.body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* ── LEFT PANEL ───────────────────────────────────── */
|
||||
.panel-left {
|
||||
width: 310px;
|
||||
flex-shrink: 0;
|
||||
padding: 24px 20px 20px 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
border-right: 2px solid #1a1a1a;
|
||||
}
|
||||
|
||||
.main-heading {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.2;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.main-heading em {
|
||||
font-style: normal;
|
||||
color: #1a1a1a;
|
||||
/* Underline in yellow: simulate with border since no CSS effects */
|
||||
border-bottom: 3px solid #f0d000;
|
||||
}
|
||||
|
||||
.step-list {
|
||||
list-style: none;
|
||||
margin-top: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.step-num {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: #1a1a1a;
|
||||
color: #f0d000;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-text {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 15px;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.35;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.step-text strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Divider */
|
||||
.left-divider {
|
||||
height: 2px;
|
||||
background: #1a1a1a;
|
||||
margin: 16px 0 14px;
|
||||
}
|
||||
|
||||
.footnote {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 13px;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.4;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* ── CENTER PANEL — orientation diagrams ──────────── */
|
||||
.panel-center {
|
||||
width: 196px;
|
||||
flex-shrink: 0;
|
||||
border-right: 2px solid #1a1a1a;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
padding: 16px 12px;
|
||||
}
|
||||
|
||||
.orient-label {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.orient-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Landscape: wide rect + bottom ribbon */
|
||||
.orient-landscape-frame {
|
||||
width: 110px;
|
||||
height: 66px;
|
||||
border: 3px solid #1a1a1a;
|
||||
background: #f5f5f0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Corner tick marks to suggest the physical frame */
|
||||
.orient-landscape-frame::before,
|
||||
.orient-landscape-frame::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
.orient-landscape-ribbon {
|
||||
width: 110px;
|
||||
height: 10px;
|
||||
background: #1a1a1a;
|
||||
/* The power ribbon / cable notch at bottom */
|
||||
}
|
||||
|
||||
/* Portrait: tall rect + left ribbon */
|
||||
.orient-portrait-frame {
|
||||
width: 64px;
|
||||
height: 106px;
|
||||
border: 3px solid #1a1a1a;
|
||||
background: #f5f5f0;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.orient-portrait-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.orient-portrait-ribbon {
|
||||
width: 10px;
|
||||
height: 106px;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Active/current orientation highlight */
|
||||
.orient-active .orient-landscape-frame,
|
||||
.orient-active .orient-portrait-frame {
|
||||
border-color: #f0d000;
|
||||
border-width: 3px;
|
||||
}
|
||||
|
||||
.orient-active .orient-landscape-ribbon,
|
||||
.orient-active .orient-portrait-ribbon {
|
||||
background: #f0d000;
|
||||
}
|
||||
|
||||
.orient-active .orient-label {
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Tiny check mark for active orientation */
|
||||
.active-badge {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: #f0d000;
|
||||
border: 2px solid #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
font-weight: 900;
|
||||
color: #1a1a1a;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.orient-divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #1a1a1a;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.orient-section-title {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.25em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
opacity: 0.55;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* ── RIGHT PANEL — QR code ────────────────────────── */
|
||||
.panel-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.qr-instruction {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-wrapper {
|
||||
width: 196px;
|
||||
height: 196px;
|
||||
background: #f5f5f0;
|
||||
border: 3px solid #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Yellow corner brackets — frame the QR */
|
||||
.qr-wrapper::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
right: -3px;
|
||||
bottom: -3px;
|
||||
border: 3px solid #f0d000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.qr-sub {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 12px;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
opacity: 0.65;
|
||||
max-width: 190px;
|
||||
}
|
||||
|
||||
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
QR CODE — SVG grid rendered in pure black/white
|
||||
Pattern: encodes WIFI:S:PictureFrame-A3F7;T:nopass;;
|
||||
This is a realistic-looking QR placeholder.
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="device-bezel">
|
||||
<div class="display">
|
||||
|
||||
<!-- STATUS BAR -->
|
||||
<div class="status-bar">
|
||||
<span class="status-bar-label">Setup Mode — Step 1 of 2</span>
|
||||
<span class="status-bar-network">
|
||||
Broadcasting: <span class="network-chip">PictureFrame-A3F7</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- BODY -->
|
||||
<div class="body">
|
||||
|
||||
<!-- LEFT: instructions -->
|
||||
<div class="panel-left">
|
||||
<div>
|
||||
<div class="main-heading">Connect to<br><em>WiFi</em></div>
|
||||
|
||||
<ul class="step-list">
|
||||
<li class="step-item">
|
||||
<div class="step-num">1</div>
|
||||
<div class="step-text">
|
||||
Scan the QR code →<br>
|
||||
Your phone joins <strong>PictureFrame-A3F7</strong>
|
||||
</div>
|
||||
</li>
|
||||
<li class="step-item">
|
||||
<div class="step-num">2</div>
|
||||
<div class="step-text">
|
||||
A WiFi setup page opens automatically in your browser
|
||||
</div>
|
||||
</li>
|
||||
<li class="step-item">
|
||||
<div class="step-num">3</div>
|
||||
<div class="step-text">
|
||||
Enter your <strong>home WiFi</strong> credentials and tap Connect
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="left-divider"></div>
|
||||
<div class="footnote">
|
||||
Page didn't open? Navigate to<br>
|
||||
<strong>192.168.4.1</strong> in any browser.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CENTER: orientation diagrams -->
|
||||
<div class="panel-center">
|
||||
<div class="orient-section-title">Frame orientation</div>
|
||||
|
||||
<!-- Landscape (active) -->
|
||||
<div class="orient-block orient-active">
|
||||
<div class="orient-label">Landscape</div>
|
||||
<div class="orient-landscape-frame"></div>
|
||||
<div class="orient-landscape-ribbon"></div>
|
||||
<div class="active-badge">✓</div>
|
||||
</div>
|
||||
|
||||
<div class="orient-divider"></div>
|
||||
|
||||
<!-- Portrait -->
|
||||
<div class="orient-block">
|
||||
<div class="orient-label">Portrait</div>
|
||||
<div class="orient-portrait-wrapper">
|
||||
<div class="orient-portrait-ribbon"></div>
|
||||
<div class="orient-portrait-frame"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RIGHT: QR code -->
|
||||
<div class="panel-right">
|
||||
<div class="qr-instruction">Scan to connect</div>
|
||||
|
||||
<div class="qr-wrapper">
|
||||
<!-- QR code rendered as SVG — encodes WIFI:S:PictureFrame-A3F7;T:nopass;; -->
|
||||
<svg width="178" height="178" viewBox="0 0 41 41" xmlns="http://www.w3.org/2000/svg"
|
||||
shape-rendering="crispEdges">
|
||||
<rect width="41" height="41" fill="#f5f5f0"/>
|
||||
|
||||
<!-- TOP-LEFT FINDER PATTERN -->
|
||||
<rect x="1" y="1" width="7" height="7" fill="#1a1a1a"/>
|
||||
<rect x="2" y="2" width="5" height="5" fill="#f5f5f0"/>
|
||||
<rect x="3" y="3" width="3" height="3" fill="#1a1a1a"/>
|
||||
|
||||
<!-- TOP-RIGHT FINDER PATTERN -->
|
||||
<rect x="33" y="1" width="7" height="7" fill="#1a1a1a"/>
|
||||
<rect x="34" y="2" width="5" height="5" fill="#f5f5f0"/>
|
||||
<rect x="35" y="3" width="3" height="3" fill="#1a1a1a"/>
|
||||
|
||||
<!-- BOTTOM-LEFT FINDER PATTERN -->
|
||||
<rect x="1" y="33" width="7" height="7" fill="#1a1a1a"/>
|
||||
<rect x="2" y="34" width="5" height="5" fill="#f5f5f0"/>
|
||||
<rect x="3" y="35" width="3" height="3" fill="#1a1a1a"/>
|
||||
|
||||
<!-- TIMING PATTERNS (horizontal and vertical) -->
|
||||
<rect x="9" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="6" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="13" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="15" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="17" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="19" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="21" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="25" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="27" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="29" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="31" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- DATA MODULES — WiFi QR payload simulation -->
|
||||
<!-- Row 9 -->
|
||||
<rect x="9" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="9" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="9" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="9" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="9" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 10 -->
|
||||
<rect x="9" y="10" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="10" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="10" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="10" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="10" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="10" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="10" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 11 -->
|
||||
<rect x="8" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="10" y="11" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="11" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="11" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="11" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 12 -->
|
||||
<rect x="9" y="12" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="12" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="12" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="12" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="12" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="12" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="12" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 13 -->
|
||||
<rect x="8" y="13" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="13" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="13" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="13" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="13" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="13" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="13" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 14 -->
|
||||
<rect x="9" y="14" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="14" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="14" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="14" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="14" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="14" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="14" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 15 -->
|
||||
<rect x="8" y="15" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="15" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="15" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="15" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="15" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="15" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="15" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 16 -->
|
||||
<rect x="9" y="16" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="16" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="16" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="16" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="16" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="16" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="34" y="16" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 17 -->
|
||||
<rect x="8" y="17" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="10" y="17" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="17" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="17" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="17" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="17" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="17" width="4" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 18 -->
|
||||
<rect x="9" y="18" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="18" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="18" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="18" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="18" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="18" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="18" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 19 -->
|
||||
<rect x="8" y="19" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="19" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="19" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="19" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="19" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="19" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="19" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 20 (center) -->
|
||||
<rect x="9" y="20" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="20" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="20" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="20" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="20" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="20" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="20" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 21 -->
|
||||
<rect x="8" y="21" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="21" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="21" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="21" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="21" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="21" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="21" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 22 -->
|
||||
<rect x="9" y="22" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="22" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="22" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="22" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="22" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="22" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="22" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 23 -->
|
||||
<rect x="8" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="10" y="23" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="23" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="23" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="23" width="4" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 24 -->
|
||||
<rect x="9" y="24" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="24" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="24" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="24" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="24" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="24" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="24" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 25 -->
|
||||
<rect x="8" y="25" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="25" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="25" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="25" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="25" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="25" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="25" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 26 -->
|
||||
<rect x="9" y="26" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="26" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="26" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="26" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="26" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="26" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="26" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="26" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 27 -->
|
||||
<rect x="8" y="27" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="27" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="27" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="27" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="27" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="27" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="27" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 28 -->
|
||||
<rect x="9" y="28" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="28" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="28" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="28" width="4" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 29 -->
|
||||
<rect x="8" y="29" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="10" y="29" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="29" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="29" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="29" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="29" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="29" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 30 -->
|
||||
<rect x="9" y="30" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="30" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="30" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="30" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 31 -->
|
||||
<rect x="8" y="31" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="31" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="31" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="31" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="31" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="31" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="31" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Alignment pattern bottom-right (5×5) -->
|
||||
<rect x="28" y="28" width="5" height="5" fill="#1a1a1a"/>
|
||||
<rect x="29" y="29" width="3" height="3" fill="#f5f5f0"/>
|
||||
<rect x="30" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Format info strips -->
|
||||
<rect x="8" y="8" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Extra data density rows 33–39 (below bottom-left finder) -->
|
||||
<rect x="9" y="34" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="34" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="34" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="34" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="34" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="34" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="8" y="35" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="35" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="35" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="35" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="35" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="35" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="9" y="36" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="36" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="36" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="36" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="36" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="36" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="36" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="8" y="37" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="37" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="37" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="37" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="37" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="37" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="9" y="38" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="38" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="38" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="38" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="38" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="38" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="8" y="39" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="10" y="39" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="39" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="39" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="39" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="39" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="39" width="3" height="1" fill="#1a1a1a"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="qr-sub">
|
||||
Encodes: <strong>WIFI:S:PictureFrame-A3F7;T:nopass;;</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- /.body -->
|
||||
|
||||
</div><!-- /.display -->
|
||||
</div><!-- /.device-bezel -->
|
||||
|
||||
<!--
|
||||
DESIGNER NOTES
|
||||
──────────────────────────────────────────────────────────────────
|
||||
Screen: AP Provisioning — Step 1 of 2
|
||||
State: Frame has no WiFi credentials. Broadcasting open AP.
|
||||
Accent: YELLOW — signals "action required," unconnected state.
|
||||
|
||||
Layout rationale:
|
||||
• Yellow status bar carries SSID at a glance — one horizontal scan
|
||||
tells you what network to join without reading the instructions.
|
||||
• Instructions live LEFT, not centered, to make room for the large QR
|
||||
without any elements competing at the same scale.
|
||||
• Orientation diagrams are narrow + centered — they confirm physical
|
||||
placement, not the primary action. They don't compete.
|
||||
• QR panel is RIGHT and large — the single action. Yellow bracket
|
||||
border echoes the accent and frames the eye's destination.
|
||||
• Step numbers in black/yellow inverse boxes are readable at a
|
||||
distance; the QR is readable up close. Both jobs done together.
|
||||
• "Landscape" is marked active (check mark + yellow ribbon) because
|
||||
the frame is currently held landscape. Portrait shown as the alt.
|
||||
• Footnote handles the "captive portal didn't open" edge case.
|
||||
Firmware MUST handle this — the screen already does.
|
||||
|
||||
Firmware implementation notes (for when you write the C):
|
||||
• The SSID suffix is the last 4 hex chars of the MAC.
|
||||
• The QR encodes the WIFI: string for auto-join on iOS/Android.
|
||||
• The 192.168.4.1 fallback is the ESP32 SoftAP default gateway.
|
||||
──────────────────────────────────────────────────────────────────
|
||||
-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,971 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=800">
|
||||
<title>Setup QR Screen — pictureFrame mockup</title>
|
||||
<style>
|
||||
/*
|
||||
HARDWARE CONSTRAINTS: 800×480px. Six colors only.
|
||||
#1a1a1a BLACK
|
||||
#f5f5f0 WHITE
|
||||
#f0d000 YELLOW
|
||||
#c03020 RED
|
||||
#1840c0 BLUE
|
||||
#10a040 GREEN
|
||||
|
||||
No gradients. No drop shadows. No anti-aliasing. No other colors.
|
||||
No fonts below ~16px.
|
||||
This file is a design mockup — open at 100% zoom in browser.
|
||||
*/
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #888;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
}
|
||||
|
||||
/* Outer frame — the physical bezel */
|
||||
.device-bezel {
|
||||
width: 840px;
|
||||
height: 520px;
|
||||
background: #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* The e-ink display surface — exactly 800×480 */
|
||||
.display {
|
||||
width: 800px;
|
||||
height: 480px;
|
||||
background: #f5f5f0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
GREEN STATUS BAR — signals connected / almost done
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
|
||||
.status-bar {
|
||||
width: 800px;
|
||||
height: 52px;
|
||||
background: #10a040;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 24px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-bar-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* WiFi connected indicator — pixelated bars (no border-radius) */
|
||||
.wifi-icon {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 3px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.wifi-bar {
|
||||
background: #f5f5f0;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
.wifi-bar-1 { height: 8px; }
|
||||
.wifi-bar-2 { height: 13px; }
|
||||
.wifi-bar-3 { height: 18px; }
|
||||
.wifi-bar-4 { height: 22px; }
|
||||
|
||||
.status-bar-label {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: #f5f5f0;
|
||||
}
|
||||
|
||||
.status-bar-right {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #f5f5f0;
|
||||
letter-spacing: 0.06em;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.ip-chip {
|
||||
display: inline-block;
|
||||
background: #f5f5f0;
|
||||
color: #10a040;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
padding: 3px 9px;
|
||||
}
|
||||
|
||||
/* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
MAIN BODY
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */
|
||||
.body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
/* ── LEFT PANEL ───────────────────────────────────── */
|
||||
.panel-left {
|
||||
width: 340px;
|
||||
flex-shrink: 0;
|
||||
padding: 24px 20px 20px 28px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
border-right: 2px solid #1a1a1a;
|
||||
}
|
||||
|
||||
.main-heading {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.2;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.main-heading em {
|
||||
font-style: normal;
|
||||
border-bottom: 3px solid #10a040;
|
||||
}
|
||||
|
||||
.sub-heading {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 15px;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.5;
|
||||
margin-top: 14px;
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.step-list {
|
||||
list-style: none;
|
||||
margin-top: 18px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.step-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.step-num {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: #10a040;
|
||||
color: #f5f5f0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-text {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 15px;
|
||||
color: #1a1a1a;
|
||||
line-height: 1.35;
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.step-text strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* URL hint bar */
|
||||
.url-bar {
|
||||
margin-top: 18px;
|
||||
background: #1a1a1a;
|
||||
padding: 8px 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.url-bar-label {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: #10a040;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.url-bar-value {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 12px;
|
||||
color: #f5f5f0;
|
||||
word-break: break-all;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* Progress tracker */
|
||||
.progress-track {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.progress-label {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.2em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
opacity: 0.45;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.progress-steps {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.prog-step {
|
||||
height: 6px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.prog-step.done {
|
||||
background: #10a040;
|
||||
}
|
||||
|
||||
.prog-step.active {
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
.prog-step.todo {
|
||||
background: #1a1a1a;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.prog-step-labels {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.prog-step-label {
|
||||
flex: 1;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 10px;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
opacity: 0.55;
|
||||
}
|
||||
|
||||
.prog-step-label.done {
|
||||
color: #10a040;
|
||||
opacity: 1;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.prog-step-label.active {
|
||||
opacity: 1;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* ── CENTER PANEL — orientation diagrams ──────────── */
|
||||
.panel-center {
|
||||
width: 164px;
|
||||
flex-shrink: 0;
|
||||
border-right: 2px solid #1a1a1a;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
padding: 16px 10px;
|
||||
}
|
||||
|
||||
.orient-section-title {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.25em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
opacity: 0.45;
|
||||
text-align: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.orient-label {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.orient-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Landscape: wide rect + bottom ribbon */
|
||||
.orient-landscape-frame {
|
||||
width: 100px;
|
||||
height: 60px;
|
||||
border: 3px solid #1a1a1a;
|
||||
background: #f5f5f0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Inner screen hatching — suggests image content */
|
||||
.orient-landscape-frame::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 6px; left: 6px; right: 6px; bottom: 6px;
|
||||
border: 1px solid #1a1a1a;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
.orient-landscape-ribbon {
|
||||
width: 100px;
|
||||
height: 9px;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Portrait: tall rect + left ribbon */
|
||||
.orient-portrait-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.orient-portrait-ribbon {
|
||||
width: 9px;
|
||||
height: 96px;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
.orient-portrait-frame {
|
||||
width: 58px;
|
||||
height: 96px;
|
||||
border: 3px solid #1a1a1a;
|
||||
background: #f5f5f0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.orient-portrait-frame::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 6px; left: 6px; right: 6px; bottom: 6px;
|
||||
border: 1px solid #1a1a1a;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
/* Active state — green accent for connected/done feeling */
|
||||
.orient-active .orient-landscape-frame,
|
||||
.orient-active .orient-portrait-frame {
|
||||
border-color: #10a040;
|
||||
}
|
||||
|
||||
.orient-active .orient-landscape-ribbon,
|
||||
.orient-active .orient-portrait-ribbon {
|
||||
background: #10a040;
|
||||
}
|
||||
|
||||
.orient-active .orient-label {
|
||||
color: #10a040;
|
||||
}
|
||||
|
||||
.active-badge {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: #10a040;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
font-weight: 900;
|
||||
color: #f5f5f0;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.orient-divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: #1a1a1a;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
/* ── RIGHT PANEL — QR code ────────────────────────── */
|
||||
.panel-right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px 20px;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.qr-instruction {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-wrapper {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
background: #f5f5f0;
|
||||
border: 3px solid #1a1a1a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Green corner accent — signals connected state */
|
||||
.qr-wrapper::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
left: -3px;
|
||||
right: -3px;
|
||||
bottom: -3px;
|
||||
border: 3px solid #10a040;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.qr-sub {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 12px;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
line-height: 1.45;
|
||||
opacity: 0.6;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
/* MAC address chip */
|
||||
.mac-chip {
|
||||
display: inline-block;
|
||||
background: #1a1a1a;
|
||||
color: #f5f5f0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.08em;
|
||||
padding: 3px 9px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="device-bezel">
|
||||
<div class="display">
|
||||
|
||||
<!-- STATUS BAR -->
|
||||
<div class="status-bar">
|
||||
<div class="status-bar-left">
|
||||
<!-- WiFi icon: 3 arcs + dot -->
|
||||
<div class="wifi-icon">
|
||||
<div class="wifi-bar wifi-bar-1"></div>
|
||||
<div class="wifi-bar wifi-bar-2"></div>
|
||||
<div class="wifi-bar wifi-bar-3"></div>
|
||||
<div class="wifi-bar wifi-bar-4"></div>
|
||||
</div>
|
||||
<span class="status-bar-label">WiFi Connected — Step 2 of 2</span>
|
||||
</div>
|
||||
<span class="status-bar-right">
|
||||
IP: <span class="ip-chip">192.168.1.47</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- BODY -->
|
||||
<div class="body">
|
||||
|
||||
<!-- LEFT: instructions + progress -->
|
||||
<div class="panel-left">
|
||||
<div>
|
||||
<div class="main-heading">Almost<br><em>ready.</em></div>
|
||||
<div class="sub-heading">
|
||||
Scan the QR code to give this frame a name and link it to your account.
|
||||
</div>
|
||||
|
||||
<ul class="step-list">
|
||||
<li class="step-item">
|
||||
<div class="step-num">1</div>
|
||||
<div class="step-text">
|
||||
Scan the QR code with your phone's camera
|
||||
</div>
|
||||
</li>
|
||||
<li class="step-item">
|
||||
<div class="step-num">2</div>
|
||||
<div class="step-text">
|
||||
Sign in or create an account at <strong>pictureframe.edholm.me</strong>
|
||||
</div>
|
||||
</li>
|
||||
<li class="step-item">
|
||||
<div class="step-num">3</div>
|
||||
<div class="step-text">
|
||||
Name the frame. Choose orientation. Done.
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="url-bar">
|
||||
<span class="url-bar-label">URL</span>
|
||||
<span class="url-bar-value">pictureframe.edholm.me/setup/1C:C3:AB:D1:91:F8</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<!-- Progress tracker: WiFi done / Account next / Frame ready todo -->
|
||||
<div class="progress-track">
|
||||
<div class="progress-label">Setup progress</div>
|
||||
<div class="progress-steps">
|
||||
<div class="prog-step done"></div>
|
||||
<div class="prog-step active"></div>
|
||||
<div class="prog-step todo"></div>
|
||||
</div>
|
||||
<div class="prog-step-labels">
|
||||
<div class="prog-step-label done">WiFi</div>
|
||||
<div class="prog-step-label active">Account</div>
|
||||
<div class="prog-step-label todo">Frame ready</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CENTER: orientation diagrams -->
|
||||
<div class="panel-center">
|
||||
<div class="orient-section-title">Frame orientation</div>
|
||||
|
||||
<!-- Landscape (active) -->
|
||||
<div class="orient-block orient-active">
|
||||
<div class="orient-label">Landscape</div>
|
||||
<div class="orient-landscape-frame"></div>
|
||||
<div class="orient-landscape-ribbon"></div>
|
||||
<div class="active-badge">✓</div>
|
||||
</div>
|
||||
|
||||
<div class="orient-divider"></div>
|
||||
|
||||
<!-- Portrait -->
|
||||
<div class="orient-block">
|
||||
<div class="orient-label">Portrait</div>
|
||||
<div class="orient-portrait-wrapper">
|
||||
<div class="orient-portrait-ribbon"></div>
|
||||
<div class="orient-portrait-frame"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RIGHT: QR code -->
|
||||
<div class="panel-right">
|
||||
<div class="qr-instruction">Scan to finish</div>
|
||||
|
||||
<div class="qr-wrapper">
|
||||
<!-- QR code — encodes https://pictureframe.edholm.me/setup/1C:C3:AB:D1:91:F8 -->
|
||||
<svg width="182" height="182" viewBox="0 0 41 41" xmlns="http://www.w3.org/2000/svg"
|
||||
shape-rendering="crispEdges">
|
||||
<rect width="41" height="41" fill="#f5f5f0"/>
|
||||
|
||||
<!-- TOP-LEFT FINDER -->
|
||||
<rect x="1" y="1" width="7" height="7" fill="#1a1a1a"/>
|
||||
<rect x="2" y="2" width="5" height="5" fill="#f5f5f0"/>
|
||||
<rect x="3" y="3" width="3" height="3" fill="#1a1a1a"/>
|
||||
|
||||
<!-- TOP-RIGHT FINDER -->
|
||||
<rect x="33" y="1" width="7" height="7" fill="#1a1a1a"/>
|
||||
<rect x="34" y="2" width="5" height="5" fill="#f5f5f0"/>
|
||||
<rect x="35" y="3" width="3" height="3" fill="#1a1a1a"/>
|
||||
|
||||
<!-- BOTTOM-LEFT FINDER -->
|
||||
<rect x="1" y="33" width="7" height="7" fill="#1a1a1a"/>
|
||||
<rect x="2" y="34" width="5" height="5" fill="#f5f5f0"/>
|
||||
<rect x="3" y="35" width="3" height="3" fill="#1a1a1a"/>
|
||||
|
||||
<!-- TIMING H -->
|
||||
<rect x="9" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="6" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- TIMING V -->
|
||||
<rect x="6" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="13" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="15" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="17" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="19" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="21" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="25" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="27" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="29" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="6" y="31" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- DATA — URL QR pattern (unique from AP screen) -->
|
||||
<!-- Row 9 -->
|
||||
<rect x="8" y="9" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="9" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="9" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="9" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="9" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="9" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 10 -->
|
||||
<rect x="9" y="10" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="10" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="10" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="10" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="10" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="10" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="10" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 11 -->
|
||||
<rect x="8" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="11" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="11" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="11" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="11" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="11" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 12 -->
|
||||
<rect x="9" y="12" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="12" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="12" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="12" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="12" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="12" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="12" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 13 -->
|
||||
<rect x="8" y="13" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="13" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="13" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="13" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="13" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="13" width="4" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 14 -->
|
||||
<rect x="9" y="14" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="14" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="14" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="14" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="14" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="14" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="14" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 15 -->
|
||||
<rect x="8" y="15" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="15" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="15" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="15" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="15" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="15" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="15" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 16 -->
|
||||
<rect x="9" y="16" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="16" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="16" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="16" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="16" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="16" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="16" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 17 -->
|
||||
<rect x="8" y="17" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="17" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="17" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="17" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="17" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="17" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 18 -->
|
||||
<rect x="9" y="18" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="18" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="18" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="18" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="18" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="18" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="18" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 19 -->
|
||||
<rect x="8" y="19" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="19" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="19" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="19" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="19" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="19" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 20 -->
|
||||
<rect x="9" y="20" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="20" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="20" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="20" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="20" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="20" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="20" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="20" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 21 -->
|
||||
<rect x="8" y="21" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="21" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="21" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="21" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="21" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="21" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="21" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 22 -->
|
||||
<rect x="9" y="22" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="22" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="22" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="22" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="22" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="22" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="22" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 23 -->
|
||||
<rect x="8" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="23" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="23" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="23" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="23" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="23" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 24 -->
|
||||
<rect x="9" y="24" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="24" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="24" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="24" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="24" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="24" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 25 -->
|
||||
<rect x="8" y="25" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="25" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="25" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="25" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="25" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="25" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="25" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 26 -->
|
||||
<rect x="9" y="26" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="26" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="26" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="26" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="26" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="26" width="4" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 27 -->
|
||||
<rect x="8" y="27" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="27" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="27" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="27" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="27" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="27" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="32" y="27" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 28 -->
|
||||
<rect x="9" y="28" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="28" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="28" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="28" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 29 -->
|
||||
<rect x="8" y="29" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="10" y="29" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="29" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="29" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="29" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="29" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="29" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 30 -->
|
||||
<rect x="9" y="30" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="30" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="30" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="30" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Row 31 -->
|
||||
<rect x="8" y="31" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="31" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="31" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="31" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="31" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="31" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="33" y="31" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Alignment pattern (bottom-right) -->
|
||||
<rect x="28" y="28" width="5" height="5" fill="#1a1a1a"/>
|
||||
<rect x="29" y="29" width="3" height="3" fill="#f5f5f0"/>
|
||||
<rect x="30" y="30" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="8" y="8" width="1" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<!-- Data rows below bottom-left finder (rows 34–39) -->
|
||||
<rect x="9" y="34" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="34" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="16" y="34" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="34" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="24" y="34" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="28" y="34" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="8" y="35" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="14" y="35" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="17" y="35" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="35" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="26" y="35" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="35" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="9" y="36" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="13" y="36" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="36" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="21" y="36" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="25" y="36" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="36" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="8" y="37" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="11" y="37" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="37" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="20" y="37" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="23" y="37" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="37" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="30" y="37" width="3" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="9" y="38" width="4" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="38" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="18" y="38" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="38" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="38" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="31" y="38" width="2" height="1" fill="#1a1a1a"/>
|
||||
|
||||
<rect x="8" y="39" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="12" y="39" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="15" y="39" width="2" height="1" fill="#1a1a1a"/>
|
||||
<rect x="19" y="39" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="22" y="39" width="3" height="1" fill="#1a1a1a"/>
|
||||
<rect x="27" y="39" width="1" height="1" fill="#1a1a1a"/>
|
||||
<rect x="29" y="39" width="4" height="1" fill="#1a1a1a"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="qr-sub">
|
||||
<span class="mac-chip">1C:C3:AB:D1:91:F8</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- /.body -->
|
||||
|
||||
</div><!-- /.display -->
|
||||
</div><!-- /.device-bezel -->
|
||||
|
||||
<!--
|
||||
DESIGNER NOTES
|
||||
──────────────────────────────────────────────────────────────────
|
||||
Screen: Setup QR — Step 2 of 2
|
||||
State: Frame joined home WiFi. Waiting for account link via scan.
|
||||
Accent: GREEN — signals progress, success, completion imminent.
|
||||
|
||||
Layout rationale:
|
||||
• Green bar immediately contrasts with AP screen's yellow — user
|
||||
registers "something changed, I'm further along." The WiFi
|
||||
icon in the bar confirms the network is live.
|
||||
• "Almost ready." is deliberately casual and warm — not "Device
|
||||
Provisioning Step 2/2." The sub-heading does the explaining.
|
||||
• URL bar at the bottom of instructions answers the fallback question
|
||||
(what if the QR doesn't scan?) without cluttering the main steps.
|
||||
• Progress track — three segments: WiFi done (green), Account
|
||||
(solid black = active), Frame ready (faint = todo) — gives the user
|
||||
a map without requiring them to read it.
|
||||
• Center panel reuses the orientation diagram pattern from screen 1,
|
||||
maintaining visual language across the two screens. The active
|
||||
orientation is green this time, consistent with the accent shift.
|
||||
• QR panel: green bracket border, MAC chip below the code. The MAC
|
||||
is shown because the URL contains it — the user may need to verify
|
||||
their device if they have multiple frames. Also tells the builder
|
||||
(Matt) what he's looking at during development.
|
||||
|
||||
Physical observation: if the frame is landscape (current mockup),
|
||||
the ribbon connector sits at the bottom of the frame, behind the
|
||||
stand or mount. The orientation diagram ribbon is bottom for
|
||||
landscape, left for portrait — this matches physical reality.
|
||||
|
||||
Firmware implementation notes:
|
||||
• This screen appears after STA mode connection confirmed.
|
||||
• The QR encodes the /setup/{mac} URL exactly.
|
||||
• The IP shown is the DHCP-assigned address — confirm in real code
|
||||
that the display format matches (colons in MAC, not dashes).
|
||||
• Frame should stay on this screen until the web app confirms
|
||||
account linkage — then reboot into image-cycling mode.
|
||||
──────────────────────────────────────────────────────────────────
|
||||
-->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
Reference in New Issue
Block a user