:root { color-scheme: dark; --bg: #14161a; --fg: #f2f4f7; --muted: #9aa3af; --green: #1f8a4c; --yellow: #b8860b; --red: #a02c2c; --line: #2a2e36; } * { box-sizing: border-box; } body { margin: 0; background: var(--bg); color: var(--fg); font-family: system-ui, -apple-system, sans-serif; overscroll-behavior: none; } #app { display: flex; flex-direction: column; height: 100dvh; } .mode-button { min-height: 56px; width: 100%; border: none; border-bottom: 1px solid var(--line); background: #1c2027; color: var(--fg); font-size: 15px; font-weight: 600; text-align: left; padding: 0 14px; } .camera { position: relative; flex: 1; overflow: hidden; background: #000; } .camera video { width: 100%; height: 100%; object-fit: cover; } .frame { /* Lage (inset) wird von scan-view.js aus FRAME_INSET (camera.js) gesetzt - einzige Quelle, die sich auch der native Ausschnitt teilt. */ position: absolute; border: 3px solid rgba(255, 255, 255, 0.7); border-radius: 8px; pointer-events: none; } /* Dauersuche hat einen Barcode im Ausschnitt gefunden - schlichte Farbaenderung, keine Animation. */ .frame.detected { border-color: var(--green); } /* Grosse Zaehlanzeige der Funktion "Zählen" (siehe count-objects.js) - liegt ueber dem Kamerabild, aber unterhalb des Zielrahmens optisch zentriert. Der Container selbst blockiert keine Beruehrungen (pointer-events: none); die grosse Zahl darunter (.count-number) ist die einzige antippbare Flaeche darin - sie deckt den ganzen Container ab, ist also weit ueber den geforderten 56 Bildpunkten Mindestgroesse. */ .count-display { position: absolute; inset: 0; pointer-events: none; } /* Die Zahl selbst: riesige Schriftgroesse mit Schlagschatten statt Kontrastfarbe, damit sie auf jedem Untergrund (hell wie dunkel) aus Armlaenge lesbar bleibt. Als eigene, absolut positionierte Flaeche (statt als Flex-Kind neben der Diagnosezeile) bleibt sie beim Ein-/Ausblenden der Diagnosezeile darunter exakt an derselben Stelle stehen - sie "verrutscht" beim Antippen nicht, auch wenn der Nutzer dabei nur eine Hand frei hat. */ .count-number { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; width: 100%; border: none; padding: 0; background: none; font-size: min(35vw, 220px); font-weight: 800; color: #fff; text-shadow: 0 0 12px rgba(0, 0, 0, 0.9), 0 0 3px rgba(0, 0, 0, 0.9); pointer-events: auto; } /* Diagnosezeile (siehe main.js fuer den Wortlaut) - anfangs verborgen, erscheint per Antippen der grossen Zahl. Am unteren Rand des Kamerabilds verankert statt im Fluss neben der Zahl, damit sie beim Ein-/Ausblenden nicht die Zahl selbst verschiebt (siehe .count-number oben). Klein und unaufdringlich, aber mit demselben Schlagschatten-Trick auf jedem Untergrund lesbar; white-space: pre-line setzt die einzelnen, mit "\n" getrennten Werte (main.js) als eigene, kurze Zeilen. */ .count-diagnostics { position: absolute; left: 0; right: 0; bottom: 6%; padding: 0 16px; text-align: center; font-size: 14px; line-height: 1.6; color: #fff; text-shadow: 0 0 8px rgba(0, 0, 0, 0.9), 0 0 3px rgba(0, 0, 0, 0.9); white-space: pre-line; pointer-events: none; } .stacks { display: flex; gap: 8px; padding: 10px 12px; overflow-x: auto; border-top: 1px solid var(--line); min-height: 76px; align-items: center; } .stacks button { flex: none; min-height: 56px; padding: 0 14px; border: 1px solid var(--line); border-radius: 8px; background: #1c2027; color: var(--fg); font-size: 17px; font-weight: 600; } .last { display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-top: 1px solid var(--line); min-height: 56px; font-size: 15px; color: var(--muted); } .last span { flex: 1; } .action { min-height: 56px; border: none; border-radius: 10px; background: #2b6cb0; color: #fff; font-size: 18px; font-weight: 600; padding: 0 18px; } .action.secondary { background: #2a2e36; } .capture { margin: 12px; } .overlay { position: fixed; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: safe center; gap: 18px; padding: 24px; text-align: center; z-index: 10; overflow-y: auto; overscroll-behavior: contain; } .overlay.green { background: var(--green); } .overlay.yellow { background: var(--yellow); } .overlay.red { background: var(--red); } .overlay .stack-id { font-size: 68px; font-weight: 800; letter-spacing: 2px; } .overlay .detail { font-size: 20px; line-height: 1.5; } .overlay .pn { font-size: 15px; opacity: 0.85; word-break: break-all; } /* Voller OCR-Rohtext in der wartenden Rueckmeldung (Funktion "Text erkennen", siehe result-overlay.js) - linksbuendig und mit Zeilenumbruch, damit ein langer Etikettentext lesbar bleibt statt einer einzelnen, abgeschnittenen Zeile. Waechst nicht aus dem Bildschirm heraus, weil `.overlay` selbst scrollbar ist (overflow-y: auto, siehe oben). */ .overlay .raw-text { font-size: 16px; line-height: 1.5; text-align: left; white-space: pre-wrap; overflow-wrap: break-word; max-width: 420px; width: 100%; } .choices { display: grid; gap: 12px; width: 100%; max-width: 420px; } .choices button { min-height: 64px; font-size: 20px; } /* Auswahl der Scan-Funktion vor dem Scannen (mode-dialog.js): drei grosse, gleich gestaltete Flaechen statt schmaler Schaltflaechen. */ .mode-tile { min-height: 96px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 12px; } .mode-tile-label { font-size: 24px; font-weight: 700; } .mode-tile-hint { font-size: 14px; opacity: 0.8; } .mode-tile-current { outline: 3px solid var(--fg); outline-offset: -3px; } .status { padding: 8px 12px; font-size: 14px; color: var(--muted); } .status.warn { color: #f0b429; }