Mobile polish, release validation script, bump to v4.1.2
Mobile-responsive CSS improvements:
- Larger touch targets for drop zones and buttons (56px min)
- Touch feedback with active states for touch devices
- Camera hint text on mobile ("Tap to take photo or choose file")
- Mode buttons stack vertically on small screens
- Full-width download buttons on mobile
- Navbar doesn't stick on mobile to save screen space
Release validation script (scripts/validate-release.sh):
- Automated pre-release checks: ruff, imports, encode/decode sanity
- Optional Docker build/test (--docker flag)
- Optional Pi smoke test via SSH (--pi flag)
- Pass/fail summary with exit codes
Other:
- Version bump to 4.1.2 (pyproject.toml, constants.py, __init__.py)
- Fixed ruff import sorting in cli.py
- Updated PLAN-4.1.2.md (all 9 features complete)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1442,3 +1442,260 @@ footer {
|
||||
padding: 0.35rem 0.75rem;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
MOBILE RESPONSIVE IMPROVEMENTS
|
||||
============================================================================ */
|
||||
|
||||
/* Mobile-specific drop zone improvements */
|
||||
@media (max-width: 768px) {
|
||||
/* Larger drop zones on mobile for easier touch targets */
|
||||
.drop-zone {
|
||||
padding: 2rem 1.5rem;
|
||||
min-height: 140px;
|
||||
}
|
||||
|
||||
/* Larger touch target for upload icons */
|
||||
.drop-zone-label i {
|
||||
font-size: 2.5rem !important;
|
||||
}
|
||||
|
||||
/* Touch feedback - active state */
|
||||
.drop-zone:active {
|
||||
border-color: var(--gradient-start);
|
||||
background: rgba(102, 126, 234, 0.15);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Mode buttons - stack vertically on very small screens */
|
||||
.d-flex.gap-2:has(.mode-btn) {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mode-btn {
|
||||
padding: 1rem;
|
||||
min-height: 56px; /* iOS touch target minimum */
|
||||
}
|
||||
|
||||
/* Full-width primary buttons */
|
||||
.btn-primary.btn-lg {
|
||||
padding: 1rem 1.5rem;
|
||||
font-size: 1.1rem;
|
||||
min-height: 56px;
|
||||
}
|
||||
|
||||
/* Security factor boxes - more padding for touch */
|
||||
.security-box {
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
/* Form controls - larger for touch */
|
||||
.form-control,
|
||||
.form-select {
|
||||
padding: 0.75rem 1rem;
|
||||
font-size: 1rem;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
/* Input groups - consistent sizing */
|
||||
.input-group .form-control {
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
.input-group .btn {
|
||||
min-width: 48px;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
/* Password toggle button - easier to tap */
|
||||
[data-toggle-password] {
|
||||
min-width: 52px;
|
||||
}
|
||||
|
||||
/* PIN input - larger on mobile */
|
||||
.pin-input-container .form-control {
|
||||
font-size: 1.4rem;
|
||||
letter-spacing: 4px;
|
||||
padding: 0.875rem 1rem;
|
||||
}
|
||||
|
||||
/* Passphrase input - comfortable mobile size */
|
||||
.passphrase-input {
|
||||
font-size: 1rem !important;
|
||||
padding: 0.875rem 1rem !important;
|
||||
}
|
||||
|
||||
/* Card headers - compact on mobile */
|
||||
.card-header h5 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* Alert info panel - readable text */
|
||||
.alert.small {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
/* Bottom info icons - larger tap targets */
|
||||
.row.text-center .col-4 {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.row.text-center .col-4 i {
|
||||
font-size: 2rem !important;
|
||||
}
|
||||
|
||||
/* Capacity panel badges - easier to read */
|
||||
#capacityPanel .badge {
|
||||
font-size: 0.8rem;
|
||||
padding: 0.4rem 0.6rem;
|
||||
}
|
||||
|
||||
/* Payload type toggle - full width buttons */
|
||||
.btn-group[role="group"] {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.btn-group .btn {
|
||||
padding: 0.75rem 0.5rem;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
/* Textarea - comfortable height */
|
||||
textarea.form-control {
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
/* Channel select - full width */
|
||||
#channelSelect {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Very small screens (iPhone SE, etc.) */
|
||||
@media (max-width: 375px) {
|
||||
.drop-zone {
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.mode-btn {
|
||||
padding: 0.875rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.mode-btn .text-muted {
|
||||
display: none; /* Hide secondary text on tiny screens */
|
||||
}
|
||||
|
||||
.card-header h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* Stack security factor row */
|
||||
.row:has(.security-box) > .col-md-6 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Touch device optimizations */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
/* Remove hover effects that don't work on touch */
|
||||
.btn-primary:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.card-link:hover .feature-card {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* Add active states instead */
|
||||
.btn-primary:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 2px 10px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.feature-card:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Drop zone active feedback */
|
||||
.drop-zone:active {
|
||||
border-color: var(--gradient-start);
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
/* Mode button active state */
|
||||
.mode-btn:active {
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
border-color: var(--gradient-start);
|
||||
}
|
||||
}
|
||||
|
||||
/* Camera hint for mobile - shows on file inputs */
|
||||
@media (max-width: 768px) {
|
||||
.drop-zone-label span.text-muted {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Add camera icon hint on mobile */
|
||||
.drop-zone-label::after {
|
||||
content: "Tap to take photo or choose file";
|
||||
display: block;
|
||||
font-size: 0.75rem;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
/* Hide the default text and show mobile version */
|
||||
.drop-zone-label > span.text-muted {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Navbar mobile adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.navbar {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.navbar-brand img {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
/* Sticky header shouldn't eat too much space */
|
||||
.navbar.sticky-top {
|
||||
position: relative; /* Don't stick on mobile - saves screen space */
|
||||
}
|
||||
}
|
||||
|
||||
/* Results page mobile adjustments */
|
||||
@media (max-width: 768px) {
|
||||
/* Download button - full width on mobile */
|
||||
.btn-success.btn-lg,
|
||||
a.btn-success.btn-lg {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* QR codes - appropriate sizing */
|
||||
.qr-scan-container {
|
||||
max-width: 280px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Message display - readable on mobile */
|
||||
.alert-message {
|
||||
font-size: 0.9rem;
|
||||
padding: 1rem;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* Result icon - slightly smaller on mobile */
|
||||
.result-icon {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user