.app { width: 420px; max-width: 100%; margin: 0 auto; padding: 32px 16px 64px; box-sizing: border-box; } /* ── Header ─────────────────────────────────────────────────────────────────── */ .app h1 { font-family: var(--mono); font-size: 32px; font-weight: 700; letter-spacing: -0.5px; text-align: center; margin: 0 0 32px; color: var(--heading); } .app h1::before { content: '> '; color: var(--muted); font-weight: 400; } .dot { color: var(--accent); } /* ── Error banner ────────────────────────────────────────────────────────────── */ .error-banner { font-family: var(--mono); font-size: 13px; color: #ff6b6b; border: 1px solid rgba(255,107,107,0.25); border-radius: 6px; padding: 10px 14px; margin-bottom: 16px; background: rgba(255,107,107,0.06); } /* ── Card ────────────────────────────────────────────────────────────────────── */ .card { border: 1px solid var(--border); border-radius: 10px; padding: 20px; background: var(--bg-alt); box-shadow: var(--shadow); } .stack { display: flex; flex-direction: column; gap: 12px; } /* ── Buttons ─────────────────────────────────────────────────────────────────── */ .btn { font-family: var(--mono); font-size: 13px; font-weight: 600; padding: 10px 16px; border-radius: 6px; border: 1px solid var(--border); background: transparent; color: var(--text); cursor: pointer; transition: all 0.15s; letter-spacing: 0.01em; } .btn:hover { border-color: var(--accent-border); color: var(--heading); } .btn:active { transform: scale(0.98); } .btn-primary { background: var(--accent); border-color: var(--accent); color: #000; font-weight: 700; } .btn-primary:hover { background: #00ff88; border-color: #00ff88; color: #000; } .btn-sm { padding: 6px 12px; font-size: 12px; } .btn-danger { color: #ff6b6b; border-color: rgba(255,107,107,0.2); } .btn-danger:hover { border-color: #ff6b6b; background: rgba(255,107,107,0.08); } .btn-link { background: none; border: none; padding: 0; font-family: var(--mono); font-size: inherit; color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; } .btn-row { display: flex; gap: 8px; } .btn-row .btn { flex: 1; } /* ── Inputs ──────────────────────────────────────────────────────────────────── */ .text-input { font-family: var(--mono); font-size: 13px; flex: 1; min-width: 0; padding: 10px 14px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg); color: var(--heading); } .text-input::placeholder { color: var(--muted); } .text-input:focus { outline: none; border-color: var(--accent-border); } .join-row { display: flex; gap: 8px; } /* ── Divider ─────────────────────────────────────────────────────────────────── */ .divider { display: flex; align-items: center; gap: 10px; font-family: var(--mono); font-size: 11px; color: var(--muted); letter-spacing: 0.05em; } .divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: var(--border); } /* ── Mode toggle ─────────────────────────────────────────────────────────────── */ .mode-toggle { display: flex; gap: 8px; margin-bottom: 4px; } .mode-toggle .btn { flex: 1; } /* ── Known devices list ──────────────────────────────────────────────────────── */ .empty-state { text-align: center; color: var(--muted); font-size: 14px; line-height: 1.7; } .known-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; } .known-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 16px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-alt); transition: border-color 0.15s; } .known-row:hover { border-color: var(--accent-border); } .known-info { display: flex; flex-direction: column; gap: 3px; min-width: 0; } .known-label { font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--heading); } .known-label::before { content: '@ '; color: var(--accent); font-weight: 400; } .peer-id { font-family: var(--mono); font-size: 11px; color: var(--muted); } .known-actions { display: flex; gap: 6px; flex-shrink: 0; } /* ── QR / hosting card ───────────────────────────────────────────────────────── */ .qr-card { text-align: center; } .qr-hint { font-family: var(--mono); font-size: 12px; color: var(--muted); margin-bottom: 12px; } .qr-hint::before { content: '// '; } .qr-card img { width: 200px; height: 200px; border-radius: 8px; border: 1px solid var(--border); margin-bottom: 16px; image-rendering: pixelated; } /* ── Connecting / status ─────────────────────────────────────────────────────── */ .connecting-card { text-align: center; padding: 40px 20px; } .status-row { display: flex; align-items: center; justify-content: center; gap: 10px; font-family: var(--mono); font-size: 13px; color: var(--muted); } .spinner { display: inline-block; width: 12px; height: 12px; border: 2px solid rgba(0,232,122,0.2); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; flex-shrink: 0; } @keyframes spin { to { transform: rotate(360deg); } } /* ── Connected / peer info ───────────────────────────────────────────────────── */ .peer-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; } .peer-badge { font-family: var(--mono); font-size: 12px; font-weight: 600; padding: 4px 10px; border-radius: 4px; border: 1px solid; letter-spacing: 0.03em; } .peer-badge.verified { color: var(--accent); border-color: var(--accent-border); background: var(--accent-dim); } .peer-badge.unverified { color: #f59e0b; border-color: rgba(245,158,11,0.25); background: rgba(245,158,11,0.08); } /* ── Drop zone ───────────────────────────────────────────────────────────────── */ .dropzone { position: relative; border: 1px dashed var(--border); border-radius: 8px; padding: 24px 16px; text-align: center; font-family: var(--mono); font-size: 12px; color: var(--muted); cursor: pointer; transition: border-color 0.15s, background 0.15s; } .dropzone::before { content: '+ '; color: var(--accent); } .dropzone input[type='file'] { position: absolute; inset: 0; opacity: 0; cursor: pointer; width: 100%; height: 100%; } .dropzone:hover { border-color: var(--accent-border); background: var(--accent-dim); color: var(--heading); } /* ── Transfer progress ───────────────────────────────────────────────────────── */ .transfer { } .transfer-row { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 12px; color: var(--muted); margin-bottom: 6px; } .pct { color: var(--accent); } progress.bar { -webkit-appearance: none; appearance: none; width: 100%; height: 4px; border: none; border-radius: 999px; background: var(--border); overflow: hidden; } progress.bar::-webkit-progress-bar { background: var(--border); border-radius: 999px; } progress.bar::-webkit-progress-value { background: var(--accent); border-radius: 999px; transition: width 0.1s ease; box-shadow: 0 0 8px rgba(0,232,122,0.5); } progress.bar::-moz-progress-bar { background: var(--accent); border-radius: 999px; } /* ── File lists ──────────────────────────────────────────────────────────────── */ .file-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; } .file-row { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 6px; font-family: var(--mono); font-size: 12px; color: var(--text); background: var(--bg); } .file-row a { color: var(--accent); text-decoration: none; } .file-row a:hover { text-decoration: underline; } .file-size { color: var(--muted); margin-left: auto; font-size: 11px; } /* ── Incoming offer card ─────────────────────────────────────────────────────── */ .offer-card { border-color: var(--accent-border); background: linear-gradient(135deg, rgba(0,232,122,0.04) 0%, var(--bg-alt) 100%); } .offer-card .btn-row { margin-top: 4px; } .offer-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; } .offer-name { font-family: var(--mono); font-size: 13px; color: var(--heading); } /* ── QR scanner overlay ──────────────────────────────────────────────────────── */ .scanner-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.88); display: flex; align-items: center; justify-content: center; z-index: 100; padding: 16px; backdrop-filter: blur(4px); } .scanner-card { background: var(--bg-alt); border: 1px solid var(--border); border-radius: 12px; padding: 20px; width: 100%; max-width: 360px; box-shadow: var(--shadow); } .scanner-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; font-family: var(--mono); font-size: 13px; color: var(--heading); } .scanner-video { width: 100%; border-radius: 8px; border: 1px solid var(--border); aspect-ratio: 1; object-fit: cover; background: #000; } .scanner-error { font-family: var(--mono); font-size: 13px; color: var(--muted); text-align: center; padding: 24px 0; }