Files
kestrove-desktop/src/style.css
T
samiandClaude Opus 5.5 19c4ce1899 Apply the Kestrove design system to the desktop UI
- src/ui: tokens.css (generated from the design system's tokens.json), kv.css components, fonts.css with
  the bundled Inter and JetBrains Mono woff2, kv.ts DOM builders (icons, tiles, item rows, secrets,
  codes, TOTP ring, pills, banners). The browser extension uses the same module.
- Layout: custom title bar in bg (macOS overlay title bar, traffic lights kept), left rail, list and detail.
- Item detail: field rows with 10-dot masking, coloured digits/symbols on reveal (re-masks after 30 s),
  copy turns into a check for 1.5 s, TOTP in code-lg with the ring.
- Add-a-device QR card, Use my phone QR with countdown and confirmation code, approve sheet.
- Status pills, banners and the integrity alert; Light / Dark / System in Settings (also sets the window theme).
- totp command returns the period for the ring.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 16:35:58 +09:00

102 lines
6.8 KiB
CSS

/* Desktop layout. Colours, type and components come from the design system (./ui). */
@import "./ui/fonts.css";
@import "./ui/tokens.css";
@import "./ui/kv.css";
html, body { margin: 0; height: 100%; }
body { overflow: hidden; }
#app { height: 100vh; display: flex; flex-direction: column; }
p { margin: 0; }
h1, h2, h3 { margin: 0; }
.grow { flex: 1 1 auto; min-width: 0; }
.row { display: flex; gap: var(--space-2); align-items: center; flex-wrap: wrap; }
.stack { display: flex; flex-direction: column; gap: var(--space-4); min-width: 0; }
.actions { display: flex; gap: var(--space-2); align-items: center; }
.actions.end { justify-content: flex-end; }
.center-row { display: flex; justify-content: center; }
.fingerprint { font-family: var(--font-mono); font-variant-ligatures: none; letter-spacing: 0.04em; word-spacing: 0.2em; }
.fingerprint.lg { font-size: 17px; line-height: 26px; }
.kv-error-text { color: var(--danger); }
details { display: grid; gap: var(--space-2); }
summary { cursor: pointer; color: var(--text-2); }
/* Custom title bar in bg with the native window controls. */
.titlebar {
height: 44px; flex: none; display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-3) 0 var(--space-4);
background: var(--bg); border-bottom: 1px solid var(--border); user-select: none; -webkit-user-select: none;
}
.mac .titlebar { padding-left: 84px; }
.kv-word.sm { font-size: 15px; line-height: 20px; }
/* Segmented control: border-control outline (WCAG 1.4.11). */
.seg { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 2px; border: 1px solid var(--border-control); border-radius: var(--radius); background: var(--surface-2); align-self: flex-start; }
.seg .kv-btn { height: 32px; background: transparent; color: var(--text-2); border-radius: 8px; font-weight: 600; padding: 0 var(--space-3); }
.seg .kv-btn[aria-pressed="true"] { background: var(--surface); color: var(--text); box-shadow: var(--shadow-sm); }
/* Unlock and onboarding */
#app.auth { background: var(--bg); }
.center { flex: 1; overflow: auto; display: grid; place-items: center; padding: var(--space-12) var(--space-4); }
.auth-card { width: 400px; max-width: 100%; padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-5); box-shadow: var(--shadow-sm); }
.auth-card.wide { width: 580px; }
.unlock-mark { display: flex; justify-content: center; }
.auth-card .kv-title-1 { text-align: left; }
.secret-key { padding: var(--space-3) var(--space-4); border-radius: var(--radius); background: var(--surface-2); }
.secret-key .kv-secret { font-size: 17px; line-height: 26px; }
/* QR card and confirmation code (AddDevice) */
.qr-sheet { display: flex; flex-direction: column; gap: var(--space-3); align-items: center; text-align: center; }
.qr-sheet .steps { align-self: stretch; text-align: left; }
.steps { margin: 0; padding-left: var(--space-5); display: grid; gap: var(--space-1); }
.confirm { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); min-height: 54px; justify-content: center; }
.words { display: flex; flex-wrap: wrap; gap: var(--space-1\.5); }
.words span { font: 600 15px/22px var(--font-mono); padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm); background: var(--surface-2); }
/* Vault: left rail, list, detail */
#app.shell { background: var(--bg); }
.alarm-slot:not(:empty) { padding: var(--space-3) var(--space-4) 0; }
.cols { flex: 1; min-height: 0; display: grid; grid-template-columns: 200px minmax(260px, 340px) 1fr; }
.rail { background: var(--surface-2); padding: var(--space-3) var(--space-2); display: flex; flex-direction: column; gap: 2px; overflow: auto; border-right: 1px solid var(--border); }
.rail-h { padding: var(--space-3) var(--space-2\.5) var(--space-1); }
.rail-item {
display: flex; align-items: center; gap: var(--space-2\.5); padding: var(--space-1\.5) var(--space-2\.5); border-radius: var(--radius-sm);
border: 0; background: transparent; color: var(--text-2); font: 400 14px/20px var(--font-sans); cursor: pointer; text-align: left;
}
.rail-item:hover { background: var(--surface-3); color: var(--text); }
.rail-item[aria-current="page"] { background: var(--primary-soft); color: var(--text); font-weight: 600; }
.rail-foot { display: flex; flex-direction: column; gap: var(--space-2); padding-top: var(--space-2); }
.rail-foot .kv-banner { padding: var(--space-2\.5) var(--space-3); font-size: 13px; line-height: 18px; gap: var(--space-2); }
.sync-line { display: flex; align-items: center; gap: var(--space-1); padding: 0 var(--space-1) 0 var(--space-2\.5); }
.listpane { background: var(--surface); border-right: 1px solid var(--border); display: flex; flex-direction: column; min-height: 0; }
.list-head { display: flex; gap: var(--space-2); padding: var(--space-3); border-bottom: 1px solid var(--border); }
.search { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-2\.5); height: var(--control); border-radius: var(--radius); background: var(--surface-2); color: var(--text-3); }
.search:focus-within { outline: 2px solid var(--focus); outline-offset: 2px; }
.search input { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--text); font: 400 14px/20px var(--font-sans); height: 100%; outline: none; }
.search input::placeholder { color: var(--text-3); }
.listpane .kv-list { flex: 1; overflow: auto; }
.empty { padding: var(--space-6) var(--space-4); text-align: center; }
.detail { background: var(--surface); overflow: auto; padding: var(--space-5) var(--space-6) var(--space-12); min-width: 0; }
.empty-detail { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--space-3); opacity: 0.9; }
.detail-head { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-5); }
.fields { overflow: hidden; }
.notes { white-space: pre-wrap; }
.editor { max-width: 520px; }
.editor .row .kv-field { flex: 1; }
/* Settings */
.settings { max-width: 640px; gap: var(--space-6); }
.settings-section { display: flex; flex-direction: column; gap: var(--space-2\.5); }
.rows { overflow: hidden; }
.pad { padding: var(--space-4); }
.badges { display: inline-flex; gap: var(--space-1); }
.device-ico { color: var(--text-2); display: grid; }
/* Dialogs and browser prompts */
#overlay, #modal { position: fixed; inset: 0; background: rgb(6 14 11 / 0.5); display: grid; place-content: center; gap: var(--space-3); padding: var(--space-4); }
#modal { z-index: 2; }
#overlay[hidden], #modal[hidden] { display: none; }
.prompt { width: 440px; max-width: calc(100vw - 32px); max-height: calc(100vh - 48px); overflow: auto; padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-4); }
@media (prefers-reduced-motion: no-preference) {
.prompt { animation: pop 160ms var(--ease); }
}
@keyframes pop { from { opacity: 0; transform: translateY(6px) scale(0.985); } }