Files
curios/curios/harmony-connector/ui/style.css
T
render 6bdcfdb44e fix(harmony): discover devices and release disconnected sessions asynchronously
Use USB descriptors and MTP identity instead of the static libmtp product label. Monitor attachment, discard stale UI responses, clear disconnected views, and release slow MTP sessions in the background while preserving operation serialization.

Publish 0.1.1 with immutable source history. Cover discovery, names, unplugging and slow disconnect with native and UI regressions. Verify real Pura 70 Ultra identity and prompt disconnect; run the newest published backend during Git-source checks.
2026-09-10 10:57:10 +08:00

814 lines
13 KiB
CSS

:root {
font-family:
-apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", sans-serif;
color: #222c3c;
background: #f8f9fc;
font-size: 13px;
font-synthesis: none;
-webkit-font-smoothing: antialiased;
--bg: #fff;
--ink: #222c3c;
--muted: #7b8596;
--line: #e9edf3;
--blue: #4269e2;
--soft: #eef2fd;
--side: #f3f5fa;
--hover: #f6f8fd;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
button,
input,
select {
font: inherit;
}
button {
cursor: pointer;
min-height: 40px;
border: 0;
border-radius: 10px;
padding: 0 14px;
color: inherit;
background: transparent;
transition:
background 0.15s,
transform 0.15s,
opacity 0.15s;
}
button:active:not(:disabled) {
transform: scale(0.97);
}
button:disabled {
cursor: default;
opacity: 0.42;
}
button:focus-visible,
input:focus-visible,
select:focus-visible {
outline: 3px solid #8ba6ff;
outline-offset: 2px;
}
button:hover:not(:disabled) {
background: var(--soft);
}
[hidden] {
display: none !important;
}
.primary {
background: var(--blue);
color: white;
box-shadow: 0 3px 7px #4269e21a;
}
.primary:hover:not(:disabled) {
background: #345bd1;
}
.secondary {
background: var(--bg);
border: 1px solid var(--line);
box-shadow: 0 2px 3px #15213a03;
}
.subtle {
color: var(--muted);
font-size: 12px;
}
.text-button {
color: var(--blue);
padding: 0;
font-size: 12px;
}
.app {
display: flex;
min-height: 100dvh;
}
.sidebar {
width: 232px;
flex-shrink: 0;
background: var(--side);
border-right: 1px solid var(--line);
padding: 34px 22px 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 32px;
}
.brand-mark {
background: linear-gradient(140deg, #7392fb, #3f61d7);
color: #fff;
width: 44px;
height: 44px;
display: grid;
place-items: center;
border-radius: 14px;
font-size: 29px;
box-shadow: 0 4px 10px #4163d722;
}
.brand strong {
font-size: 17px;
letter-spacing: -0.45px;
line-height: 1.12;
}
.brand span {
display: block;
color: var(--muted);
font-size: 10px;
margin-top: 6px;
letter-spacing: 1px;
}
.section-label {
font-size: 10px;
color: var(--muted);
letter-spacing: 1.4px;
font-weight: 600;
margin: 8px 8px;
}
.device-card {
display: flex;
align-items: center;
gap: 10px;
background: var(--bg);
padding: 14px 12px;
border-radius: 13px;
box-shadow: 0 2px 8px #25305305;
}
.device-card > div {
min-width: 0;
flex: 1;
}
.device-card strong {
display: block;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.device-card span:not(.device-icon) {
display: block;
color: var(--muted);
font-size: 10px;
margin-top: 5px;
}
.device-icon {
font-size: 30px;
line-height: 1;
color: var(--blue);
}
#device-model {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.device-card i,
.status-dot {
width: 6px;
height: 6px;
border-radius: 100%;
display: inline-block;
background: #b5bfcd;
}
.device-card i.connected,
.status-dot {
background: #70b496;
}
.storage-label {
margin-top: 28px;
}
#storages .muted {
font-size: 11px;
margin: 5px 8px;
}
#storages button {
text-align: left;
width: 100%;
padding: 12px;
margin-bottom: 4px;
}
#storages button.active {
background: #e6ecfc;
color: var(--blue);
}
.storage-title {
display: block;
font-weight: 600;
font-size: 12px;
}
.storage-capacity {
display: block;
font-size: 10px;
margin-top: 7px;
color: var(--muted);
}
.sidebar-bottom {
margin-top: auto;
padding-top: 50px;
}
.small-badge {
display: inline-block;
background: var(--soft);
color: var(--blue);
font-size: 10px;
letter-spacing: 0.8px;
padding: 6px 9px;
border-radius: 6px;
font-weight: 600;
}
.sidebar-bottom p {
font-size: 11px;
color: var(--muted);
line-height: 1.9;
margin: 15px 0 6px;
}
main {
display: flex;
flex-direction: column;
flex: 1;
min-width: 0;
min-height: 100dvh;
background: var(--bg);
}
.topbar {
padding: 32px 36px 25px;
display: flex;
justify-content: space-between;
align-items: center;
gap: 16px;
border-bottom: 1px solid var(--line);
}
.eyebrow {
font-size: 9px;
letter-spacing: 1.8px;
color: var(--muted);
margin: 0 0 9px;
}
h1 {
font-size: 21px;
margin: 0;
font-weight: 600;
letter-spacing: -0.5px;
}
h2 {
text-wrap: balance;
}
p {
line-height: 1.7;
}
.muted {
color: var(--muted);
font-size: 12px;
}
.welcome {
margin: auto;
padding: 36px 24px 22px;
text-align: center;
width: 100%;
max-width: 620px;
}
.welcome h2 {
font-size: 34px;
letter-spacing: -1px;
line-height: 1.45;
font-weight: 600;
margin: 18px 0 12px;
}
.intro {
color: var(--muted);
font-size: 13px;
margin: 0 0 26px;
}
.connection-art {
display: flex;
align-items: center;
justify-content: center;
height: 110px;
margin: 0 0 24px;
gap: 18px;
}
.mac {
width: 123px;
position: relative;
}
.mac > div {
height: 78px;
border: 3px solid #acbde5;
background: linear-gradient(140deg, #f1f5ff, #e4ebfc);
border-radius: 9px;
display: grid;
place-items: center;
box-shadow: 0 6px 20px #466cd014;
}
.mac span {
font-size: 31px;
color: #8aa5ed;
}
.mac > i {
display: block;
height: 5px;
background: #b6c5e8;
margin: 4px -10px 0;
border-radius: 2px 2px 6px 6px;
}
.phone {
width: 45px;
height: 87px;
border: 3px solid #7998e6;
background: linear-gradient(150deg, #eef3ff, #d7e3ff);
border-radius: 11px;
position: relative;
display: grid;
place-items: center;
transform: rotate(6deg);
box-shadow: 0 7px 17px #466cd019;
}
.phone > span {
position: absolute;
top: 4px;
background: #91abeb;
width: 12px;
height: 3px;
border-radius: 3px;
}
.phone > b {
font-size: 24px;
color: #7394e4;
font-weight: 400;
}
.phone > i {
position: absolute;
bottom: 4px;
width: 16px;
height: 2px;
background: #92aaea;
border-radius: 2px;
}
.connection-line {
display: flex;
gap: 7px;
}
.connection-line i {
width: 4px;
height: 4px;
border-radius: 50%;
background: #b2c2e7;
}
.steps {
list-style: none;
display: grid;
gap: 12px;
padding: 0;
margin: 0 auto 23px;
width: max-content;
max-width: 100%;
text-align: left;
color: #64718a;
font-size: 12px;
}
.steps li {
display: flex;
gap: 10px;
align-items: center;
}
.steps b {
background: var(--side);
font-size: 10px;
font-weight: 500;
width: 21px;
height: 21px;
display: grid;
place-items: center;
border-radius: 50%;
color: var(--muted);
}
#device-picker {
background: var(--side);
padding: 14px;
border-radius: 13px;
max-width: 370px;
margin: 20px auto;
text-align: left;
}
label {
font-size: 12px;
}
.device-picker-row {
display: flex;
gap: 8px;
margin-top: 9px;
}
select,
input:not([type="search"]) {
height: 42px;
background: var(--bg);
color: var(--ink);
border: 1px solid var(--line);
border-radius: 8px;
padding: 0 11px;
min-width: 0;
}
select {
flex: 1;
}
#scan-status {
font-size: 11px;
min-height: 20px;
}
.notice {
display: flex;
align-items: center;
justify-content: space-between;
background: #fff6e8;
color: #8a5b23;
border: 1px solid #f8e3c2;
border-radius: 10px;
padding: 5px 8px 5px 16px;
margin: 16px 28px 0;
font-size: 12px;
gap: 8px;
line-height: 1.7;
}
.notice button {
font-size: 22px;
}
.browser {
padding: 24px 28px 0;
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
}
.toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
flex-wrap: wrap;
}
.actions {
display: flex;
gap: 7px;
}
#breadcrumbs {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 2px;
min-width: 0;
max-width: 100%;
font-size: 12px;
}
#breadcrumbs button {
padding: 0 8px;
max-width: 170px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
#breadcrumbs span {
color: #bbc3d1;
}
.list-heading {
display: flex;
align-items: center;
justify-content: space-between;
gap: 15px;
margin: 22px 0 14px;
}
.search {
display: flex;
align-items: center;
gap: 8px;
color: var(--muted);
border-radius: 9px;
background: var(--side);
padding: 0 12px;
height: 36px;
max-width: 270px;
flex: 1;
}
.search span {
font-size: 24px;
}
.search input {
border: 0;
background: transparent;
outline: none;
min-width: 0;
color: var(--ink);
font-size: 12px;
width: 100%;
}
.file-table-wrap {
border: 1px solid var(--line);
border-radius: 12px;
overflow: auto;
max-height: calc(100dvh - 330px);
min-height: 200px;
flex: 1;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th {
background: var(--hover);
text-align: left;
color: var(--muted);
font-size: 10px;
font-weight: 500;
height: 34px;
position: sticky;
top: 0;
z-index: 1;
}
th:first-child {
width: auto;
padding-left: 17px;
}
th:nth-child(2) {
width: 82px;
}
th:nth-child(3) {
width: 116px;
}
th:last-child {
width: 68px;
}
td {
height: 52px;
border-top: 1px solid var(--line);
font-size: 11px;
color: var(--muted);
font-variant-numeric: tabular-nums;
padding-right: 8px;
}
td:first-child {
padding-left: 10px;
color: var(--ink);
}
tbody tr:hover {
background: var(--hover);
}
.entry-name {
display: flex;
align-items: center;
gap: 10px;
width: 100%;
text-align: left;
padding: 0 7px;
overflow: hidden;
font-size: 12px;
}
.entry-name span:last-child {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.file-icon {
color: #99a8c8;
flex-shrink: 0;
display: grid;
place-items: center;
width: 22px;
height: 28px;
}
.file-icon.folder {
color: #d6aa59;
}
.download-button {
padding: 0 8px;
color: var(--blue);
font-size: 11px;
}
.empty {
text-align: center;
padding: 54px 20px;
color: var(--muted);
font-size: 12px;
}
.load-more {
display: block;
margin: 14px auto;
}
.browser-footnote {
font-size: 10px;
color: var(--muted);
margin: 13px 0 18px;
}
.transfer {
margin: 0 28px 18px;
background: var(--soft);
padding: 16px 18px;
border-radius: 12px;
}
.transfer-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.transfer strong {
font-size: 12px;
}
.transfer p {
font-size: 11px;
color: var(--muted);
margin: 6px 0 0;
overflow-wrap: anywhere;
font-variant-numeric: tabular-nums;
}
progress {
appearance: none;
width: 100%;
height: 4px;
display: block;
margin-top: 13px;
border: 0;
border-radius: 6px;
background: #dce4fa;
overflow: hidden;
}
progress::-webkit-progress-bar {
background: #dce4fa;
}
progress::-webkit-progress-value {
background: var(--blue);
border-radius: 6px;
}
progress::-moz-progress-bar {
background: var(--blue);
}
footer {
display: flex;
justify-content: space-between;
color: var(--muted);
font-size: 10px;
padding: 14px 28px;
border-top: 1px solid var(--line);
gap: 12px;
}
footer span:first-child {
display: flex;
gap: 6px;
align-items: center;
}
dialog {
color: var(--ink);
background: var(--bg);
border: 1px solid var(--line);
border-radius: 18px;
padding: 26px;
max-width: 520px;
width: calc(100% - 48px);
box-shadow: 0 20px 70px #13204422;
max-height: 85dvh;
}
dialog::backdrop {
background: #13204444;
backdrop-filter: blur(3px);
}
dialog h2 {
font-size: 20px;
margin: 0 0 16px;
}
dialog h3 {
font-size: 13px;
margin: 22px 0 6px;
}
dialog p,
dialog li {
font-size: 12px;
color: var(--muted);
line-height: 1.9;
}
dialog ol {
padding-left: 18px;
}
dialog li {
margin: 9px 0;
}
.dialog-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.dialog-header button {
font-size: 24px;
min-width: 40px;
}
.dialog-header h2 {
margin: 0;
}
#folder-dialog {
max-width: 380px;
}
#folder-name {
display: block;
width: 100%;
margin-top: 10px;
}
.field-error {
color: #bd4d41;
font-size: 12px;
min-height: 20px;
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 9px;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
}
@media (max-width: 850px) {
.sidebar {
width: 195px;
padding: 26px 16px 16px;
}
.topbar {
padding: 26px;
}
.browser {
padding: 20px;
}
.actions button {
padding: 0 10px;
}
.toolbar {
align-items: flex-start;
}
.welcome h2 {
font-size: 29px;
}
th:nth-child(3),
td:nth-child(3) {
display: none;
}
.transfer {
margin: 0 20px 16px;
}
.brand strong {
font-size: 16px;
}
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #20252e;
--ink: #e6eaf3;
--muted: #98a3b6;
--line: #333b49;
--blue: #92abff;
--soft: #2e3a56;
--side: #1a1f28;
--hover: #262e3b;
color: var(--ink);
background: var(--bg);
}
.primary {
background: #4e73ea;
color: white;
}
#storages button.active {
background: #2e3a56;
}
.steps {
color: #a5b3ca;
}
.notice {
background: #3c3223;
border-color: #57472e;
color: #edc594;
}
.mac > div {
background: linear-gradient(140deg, #293e65, #3a527c);
}
.phone {
background: linear-gradient(150deg, #374e7b, #273b63);
}
.brand-mark {
color: #fff;
}
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
transition: none !important;
}
button:active:not(:disabled) {
transform: none;
}
}