Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 62 additions & 40 deletions src/ui/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -519,50 +519,65 @@ fieldset:disabled :is(.color-options, .scanner-colours) label:not(:has(input:che
.mobile-pairing li + li { margin-top: 8px; }
.mobile-pairing .teaching-disclosure { margin-bottom: 0; }

/* --- Dialogs ------------------------------------------------------------------ */
.modal-backdrop { position: fixed; z-index: 20; inset: 0; display: grid; place-items: center; padding: 12px; background: rgba(28, 27, 31, 0.48); }
.pairing-dialog, .profile-dialog, .switch-practice-dialog { width: min(100%, 900px); max-height: calc(100dvh - 24px); overflow: auto; border: 1px solid var(--border); border-radius: 8px; padding: 20px; color: var(--text); background: var(--surface); box-shadow: var(--shadow-dialog); }
.switch-practice-dialog { border-radius: 12px; }
.confirm-dialog { width: min(100%, 480px); }
.dialog-error { margin-top: 16px; border-left: 3px solid var(--status-error); padding: 9px 11px; color: var(--status-error); background: var(--status-error-soft); }

.setup-dialog { display: flex; flex-direction: column; width: min(100%, 920px); height: min(900px, calc(100dvh - 24px)); min-height: 0; max-height: calc(100dvh - 24px); overflow: hidden; border: 1px solid var(--border); border-radius: 10px; padding: 20px; color: var(--text); background: var(--surface); box-shadow: var(--shadow-dialog); }
.setup-dialog:focus { outline: 2px solid var(--focus); outline-offset: 2px; }
.setup-dialog > header, .setup-dialog > footer { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.setup-dialog > header { justify-content: space-between; }
.setup-dialog > header span { color: var(--brand); font-size: 16px; font-weight: 700; text-transform: uppercase; }
.setup-dialog > header h2 { margin-top: 4px; font-size: 24px; line-height: 1.33; }
.setup-dialog > header strong { color: var(--muted); font-size: 16px; }
.setup-progress { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; margin-top: 18px; }
.setup-progress span { height: 4px; border-radius: 2px; background: var(--border); }
/* --- Dialogs ------------------------------------------------------------------
Every main-window dialog shares one shell: the same surface, radius,
padding and shadow; a header with the title and any close control; a body;
and a footer whose spacer pushes the main actions to the end. Opening is
the one moment of motion, and it is skipped under reduced motion. */
.modal-backdrop { position: fixed; z-index: 20; inset: 0; display: grid; place-items: center; padding: 12px; background: rgba(28, 27, 31, 0.5); }
.setup-dialog, .pairing-dialog, .profile-dialog, .switch-practice-dialog, .capture-dialog { max-height: calc(100dvh - 24px); overflow: auto; border: 1px solid var(--border); border-radius: var(--radius-dialog); padding: 28px; color: var(--text); background: var(--surface); box-shadow: var(--shadow-dialog); }
.setup-dialog, .pairing-dialog, .profile-dialog, .switch-practice-dialog { animation: dialog-in 160ms ease-out; }
/* No fill mode, and never a lasting transform: the switch capture dialog
renders inside the setup guide with position: fixed, and a transform on the
guide would trap it inside the guide's clipped box instead of the window. */
@keyframes dialog-in { from { opacity: 0; transform: translateY(8px) scale(0.985); } }
:is(.setup-dialog, .pairing-dialog, .profile-dialog, .switch-practice-dialog):focus { outline: none; }
:is(.setup-dialog, .pairing-dialog, .profile-dialog, .switch-practice-dialog):focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.pairing-dialog { width: min(100%, 640px); }
.profile-dialog, .switch-practice-dialog { width: min(100%, 760px); }
.confirm-dialog { width: min(100%, 520px); }
:is(.setup-dialog, .pairing-dialog, .profile-dialog) > header h2, .switch-practice-dialog > h2 { font-size: 24px; line-height: 1.3; font-weight: 700; }
:is(.setup-dialog, .pairing-dialog, .profile-dialog) > header p { margin-top: 4px; color: var(--muted); }
:is(.setup-dialog, .profile-dialog) > footer { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-top: 24px; border-top: 1px solid var(--border); padding-top: 20px; }
:is(.setup-dialog, .profile-dialog) > footer > span { flex: 1; }
.confirm-dialog > footer { border-top: 0; padding-top: 0; }
.dialog-error { margin-top: 16px; border-left: 4px solid var(--status-error); border-radius: 0 8px 8px 0; padding: 10px 14px; color: var(--status-error); background: var(--status-error-soft); }

/* The setup guide sizes to its step, up to the window, and scrolls only its
middle so the step rail and the navigation stay in view. */
.setup-dialog { display: flex; flex-direction: column; width: min(100%, 880px); min-height: min(480px, calc(100dvh - 24px)); overflow: hidden; }
.setup-dialog > header { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 8px 16px; }
.setup-dialog > header span { color: var(--muted); font-size: 16px; font-weight: 600; }
.setup-dialog > header h2 { margin-top: 2px; }
.setup-dialog > header strong { color: var(--muted); font-size: 16px; font-variant-numeric: tabular-nums; }
.setup-progress { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; margin-top: 16px; }
.setup-progress span { height: 6px; border-radius: 3px; background: var(--border); }
.setup-progress span[data-active="true"] { background: var(--brand); }
.setup-content { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 16px 4px; }
.setup-content { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 24px 4px 8px; }
.setup-content > div > p { max-width: 68ch; }
.setup-content p { margin-top: 8px; color: var(--muted); }
.setup-choices { margin-top: 22px; }
.setup-privacy { margin-top: 18px; color: var(--brand-label); }
.setup-choices { margin-top: 24px; }
.setup-privacy { margin-top: 16px; color: var(--brand-label); }
.setup-navigation-guidance { flex: 0 0 auto; margin: 0; color: var(--muted); line-height: 1.5; }
.setup-navigation-guidance:not(:empty) { padding-bottom: 16px; }
.setup-dialog > footer { gap: 12px; border-top: 1px solid var(--border); padding-top: 12px; }
.setup-dialog > footer > span { flex: 1; }
.setup-navigation-guidance:not(:empty) { padding-top: 12px; }
.setup-dialog > footer { flex: none; margin-top: 12px; }
.setup-backdrop[hidden] { display: none; }

.pairing-dialog:focus { outline: 2px solid var(--focus); outline-offset: 2px; }
.pairing-dialog > header { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: start; gap: 12px; }
.pairing-dialog > header { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: start; gap: 16px; }
.pairing-dialog > header > svg { margin-top: 2px; color: var(--brand); }
.pairing-dialog > header > span { display: grid; place-items: center; min-width: 28px; height: 28px; border-radius: 14px; color: var(--on-brand-container); background: var(--brand-container); font-weight: 700; }
.pairing-dialog > header > span { display: grid; place-items: center; min-width: 32px; height: 32px; border-radius: 16px; color: var(--on-brand-container); background: var(--brand-container); font-weight: 700; }
.pairing-dialog p { margin-top: 4px; color: var(--muted); line-height: 1.4; }
.pairing-dialog .pairing-connection { color: var(--text); }
.pairing-list { margin-top: 20px; border-top: 1px solid var(--border); }
.pairing-list article { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; min-height: 88px; border-bottom: 1px solid var(--border); padding: 12px 0; }
.pairing-list output { color: var(--text); font: 700 25px/1 ui-monospace, monospace; letter-spacing: 0.12em; white-space: nowrap; }
.pairing-actions { display: flex; flex-wrap: wrap; gap: 12px; }

.profile-dialog > header, .profile-dialog > footer { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.profile-dialog > header { justify-content: space-between; }
.profile-dialog header p { margin-top: 4px; color: var(--muted); }
.profile-dialog > footer { margin-top: 20px; }
.profile-dialog > footer > span { flex: 1; }
.binding-list { margin-top: 18px; border-top: 1px solid var(--border); }
/* Each request is a card whose code is the thing to compare, so the code is
set large and spaced like the code on the phone. */
.pairing-list { display: grid; gap: 12px; margin-top: 24px; }
.pairing-list article { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 12px 16px; border: 1px solid var(--border); border-radius: var(--radius-card); padding: 16px 20px; background: var(--surface-muted); }
.pairing-list h3 { overflow-wrap: anywhere; }
.pairing-list output { border-radius: 10px; padding: 8px 14px; color: var(--text); background: var(--surface); font: 700 28px/1 ui-monospace, Consolas, monospace; letter-spacing: 0.12em; white-space: nowrap; }
.pairing-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 12px; grid-column: 1 / -1; }

.profile-dialog > header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.binding-list { margin-top: 20px; border-top: 1px solid var(--border); }
/* Switch label, action, then the action's value; both controls share the
row instead of the action squeezing into a fixed narrow column. */
.profile-dialog { container-type: inline-size; }
Expand All @@ -573,14 +588,20 @@ fieldset:disabled :is(.color-options, .scanner-colours) label:not(:has(input:che
.binding-row > :nth-child(3):not(.binding-error) { grid-column: 2; }
}

.capture-dialog { display: grid; justify-items: center; width: min(100%, 420px); border: 1px solid var(--brand-border); border-radius: 10px; padding: 32px 28px 24px; color: var(--text); background: var(--surface); box-shadow: var(--shadow-dialog); text-align: center; animation: capture-pulse 1.4s ease-in-out infinite; }
.switch-practice-dialog > p { max-width: 68ch; margin-top: 8px; color: var(--muted); }
.switch-practice-dialog > p[role="status"] { color: var(--text); font-weight: 600; }

.capture-dialog { display: grid; justify-items: center; width: min(100%, 440px); border-color: var(--brand-border); padding: 36px 28px 28px; text-align: center; animation: capture-pulse 1.4s ease-in-out infinite; }
.capture-dialog:focus { outline: none; }
.capture-dialog > svg { color: var(--brand); }
.capture-dialog h2 { margin-top: 14px; }
.capture-dialog h2 { margin-top: 14px; font-size: 24px; line-height: 1.3; font-weight: 700; }
.capture-dialog p { margin-top: 8px; color: var(--muted); }
.capture-dialog .btn { margin-top: 20px; }
@keyframes capture-pulse { 50% { border-color: var(--brand); box-shadow: var(--shadow-dialog), 0 0 0 4px var(--brand-container); } }
@media (prefers-reduced-motion: reduce) { .capture-dialog, .btn { animation: none; transition: none; } }
@media (prefers-reduced-motion: reduce) {
.setup-dialog, .pairing-dialog, .profile-dialog, .switch-practice-dialog, .capture-dialog { animation: none; }
.btn { transition: none; }
}

@media (forced-colors: active) {
.btn.nav-button[data-active="true"] { outline: 2px solid Highlight; outline-offset: -2px; }
Expand Down Expand Up @@ -608,6 +629,7 @@ fieldset:disabled :is(.color-options, .scanner-colours) label:not(:has(input:che
.update-banner .btn.text-button { grid-column: 2; justify-self: start; padding-left: 0; }
}
@media (max-width: 480px) {
.setup-dialog, .pairing-dialog, .profile-dialog, .switch-practice-dialog { padding: 20px; }
.app-shell nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.view { padding: 12px; }
.btn.profile-row { display: flex; flex-wrap: wrap; }
Expand All @@ -617,7 +639,7 @@ fieldset:disabled :is(.color-options, .scanner-colours) label:not(:has(input:che
.scanner-preferences .segmented { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-height: 600px) {
.setup-dialog { overflow-y: auto; }
.setup-dialog { min-height: 0; overflow-y: auto; }
.setup-dialog > * { flex-shrink: 0; }
.setup-dialog .setup-content { overflow: visible; }
}
Expand Down
Loading