ed5d1c0e57eb
reconcile the last chirp-era names: peach-chirp-* CSS classes become peach-pair-*, the three CHIRP_-prefixed device messages drop the prefix, stale comments stop pointing at deleted files, and the dead peach-pair-pro-chirp rule goes (v4.0.37)
- time
- 2026-07-25 01:22 UTC · 3 months ago
- machine
- koh2
- agent
- claude-opus-5
- session
- chirp era naming reconcile
- parent
- ba8d30d4cb70
↓ peach-browser-ed5d1c0e.tar.gzatlas at this save
files changed10 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/background/messages.ts+3 −3src/popup/components/PairingBirds.tsx+37 −37src/popup/styles/popup.css+233 −252src/popup/views/PairDevice.test.tsx+1 −1src/popup/views/PairDevice.tsx+23 −23src/popup/views/Settings.tsx+2 −2src/shared/types.ts+3 −3manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach Password Manager",4- "version": "4.0.36",4+ "version": "4.0.37",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {manifest.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach Password Manager",4- "version": "4.0.36",4+ "version": "4.0.37",55 "description": "Zero-knowledge password manager",66 "action": {77 "default_popup": "src/popup/index.html",package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "peach",3- "version": "4.0.36",3+ "version": "4.0.37",44 "description": "Zero-knowledge password manager",55 "license": "GPL-3.0-only",66 "type": "module",src/background/messages.ts+3 −3
@@ -1407,12 +1407,12 @@14071407 return { ok: true };14081408 }14091409 1410- case "CHIRP_LIST_PAIRED_DEVICES": {1410+ case "LIST_PAIRED_DEVICES": {14111411 const devices = await listPairedDevicesV3();14121412 return { ok: true, data: { devices } };14131413 }14141414 1415- case "CHIRP_UNPAIR_DEVICE": {1415+ case "UNPAIR_DEVICE": {14161416 const { deviceId } = (msg.payload ?? {}) as { deviceId?: string };14171417 if (typeof deviceId !== "string" || !deviceId) {14181418 return { ok: false, error: "invalid_payload" };@@ -1421,7 +1421,7 @@14211421 return { ok: true };14221422 }14231423 1424- case "CHIRP_RENAME_LOCAL_DEVICE": {1424+ case "RENAME_LOCAL_DEVICE": {14251425 const { name } = (msg.payload ?? {}) as { name?: string };14261426 if (typeof name !== "string") return { ok: false, error: "invalid_payload" };14271427 await setDeviceNameV3(name);src/popup/components/PairingBirds.tsx+37 −37
@@ -1,9 +1,9 @@11 // Pairing birds — the two illustrated characters used on the pairing screens.22 //3-// These are all that remains of the audio-chirp pairing animation this file is4-// named after: the flow itself was removed with Chirp, but the birds outlived5-// it and still animate above the code-entry, connecting, SAS and paired6-// screens (ChirpSync.tsx's `desktopBirdStage`).3+// These are all that remains of the removed audio-pairing animation: the flow4+// itself went with it, but the birds outlived it and still animate above the5+// code-entry, connecting, SAS and paired screens (PairDevice.tsx's bird stage).6+// The `-chirping` pose names are kept on purpose — the bird visibly chirps.77 88 import { Component } from "solid-js";99 @@ -19,43 +19,43 @@1919 export const DesktopBird: Component<{ pose: string }> = (props) => {2020 const p = FINCH;2121 return (22- <div class={`peach-chirp-bird peach-chirp-bird-desktop peach-chirp-bird-pose-${props.pose}`}>22+ <div class={`peach-pair-bird peach-pair-bird-desktop peach-pair-bird-pose-${props.pose}`}>2323 <svg viewBox="0 0 160 150" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMax meet">2424 <defs>25- <radialGradient id="peach-chirp-finch-body" cx="0.42" cy="0.32" r="0.72">25+ <radialGradient id="peach-pair-finch-body" cx="0.42" cy="0.32" r="0.72">2626 <stop offset="0%" stop-color={p.hi} />2727 <stop offset="55%" stop-color={p.mid} />2828 <stop offset="100%" stop-color={p.lo} />2929 </radialGradient>30- <radialGradient id="peach-chirp-finch-head" cx="0.5" cy="0.4" r="0.7">30+ <radialGradient id="peach-pair-finch-head" cx="0.5" cy="0.4" r="0.7">3131 <stop offset="0%" stop-color={p.hi} />3232 <stop offset="100%" stop-color={p.mid} />3333 </radialGradient>34- <linearGradient id="peach-chirp-finch-belly" x1="0" y1="0" x2="0" y2="1">34+ <linearGradient id="peach-pair-finch-belly" x1="0" y1="0" x2="0" y2="1">3535 <stop offset="0%" stop-color={p.cream} stop-opacity="0" />3636 <stop offset="50%" stop-color={p.cream} stop-opacity="0.85" />3737 <stop offset="100%" stop-color={p.cream} stop-opacity="0.5" />3838 </linearGradient>3939 </defs>40- <ellipse class="peach-chirp-bird-shadow" cx="78" cy="138" rx="40" ry="3.5" fill="rgba(0,0,0,0.45)" />41- <g class="peach-chirp-bird-aura" opacity="0">40+ <ellipse class="peach-pair-bird-shadow" cx="78" cy="138" rx="40" ry="3.5" fill="rgba(0,0,0,0.45)" />41+ <g class="peach-pair-bird-aura" opacity="0">4242 <ellipse cx="76" cy="74" rx="60" ry="46" fill={p.hi} opacity="0.18" style={{ filter: "blur(8px)" }} />4343 </g>44- <g class="peach-chirp-bird-tail">44+ <g class="peach-pair-bird-tail">4545 <path d="M 32 92 Q 8 90, 6 80 Q 10 95, 28 100 Z" fill={p.lo} />4646 <path d="M 32 95 Q 4 99, 4 92 Q 10 102, 28 102 Z" fill={p.shade} opacity="0.85" />4747 <path d="M 32 98 Q 8 108, 12 110 Q 20 110, 30 105 Z" fill={p.lo} opacity="0.9" />4848 </g>49- <g class="peach-chirp-bird-feet" stroke={p.legs} stroke-width="1.6" stroke-linecap="round" fill="none">49+ <g class="peach-pair-bird-feet" stroke={p.legs} stroke-width="1.6" stroke-linecap="round" fill="none">5050 <line x1="62" y1="118" x2="60" y2="134" />5151 <path d="M 60 134 L 55 138 M 60 134 L 60 139 M 60 134 L 65 138" stroke-width="1.2" />5252 <line x1="84" y1="118" x2="86" y2="134" />5353 <path d="M 86 134 L 81 138 M 86 134 L 86 139 M 86 134 L 91 138" stroke-width="1.2" />5454 </g>55- <g class="peach-chirp-bird-body">56- <path d="M 30 88 C 24 64, 40 38, 72 36 C 105 34, 124 56, 122 84 C 120 110, 100 122, 70 120 C 44 118, 32 108, 30 88 Z" fill="url(#peach-chirp-finch-body)" />57- <path d="M 40 82 C 42 100, 60 112, 80 110 C 100 108, 110 100, 112 86 C 100 102, 80 106, 60 102 C 50 100, 44 92, 40 82 Z" fill="url(#peach-chirp-finch-belly)" />58- <g class="peach-chirp-bird-wing">55+ <g class="peach-pair-bird-body">56+ <path d="M 30 88 C 24 64, 40 38, 72 36 C 105 34, 124 56, 122 84 C 120 110, 100 122, 70 120 C 44 118, 32 108, 30 88 Z" fill="url(#peach-pair-finch-body)" />57+ <path d="M 40 82 C 42 100, 60 112, 80 110 C 100 108, 110 100, 112 86 C 100 102, 80 106, 60 102 C 50 100, 44 92, 40 82 Z" fill="url(#peach-pair-finch-belly)" />58+ <g class="peach-pair-bird-wing">5959 <path d="M 56 60 C 68 56, 88 60, 102 68 C 108 76, 106 86, 96 90 C 80 92, 64 86, 54 78 C 50 70, 50 64, 56 60 Z" fill={p.lo} />6060 <g stroke={p.shade} stroke-width="0.7" stroke-linecap="round" fill="none" opacity="0.55">6161 <path d="M 64 64 Q 72 70, 78 80" />@@ -65,20 +65,20 @@6565 <path d="M 56 60 C 68 56, 88 60, 102 68" stroke={p.shade} stroke-width="1" fill="none" opacity="0.4" />6666 </g>6767 </g>68- <g class="peach-chirp-bird-head-group" style={{ "transform-origin": "95px 52px" }}>69- <g class="peach-chirp-bird-tuft">68+ <g class="peach-pair-bird-head-group" style={{ "transform-origin": "95px 52px" }}>69+ <g class="peach-pair-bird-tuft">7070 <path d="M 88 22 Q 86 12, 94 12 Q 94 20, 92 26 Z" fill={p.lo} />7171 <path d="M 96 20 Q 96 10, 104 14 Q 102 22, 100 26 Z" fill={p.shade} opacity="0.95" />7272 <path d="M 104 24 Q 108 16, 114 20 Q 110 28, 106 30 Z" fill={p.lo} opacity="0.85" />7373 </g>74- <circle cx="98" cy="48" r="26" fill="url(#peach-chirp-finch-head)" />74+ <circle cx="98" cy="48" r="26" fill="url(#peach-pair-finch-head)" />7575 <path d="M 76 46 Q 80 30, 96 26 Q 86 32, 80 48 Z" fill={p.shade} opacity="0.35" />76- <g class="peach-chirp-bird-eye-group">76+ <g class="peach-pair-bird-eye-group">7777 <circle cx="108" cy="42" r="4.5" fill="#1f0a10" />7878 <circle cx="109.4" cy="40.5" r="1.4" fill="rgba(255,240,225,0.95)" />7979 <circle cx="106.5" cy="44" r="0.5" fill="rgba(255,240,225,0.6)" />8080 </g>81- <g class="peach-chirp-bird-beak" style={{ "transform-origin": "120px 52px" }}>81+ <g class="peach-pair-bird-beak" style={{ "transform-origin": "120px 52px" }}>8282 <path d="M 120 48 L 138 50 L 122 56 Z" fill={p.beak} />8383 <path d="M 120 48 L 138 50 L 128 52 Z" fill={p.beakShade} opacity="0.55" />8484 <path d="M 122 52 L 134 51" stroke={p.beakShade} stroke-width="0.6" opacity="0.6" />@@ -92,42 +92,42 @@9292 export const MobileBird: Component<{ pose: string }> = (props) => {9393 const p = SWALLOW;9494 return (95- <div class={`peach-chirp-bird peach-chirp-bird-mobile peach-chirp-bird-pose-${props.pose}`}>95+ <div class={`peach-pair-bird peach-pair-bird-mobile peach-pair-bird-pose-${props.pose}`}>9696 <svg viewBox="0 0 160 150" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMax meet" style={{ transform: "scaleX(-1)" }}>9797 <defs>98- <radialGradient id="peach-chirp-swallow-body" cx="0.55" cy="0.35" r="0.75">98+ <radialGradient id="peach-pair-swallow-body" cx="0.55" cy="0.35" r="0.75">9999 <stop offset="0%" stop-color={p.hi} />100100 <stop offset="50%" stop-color={p.mid} />101101 <stop offset="100%" stop-color={p.lo} />102102 </radialGradient>103- <radialGradient id="peach-chirp-swallow-head" cx="0.45" cy="0.4" r="0.7">103+ <radialGradient id="peach-pair-swallow-head" cx="0.45" cy="0.4" r="0.7">104104 <stop offset="0%" stop-color={p.hi} />105105 <stop offset="100%" stop-color={p.mid} />106106 </radialGradient>107- <linearGradient id="peach-chirp-swallow-throat" x1="0" y1="0" x2="0" y2="1">107+ <linearGradient id="peach-pair-swallow-throat" x1="0" y1="0" x2="0" y2="1">108108 <stop offset="0%" stop-color={p.cream} stop-opacity="0.95" />109109 <stop offset="100%" stop-color={p.cream} stop-opacity="0.2" />110110 </linearGradient>111111 </defs>112- <ellipse class="peach-chirp-bird-shadow" cx="86" cy="140" rx="34" ry="3" fill="rgba(0,0,0,0.45)" />113- <g class="peach-chirp-bird-aura" opacity="0">112+ <ellipse class="peach-pair-bird-shadow" cx="86" cy="140" rx="34" ry="3" fill="rgba(0,0,0,0.45)" />113+ <g class="peach-pair-bird-aura" opacity="0">114114 <ellipse cx="80" cy="78" rx="60" ry="42" fill={p.hi} opacity="0.18" style={{ filter: "blur(8px)" }} />115115 </g>116- <g class="peach-chirp-bird-tail">116+ <g class="peach-pair-bird-tail">117117 <path d="M 38 80 Q 8 70, 0 60 Q 8 78, 28 88 Q 14 90, 6 96 Q 16 94, 32 92 L 38 84 Z" fill={p.lo} />118118 <path d="M 30 84 Q 14 78, 6 70 Q 18 84, 30 88 Z" fill={p.shade} opacity="0.7" />119119 </g>120- <g class="peach-chirp-bird-feet" stroke={p.legs} stroke-width="1.5" stroke-linecap="round" fill="none">120+ <g class="peach-pair-bird-feet" stroke={p.legs} stroke-width="1.5" stroke-linecap="round" fill="none">121121 <line x1="76" y1="118" x2="74" y2="136" />122122 <path d="M 74 136 L 69 140 M 74 136 L 74 141 M 74 136 L 79 140" stroke-width="1.1" />123123 <line x1="96" y1="118" x2="98" y2="136" />124124 <path d="M 98 136 L 93 140 M 98 136 L 98 141 M 98 136 L 103 140" stroke-width="1.1" />125125 </g>126- <g class="peach-chirp-bird-body">127- <path d="M 36 82 C 32 56, 56 42, 88 44 C 116 46, 134 60, 134 80 C 134 102, 116 118, 90 118 C 60 118, 40 104, 36 82 Z" fill="url(#peach-chirp-swallow-body)" />126+ <g class="peach-pair-bird-body">127+ <path d="M 36 82 C 32 56, 56 42, 88 44 C 116 46, 134 60, 134 80 C 134 102, 116 118, 90 118 C 60 118, 40 104, 36 82 Z" fill="url(#peach-pair-swallow-body)" />128128 <path d="M 50 64 C 60 52, 80 46, 100 48 C 116 50, 126 60, 128 70 C 120 60, 100 56, 80 60 C 64 64, 56 68, 50 64 Z" fill={p.shade} opacity="0.5" />129- <path d="M 64 82 C 66 100, 86 114, 102 112 C 116 110, 124 100, 126 88 C 116 102, 100 108, 84 104 C 74 102, 68 94, 64 82 Z" fill="url(#peach-chirp-swallow-throat)" />130- <g class="peach-chirp-bird-wing">129+ <path d="M 64 82 C 66 100, 86 114, 102 112 C 116 110, 124 100, 126 88 C 116 102, 100 108, 84 104 C 74 102, 68 94, 64 82 Z" fill="url(#peach-pair-swallow-throat)" />130+ <g class="peach-pair-bird-wing">131131 <path d="M 50 70 C 64 64, 84 66, 100 72 C 112 78, 112 90, 100 96 C 84 100, 64 96, 52 88 C 46 80, 46 74, 50 70 Z" fill={p.lo} />132132 <g fill={p.shade} opacity="0.85">133133 <path d="M 96 88 L 110 92 L 100 96 Z" />@@ -142,14 +142,14 @@142142 <path d="M 50 70 C 64 64, 84 66, 100 72" stroke={p.shade} stroke-width="1" fill="none" opacity="0.55" />143143 </g>144144 </g>145- <g class="peach-chirp-bird-head-group" style={{ "transform-origin": "116px 64px" }}>146- <circle cx="118" cy="64" r="20" fill="url(#peach-chirp-swallow-head)" />145+ <g class="peach-pair-bird-head-group" style={{ "transform-origin": "116px 64px" }}>146+ <circle cx="118" cy="64" r="20" fill="url(#peach-pair-swallow-head)" />147147 <path d="M 100 60 Q 108 46, 124 46 Q 134 50, 136 60 Q 124 54, 108 60 Z" fill={p.shade} opacity="0.55" />148- <g class="peach-chirp-bird-eye-group">148+ <g class="peach-pair-bird-eye-group">149149 <circle cx="126" cy="60" r="4" fill="#1f0a10" />150150 <circle cx="127.2" cy="58.8" r="1.2" fill="rgba(255,240,225,0.95)" />151151 </g>152- <g class="peach-chirp-bird-beak" style={{ "transform-origin": "136px 64px" }}>152+ <g class="peach-pair-bird-beak" style={{ "transform-origin": "136px 64px" }}>153153 <path d="M 136 60 L 154 62 L 138 66 Z" fill={p.beak} />154154 <path d="M 136 60 L 154 62 L 145 63 Z" fill={p.beakShade} opacity="0.5" />155155 <path d="M 138 63 L 152 63" stroke={p.beakShade} stroke-width="0.5" opacity="0.6" />src/popup/styles/popup.css+233 −252
@@ -194,7 +194,7 @@194194 visibility: hidden;195195 pointer-events: none;196196 }197-/* Chirp-sync owns its own surface and header — fully collapse the global197+/* The pair-device surface owns its own header and header — fully collapse the global198198 chrome row so the warm gradient reaches the popup edge. */199199 .peach-chrome.is-collapsed,200200 .peach-search-wrap.is-collapsed {@@ -1027,8 +1027,8 @@10271027 padding-top: 2px;10281028 }10291029 1030-/* Desktop helper (peach-sync) code pairing — additive hooks. The chirp pairing1031- classes (peach-chirp-*) carry the shared layout; these only style the parts1030+/* Desktop helper (peach-sync) code pairing — additive hooks. The shared pairing1031+ classes (peach-pair-*) carry the shared layout; these only style the parts10321032 unique to the typed-code path. Inline styles cover the SAS/confirm gate. */10331033 .peach-desktop-pair { display: flex; flex-direction: column; }10341034 .peach-desktop-enter,@@ -9343,16 +9343,16 @@93439343 }93449344 93459345 /* ──────────────────────────────────────────────────────────────────────────9346- Chirp pairing flow — bird-stage animation (Phase 1)9347- See src/popup/components/ChirpPairingFlow.tsx and the brief §6.2.9346+ Pair-device flow — bird-stage animation (Phase 1)9347+ See src/popup/components/PairingBirds.tsx and the brief §6.2.93489348 Three-act animation gated on the [data-phase] attribute of9349- .peach-chirp-pair; child layers (birds, chirp arcs, flight wave, dot)9349+ .peach-pair-pair; child layers (birds, sound arcs, flight wave, dot)93509350 each react via either pose class or visibility flag.93519351 Tokens: accent surfaces use var(--peach-accent); bird illustration93529352 colours are baked into the SVG per the brand-peach exception in §3.1.93539353 ────────────────────────────────────────────────────────────────────── */93549354 9355-.peach-chirp-pair {9355+.peach-pair-pair {93569356 position: absolute;93579357 inset: 0;93589358 z-index: 3;@@ -9370,14 +9370,14 @@93709370 overflow-x: hidden;93719371 scrollbar-width: none;93729372 isolation: isolate;9373- animation: peach-chirp-overlay-in 180ms cubic-bezier(0.4, 0, 0.2, 1) both;9373+ animation: peach-pair-overlay-in 180ms cubic-bezier(0.4, 0, 0.2, 1) both;93749374 }9375-@keyframes peach-chirp-overlay-in {9375+@keyframes peach-pair-overlay-in {93769376 from { opacity: 0; transform: translateY(8px); }93779377 to { opacity: 1; transform: translateY(0); }93789378 }9379-.peach-chirp-pair::-webkit-scrollbar { width: 0; height: 0; display: none; }9380-.peach-chirp-pair::before {9379+.peach-pair-pair::-webkit-scrollbar { width: 0; height: 0; display: none; }9380+.peach-pair-pair::before {93819381 content: '';93829382 position: absolute;93839383 inset: 0;@@ -9386,13 +9386,13 @@93869386 background: radial-gradient(ellipse 90% 30% at 50% 0%, color-mix(in srgb, var(--peach-accent) 6%, transparent), transparent 70%);93879387 z-index: 0;93889388 }9389-.peach-chirp-pair > * { position: relative; z-index: 1; }9389+.peach-pair-pair > * { position: relative; z-index: 1; }93909390 93919391 /* Header --------------------------------------------------------------- */9392-.peach-chirp-head {9392+.peach-pair-head {93939393 display: flex; align-items: center; gap: 10px;93949394 }9395-.peach-chirp-back {9395+.peach-pair-back {93969396 width: 32px; height: 32px;93979397 display: inline-flex; align-items: center; justify-content: center;93989398 background: transparent;@@ -9402,11 +9402,11 @@94029402 cursor: pointer;94039403 transition: color 0.15s ease, box-shadow 0.15s ease;94049404 }9405-.peach-chirp-back:hover {9405+.peach-pair-back:hover {94069406 color: var(--peach-accent);94079407 box-shadow: 0 0 10px color-mix(in srgb, var(--peach-accent) 24%, transparent);94089408 }9409-.peach-chirp-title {9409+.peach-pair-title {94109410 font-family: var(--font-display, Georgia, serif);94119411 font-style: italic;94129412 font-size: 24px;@@ -9415,16 +9415,16 @@94159415 color: var(--peach-t0);94169416 line-height: 1;94179417 }9418-.peach-chirp-head-spacer { flex: 1; }9418+.peach-pair-head-spacer { flex: 1; }94199419 94209420 /* Chip row ------------------------------------------------------------- */9421-.peach-chirp-chip-row {9421+.peach-pair-chip-row {94229422 display: flex;94239423 align-items: center;94249424 justify-content: flex-start;94259425 margin-top: 12px;94269426 }9427-.peach-chirp-chip {9427+.peach-pair-chip {94289428 display: inline-flex; align-items: center; gap: 8px;94299429 padding: 5px 10px 5px 8px;94309430 background: color-mix(in srgb, var(--peach-accent) 16%, transparent);@@ -9435,38 +9435,38 @@94359435 letter-spacing: 0.04em;94369436 color: color-mix(in srgb, var(--peach-accent) 70%, var(--peach-t0));94379437 }9438-.peach-chirp-chip-dot {9438+.peach-pair-chip-dot {94399439 width: 6px; height: 6px; border-radius: 50%;94409440 background: var(--peach-accent);94419441 box-shadow: 0 0 6px color-mix(in srgb, var(--peach-accent) 50%, transparent);94429442 }9443-.peach-chirp-chip[data-phase="paired"] {9443+.peach-pair-chip[data-phase="paired"] {94449444 background: color-mix(in srgb, #4f9eda 12%, transparent);94459445 border-color: color-mix(in srgb, #4f9eda 28%, transparent);94469446 color: #76b6e8;94479447 }9448-.peach-chirp-chip[data-phase="paired"] .peach-chirp-chip-dot {9448+.peach-pair-chip[data-phase="paired"] .peach-pair-chip-dot {94499449 background: #76b6e8;94509450 box-shadow: 0 0 6px rgba(118, 182, 232, 0.55);94519451 }9452-.peach-chirp-chip[data-phase="timeout"],9453-.peach-chirp-chip[data-phase="mic_denied"],9454-.peach-chirp-chip[data-phase="version_mismatch"],9455-.peach-chirp-chip[data-phase="handshake_failed"] {9452+.peach-pair-chip[data-phase="timeout"],9453+.peach-pair-chip[data-phase="mic_denied"],9454+.peach-pair-chip[data-phase="version_mismatch"],9455+.peach-pair-chip[data-phase="handshake_failed"] {94569456 background: color-mix(in srgb, var(--peach-warn, #d29257) 14%, transparent);94579457 border-color: color-mix(in srgb, var(--peach-warn, #d29257) 28%, transparent);94589458 color: var(--peach-warn, #d29257);94599459 }9460-.peach-chirp-chip[data-phase="timeout"] .peach-chirp-chip-dot,9461-.peach-chirp-chip[data-phase="mic_denied"] .peach-chirp-chip-dot,9462-.peach-chirp-chip[data-phase="version_mismatch"] .peach-chirp-chip-dot,9463-.peach-chirp-chip[data-phase="handshake_failed"] .peach-chirp-chip-dot {9460+.peach-pair-chip[data-phase="timeout"] .peach-pair-chip-dot,9461+.peach-pair-chip[data-phase="mic_denied"] .peach-pair-chip-dot,9462+.peach-pair-chip[data-phase="version_mismatch"] .peach-pair-chip-dot,9463+.peach-pair-chip[data-phase="handshake_failed"] .peach-pair-chip-dot {94649464 background: var(--peach-warn, #d29257);94659465 box-shadow: 0 0 6px color-mix(in srgb, var(--peach-warn, #d29257) 55%, transparent);94669466 }94679467 94689468 /* Bird stage ----------------------------------------------------------- */9469-.peach-chirp-stage {9469+.peach-pair-stage {94709470 position: relative;94719471 margin: 14px 0 8px;94729472 height: 180px;@@ -9479,7 +9479,7 @@94799479 overflow: hidden;94809480 isolation: isolate;94819481 }9482-.peach-chirp-stage::after {9482+.peach-pair-stage::after {94839483 content: '';94849484 position: absolute;94859485 left: 12%; right: 12%;@@ -9488,7 +9488,7 @@94889488 background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--peach-t0) 14%, transparent), transparent);94899489 }94909490 9491-.peach-chirp-bird-slot {9491+.peach-pair-bird-slot {94929492 position: absolute;94939493 bottom: 8px;94949494 width: 100px;@@ -9497,186 +9497,186 @@94979497 align-items: flex-end;94989498 justify-content: center;94999499 }9500-.peach-chirp-bird-slot-desktop { left: 28px; }9501-.peach-chirp-bird-slot-mobile { right: 28px; }9500+.peach-pair-bird-slot-desktop { left: 28px; }9501+.peach-pair-bird-slot-mobile { right: 28px; }95029502 95039503 /* Mobile bird hops in from the right when handshake begins */9504-.peach-chirp-bird-slot-mobile {9504+.peach-pair-bird-slot-mobile {95059505 opacity: 1;95069506 transform: translateX(-6px);95079507 transition: opacity 0.4s ease, transform 0.65s cubic-bezier(.5, 1.7, .4, 1);95089508 }9509-.peach-chirp-stage.act-listening .peach-chirp-bird-slot-mobile,9510-.peach-chirp-stage.act-chirping .peach-chirp-bird-slot-mobile,9511-.peach-chirp-stage.act-idle .peach-chirp-bird-slot-mobile {9509+.peach-pair-stage.act-listening .peach-pair-bird-slot-mobile,9510+.peach-pair-stage.act-chirping .peach-pair-bird-slot-mobile,9511+.peach-pair-stage.act-idle .peach-pair-bird-slot-mobile {95129512 opacity: 0;95139513 transform: translateX(60px) rotate(8deg);95149514 }9515-.peach-chirp-stage.act-handshake .peach-chirp-bird-slot-desktop,9516-.peach-chirp-stage.act-paired .peach-chirp-bird-slot-desktop {9515+.peach-pair-stage.act-handshake .peach-pair-bird-slot-desktop,9516+.peach-pair-stage.act-paired .peach-pair-bird-slot-desktop {95179517 transform: translateX(6px);95189518 transition: transform 0.5s cubic-bezier(.4, 1.4, .4, 1);95199519 }95209520 95219521 /* Paired: both birds bob together */9522-.peach-chirp-stage.act-paired .peach-chirp-bird-slot {9523- animation: peach-chirp-happy-bob 1.2s ease-in-out infinite;9522+.peach-pair-stage.act-paired .peach-pair-bird-slot {9523+ animation: peach-pair-happy-bob 1.2s ease-in-out infinite;95249524 }9525-.peach-chirp-stage.act-paired .peach-chirp-bird-slot-mobile { animation-delay: 0.2s; }9526-.peach-chirp-stage.act-paired .peach-chirp-bird-slot-desktop { --bb-x: 6px; }9527-.peach-chirp-stage.act-paired .peach-chirp-bird-slot-mobile { --bb-x: -6px; }9528-@keyframes peach-chirp-happy-bob {9525+.peach-pair-stage.act-paired .peach-pair-bird-slot-mobile { animation-delay: 0.2s; }9526+.peach-pair-stage.act-paired .peach-pair-bird-slot-desktop { --bb-x: 6px; }9527+.peach-pair-stage.act-paired .peach-pair-bird-slot-mobile { --bb-x: -6px; }9528+@keyframes peach-pair-happy-bob {95299529 0%, 100% { transform: translateX(var(--bb-x, 0)) translateY(0); }95309530 50% { transform: translateX(var(--bb-x, 0)) translateY(-3px); }95319531 }95329532 95339533 /* Bird internal -------------------------------------------------------- */9534-.peach-chirp-bird {9534+.peach-pair-bird {95359535 width: 108px;95369536 height: 108px;95379537 transform-origin: 50% 95%;95389538 }9539-.peach-chirp-bird svg { width: 100%; height: 100%; overflow: visible; }9539+.peach-pair-bird svg { width: 100%; height: 100%; overflow: visible; }95409540 9541-.peach-chirp-bird-body {9541+.peach-pair-bird-body {95429542 transform-origin: 50% 80%;9543- animation: peach-chirp-bird-bob 2.4s ease-in-out infinite;9543+ animation: peach-pair-bird-bob 2.4s ease-in-out infinite;95449544 }9545-@keyframes peach-chirp-bird-bob {9545+@keyframes peach-pair-bird-bob {95469546 0%, 100% { transform: translateY(0) scale(1, 1); }95479547 50% { transform: translateY(-1.5px) scale(1.01, 0.99); }95489548 }95499549 9550-.peach-chirp-bird-eye-group {9551- animation: peach-chirp-blink 5.2s steps(1, end) infinite;9550+.peach-pair-bird-eye-group {9551+ animation: peach-pair-blink 5.2s steps(1, end) infinite;95529552 transform-origin: center;95539553 transform-box: fill-box;95549554 }9555-@keyframes peach-chirp-blink {9555+@keyframes peach-pair-blink {95569556 0%, 92%, 96%, 100% { transform: scaleY(1); }95579557 94% { transform: scaleY(0.05); }95589558 }95599559 95609560 /* Pose: chirping — beak opens, head bobs, aura blooms */9561-.peach-chirp-bird-pose-chirping .peach-chirp-bird-body {9561+.peach-pair-bird-pose-chirping .peach-pair-bird-body {95629562 animation:9563- peach-chirp-bird-bob 2.4s ease-in-out infinite,9564- peach-chirp-squeeze 1.7s ease-in-out infinite;9563+ peach-pair-bird-bob 2.4s ease-in-out infinite,9564+ peach-pair-squeeze 1.7s ease-in-out infinite;95659565 }9566-@keyframes peach-chirp-squeeze {9566+@keyframes peach-pair-squeeze {95679567 0%, 70%, 100% { transform-origin: 50% 85%; }95689568 78% { transform: scale(1.04, 0.96) translateY(1px); }95699569 86% { transform: scale(0.98, 1.02); }95709570 }9571-.peach-chirp-bird-pose-chirping .peach-chirp-bird-head-group {9572- animation: peach-chirp-head-bob 1.7s ease-in-out infinite;9571+.peach-pair-bird-pose-chirping .peach-pair-bird-head-group {9572+ animation: peach-pair-head-bob 1.7s ease-in-out infinite;95739573 }9574-@keyframes peach-chirp-head-bob {9574+@keyframes peach-pair-head-bob {95759575 0%, 70%, 100% { transform: translateY(0) rotate(0); }95769576 78% { transform: translateY(-3px) rotate(-4deg); }95779577 86% { transform: translateY(-1px) rotate(-2deg); }95789578 }9579-.peach-chirp-bird-pose-chirping .peach-chirp-bird-beak {9580- animation: peach-chirp-beak-open 1.7s ease-in-out infinite;9579+.peach-pair-bird-pose-chirping .peach-pair-bird-beak {9580+ animation: peach-pair-beak-open 1.7s ease-in-out infinite;95819581 }9582-@keyframes peach-chirp-beak-open {9582+@keyframes peach-pair-beak-open {95839583 0%, 70%, 100% { transform: rotate(0) scaleX(1); }95849584 78% { transform: rotate(-14deg) scaleX(1.05) translateY(-1px); }95859585 86% { transform: rotate(-6deg); }95869586 }9587-.peach-chirp-bird-pose-chirping .peach-chirp-bird-aura {9588- animation: peach-chirp-aura 1.7s ease-in-out infinite;9587+.peach-pair-bird-pose-chirping .peach-pair-bird-aura {9588+ animation: peach-pair-aura 1.7s ease-in-out infinite;95899589 }9590-@keyframes peach-chirp-aura {9590+@keyframes peach-pair-aura {95919591 0%, 100% { opacity: 0; }95929592 50% { opacity: 0.8; }95939593 }9594-.peach-chirp-bird-pose-chirping .peach-chirp-bird-tail {9595- animation: peach-chirp-tail-twitch 1.7s ease-in-out infinite;9594+.peach-pair-bird-pose-chirping .peach-pair-bird-tail {9595+ animation: peach-pair-tail-twitch 1.7s ease-in-out infinite;95969596 transform-origin: 100% 50%;95979597 }9598-@keyframes peach-chirp-tail-twitch {9598+@keyframes peach-pair-tail-twitch {95999599 0%, 75%, 100% { transform: rotate(0); }96009600 82% { transform: rotate(-3deg) translateX(-1px); }96019601 }96029602 96039603 /* Pose: attentive — head tilts toward partner */9604-.peach-chirp-bird-pose-attentive .peach-chirp-bird-head-group {9605- animation: peach-chirp-head-tilt 0.6s cubic-bezier(.4, 1.6, .5, 1) both;9604+.peach-pair-bird-pose-attentive .peach-pair-bird-head-group {9605+ animation: peach-pair-head-tilt 0.6s cubic-bezier(.4, 1.6, .5, 1) both;96069606 }9607-@keyframes peach-chirp-head-tilt {9607+@keyframes peach-pair-head-tilt {96089608 0% { transform: rotate(0) translateY(0); }96099609 60% { transform: rotate(-10deg) translateY(-1px) translateX(2px); }96109610 100% { transform: rotate(-6deg); }96119611 }9612-.peach-chirp-bird-pose-attentive .peach-chirp-bird-tail {9613- animation: peach-chirp-tail-cock 0.6s cubic-bezier(.4, 1.6, .5, 1) both;9612+.peach-pair-bird-pose-attentive .peach-pair-bird-tail {9613+ animation: peach-pair-tail-cock 0.6s cubic-bezier(.4, 1.6, .5, 1) both;96149614 transform-origin: 100% 50%;96159615 }9616-@keyframes peach-chirp-tail-cock {9616+@keyframes peach-pair-tail-cock {96179617 0% { transform: rotate(0); }96189618 100% { transform: rotate(-4deg); }96199619 }96209620 96219621 /* Pose: happy — wing flutter, tuft perk, tail wag */9622-.peach-chirp-bird-pose-happy .peach-chirp-bird-wing {9622+.peach-pair-bird-pose-happy .peach-pair-bird-wing {96239623 transform-origin: 80% 60%;9624- animation: peach-chirp-wing-flutter 0.32s ease-in-out 5;9624+ animation: peach-pair-wing-flutter 0.32s ease-in-out 5;96259625 }9626-@keyframes peach-chirp-wing-flutter {9626+@keyframes peach-pair-wing-flutter {96279627 0%, 100% { transform: rotate(0) translateY(0); }96289628 50% { transform: rotate(-16deg) translateY(-2px); }96299629 }9630-.peach-chirp-bird-pose-happy .peach-chirp-bird-tuft {9630+.peach-pair-bird-pose-happy .peach-pair-bird-tuft {96319631 transform-origin: 0% 100%;9632- animation: peach-chirp-tuft-perk 0.4s ease-in-out 3;9632+ animation: peach-pair-tuft-perk 0.4s ease-in-out 3;96339633 }9634-@keyframes peach-chirp-tuft-perk {9634+@keyframes peach-pair-tuft-perk {96359635 0%, 100% { transform: rotate(0); }96369636 50% { transform: rotate(-15deg) translateY(-1px); }96379637 }9638-.peach-chirp-bird-pose-happy .peach-chirp-bird-tail {9638+.peach-pair-bird-pose-happy .peach-pair-bird-tail {96399639 transform-origin: 100% 50%;9640- animation: peach-chirp-tail-wag 0.5s ease-in-out 4;9640+ animation: peach-pair-tail-wag 0.5s ease-in-out 4;96419641 }9642-@keyframes peach-chirp-tail-wag {9642+@keyframes peach-pair-tail-wag {96439643 0%, 100% { transform: rotate(0); }96449644 25% { transform: rotate(6deg); }96459645 75% { transform: rotate(-6deg); }96469646 }9647-.peach-chirp-bird-pose-happy .peach-chirp-bird-head-group {9648- animation: peach-chirp-head-perk 0.5s ease-out;9647+.peach-pair-bird-pose-happy .peach-pair-bird-head-group {9648+ animation: peach-pair-head-perk 0.5s ease-out;96499649 }9650-@keyframes peach-chirp-head-perk {9650+@keyframes peach-pair-head-perk {96519651 0% { transform: translateY(0); }96529652 40% { transform: translateY(-3px) rotate(2deg); }96539653 100% { transform: translateY(0); }96549654 }96559655 96569656 /* Pose: sad — body droops forward */9657-.peach-chirp-bird-pose-sad .peach-chirp-bird-body {9657+.peach-pair-bird-pose-sad .peach-pair-bird-body {96589658 transform: translateY(5px) rotate(-2deg);96599659 animation: none;96609660 }9661-.peach-chirp-bird-pose-sad .peach-chirp-bird-head-group {9661+.peach-pair-bird-pose-sad .peach-pair-bird-head-group {96629662 transform: translateY(4px) rotate(8deg);96639663 }9664-.peach-chirp-bird-pose-sad .peach-chirp-bird-tuft { transform: rotate(15deg) translateY(2px); }9665-.peach-chirp-bird-pose-sad .peach-chirp-bird-tail { transform: rotate(8deg) translateY(2px); }9664+.peach-pair-bird-pose-sad .peach-pair-bird-tuft { transform: rotate(15deg) translateY(2px); }9665+.peach-pair-bird-pose-sad .peach-pair-bird-tail { transform: rotate(8deg) translateY(2px); }96669666 9667-.peach-chirp-bird-pose-hidden { opacity: 0; }9667+.peach-pair-bird-pose-hidden { opacity: 0; }96689668 9669-/* Chirp arcs ----------------------------------------------------------- */9670-.peach-chirp-arcs {9669+/* Sound arcs ----------------------------------------------------------- */9670+.peach-pair-arcs {96719671 position: absolute;96729672 top: 18px;96739673 width: 96px;96749674 height: 70px;96759675 pointer-events: none;96769676 }9677-.peach-chirp-arcs-right { right: -60px; }9678-.peach-chirp-arcs-left { left: -60px; transform: scaleX(-1); }9679-.peach-chirp-arc {9677+.peach-pair-arcs-right { right: -60px; }9678+.peach-pair-arcs-left { left: -60px; transform: scaleX(-1); }9679+.peach-pair-arc {96809680 position: absolute;96819681 top: 50%;96829682 left: 0;@@ -9687,21 +9687,21 @@96879687 border-color: transparent #f4d5a8 transparent transparent;96889688 border-radius: 50%;96899689 opacity: 0;9690- animation: peach-chirp-arc-expand 1.7s cubic-bezier(.2, .6, .2, 1) infinite;9690+ animation: peach-pair-arc-expand 1.7s cubic-bezier(.2, .6, .2, 1) infinite;96919691 }9692-@keyframes peach-chirp-arc-expand {9692+@keyframes peach-pair-arc-expand {96939693 0% { transform: scale(0.4); opacity: 0; }96949694 20% { opacity: 0.9; }96959695 100% { transform: scale(1.6); opacity: 0; }96969696 }96979697 96989698 /* Flight wave ---------------------------------------------------------- */9699-.peach-chirp-flight-track {9699+.peach-pair-flight-track {97009700 position: absolute;97019701 inset: 32px 36px 38px 36px;97029702 pointer-events: none;97039703 }9704-.peach-chirp-flight-wave {9704+.peach-pair-flight-wave {97059705 position: absolute;97069706 top: 8px;97079707 left: 76px;@@ -9713,31 +9713,31 @@97139713 stroke: #f4d5a8;97149714 fill: none;97159715 }9716-.peach-chirp-flight-wave[data-from="mobile"] { transform: scaleX(-1); }9717-.peach-chirp-flight-wave.is-visible { opacity: 1; }9718-.peach-chirp-flight-path,9719-.peach-chirp-flight-path-2 {9716+.peach-pair-flight-wave[data-from="mobile"] { transform: scaleX(-1); }9717+.peach-pair-flight-wave.is-visible { opacity: 1; }9718+.peach-pair-flight-path,9719+.peach-pair-flight-path-2 {97209720 stroke-dasharray: 240;97219721 stroke-dashoffset: 240;97229722 stroke-linecap: round;97239723 fill: none;97249724 }9725-.peach-chirp-flight-path { stroke-width: 1.6; stroke: #f4d5a8; }9726-.peach-chirp-flight-path-2 { stroke-width: 1; stroke: #f4d5a8; opacity: 0.55; }9727-.peach-chirp-flight-wave.is-visible .peach-chirp-flight-path {9728- animation: peach-chirp-fly 700ms cubic-bezier(.2,.6,.2,1) forwards;9725+.peach-pair-flight-path { stroke-width: 1.6; stroke: #f4d5a8; }9726+.peach-pair-flight-path-2 { stroke-width: 1; stroke: #f4d5a8; opacity: 0.55; }9727+.peach-pair-flight-wave.is-visible .peach-pair-flight-path {9728+ animation: peach-pair-fly 700ms cubic-bezier(.2,.6,.2,1) forwards;97299729 }9730-.peach-chirp-flight-wave.is-visible .peach-chirp-flight-path-2 {9731- animation: peach-chirp-fly 700ms cubic-bezier(.2,.6,.2,1) 80ms forwards;9730+.peach-pair-flight-wave.is-visible .peach-pair-flight-path-2 {9731+ animation: peach-pair-fly 700ms cubic-bezier(.2,.6,.2,1) 80ms forwards;97329732 }9733-@keyframes peach-chirp-fly {9733+@keyframes peach-pair-fly {97349734 0% { stroke-dashoffset: 240; opacity: 0; }97359735 20% { opacity: 1; }97369736 100% { stroke-dashoffset: -120; opacity: 0; }97379737 }97389738 97399739 /* Connection dot ------------------------------------------------------- */9740-.peach-chirp-dot {9740+.peach-pair-dot {97419741 position: absolute;97429742 top: 50%; left: 50%;97439743 transform: translate(-50%, -50%);@@ -9747,8 +9747,8 @@97479747 transition: opacity 0.3s ease;97489748 color: var(--peach-accent);97499749 }9750-.peach-chirp-dot.is-visible { opacity: 1; }9751-.peach-chirp-dot-glow {9750+.peach-pair-dot.is-visible { opacity: 1; }9751+.peach-pair-dot-glow {97529752 position: absolute; top: 50%; left: 50%;97539753 transform: translate(-50%, -50%);97549754 width: 38px; height: 38px;@@ -9756,47 +9756,47 @@97569756 filter: blur(10px);97579757 opacity: 0.55;97589758 background: var(--peach-accent);9759- animation: peach-chirp-dot-bloom 1.4s ease-out;9759+ animation: peach-pair-dot-bloom 1.4s ease-out;97609760 }9761-.peach-chirp-dot-core {9761+.peach-pair-dot-core {97629762 position: absolute; top: 50%; left: 50%;97639763 transform: translate(-50%, -50%);97649764 width: 8px; height: 8px;97659765 border-radius: 50%;97669766 background: var(--peach-accent);97679767 box-shadow: 0 0 12px currentColor;9768- animation: peach-chirp-dot-core 1.4s ease-out;9768+ animation: peach-pair-dot-core 1.4s ease-out;97699769 }9770-.peach-chirp-dot-ring {9770+.peach-pair-dot-ring {97719771 position: absolute; top: 50%; left: 50%;97729772 width: 60px; height: 60px;97739773 transform: translate(-50%, -50%);9774- animation: peach-chirp-dot-ring 1.4s linear;9774+ animation: peach-pair-dot-ring 1.4s linear;97759775 stroke: var(--peach-accent);97769776 }9777-@keyframes peach-chirp-dot-bloom {9777+@keyframes peach-pair-dot-bloom {97789778 0% { width: 4px; height: 4px; opacity: 0; }97799779 35% { width: 60px; height: 60px; opacity: 0.7; }97809780 100% { width: 38px; height: 38px; opacity: 0.55; }97819781 }9782-@keyframes peach-chirp-dot-core {9782+@keyframes peach-pair-dot-core {97839783 0% { width: 0; height: 0; }97849784 35% { width: 12px; height: 12px; }97859785 100% { width: 8px; height: 8px; }97869786 }9787-@keyframes peach-chirp-dot-ring {9787+@keyframes peach-pair-dot-ring {97889788 0% { transform: translate(-50%, -50%) scale(0.4); opacity: 0; }97899789 35% { transform: translate(-50%, -50%) scale(1.0); opacity: 0.6; }97909790 100% { transform: translate(-50%, -50%) scale(1.4); opacity: 0; }97919791 }97929792 97939793 /* Motes — drift upward across the stage */9794-.peach-chirp-motes {9794+.peach-pair-motes {97959795 position: absolute;97969796 inset: 0;97979797 pointer-events: none;97989798 }9799-.peach-chirp-mote {9799+.peach-pair-mote {98009800 position: absolute;98019801 width: 2px; height: 2px;98029802 background: color-mix(in srgb, var(--peach-text) 35%, transparent);@@ -9804,10 +9804,10 @@98049804 bottom: 32px;98059805 left: calc(50% + (var(--mote-i, 0) - 4) * 24px);98069806 opacity: 0;9807- animation: peach-chirp-mote-drift 6s linear infinite;9807+ animation: peach-pair-mote-drift 6s linear infinite;98089808 animation-delay: calc(var(--mote-i, 0) * 0.7s);98099809 }9810-@keyframes peach-chirp-mote-drift {9810+@keyframes peach-pair-mote-drift {98119811 0% { transform: translateY(0); opacity: 0; }98129812 10% { opacity: 0.6; }98139813 90% { opacity: 0.1; }@@ -9815,19 +9815,19 @@98159815 }98169816 98179817 /* Status copy ---------------------------------------------------------- */9818-.peach-chirp-copy-host {9818+.peach-pair-copy-host {98199819 margin: 4px 4px 10px;98209820 text-align: center;98219821 min-height: 50px;98229822 }9823-.peach-chirp-copy {9824- animation: peach-chirp-copy-in 0.35s ease both;9823+.peach-pair-copy {9824+ animation: peach-pair-copy-in 0.35s ease both;98259825 }9826-@keyframes peach-chirp-copy-in {9826+@keyframes peach-pair-copy-in {98279827 from { opacity: 0; transform: translateY(4px); }98289828 to { opacity: 1; transform: translateY(0); }98299829 }9830-.peach-chirp-headline {9830+.peach-pair-headline {98319831 font-family: var(--font-display, Georgia, serif);98329832 font-style: italic;98339833 font-size: 20px;@@ -9837,9 +9837,9 @@98379837 color: var(--peach-t0);98389838 margin-bottom: 6px;98399839 }9840-.peach-chirp-copy-listening .peach-chirp-headline,9841-.peach-chirp-copy-chirping .peach-chirp-headline,9842-.peach-chirp-copy-idle .peach-chirp-headline {9840+.peach-pair-copy-listening .peach-pair-headline,9841+.peach-pair-copy-chirping .peach-pair-headline,9842+.peach-pair-copy-idle .peach-pair-headline {98439843 font-family: inherit;98449844 font-style: normal;98459845 font-weight: 500;@@ -9847,11 +9847,11 @@98479847 color: var(--peach-t0);98489848 letter-spacing: 0;98499849 }9850-.peach-chirp-copy-paired .peach-chirp-headline {9850+.peach-pair-copy-paired .peach-pair-headline {98519851 color: var(--peach-t0);98529852 font-weight: 600;98539853 }9854-.peach-chirp-sub {9854+.peach-pair-sub {98559855 font-size: 12.5px;98569856 line-height: 1.45;98579857 color: var(--peach-t1);@@ -9861,23 +9861,23 @@98619861 }98629862 98639863 /* Status action -------------------------------------------------------- */9864-.peach-chirp-action {9864+.peach-pair-action {98659865 margin: 2px 4px 10px;98669866 margin-top: auto;98679867 display: flex;98689868 flex-direction: column;98699869 gap: 8px;98709870 }9871-.peach-chirp-action-waiting {9871+.peach-pair-action-waiting {98729872 display: flex;98739873 align-items: center;98749874 justify-content: space-between;98759875 gap: 12px;98769876 }9877-.peach-chirp-cancel {9877+.peach-pair-cancel {98789878 min-width: 96px;98799879 }9880-.peach-chirp-listening {9880+.peach-pair-listening {98819881 display: inline-flex; align-items: center; gap: 4px;98829882 font-family: var(--peach-mono, ui-monospace, monospace);98839883 font-size: 9.5px;@@ -9886,28 +9886,28 @@98869886 color: var(--peach-t1);98879887 padding: 8px 10px;98889888 }9889-.peach-chirp-listen-dot {9889+.peach-pair-listen-dot {98909890 width: 4px; height: 4px;98919891 border-radius: 50%;98929892 background: color-mix(in srgb, var(--peach-accent) 55%, transparent);9893- animation: peach-chirp-listen-pulse 1.2s ease-in-out infinite;9893+ animation: peach-pair-listen-pulse 1.2s ease-in-out infinite;98949894 }9895-.peach-chirp-listen-dot:nth-child(2) { animation-delay: 0.2s; }9896-.peach-chirp-listen-dot:nth-child(3) { animation-delay: 0.4s; }9897-.peach-chirp-listen-label { margin-left: 6px; }9898-@keyframes peach-chirp-listen-pulse {9895+.peach-pair-listen-dot:nth-child(2) { animation-delay: 0.2s; }9896+.peach-pair-listen-dot:nth-child(3) { animation-delay: 0.4s; }9897+.peach-pair-listen-label { margin-left: 6px; }9898+@keyframes peach-pair-listen-pulse {98999899 0%, 100% { opacity: 0.25; transform: scale(0.9); }99009900 50% { opacity: 1; transform: scale(1.15); }99019901 }99029902 9903-.peach-chirp-action-handshake {9903+.peach-pair-action-handshake {99049904 display: flex;99059905 flex-direction: column;99069906 align-items: center;99079907 gap: 8px;99089908 padding: 8px 4px;99099909 }9910-.peach-chirp-meter {9910+.peach-pair-meter {99119911 width: 100%;99129912 max-width: 280px;99139913 height: 2px;@@ -9916,19 +9916,19 @@99169916 position: relative;99179917 overflow: hidden;99189918 }9919-.peach-chirp-meter-bar {9919+.peach-pair-meter-bar {99209920 position: absolute;99219921 top: 0; bottom: 0;99229922 width: 30%;99239923 left: -30%;99249924 background: linear-gradient(90deg, transparent, var(--peach-accent), transparent);9925- animation: peach-chirp-meter-sweep 1.4s ease-in-out infinite;9925+ animation: peach-pair-meter-sweep 1.4s ease-in-out infinite;99269926 }9927-@keyframes peach-chirp-meter-sweep {9927+@keyframes peach-pair-meter-sweep {99289928 0% { left: -30%; }99299929 100% { left: 100%; }99309930 }9931-.peach-chirp-meter-label {9931+.peach-pair-meter-label {99329932 font-family: var(--peach-mono, ui-monospace, monospace);99339933 font-size: 9.5px;99349934 text-transform: uppercase;@@ -9936,12 +9936,12 @@99369936 color: var(--peach-t1);99379937 }99389938 9939-.peach-chirp-action-paired {9939+.peach-pair-action-paired {99409940 display: flex;99419941 align-items: center;99429942 gap: 10px;99439943 }9944-.peach-chirp-device-confirm {9944+.peach-pair-device-confirm {99459945 flex: 1;99469946 display: inline-flex;99479947 align-items: center;@@ -9954,17 +9954,17 @@99549954 color: var(--peach-t0);99559955 min-width: 0;99569956 }9957-.peach-chirp-device-confirm-glyph {9957+.peach-pair-device-confirm-glyph {99589958 display: inline-flex;99599959 color: #76b6e8;99609960 }9961-.peach-chirp-device-confirm-name {9961+.peach-pair-device-confirm-name {99629962 flex: 1;99639963 overflow: hidden;99649964 text-overflow: ellipsis;99659965 white-space: nowrap;99669966 }9967-.peach-chirp-device-confirm-trust {9967+.peach-pair-device-confirm-trust {99689968 font-family: var(--peach-mono, ui-monospace, monospace);99699969 font-size: 9.5px;99709970 text-transform: uppercase;@@ -9974,16 +9974,16 @@99749974 border-radius: 4px;99759975 background: color-mix(in srgb, #76b6e8 14%, transparent);99769976 }9977-.peach-chirp-done {9977+.peach-pair-done {99789978 min-width: 80px;99799979 }9980-.peach-chirp-retry {9980+.peach-pair-retry {99819981 align-self: center;99829982 display: block;99839983 margin: 6px auto 0;99849984 min-width: 120px;99859985 }9986-.peach-chirp-mic-help {9986+.peach-pair-mic-help {99879987 font-size: 12px;99889988 color: var(--peach-t1);99899989 text-align: center;@@ -9992,11 +9992,11 @@99929992 }99939993 99949994 /* Rest state — bird stage at idle pose, primary CTA + paired list */9995-.peach-chirp-pair[data-phase="idle"] .peach-chirp-stage {9995+.peach-pair-pair[data-phase="idle"] .peach-pair-stage {99969996 /* Slightly shorter stage when at rest — no flight wave or motes to fill it */99979997 height: 160px;99989998 }9999-.peach-chirp-pair-start {9999+.peach-pair-pair-start {1000010000 width: 100%;1000110001 display: inline-flex;1000210002 align-items: center;@@ -10014,16 +10014,16 @@1001410014 cursor: pointer;1001510015 transition: filter 0.15s ease, transform 0.1s ease;1001610016 }10017-.peach-chirp-pair-start:hover { filter: brightness(1.08); }10018-.peach-chirp-pair-start:active { transform: translateY(1px); }10017+.peach-pair-pair-start:hover { filter: brightness(1.08); }10018+.peach-pair-pair-start:active { transform: translateY(1px); }1001910019 10020-.peach-chirp-paired-section {10020+.peach-pair-paired-section {1002110021 margin-top: 14px;1002210022 display: flex;1002310023 flex-direction: column;1002410024 gap: 8px;1002510025 }10026-.peach-chirp-paired-heading {10026+.peach-pair-paired-heading {1002710027 margin: 0;1002810028 font-family: var(--peach-mono, ui-monospace, monospace);1002910029 font-size: 10px;@@ -10034,16 +10034,16 @@1003410034 }1003510035 1003610036 /* Footer --------------------------------------------------------------- */10037-.peach-chirp-foot {10037+.peach-pair-foot {1003810038 margin: 10px -4px -2px;1003910039 margin-top: auto;1004010040 }10041-.peach-chirp-foot-divider {10041+.peach-pair-foot-divider {1004210042 height: 1px;1004310043 background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--peach-t0) 18%, transparent), transparent);1004410044 margin-bottom: 10px;1004510045 }10046-.peach-chirp-foot-text {10046+.peach-pair-foot-text {1004710047 font-size: 11px;1004810048 line-height: 1.5;1004910049 color: var(--peach-t1);@@ -10066,36 +10066,36 @@1006610066 1006710067 /* Reduced motion — stage simplifies to opacity transitions only */1006810068 @media (prefers-reduced-motion: reduce) {10069- .peach-chirp-bird-body,10070- .peach-chirp-bird-head-group,10071- .peach-chirp-bird-beak,10072- .peach-chirp-bird-wing,10073- .peach-chirp-bird-tuft,10074- .peach-chirp-bird-tail,10075- .peach-chirp-bird-eye-group,10076- .peach-chirp-bird-aura,10077- .peach-chirp-arc,10078- .peach-chirp-flight-path,10079- .peach-chirp-flight-path-2,10080- .peach-chirp-dot-glow,10081- .peach-chirp-dot-core,10082- .peach-chirp-dot-ring,10083- .peach-chirp-mote,10084- .peach-chirp-meter-bar,10085- .peach-chirp-listen-dot,10086- .peach-chirp-bird-slot,10087- .peach-chirp-bird-slot-mobile {10069+ .peach-pair-bird-body,10070+ .peach-pair-bird-head-group,10071+ .peach-pair-bird-beak,10072+ .peach-pair-bird-wing,10073+ .peach-pair-bird-tuft,10074+ .peach-pair-bird-tail,10075+ .peach-pair-bird-eye-group,10076+ .peach-pair-bird-aura,10077+ .peach-pair-arc,10078+ .peach-pair-flight-path,10079+ .peach-pair-flight-path-2,10080+ .peach-pair-dot-glow,10081+ .peach-pair-dot-core,10082+ .peach-pair-dot-ring,10083+ .peach-pair-mote,10084+ .peach-pair-meter-bar,10085+ .peach-pair-listen-dot,10086+ .peach-pair-bird-slot,10087+ .peach-pair-bird-slot-mobile {1008810088 animation: none !important;1008910089 transition: opacity 0.2s linear !important;1009010090 }1009110091 }1009210092 1009310093 /* ─────────────────────────────────────────────────────────────────10094- Settings → Sync surface (v3 ChirpSync). Wraps the same bird10094+ Settings → Sync surface. Wraps the same bird1009510095 animation used by the pairing flow with a paired-devices list and1009610096 the "Pair a device" CTA.1009710097 ───────────────────────────────────────────────────────────────── */10098-.peach-chirp-settings {10098+.peach-pair-settings {1009910099 position: absolute;1010010100 inset: 0;1010110101 z-index: 3;@@ -10107,7 +10107,7 @@1010710107 box-sizing: border-box;1010810108 overflow-y: auto;1010910109 overflow-x: hidden;10110- /* Same warm Chirp surface as the pairing screen — unifies the two views. */10110+ /* Same warm surface as the pairing screen — unifies the two views. */1011110111 background:1011210112 radial-gradient(ellipse 70% 50% at 30% 0%, color-mix(in srgb, var(--peach-accent) 10%, transparent), transparent 70%),1011310113 var(--peach-bg);@@ -10116,10 +10116,10 @@1011610116 /* Hide native scrollbar — content fits 99% of the time and a chunky1011710117 gutter ruins the surface. */1011810118 scrollbar-width: none;10119- animation: peach-chirp-overlay-in 180ms cubic-bezier(0.4, 0, 0.2, 1) both;10119+ animation: peach-pair-overlay-in 180ms cubic-bezier(0.4, 0, 0.2, 1) both;1012010120 }10121-.peach-chirp-settings::-webkit-scrollbar { width: 0; height: 0; display: none; }10122-.peach-chirp-settings::before {10121+.peach-pair-settings::-webkit-scrollbar { width: 0; height: 0; display: none; }10122+.peach-pair-settings::before {1012310123 content: '';1012410124 position: absolute;1012510125 inset: 0;@@ -10127,23 +10127,23 @@1012710127 background: radial-gradient(ellipse 90% 30% at 50% 0%, color-mix(in srgb, var(--peach-accent) 6%, transparent), transparent 70%);1012810128 z-index: 0;1012910129 }10130-.peach-chirp-settings > * { position: relative; z-index: 1; }10130+.peach-pair-settings > * { position: relative; z-index: 1; }1013110131 10132-.peach-chirp-settings--pairing {10132+.peach-pair-settings--pairing {1013310133 padding: 0;1013410134 align-items: stretch;1013510135 justify-content: stretch;1013610136 background: none;1013710137 isolation: auto;1013810138 }10139-.peach-chirp-settings--pairing::before { display: none; }10139+.peach-pair-settings--pairing::before { display: none; }1014010140 10141-.peach-chirp-settings-header {10141+.peach-pair-settings-header {1014210142 display: flex;1014310143 align-items: center;1014410144 gap: 10px;1014510145 }10146-.peach-chirp-settings-title {10146+.peach-pair-settings-title {1014710147 margin: 0;1014810148 font-family: var(--font-display, Georgia, serif);1014910149 font-style: italic;@@ -10153,7 +10153,7 @@1015310153 color: var(--peach-t0);1015410154 letter-spacing: 0.005em;1015510155 }10156-.peach-chirp-settings-section {10156+.peach-pair-settings-section {1015710157 margin: 6px 0 -4px;1015810158 font-size: 11px;1015910159 font-weight: 600;@@ -10161,14 +10161,14 @@1016110161 text-transform: uppercase;1016210162 color: var(--peach-text-muted);1016310163 }10164-.peach-chirp-settings-error {10164+.peach-pair-settings-error {1016510165 font-size: 12px;1016610166 padding: 8px 10px;1016710167 border-radius: 8px;1016810168 background: color-mix(in srgb, var(--peach-danger, #c25b4a) 18%, transparent);1016910169 color: var(--peach-text);1017010170 }10171-.peach-chirp-settings-footer {10171+.peach-pair-settings-footer {1017210172 margin-top: auto;1017310173 padding-top: 18px;1017410174 font-size: 11.5px;@@ -10178,7 +10178,7 @@1017810178 }1017910179 1018010180 /* Hero card shown when no devices are paired yet. */10181-.peach-chirp-hero {10181+.peach-pair-hero {1018210182 display: flex;1018310183 flex-direction: column;1018410184 align-items: center;@@ -10186,12 +10186,12 @@1018610186 padding: 20px 12px 8px;1018710187 text-align: center;1018810188 }10189-.peach-chirp-hero-svg {10189+.peach-pair-hero-svg {1019010190 display: block;1019110191 max-width: 100%;1019210192 filter: drop-shadow(0 4px 12px color-mix(in srgb, var(--peach-accent) 25%, transparent));1019310193 }10194-.peach-chirp-hero-headline {10194+.peach-pair-hero-headline {1019510195 margin: 0;1019610196 font-family: var(--font-display, Georgia, serif);1019710197 font-style: italic;@@ -10201,7 +10201,7 @@1020110201 letter-spacing: 0.005em;1020210202 color: var(--peach-t0);1020310203 }10204-.peach-chirp-hero-sub {10204+.peach-pair-hero-sub {1020510205 margin: 0;1020610206 font-size: 13px;1020710207 line-height: 1.5;@@ -10210,25 +10210,25 @@1021010210 text-wrap: pretty;1021110211 }1021210212 10213-.peach-chirp-pair-cta {10213+.peach-pair-pair-cta {1021410214 display: flex;1021510215 justify-content: center;1021610216 padding: 4px 0 6px;1021710217 }10218-.peach-chirp-pair-button {10218+.peach-pair-pair-button {1021910219 display: inline-flex;1022010220 align-items: center;1022110221 gap: 8px;1022210222 min-width: 220px;1022310223 justify-content: center;1022410224 }10225-.peach-chirp-pair-button-icon {10225+.peach-pair-pair-button-icon {1022610226 flex: 0 0 auto;1022710227 }1022810228 1022910229 /* Paired devices list. Roomy rows that look at home next to the rest1023010230 of Settings; stale rows get a soft warm-warning border tint. */10231-.peach-chirp-device-list {10231+.peach-pair-device-list {1023210232 list-style: none;1023310233 margin: 0;1023410234 padding: 0;@@ -10236,7 +10236,7 @@1023610236 flex-direction: column;1023710237 gap: 8px;1023810238 }10239-.peach-chirp-device-row {10239+.peach-pair-device-row {1024010240 display: flex;1024110241 align-items: center;1024210242 gap: 12px;@@ -10245,10 +10245,10 @@1024510245 background: color-mix(in srgb, var(--peach-bg-elevated, var(--peach-bg)) 88%, var(--peach-accent) 12%);1024610246 border: 1px solid color-mix(in srgb, var(--peach-accent) 12%, transparent);1024710247 }10248-.peach-chirp-device-row[data-stale="true"] {10248+.peach-pair-device-row[data-stale="true"] {1024910249 border-color: color-mix(in srgb, var(--peach-warn, #d29257) 36%, transparent);1025010250 }10251-.peach-chirp-device-icon {10251+.peach-pair-device-icon {1025210252 width: 32px;1025310253 height: 32px;1025410254 display: flex;@@ -10258,14 +10258,14 @@1025810258 color: var(--peach-text);1025910259 background: color-mix(in srgb, var(--peach-accent) 18%, transparent);1026010260 }10261-.peach-chirp-device-info {10261+.peach-pair-device-info {1026210262 flex: 1;1026310263 display: flex;1026410264 flex-direction: column;1026510265 gap: 2px;1026610266 min-width: 0;1026710267 }10268-.peach-chirp-device-name {10268+.peach-pair-device-name {1026910269 font-size: 14px;1027010270 font-weight: 600;1027110271 color: var(--peach-text);@@ -10273,7 +10273,7 @@1027310273 text-overflow: ellipsis;1027410274 white-space: nowrap;1027510275 }10276-.peach-chirp-device-meta {10276+.peach-pair-device-meta {1027710277 font-size: 11.5px;1027810278 color: var(--peach-text-muted);1027910279 display: flex;@@ -10281,7 +10281,7 @@1028110281 align-items: center;1028210282 gap: 8px;1028310283 }10284-.peach-chirp-device-badge {10284+.peach-pair-device-badge {1028510285 font-size: 10.5px;1028610286 font-weight: 500;1028710287 letter-spacing: 0.02em;@@ -10290,26 +10290,26 @@1029010290 background: color-mix(in srgb, var(--peach-accent) 22%, transparent);1029110291 color: var(--peach-text);1029210292 }10293-.peach-chirp-device-stale {10293+.peach-pair-device-stale {1029410294 font-size: 10.5px;1029510295 font-weight: 500;1029610296 color: var(--peach-warn, #d29257);1029710297 }10298-.peach-chirp-device-remove {10298+.peach-pair-device-remove {1029910299 flex: 0 0 auto;1030010300 color: var(--peach-text-muted);1030110301 }10302-.peach-chirp-device-remove:hover {10302+.peach-pair-device-remove:hover {1030310303 color: var(--peach-danger, #c25b4a);1030410304 }10305-.peach-chirp-unpair-confirm {10305+.peach-pair-unpair-confirm {1030610306 display: flex;1030710307 gap: 6px;1030810308 align-items: center;1030910309 }1031010310 1031110311 /* Pro-gate card — soft upsell with the mobile bird perched, chirping. */10312-.peach-chirp-pro-card {10312+.peach-pair-pro-card {1031310313 position: relative;1031410314 margin: 18px 12px;1031510315 padding: 18px 20px 22px;@@ -10330,7 +10330,7 @@1033010330 text-align: center;1033110331 overflow: hidden;1033210332 }10333-.peach-chirp-pro-stage {10333+.peach-pair-pro-stage {1033410334 position: relative;1033510335 width: 220px;1033610336 height: 140px;@@ -10339,7 +10339,7 @@1033910339 justify-content: center;1034010340 margin-bottom: 2px;1034110341 }10342-.peach-chirp-pro-bird-slot {10342+.peach-pair-pro-bird-slot {1034310343 width: 140px;1034410344 height: 132px;1034510345 display: flex;@@ -10347,35 +10347,16 @@1034710347 justify-content: center;1034810348 filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.35));1034910349 }10350-.peach-chirp-pro-bird-slot .peach-chirp-bird {10350+.peach-pair-pro-bird-slot .peach-pair-bird {1035110351 width: 100%;1035210352 height: 100%;1035310353 }10354-.peach-chirp-pro-bird-slot .peach-chirp-bird svg {10354+.peach-pair-pro-bird-slot .peach-pair-bird svg {1035510355 width: 100%;1035610356 height: 100%;1035710357 overflow: visible;1035810358 }10359-.peach-chirp-pro-chirp {10360- position: absolute;10361- top: 14px;10362- right: 8px;10363- width: 96px;10364- height: 80px;10365- color: var(--peach-accent);10366- animation: peach-chirp-pulse 2.6s ease-in-out infinite;10367- transform-origin: 0% 50%;10368- pointer-events: none;10369-}10370-@keyframes peach-chirp-pulse {10371- 0%, 100% { opacity: 0.35; transform: translateX(0) scale(0.92); }10372- 45% { opacity: 1; transform: translateX(2px) scale(1); }10373- 70% { opacity: 0.6; transform: translateX(4px) scale(1.04); }10374-}10375-@media (prefers-reduced-motion: reduce) {10376- .peach-chirp-pro-chirp { animation: none; opacity: 0.7; }10377-}10378-.peach-chirp-pro-headline {10359+.peach-pair-pro-headline {1037910360 margin: 4px 0 0;1038010361 font-family: var(--font-display, "Cormorant Garamond", serif);1038110362 font-style: italic;@@ -10386,17 +10367,17 @@1038610367 max-width: 280px;1038710368 line-height: 1.25;1038810369 }10389-.peach-chirp-pro-body {10370+.peach-pair-pro-body {1039010371 margin: 0;1039110372 font-size: 13px;1039210373 line-height: 1.55;1039310374 color: var(--peach-t1);1039410375 max-width: 300px;1039510376 }10396-.peach-chirp-pro-cta {10377+.peach-pair-pro-cta {1039710378 margin-top: 4px;1039810379 }10399-.peach-chirp-pro-foot {10380+.peach-pair-pro-foot {1040010381 margin: 2px 0 0;1040110382 font-family: "IBM Plex Mono", "SFMono-Regular", Menlo, monospace;1040210383 font-size: 0.625rem;src/popup/views/PairDevice.test.tsx+1 −1
@@ -99,7 +99,7 @@9999 expect(input.getAttribute("inputmode")).toBeNull();100100 expect(input.getAttribute("maxlength")).toBe("32");101101 // birds always animate on the code screens (design correction)102- expect(container.querySelector(".peach-chirp-bird-desktop")).toBeTruthy();102+ expect(container.querySelector(".peach-pair-bird-desktop")).toBeTruthy();103103 });104104 105105 it("uppercases and regroups a pairing code as it is typed", () => {src/popup/views/PairDevice.tsx+23 −23
@@ -10,7 +10,7 @@1010 // so it is always the side that dials.1111 //1212 // The pairing itself runs in the background (code-pairing.ts) and reaches13-// this view via the PAIR_WITH_CODE / DESKTOP_PAIR_* messages.13+// this view via the PAIR_WITH_CODE / CODE_PAIR_* messages.1414 1515 import {1616 Component,@@ -86,7 +86,7 @@8686 export const PairDeviceView: Component<PairDeviceViewProps> = (props) => {8787 // The whole NK pairing runs in the background; this view drives the UI and8888 // the out-of-band SAS confirmation round-trip via the PAIR_WITH_CODE /89- // DESKTOP_PAIR_* messages. The SAS gate is what authenticates the peer89+ // CODE_PAIR_* messages. The SAS gate is what authenticates the peer9090 // (audit HIGH — pairing initiator authentication), not the pairing token.9191 const [phase, setPhase] = createSignal<PairPhase>("enter");9292 const [code, setCode] = createSignal("");@@ -209,11 +209,11 @@209209 210210 // The bird stage — always animating — shared by every pairing screen.211211 const birdStage = (active: boolean) => (212- <div class={`peach-chirp-stage ${active ? "act-handshake" : "act-listening"}`} aria-hidden="true">213- <div class="peach-chirp-bird-slot peach-chirp-bird-slot-desktop">212+ <div class={`peach-pair-stage ${active ? "act-handshake" : "act-listening"}`} aria-hidden="true">213+ <div class="peach-pair-bird-slot peach-pair-bird-slot-desktop">214214 <DesktopBird pose="chirping" />215215 </div>216- <div class="peach-chirp-bird-slot peach-chirp-bird-slot-mobile">216+ <div class="peach-pair-bird-slot peach-pair-bird-slot-mobile">217217 <MobileBird pose="attentive" />218218 </div>219219 </div>@@ -231,19 +231,19 @@231231 232232 // Code pairing — birds animate on every screen below.233233 const pairingScreen = () => (234- <div class="peach-chirp-pair peach-desktop-pair" data-phase={phase()} role="dialog" aria-label="Pair a device with a code">235- <header class="peach-chirp-head">236- <button class="peach-chirp-back" aria-label="Back" onClick={() => props.onBack()}>{backArrow}</button>237- <div class="peach-chirp-title">Enter a code</div>238- <div class="peach-chirp-head-spacer" />234+ <div class="peach-pair-pair peach-desktop-pair" data-phase={phase()} role="dialog" aria-label="Pair a device with a code">235+ <header class="peach-pair-head">236+ <button class="peach-pair-back" aria-label="Back" onClick={() => props.onBack()}>{backArrow}</button>237+ <div class="peach-pair-title">Enter a code</div>238+ <div class="peach-pair-head-spacer" />239239 </header>240240 241241 {birdStage(phase() !== "enter")}242242 243243 <Show when={phase() === "enter"}>244244 <div class="peach-desktop-enter">245- <div class="peach-chirp-headline">Enter the code from your phone</div>246- <div class="peach-chirp-sub">245+ <div class="peach-pair-headline">Enter the code from your phone</div>246+ <div class="peach-pair-sub">247247 Open Peach on your phone, tap “Pair a device”, and type the code it shows.248248 Both devices need to be on the same Wi-Fi.249249 </div>@@ -263,7 +263,7 @@263263 onInput={(e) => onCodeInput((e.target as HTMLInputElement).value)}264264 onKeyDown={(e) => { if (e.key === "Enter") void handleConnect(); }}265265 />266- <div class="peach-chirp-action">266+ <div class="peach-pair-action">267267 <button class="peach-btn peach-btn-ghost" onClick={() => props.onBack()}>Cancel</button>268268 <button269269 class="peach-btn peach-btn-primary peach-desktop-connect"@@ -278,21 +278,21 @@278278 279279 <Show when={phase() === "connecting"}>280280 <div class="peach-desktop-searching">281- <div class="peach-chirp-headline">Connecting…</div>282- <div class="peach-chirp-sub">Reaching your phone over the local network.</div>281+ <div class="peach-pair-headline">Connecting…</div>282+ <div class="peach-pair-sub">Reaching your phone over the local network.</div>283283 </div>284284 </Show>285285 286286 <Show when={phase() === "sas"}>287287 <div class="peach-desktop-confirm" style="display:flex;flex-direction:column;align-items:center;gap:12px;padding:8px 18px 16px;text-align:center;">288- <div class="peach-chirp-headline">Confirm this code matches on your phone:</div>288+ <div class="peach-pair-headline">Confirm this code matches on your phone:</div>289289 <div290290 class="peach-desktop-sas"291291 style="font-size:30px;font-weight:700;letter-spacing:0.32em;font-family:'IBM Plex Mono',monospace;color:var(--peach-accent);padding:6px 0 2px;"292292 >293293 {sas()}294294 </div>295- <div class="peach-chirp-sub" style="max-width:240px;">295+ <div class="peach-pair-sub" style="max-width:240px;">296296 Only continue if this 6-digit code is identical on both screens. This is297297 what proves you're talking to your own device.298298 </div>@@ -309,11 +309,11 @@309309 310310 <Show when={phase() === "paired"}>311311 <div class="peach-desktop-paired">312- <div class="peach-chirp-headline">Paired!</div>313- <div class="peach-chirp-sub">312+ <div class="peach-pair-headline">Paired!</div>313+ <div class="peach-pair-sub">314314 {pairedDevice()?.deviceName ? `Connected to ${pairedDevice()!.deviceName}` : "Connected to your phone"}315315 </div>316- <div class="peach-chirp-action">316+ <div class="peach-pair-action">317317 <button class="peach-btn peach-btn-primary" onClick={() => props.onBack()}>Done</button>318318 </div>319319 </div>@@ -321,9 +321,9 @@321321 322322 <Show when={phase() === "error"}>323323 <div class="peach-desktop-error">324- <div class="peach-chirp-headline">{errorCopy(errorKind()).headline}</div>325- <div class="peach-chirp-sub">{errorCopy(errorKind()).sub}</div>326- <div class="peach-chirp-action">324+ <div class="peach-pair-headline">{errorCopy(errorKind()).headline}</div>325+ <div class="peach-pair-sub">{errorCopy(errorKind()).sub}</div>326+ <div class="peach-pair-action">327327 <button class="peach-btn peach-btn-ghost" onClick={() => props.onBack()}>Cancel</button>328328 <button class="peach-btn peach-btn-primary" onClick={() => startFlow()}>Try again</button>329329 </div>src/popup/views/Settings.tsx+2 −2
@@ -297,14 +297,14 @@297297 298298 async function loadPairedDevices() {299299 if (!isPro()) return;300- const r = (await sendMessage({ type: "CHIRP_LIST_PAIRED_DEVICES" })) as {300+ const r = (await sendMessage({ type: "LIST_PAIRED_DEVICES" })) as {301301 ok: boolean;302302 data?: { devices: PairedDevice[] };303303 };304304 if (r.ok) setPairedDevices(r.data?.devices ?? []);305305 }306306 async function unpairDevice(deviceId: string) {307- await sendMessage({ type: "CHIRP_UNPAIR_DEVICE", payload: { deviceId } });307+ await sendMessage({ type: "UNPAIR_DEVICE", payload: { deviceId } });308308 setConfirmUnpair(null);309309 await loadPairedDevices();310310 }src/shared/types.ts+3 −3
@@ -300,9 +300,9 @@300300 | "GET_LOCAL_IDENTITY"301301 | "GET_ADOPTION_MATERIAL"302302 | "COMPLETE_PAIRING"303- | "CHIRP_LIST_PAIRED_DEVICES"304- | "CHIRP_UNPAIR_DEVICE"305- | "CHIRP_RENAME_LOCAL_DEVICE"303+ | "LIST_PAIRED_DEVICES"304+ | "UNPAIR_DEVICE"305+ | "RENAME_LOCAL_DEVICE"306306 // Code pairing. PAIR_WITH_CODE / CODE_PAIR_CONFIRM are popup→bg requests307307 // handled in the switch; CODE_PAIR_SAS / CODE_PAIR_RESULT are bg→popup pushes.308308 | "PAIR_WITH_CODE"