/* Modal animations and enhancements */ #scan-modal { backdrop-filter: blur(8px); transition: all 0.3s ease; } #scan-modal .bg-white { transform-origin: center center; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } /* Enhanced modal auto-hide animation */ .modal-auto-hide { animation: modalAutoHide 0.4s ease-in-out; } @keyframes modalAutoHide { 0% { opacity: 1; transform: scale(1); } 80% { opacity: 1; transform: scale(1.02); } 100% { opacity: 0; transform: scale(0.95); } } /* Success modal specific animations */ .success-gradient-bg { background: linear-gradient(135deg, #10b981, #059669, #047857); animation: gradientShift 2s ease-in-out; } @keyframes gradientShift { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } } /* Error modal specific animations */ .error-gradient-bg { background: linear-gradient(135deg, #ef4444, #dc2626, #b91c1c); animation: gradientShift 2s ease-in-out; } /* Enhanced pulse animation for icons */ .icon-pulse { animation: iconPulse 1.5s ease-in-out infinite; } @keyframes iconPulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.1); opacity: 0.8; } } /* Card shadow effects */ .card-shadow-success { box-shadow: 0 10px 25px rgba(16, 185, 129, 0.2); } .card-shadow-error { box-shadow: 0 10px 25px rgba(239, 68, 68, 0.2); } /* Responsive modal improvements */ @media (max-width: 640px) { #scan-modal .bg-white { margin: 16px; max-width: calc(100vw - 32px); } #scan-modal .bg-white .space-y-4 > div { margin-bottom: 12px; } } .scanner-container { position: relative; background: #1a1a1a; border-radius: 8px; overflow: hidden; } .scanner-overlay { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 250px; height: 120px; border: 2px dashed rgba(255, 255, 255, 0.7); border-radius: 8px; display: flex; align-items: center; justify-content: center; pointer-events: none; z-index: 10; } .scanner-overlay::before { content: ""; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient( 90deg, transparent, rgba(255, 255, 255, 0.2), transparent ); animation: scan-line 2s linear infinite; } @keyframes scan-line { 0% { left: -100%; } 100% { left: 100%; } } #video-preview { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); } .drawingBuffer { position: absolute !important; top: 0 !important; left: 0 !important; z-index: 5 !important; } .btn-scanner { transition: all 0.3s ease; } .btn-scanner:active { transform: scale(0.98); } .loading-spinner { border: 2px solid rgba(255, 255, 255, 0.3); border-top: 2px solid white; border-radius: 50%; width: 32px; height: 32px; animation: spin 1s linear infinite; } .loading-spinner-small { border: 2px solid rgba(245, 158, 11, 0.3); border-top: 2px solid #f59e0b; border-radius: 50%; width: 16px; height: 16px; animation: spin 1s linear infinite; } .loading-spinner-modal { border: 3px solid rgba(59, 130, 246, 0.3); border-top: 3px solid #3b82f6; border-radius: 50%; width: 24px; height: 24px; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .scan-result-card { animation: slideInUp 0.3s ease-out; } @keyframes slideInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } /* OCR Processing Animation */ .ocr-processing { animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } } /* Receipt capture overlay */ .receipt-overlay { position: absolute; top: 10%; left: 10%; right: 10%; bottom: 10%; border: 2px dashed rgba(245, 158, 11, 0.8); border-radius: 8px; pointer-events: none; z-index: 10; } .receipt-overlay::before { content: "Arahkan ke teks struk"; position: absolute; top: -30px; left: 50%; transform: translateX(-50%); background: rgba(245, 158, 11, 0.9); color: white; padding: 4px 8px; border-radius: 4px; font-size: 12px; white-space: nowrap; } /* Form transition effects */ .form-section { transition: all 0.3s ease; } .form-section.disabled { opacity: 0.6; pointer-events: none; } @media (max-width: 640px) { .scanner-overlay { width: 200px; height: 100px; } .scanner-container { height: 250px !important; } .receipt-overlay::before { font-size: 11px; padding: 3px 6px; } } @media (prefers-color-scheme: dark) { .scanner-container { background: #0a0a0a; } } #scanner-container video { width: 100% !important; height: 100% !important; object-fit: cover !important; border-radius: 8px; } #scanner-container canvas { position: absolute !important; top: 0 !important; left: 0 !important; width: 100% !important; height: 100% !important; border-radius: 8px; } #scanner-container select, #scanner-container button { display: none !important; } /* Success feedback */ .success-flash { position: absolute; inset: 0; background: rgba(34, 197, 94, 0.3); border-radius: 8px; z-index: 15; animation: flash 0.3s ease-out; } @keyframes flash { 0% { opacity: 0; } 50% { opacity: 1; } 100% { opacity: 0; } } /* Input highlight when auto-filled */ .auto-filled { background-color: rgba(34, 197, 94, 0.1) !important; border-color: rgb(34, 197, 94) !important; animation: highlight 1s ease-out; } @keyframes highlight { 0% { box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.3); } 100% { box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); } } /* Upload functionality styling */ .upload-label { transition: all 0.3s ease; } .upload-label:hover { transform: translateY(-1px); box-shadow: 0 4px 8px rgba(59, 130, 246, 0.3); } .upload-label:active { transform: translateY(0); } /* Uploaded image display */ #scanner-container img { border: 2px dashed rgba(245, 158, 11, 0.3); background-color: #f9fafb; } /* Receipt format hints */ .receipt-format-hint { background: linear-gradient( 135deg, rgba(245, 158, 11, 0.1), rgba(245, 158, 11, 0.05) ); border-left: 4px solid #f59e0b; } /* Enhanced OCR feedback */ .ocr-success { animation: successPulse 0.6s ease-out; } @keyframes successPulse { 0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.4); } 50% { transform: scale(1.02); box-shadow: 0 0 0 10px rgba(34, 197, 94, 0); } 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(34, 197, 94, 0); } } /* Better mobile responsiveness for file upload */ @media (max-width: 640px) { .upload-label { padding: 12px 16px; font-size: 14px; } .upload-label i { width: 16px; height: 16px; } }