diff --git a/webapp/src/components/LoadingSkeleton.tsx b/webapp/src/components/LoadingSkeleton.tsx new file mode 100644 index 0000000..a63d6f9 --- /dev/null +++ b/webapp/src/components/LoadingSkeleton.tsx @@ -0,0 +1,40 @@ +export function CardSkeleton() { + return ( +
+
+
+
+
+
+
+ ); +} + +export function ListSkeleton({ count = 5 }: { count?: number }) { + return ( + <> + {Array.from({ length: count }).map((_, i) => ( +
+
+
+
+
+
+
+ ))} + + ); +} + +export function PageSkeleton() { + return ( +
+
+
+
+
+ +
+
+ ); +} diff --git a/webapp/src/styles.css b/webapp/src/styles.css index 2acd6bd..3dd0475 100644 --- a/webapp/src/styles.css +++ b/webapp/src/styles.css @@ -7,6 +7,7 @@ @import './styles/management.css'; @import './styles/overlays.css'; @import './styles/motion.css'; +@import './styles/skeleton.css'; @import './styles/responsive.css'; @import './styles/dark.css'; diff --git a/webapp/src/styles/base.css b/webapp/src/styles/base.css index 09e6195..ee7654d 100644 --- a/webapp/src/styles/base.css +++ b/webapp/src/styles/base.css @@ -8,7 +8,14 @@ body, @apply m-0 h-full w-full p-0; color: var(--text); background: var(--bg-accent); - font-family: 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans SC', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', 'Noto Sans SC', sans-serif; + font-size: var(--font-base); + line-height: var(--leading-normal); + letter-spacing: var(--tracking-normal); + font-feature-settings: 'liga' 1, 'kern' 1; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } html { @@ -16,7 +23,7 @@ html { } body { - @apply relative antialiased; + @apply relative; transition: background-color var(--dur-medium) var(--ease-smooth), color var(--dur-medium) var(--ease-smooth); } @@ -25,6 +32,28 @@ body.dialog-open { overscroll-behavior: contain; } +h1, h2, h3, h4, h5, h6 { + font-weight: 600; + letter-spacing: var(--tracking-tight); + line-height: var(--leading-tight); + margin: 0; +} + +h1 { font-size: var(--font-4xl); } +h2 { font-size: var(--font-3xl); } +h3 { font-size: var(--font-xl); } +h4 { font-size: var(--font-lg); } + +p { + margin: 0; + line-height: var(--leading-relaxed); +} + +small { + font-size: var(--font-sm); + line-height: var(--leading-snug); +} + ::selection { background: color-mix(in srgb, var(--primary) 20%, transparent); color: var(--text); diff --git a/webapp/src/styles/forms.css b/webapp/src/styles/forms.css index 5ca2cf6..3f09d1a 100644 --- a/webapp/src/styles/forms.css +++ b/webapp/src/styles/forms.css @@ -1,20 +1,33 @@ .muted { - @apply m-0 mb-4 text-center leading-relaxed text-muted; + @apply m-0 mb-4 text-center text-muted; + font-size: var(--font-sm); + line-height: var(--leading-relaxed); + letter-spacing: var(--tracking-normal); } .field { - @apply mb-3.5 block; + @apply mb-4 block; } .field > span { - @apply mb-2 mt-2.5 block text-sm font-semibold; + @apply mb-2 block; + font-size: var(--font-sm); + font-weight: 600; + letter-spacing: var(--tracking-wide); + color: var(--muted-strong); + line-height: var(--leading-snug); } .input { - @apply h-12 w-full rounded-xl border px-3.5 py-2.5 text-base leading-normal text-ink outline-none transition; + @apply h-12 w-full rounded-xl border px-3.5 py-2.5 outline-none; background: var(--panel); border-color: rgba(74, 103, 150, 0.34); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.82); + transition: all var(--dur-fast) var(--ease-smooth); + font-size: var(--font-base); + line-height: var(--leading-snug); + letter-spacing: var(--tracking-normal); + color: var(--text); } select.input { @@ -54,9 +67,10 @@ input[type='file'].input::file-selector-button:hover { } .input:focus { - border-color: rgba(43, 102, 217, 0.6); + border-color: var(--primary); background-color: #fbfdff; - box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.10), 0 8px 18px rgba(37, 99, 235, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.95); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12), 0 8px 20px rgba(37, 99, 235, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.95); + transform: translateY(-1px); } .input-readonly { @@ -115,7 +129,12 @@ input[type='file'].input::file-selector-button:hover { } .btn { - @apply inline-flex h-9 cursor-pointer items-center justify-center gap-1.5 rounded-full border border-transparent px-4 text-[15px] font-bold no-underline transition; + @apply inline-flex h-9 cursor-pointer items-center justify-center gap-1.5 rounded-full border border-transparent px-4 no-underline; + font-size: var(--font-sm); + font-weight: 600; + letter-spacing: var(--tracking-wide); + line-height: 1; + transition: all var(--dur-fast) var(--ease-smooth); } .topbar-actions .btn, @@ -161,28 +180,53 @@ input[type='file'].input::file-selector-button:hover { } .btn.full { - @apply my-2.5 h-12 w-full text-lg; + @apply my-2.5 h-12 w-full; + font-size: var(--font-md); + font-weight: 600; } .btn-primary { - @apply border-blue-700/30 bg-blue-600 text-white; - box-shadow: 0 10px 22px rgba(37, 99, 235, 0.20); + @apply text-white; + background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%); + border: 1px solid rgba(37, 99, 235, 0.4); + box-shadow: 0 4px 14px rgba(37, 99, 235, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.2); + position: relative; + overflow: hidden; +} + +.btn-primary::before { + content: ''; + position: absolute; + inset: 0; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, transparent 50%); + opacity: 0; + transition: opacity var(--dur-fast) var(--ease-smooth); } .btn-primary:hover { - @apply bg-blue-700; - box-shadow: 0 12px 26px rgba(37, 99, 235, 0.22); + background: linear-gradient(135deg, #1d4ed8 0%, #1e3a8a 100%); + box-shadow: 0 6px 20px rgba(37, 99, 235, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.25); + transform: translateY(-2px); +} + +.btn-primary:hover::before { + opacity: 1; +} + +.btn-primary:active:not(:disabled) { + transform: translateY(0) scale(0.98); } .btn-secondary { @apply bg-panel text-brand-strong; - border-color: rgba(37, 99, 235, 0.20); - box-shadow: 0 6px 14px rgba(13, 31, 68, 0.04); + border: 1px solid rgba(37, 99, 235, 0.22); + box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.8); } .btn-secondary:hover { - background: #f4f8ff; - border-color: rgba(37, 99, 235, 0.34); + background: linear-gradient(180deg, #ffffff 0%, #f8fafc 100%); + border-color: rgba(37, 99, 235, 0.40); + box-shadow: 0 4px 12px rgba(37, 99, 235, 0.15), inset 0 1px 0 rgba(255, 255, 255, 1); } .btn-danger { @@ -200,11 +244,21 @@ input[type='file'].input::file-selector-button:hover { } .or { - @apply text-center text-slate-700; + @apply text-center; + font-size: var(--font-sm); + color: var(--muted); + line-height: var(--leading-snug); + letter-spacing: var(--tracking-wide); + text-transform: uppercase; + font-weight: 600; } .field-help { - @apply mt-2 text-[13px] leading-normal text-slate-500; + @apply mt-2; + font-size: var(--font-xs); + line-height: var(--leading-relaxed); + letter-spacing: var(--tracking-normal); + color: var(--muted); } .check-line-compact { @@ -216,14 +270,21 @@ input[type='file'].input::file-selector-button:hover { } .auth-link-btn { - @apply cursor-pointer border-0 bg-transparent p-0 text-[13px] font-bold text-blue-700 transition; + @apply cursor-pointer border-0 bg-transparent p-0 transition; + font-size: var(--font-xs); + font-weight: 600; + letter-spacing: var(--tracking-wide); + color: var(--primary-strong); + line-height: var(--leading-snug); } .auth-link-btn:hover { text-decoration: underline; + text-underline-offset: 2px; transform: translateX(2px); } .auth-link-btn:disabled { - @apply cursor-not-allowed text-slate-400 no-underline; + @apply cursor-not-allowed no-underline; + color: var(--muted); } diff --git a/webapp/src/styles/motion.css b/webapp/src/styles/motion.css index 2d15735..3471e17 100644 --- a/webapp/src/styles/motion.css +++ b/webapp/src/styles/motion.css @@ -64,6 +64,26 @@ to { opacity: 1; transform: translateY(0); } } +@keyframes shimmer { + 0% { background-position: -200% center; } + 100% { background-position: 200% center; } +} + +@keyframes pulse-glow { + 0%, 100% { box-shadow: 0 0 20px rgba(37, 99, 235, 0.3); } + 50% { box-shadow: 0 0 30px rgba(37, 99, 235, 0.5), 0 0 40px rgba(37, 99, 235, 0.2); } +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +@keyframes skeleton-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } +} + @media (prefers-reduced-motion: reduce) { *, *::before, diff --git a/webapp/src/styles/shell.css b/webapp/src/styles/shell.css index 27f1963..71f92a1 100644 --- a/webapp/src/styles/shell.css +++ b/webapp/src/styles/shell.css @@ -3,10 +3,15 @@ } .app-shell { - @apply relative mx-auto flex max-w-[1600px] flex-col overflow-hidden border bg-panel-soft shadow-elevated; + @apply relative mx-auto flex max-w-[1600px] flex-col overflow-hidden border bg-panel-soft; height: calc(100vh - 40px); border-color: var(--line); @apply rounded-3xl; + box-shadow: + 0 20px 60px rgba(15, 23, 42, 0.12), + 0 8px 24px rgba(15, 23, 42, 0.08), + 0 0 0 1px rgba(15, 23, 42, 0.04); + transition: box-shadow var(--dur-medium) var(--ease-smooth); } .topbar { @@ -104,7 +109,7 @@ } .theme-switch-slider::before { - @apply absolute h-[26px] w-[26px] rounded-full; + @apply absolute h-[23px] w-[26px] rounded-full; content: ''; left: 2px; bottom: 2px; @@ -119,8 +124,8 @@ .theme-switch .sun svg { @apply absolute h-[18px] w-[18px]; - top: 6px; - left: 32px; + top: 5px; + left: 29px; z-index: 1; opacity: 0.95; transition: transform var(--dur-medium) var(--ease-out-soft), opacity var(--dur-fast) var(--ease-smooth); @@ -193,7 +198,13 @@ } .side-link { - @apply flex items-center gap-2.5 rounded-xl border border-transparent px-3 py-2.5 text-sm font-semibold text-muted-strong no-underline transition; + @apply flex items-center rounded-xl border border-transparent px-3 py-2.5 no-underline transition; + gap: var(--space-2); + font-size: var(--font-sm); + font-weight: 500; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-normal); + color: var(--muted-strong); } .side-link span, @@ -213,24 +224,33 @@ } .side-group-trigger { - @apply flex w-full cursor-pointer items-center gap-2.5 rounded-xl border border-transparent px-3 py-2.5 text-left text-sm font-semibold text-muted-strong transition; + @apply flex w-full cursor-pointer items-center rounded-xl border border-transparent px-3 py-2.5 text-left transition; + gap: var(--space-2); background: transparent; + font-size: var(--font-sm); + font-weight: 500; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-normal); + color: var(--muted-strong); } .side-link:hover, .side-group-trigger:hover { - background: #fff; - border-color: rgba(128, 152, 192, 0.18); + background: linear-gradient(135deg, #ffffff 0%, #fafbfc 100%); + border-color: rgba(128, 152, 192, 0.20); color: var(--text); - box-shadow: 0 10px 18px rgba(15, 23, 42, 0.04); + box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06), inset 0 1px 0 rgba(255, 255, 255, 1); + transform: translateX(2px); } .side-link.active, .side-group-trigger.active { - background: rgba(37, 99, 235, 0.11); - border-color: rgba(37, 99, 235, 0.28); + background: linear-gradient(135deg, rgba(37, 99, 235, 0.12) 0%, rgba(37, 99, 235, 0.08) 100%); + border-color: rgba(37, 99, 235, 0.32); color: var(--primary-strong); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.58); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.5), + 0 2px 8px rgba(37, 99, 235, 0.15); } .side-group-chevron { @@ -264,7 +284,13 @@ } .side-sub-link { - @apply flex items-center gap-2 rounded-lg border border-transparent px-2.5 py-2 text-sm font-semibold text-muted no-underline transition; + @apply flex items-center rounded-lg border border-transparent px-2.5 py-2 no-underline transition; + gap: var(--space-2); + font-size: var(--font-sm); + font-weight: 500; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-normal); + color: var(--muted); } .side-sub-link:hover { diff --git a/webapp/src/styles/skeleton.css b/webapp/src/styles/skeleton.css new file mode 100644 index 0000000..253346f --- /dev/null +++ b/webapp/src/styles/skeleton.css @@ -0,0 +1,75 @@ +.skeleton-card, +.skeleton-list-item { + @apply flex items-center gap-3 rounded-xl border p-4; + background: var(--panel); + border-color: var(--line-soft); + animation: skeleton-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; +} + +.skeleton-avatar { + @apply h-12 w-12 shrink-0 rounded-full; + background: linear-gradient( + 90deg, + var(--panel-muted) 0%, + var(--panel-soft) 50%, + var(--panel-muted) 100% + ); + background-size: 200% 100%; + animation: shimmer 1.5s ease-in-out infinite; +} + +.skeleton-icon { + @apply h-10 w-10 shrink-0 rounded-lg; + background: linear-gradient( + 90deg, + var(--panel-muted) 0%, + var(--panel-soft) 50%, + var(--panel-muted) 100% + ); + background-size: 200% 100%; + animation: shimmer 1.5s ease-in-out infinite; +} + +.skeleton-content { + @apply min-w-0 flex-1 space-y-2; +} + +.skeleton-line { + @apply h-3 rounded-full; + background: linear-gradient( + 90deg, + var(--panel-muted) 0%, + var(--panel-soft) 50%, + var(--panel-muted) 100% + ); + background-size: 200% 100%; + animation: shimmer 1.5s ease-in-out infinite; +} + +.skeleton-line-sm { + @apply w-1/3; +} + +.skeleton-line-md { + @apply w-2/3; +} + +.skeleton-line-lg { + @apply w-4/5; +} + +.skeleton-line-xl { + @apply w-full; +} + +.skeleton-page { + @apply h-full space-y-4 p-4; +} + +.skeleton-header { + @apply mb-6; +} + +.skeleton-body { + @apply space-y-3; +} diff --git a/webapp/src/styles/tokens.css b/webapp/src/styles/tokens.css index b16cad4..0192700 100644 --- a/webapp/src/styles/tokens.css +++ b/webapp/src/styles/tokens.css @@ -7,66 +7,108 @@ --surface: #ffffff; --line: rgba(100, 116, 139, 0.24); --line-soft: rgba(100, 116, 139, 0.14); - --text: #111827; + --text: #0f172a; --text-muted: #64748b; --muted: #64748b; --muted-strong: #334155; - --primary: #2457c5; - --primary-hover: #1d4aa7; - --primary-strong: #173f8f; + --primary: #2563eb; + --primary-hover: #1d4ed8; + --primary-strong: #1e40af; --brand: var(--primary); --brand-strong: var(--primary-strong); - --accent: #0f766e; + --accent: #0d9488; --accent-soft: #e6f6f3; - --danger: #c92f4e; - --success: #0f766e; - --warning: #b7791f; - --overlay-strong: rgba(15, 23, 42, 0.58); - --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.045); - --shadow-md: 0 8px 18px rgba(15, 23, 42, 0.075); - --shadow-lg: 0 18px 44px rgba(15, 23, 42, 0.105); + --danger: #dc2626; + --success: #059669; + --warning: #d97706; + --overlay-strong: rgba(15, 23, 42, 0.62); + --shadow-sm: 0 1px 3px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04); + --shadow-md: 0 4px 6px -1px rgba(15, 23, 42, 0.08), 0 2px 4px -1px rgba(15, 23, 42, 0.05); + --shadow-lg: 0 20px 25px -5px rgba(15, 23, 42, 0.10), 0 10px 10px -5px rgba(15, 23, 42, 0.04); + --shadow-xl: 0 25px 50px -12px rgba(15, 23, 42, 0.25); + --shadow-glow: 0 0 20px rgba(37, 99, 235, 0.15), 0 8px 24px rgba(37, 99, 235, 0.12); --radius-sm: 6px; --radius-md: 8px; --radius-lg: 10px; --radius-xl: 14px; + --radius-2xl: 18px; --ease-out-strong: cubic-bezier(0.22, 1, 0.36, 1); --ease-out-soft: cubic-bezier(0.24, 0.8, 0.32, 1); --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1); --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); + --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55); --dur-instant: 80ms; --dur-quick: 120ms; --dur-fast: 180ms; --dur-medium: 240ms; --dur-panel: 280ms; + --dur-slow: 350ms; --actions-gap: clamp(5px, calc((100vw - 520px) * 1), 10px); + + /* Typography Scale */ + --font-xs: 11px; + --font-sm: 13px; + --font-base: 14px; + --font-md: 15px; + --font-lg: 16px; + --font-xl: 18px; + --font-2xl: 20px; + --font-3xl: 24px; + --font-4xl: 28px; + + /* Line Heights */ + --leading-tight: 1.25; + --leading-snug: 1.375; + --leading-normal: 1.5; + --leading-relaxed: 1.625; + --leading-loose: 1.75; + + /* Letter Spacing */ + --tracking-tighter: -0.02em; + --tracking-tight: -0.01em; + --tracking-normal: 0; + --tracking-wide: 0.01em; + --tracking-wider: 0.02em; + + /* Spacing Scale */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --space-8: 32px; + --space-10: 40px; } :root[data-theme='dark'] { - --bg-accent: #101418; - --panel: #171d25; - --panel-soft: #131922; - --panel-muted: #0f151d; - --panel-subtle: #1c2430; - --surface: #171d25; - --line: rgba(148, 163, 184, 0.18); - --line-soft: rgba(148, 163, 184, 0.11); - --text: #e8edf4; - --text-muted: #9aa8ba; - --muted: #9aa8ba; - --muted-strong: #c4cfdc; - --primary: #80b6ff; - --primary-hover: #a6cbff; - --primary-strong: #d7e8ff; + --bg-accent: #0a0e13; + --panel: #151b24; + --panel-soft: #111720; + --panel-muted: #0d1219; + --panel-subtle: #1a2230; + --surface: #151b24; + --line: rgba(148, 163, 184, 0.16); + --line-soft: rgba(148, 163, 184, 0.09); + --text: #f1f5f9; + --text-muted: #94a3b8; + --muted: #94a3b8; + --muted-strong: #cbd5e1; + --primary: #60a5fa; + --primary-hover: #93c5fd; + --primary-strong: #bfdbfe; --brand: var(--primary); --brand-strong: var(--primary-strong); - --accent: #5eead4; - --accent-soft: rgba(94, 234, 212, 0.12); - --danger: #fb7185; - --success: #5eead4; + --accent: #2dd4bf; + --accent-soft: rgba(45, 212, 191, 0.12); + --danger: #f87171; + --success: #34d399; --warning: #fbbf24; - --overlay-strong: rgba(2, 6, 23, 0.74); - --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.26); - --shadow-md: 0 8px 24px rgba(0, 0, 0, 0.30); - --shadow-lg: 0 14px 38px rgba(0, 0, 0, 0.34); + --overlay-strong: rgba(0, 0, 0, 0.75); + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.45), 0 2px 4px -1px rgba(0, 0, 0, 0.35); + --shadow-lg: 0 20px 25px -5px rgba(0, 0, 0, 0.50), 0 10px 10px -5px rgba(0, 0, 0, 0.40); + --shadow-xl: 0 25px 50px -12px rgba(0, 0, 0, 0.60); + --shadow-glow: 0 0 20px rgba(96, 165, 250, 0.20), 0 8px 24px rgba(96, 165, 250, 0.15); } diff --git a/webapp/src/styles/vault.css b/webapp/src/styles/vault.css index 57c779c..7d14c28 100644 --- a/webapp/src/styles/vault.css +++ b/webapp/src/styles/vault.css @@ -21,7 +21,13 @@ } .sidebar-title { - @apply mb-2 text-[13px] font-bold text-slate-700; + @apply mb-2; + font-size: var(--font-xs); + font-weight: 700; + letter-spacing: var(--tracking-wider); + text-transform: uppercase; + color: var(--muted); + line-height: var(--leading-tight); } .sidebar-title-row { @@ -86,17 +92,25 @@ } .tree-btn { - @apply mb-1 flex w-full min-w-0 cursor-pointer items-center gap-2 rounded-lg border-0 bg-transparent px-2.5 py-2 text-left transition; + @apply mb-1 flex w-full min-w-0 cursor-pointer items-center border-0 bg-transparent px-2.5 py-2 text-left transition; + gap: var(--space-2); + border-radius: var(--radius-md); + font-size: var(--font-sm); + font-weight: 500; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-normal); + color: var(--muted-strong); } .tree-btn:hover { background: rgba(37, 99, 235, 0.05); + color: var(--text); } .tree-btn.active { background: rgba(37, 99, 235, 0.09); color: var(--primary-strong); - font-weight: 700; + font-weight: 600; } .tree-icon { @@ -191,8 +205,12 @@ } .list-count { - @apply shrink-0 whitespace-nowrap text-xs; - color: var(--text-muted); + @apply shrink-0 whitespace-nowrap; + font-size: var(--font-xs); + font-weight: 600; + letter-spacing: var(--tracking-wide); + color: var(--muted); + line-height: var(--leading-tight); } .list-icon-btn { @@ -525,7 +543,12 @@ } .list-title { - @apply flex min-w-0 items-center gap-1.5 text-[15px] font-bold; + @apply flex min-w-0 items-center; + gap: var(--space-2); + font-size: var(--font-base); + font-weight: 600; + line-height: var(--leading-tight); + letter-spacing: var(--tracking-tight); color: var(--primary-strong); transition: color var(--dur-fast) var(--ease-smooth), letter-spacing 220ms var(--ease-out-soft); } @@ -569,7 +592,7 @@ .list-item:hover .list-title, .list-item.active .list-title { - letter-spacing: -0.012em; + letter-spacing: var(--tracking-tighter); } .list-item:hover .list-sub, @@ -614,11 +637,19 @@ .detail-title { @apply m-0 overflow-hidden text-ellipsis whitespace-nowrap; + font-size: var(--font-2xl); + font-weight: 600; + line-height: var(--leading-tight); + letter-spacing: var(--tracking-tighter); + color: var(--text); } .detail-sub { @apply mt-2; - color: #667085; + font-size: var(--font-sm); + line-height: var(--leading-relaxed); + letter-spacing: var(--tracking-normal); + color: var(--muted); } .password-history-link {