Files
local-ocr/static/style.css
2025-12-31 01:41:05 +08:00

936 lines
18 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* OCR KTP/KK - Modern Dark Theme */
:root {
--bg-primary: #0f0f1a;
--bg-secondary: #1a1a2e;
--bg-tertiary: #252540;
--accent-primary: #6366f1;
--accent-secondary: #818cf8;
--accent-gradient: linear-gradient(135deg, #6366f1 0%, #a855f7 100%);
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
--text-muted: #64748b;
--success: #22c55e;
--error: #ef4444;
--warning: #f59e0b;
--border: #334155;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.4);
--radius: 12px;
--radius-lg: 16px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
min-height: 100vh;
line-height: 1.6;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 2rem 1rem;
}
/* Header */
header {
text-align: center;
margin-bottom: 2rem;
}
header h1 {
font-size: 2.5rem;
font-weight: 700;
background: var(--accent-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 0.5rem;
}
.subtitle {
color: var(--text-secondary);
font-size: 1.1rem;
}
/* Upload Section */
.upload-section {
background: var(--bg-secondary);
border-radius: var(--radius-lg);
padding: 2rem;
box-shadow: var(--shadow-lg);
margin-bottom: 2rem;
}
/* Document Type Selector */
.doc-type-selector {
display: flex;
gap: 1rem;
margin-bottom: 1.5rem;
}
.doc-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 1rem;
background: var(--bg-tertiary);
border: 2px solid transparent;
border-radius: var(--radius);
color: var(--text-secondary);
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.doc-btn:hover {
background: var(--bg-primary);
color: var(--text-primary);
}
.doc-btn.active {
background: var(--accent-gradient);
color: white;
border-color: var(--accent-secondary);
}
.doc-btn .icon {
font-size: 1.5rem;
}
/* Dropzone */
.dropzone {
border: 2px dashed var(--border);
border-radius: var(--radius);
padding: 3rem 2rem;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
background: var(--bg-tertiary);
position: relative;
overflow: hidden;
}
.dropzone:hover,
.dropzone.dragover {
border-color: var(--accent-primary);
background: rgba(99, 102, 241, 0.1);
}
.dropzone-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.upload-icon {
font-size: 4rem;
margin-bottom: 0.5rem;
}
.dropzone p {
color: var(--text-secondary);
}
.dropzone .hint {
color: var(--text-muted);
font-size: 0.875rem;
}
.file-btn {
display: inline-block;
padding: 0.75rem 1.5rem;
background: var(--accent-gradient);
color: white;
border-radius: var(--radius);
font-weight: 600;
cursor: pointer;
margin: 0.5rem 0;
transition: transform 0.2s ease;
}
.file-btn:hover {
transform: scale(1.05);
}
.file-types {
font-size: 0.75rem;
color: var(--text-muted);
}
.preview-image {
max-width: 100%;
max-height: 400px;
border-radius: var(--radius);
cursor: pointer;
display: block;
margin: 0 auto;
}
/* Crop Container */
.crop-container {
position: relative;
max-width: 100%;
margin-bottom: 1rem;
overflow: hidden;
border-radius: var(--radius);
background: #000;
}
.crop-area {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
/* Let clicks pass through, handles catch them */
}
/* Perspective Crop Handles */
.crop-handle {
position: absolute;
width: 20px;
height: 20px;
background: var(--accent-primary);
border: 2px solid #fff;
border-radius: 50%;
transform: translate(-50%, -50%);
cursor: move;
pointer-events: auto;
z-index: 10;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
transition: transform 0.1s ease;
}
.crop-handle:hover,
.crop-handle.active {
background: #fff;
border-color: var(--accent-primary);
transform: translate(-50%, -50%) scale(1.2);
}
/* Crop Actions & Controls */
.crop-actions-container {
display: flex;
flex-direction: column;
gap: 1rem;
margin-top: 1rem;
padding: 1rem;
background: var(--bg-secondary);
border-radius: var(--radius);
border: 1px solid var(--border);
}
.rotation-control {
display: flex;
align-items: center;
gap: 1rem;
color: var(--text-secondary);
}
.rotation-control label {
font-weight: 500;
min-width: 80px;
}
.rotation-control input[type="range"] {
flex: 1;
cursor: pointer;
accent-color: var(--accent-primary);
}
.crop-buttons {
display: flex;
gap: 1rem;
justify-content: center;
}
.crop-action-btn {
padding: 0.5rem 1rem;
border: none;
border-radius: var(--radius);
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
flex: 1;
}
.crop-action-btn.primary {
background: var(--accent-gradient);
color: white;
}
.crop-action-btn.primary:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: var(--shadow);
}
.crop-action-btn.primary:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.crop-action-btn.secondary {
background: var(--bg-tertiary);
color: var(--text-secondary);
border: 1px solid var(--border);
}
.crop-action-btn.secondary:hover {
background: var(--bg-primary);
color: var(--text-primary);
}
/* Process Button */
.process-btn {
width: 100%;
padding: 1rem;
margin-top: 1.5rem;
background: var(--accent-gradient);
border: none;
border-radius: var(--radius);
color: white;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: var(--shadow);
}
.process-btn:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.process-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Results Section */
.results-section {
background: var(--bg-secondary);
border-radius: var(--radius-lg);
padding: 2rem;
box-shadow: var(--shadow-lg);
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
flex-wrap: wrap;
gap: 1rem;
}
.results-header h2 {
font-size: 1.5rem;
}
.results-actions {
display: flex;
gap: 0.5rem;
}
.action-btn {
padding: 0.5rem 1rem;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: var(--radius);
color: var(--text-primary);
font-size: 0.875rem;
cursor: pointer;
transition: all 0.2s ease;
}
.action-btn:hover {
background: var(--accent-primary);
border-color: var(--accent-primary);
}
.action-btn.secondary {
background: transparent;
}
/* Results Table */
.results-table {
width: 100%;
border-collapse: collapse;
}
.results-table th,
.results-table td {
padding: 0.875rem 1rem;
text-align: left;
border-bottom: 1px solid var(--border);
}
.results-table th {
background: var(--bg-tertiary);
color: var(--text-secondary);
font-weight: 600;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.results-table th:first-child {
border-radius: var(--radius) 0 0 0;
}
.results-table th:last-child {
border-radius: 0 var(--radius) 0 0;
}
.field-label {
color: var(--text-secondary);
font-weight: 500;
width: 40%;
}
.field-value {
color: var(--text-primary);
font-weight: 600;
}
.results-table tr:hover {
background: rgba(99, 102, 241, 0.05);
}
/* Editable Fields */
.editable-field {
width: 100%;
padding: 0.5rem 0.75rem;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-primary);
font-size: 0.95rem;
font-weight: 600;
font-family: inherit;
transition: all 0.2s ease;
}
.editable-field:focus {
outline: none;
border-color: var(--accent-primary);
background: var(--bg-secondary);
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);
}
.editable-field::placeholder {
color: var(--text-muted);
font-weight: 400;
}
/* Region Dropdown Styles */
.region-field-wrapper {
display: flex;
gap: 0.5rem;
align-items: center;
}
.region-field-wrapper input,
.region-field-wrapper select {
flex: 1;
}
.region-dropdown {
width: 100%;
padding: 0.5rem 0.75rem;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-primary);
font-size: 0.95rem;
font-family: inherit;
cursor: pointer;
}
.region-dropdown:focus {
outline: none;
border-color: var(--accent-primary);
}
.dropdown-toggle {
padding: 0.5rem 0.75rem;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.2s ease;
flex-shrink: 0;
}
.dropdown-toggle:hover {
background: var(--accent-primary);
color: white;
}
.dropdown-toggle.confirmed {
background: var(--success);
color: white;
border-color: var(--success);
}
/* Validation Indicators */
.validation-status {
margin-left: 0.5rem;
font-size: 0.875rem;
}
.validation-status.valid-field {
color: var(--success);
}
.validation-status.invalid-field {
color: var(--warning);
}
.editable-field.valid-field {
border-color: var(--success);
}
.editable-field.invalid-field {
border-color: var(--warning);
}
.suggestion-text {
font-size: 0.75rem;
color: var(--text-muted);
margin-top: 0.25rem;
font-style: italic;
}
/* Raw Text Section */
.raw-text-section {
margin-top: 1.5rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border);
}
.raw-text-section h3 {
font-size: 1rem;
color: var(--text-secondary);
margin-bottom: 1rem;
}
.raw-text-section pre {
background: var(--bg-primary);
padding: 1rem;
border-radius: var(--radius);
font-family: 'Consolas', monospace;
font-size: 0.875rem;
color: var(--text-secondary);
white-space: pre-wrap;
word-wrap: break-word;
max-height: 300px;
overflow-y: auto;
}
/* Error Section */
.error-section {
margin-top: 1rem;
}
.error-content {
background: rgba(239, 68, 68, 0.1);
border: 1px solid var(--error);
border-radius: var(--radius);
padding: 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
}
.error-icon {
font-size: 1.5rem;
}
.error-content p {
color: var(--error);
}
/* Footer */
footer {
text-align: center;
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
}
footer p {
color: var(--text-muted);
font-size: 0.875rem;
}
footer a {
color: var(--accent-secondary);
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
/* Responsive */
@media (max-width: 600px) {
.container {
padding: 1rem;
}
header h1 {
font-size: 2rem;
}
.upload-section,
.results-section {
padding: 1.5rem;
}
.doc-type-selector {
flex-direction: column;
}
.results-header {
flex-direction: column;
align-items: flex-start;
}
.results-actions {
width: 100%;
justify-content: flex-start;
}
.field-label {
width: 45%;
}
}
/* Scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: var(--bg-tertiary);
}
::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 4px;
}
/* Archive Header Button */
.header-actions {
display: flex;
gap: 1rem;
justify-content: center;
margin-top: 1rem;
}
.archive-header-btn {
padding: 0.5rem 1.25rem;
background: transparent;
border: 1px solid var(--accent-secondary);
color: var(--accent-secondary);
border-radius: var(--radius);
cursor: pointer;
font-weight: 600;
transition: all 0.2s ease;
}
.archive-header-btn:hover {
background: var(--accent-primary);
color: white;
border-color: var(--accent-primary);
}
/* Modal Styles */
.modal {
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(4px);
overflow: auto;
animation: fadeIn 0.3s;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.modal-content {
background-color: var(--bg-secondary);
margin: 5% auto;
padding: 2rem;
border: 1px solid var(--border);
border-radius: var(--radius-lg);
width: 90%;
max-width: 1000px;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
position: relative;
animation: slideDown 0.3s;
}
@keyframes slideDown {
from {
transform: translateY(-50px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--border);
}
.modal-header h2 {
color: var(--text-primary);
font-size: 1.5rem;
}
.close-btn {
background: transparent;
border: none;
color: var(--text-muted);
font-size: 2rem;
cursor: pointer;
line-height: 1;
transition: color 0.2s;
}
.close-btn:hover {
color: var(--text-primary);
}
/* Archive List Grid */
.archive-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 1.5rem;
max-height: 70vh;
overflow-y: auto;
padding-right: 0.5rem;
}
.archive-card {
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
transition: transform 0.2s, box-shadow 0.2s;
display: flex;
flex-direction: column;
}
.archive-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
border-color: var(--accent-primary);
}
.archive-card-img {
width: 100%;
height: 160px;
background: #000;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.archive-card-img img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.archive-card:hover .archive-card-img img {
transform: scale(1.05);
}
.archive-card-content {
padding: 1rem;
flex: 1;
display: flex;
flex-direction: column;
}
.archive-card-content h3 {
font-size: 1rem;
margin-bottom: 0.5rem;
color: var(--text-primary);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.archive-card-meta {
margin-bottom: 1rem;
font-size: 0.8rem;
color: var(--text-muted);
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.archive-card-actions {
margin-top: auto;
}
.view-btn {
width: 100%;
padding: 0.5rem;
background: var(--bg-primary);
border: 1px solid var(--border);
color: var(--text-secondary);
border-radius: 6px;
cursor: pointer;
font-size: 0.875rem;
transition: all 0.2s;
}
.view-btn:hover {
background: var(--accent-primary);
color: white;
border-color: var(--accent-primary);
}
.archive-loading,
.archive-empty {
text-align: center;
padding: 3rem;
color: var(--text-muted);
font-size: 1.1rem;
}
/* Print Styles */
@media print {
/* Reset Page */
@page {
margin: 0;
size: auto;
}
body {
margin: 0;
padding: 0;
background: white !important;
/* Ensure no scroll or extra pages from hidden content */
height: 100vh !important;
overflow: hidden !important;
}
/* Hide EVERYTHING initially with high specificity */
body * {
visibility: hidden !important;
display: none !important;
/* Force display none to remove layout space */
}
/* Show ONLY Print Area and its children */
#printArea,
#printArea * {
visibility: visible !important;
display: flex !important;
/* Restore display for parent */
}
/* Reset display for children of printArea specifically */
#printArea * {
display: block !important;
/* Default to block or whatever needed */
}
/* Specific fix for image inside */
#printArea img {
display: inline-block !important;
}
#printArea {
position: fixed !important;
/* Fixed helps detach from flow */
left: 0 !important;
top: 0 !important;
width: 100% !important;
height: 100% !important;
overflow: visible !important;
z-index: 99999 !important;
background: white !important;
display: flex !important;
justify-content: center !important;
align-items: center !important;
padding: 0 !important;
}
.ktp-print-size {
/* Standar ISO/IEC 7810 ID-1: 85.60 × 53.98 mm */
width: 85.60mm !important;
height: 53.98mm !important;
max-width: none !important;
max-height: none !important;
border: 1px dashed #ccc;
box-shadow: none !important;
/* Remove any shadow */
}
.a4-print-size {
/* A4 Landscape: 297mm x 210mm */
/* Use slightly less to account for margins if necessary, but standard is distinct */
width: 297mm !important;
height: 210mm !important;
max-width: none !important;
max-height: none !important;
border: none;
}
}