Files

380 lines
38 KiB
HTML

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#f5f5f3" />
<meta name="description" content="Weave,一个原创的串联式文本社交界面。" />
<title>Weave · 串联想法</title>
<style>
:root {
color-scheme: light;
--page: #f4f4f2;
--surface: #fff;
--surface-2: #f7f7f6;
--text: #101010;
--muted: #777779;
--muted-2: #a0a0a2;
--line: #e7e7e5;
--line-strong: #d2d2cf;
--accent: #111;
--accent-on: #fff;
--danger: #ef3f5e;
--success: #1b9b68;
--shadow: 0 10px 34px rgba(18,18,18,.06);
--focus: 0 0 0 3px rgba(0,0,0,.18);
--header-h: 70px;
}
[data-theme="dark"] {
color-scheme: dark;
--page: #0a0a0a;
--surface: #161616;
--surface-2: #1d1d1d;
--text: #f4f4f4;
--muted: #99999e;
--muted-2: #747478;
--line: #2a2a2a;
--line-strong: #3a3a3a;
--accent: #f1f1f1;
--accent-on: #0b0b0b;
--shadow: 0 12px 38px rgba(0,0,0,.25);
--focus: 0 0 0 3px rgba(255,255,255,.23);
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; min-width: 320px; background: var(--page); color: var(--text); font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif; font-size: 16px; line-height: 1.5; transition: background .2s,color .2s; }
body.modal-open { overflow: hidden; }
button, input, textarea { font: inherit; }
button { color: inherit; }
button, a { -webkit-tap-highlight-color: transparent; }
button, [role="button"] { cursor: pointer; touch-action: manipulation; }
button:focus-visible, a:focus-visible, input:focus-visible, textarea:focus-visible { outline: none; box-shadow: var(--focus); }
svg { display: block; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.skip-link { position: fixed; z-index: 500; left: 14px; top: calc(var(--df-generated-header-height, 0px) + 9px); padding: 10px 15px; border-radius: 12px; color: var(--accent-on); background: var(--accent); transform: translateY(-160%); text-decoration: none; }
.skip-link:focus { transform: translateY(0); }
.topbar { position: fixed; z-index: 80; inset: var(--df-generated-header-height, 0px) 0 auto; height: var(--header-h); padding: 0 26px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; background: color-mix(in srgb,var(--page) 88%,transparent); backdrop-filter: blur(18px); border-bottom: 1px solid color-mix(in srgb,var(--line) 82%,transparent); }
.brand { width: fit-content; display: flex; align-items: center; gap: 9px; color: var(--text); text-decoration: none; font-size: 20px; font-weight: 800; letter-spacing: -.45px; }
.weave-mark { position: relative; width: 36px; height: 36px; display: grid; place-items: center; }
.weave-mark::before, .weave-mark::after { content: ""; position: absolute; width: 19px; height: 26px; border: 3px solid currentColor; border-radius: 50%; transform: rotate(45deg); }
.weave-mark::before { translate: -5px 1px; border-right-color: transparent; }
.weave-mark::after { translate: 5px -1px; border-left-color: transparent; }
.desktop-nav { display: flex; align-items: center; gap: 8px; }
.nav-button { position: relative; width: 58px; height: 48px; border: 0; border-radius: 14px; display: grid; place-items: center; color: var(--muted); background: transparent; transition: color .18s,background .18s,transform .18s; }
.nav-button:hover { color: var(--text); background: var(--surface); transform: translateY(-1px); }
.nav-button.active { color: var(--text); }
.nav-button.active::after { content: ""; position: absolute; bottom: -11px; width: 23px; height: 3px; border-radius: 3px; background: var(--text); }
.nav-button svg { width: 24px; height: 24px; }
.header-actions { justify-self: end; display: flex; align-items: center; gap: 8px; }
.round-button { position: relative; width: 44px; height: 44px; border: 1px solid var(--line); border-radius: 50%; display: grid; place-items: center; color: var(--text); background: var(--surface); transition: transform .18s,background .18s; }
.round-button:hover { transform: translateY(-1px); background: var(--surface-2); }
.round-button svg { width: 20px; height: 20px; }
.notification-dot { position: absolute; top: 5px; right: 5px; width: 8px; height: 8px; border: 2px solid var(--surface); border-radius: 50%; background: var(--danger); }
.avatar { --a:#7257f5; --b:#d94fbd; width: 44px; height: 44px; flex: 0 0 auto; border-radius: 50%; display: grid; place-items: center; color: #fff; background: linear-gradient(145deg,var(--a),var(--b)); font-size: 14px; font-weight: 800; box-shadow: inset 0 0 0 1px rgba(255,255,255,.18); }
.avatar-sm { width: 36px; height: 36px; font-size: 12px; }
.avatar-xs { width: 28px; height: 28px; font-size: 10px; }
.avatar-lg { width: 50px; height: 50px; }
.page-shell { width: min(1020px,calc(100% - 28px)); margin: 0 auto; padding: calc(var(--header-h) + 22px) 0 56px; display: grid; grid-template-columns: minmax(0,640px) 320px; gap: 24px; align-items: start; }
.feed-head { height: 58px; padding: 0 14px; display: flex; align-items: center; justify-content: space-between; }
.feed-head h1 { margin: 0; font-size: 22px; letter-spacing: -.45px; }
.feed-filter { min-height: 44px; padding: 0 12px; border: 1px solid var(--line); border-radius: 999px; display: flex; align-items: center; gap: 6px; color: var(--muted); background: var(--surface); font-size: 13px; font-weight: 650; }
.feed-filter svg { width: 14px; height: 14px; }
.card { background: var(--surface); border: 1px solid var(--line); border-radius: 24px; box-shadow: var(--shadow); }
.composer-card { min-height: 98px; margin-bottom: 12px; padding: 16px 17px; display: grid; grid-template-columns: 44px 1fr auto; align-items: start; gap: 12px; }
.composer-button { align-self: center; min-height: 44px; border: 0; color: var(--muted); background: transparent; text-align: left; font-size: 15px; }
.publish-inline { align-self: center; min-width: 68px; height: 44px; padding: 0 15px; border: 1px solid var(--line-strong); border-radius: 999px; color: var(--muted); background: var(--surface); font-size: 14px; font-weight: 700; }
.publish-inline:hover { color: var(--text); background: var(--surface-2); }
.feed-tabs { margin-bottom: 10px; padding: 5px; display: grid; grid-template-columns: repeat(2,1fr); border-radius: 16px; background: color-mix(in srgb,var(--surface) 72%,transparent); }
.feed-tab { min-height: 44px; border: 0; border-radius: 12px; color: var(--muted); background: transparent; font-weight: 650; }
.feed-tab.active { color: var(--text); background: var(--surface); box-shadow: 0 3px 12px rgba(0,0,0,.05); }
.thread-card { position: relative; margin-bottom: 12px; padding: 18px 18px 10px; overflow: hidden; }
.thread-row { position: relative; display: grid; grid-template-columns: 46px 1fr; gap: 11px; }
.thread-row + .thread-row { margin-top: 10px; padding-top: 2px; }
.avatar-column { position: relative; display: flex; justify-content: center; }
.thread-row.has-next .avatar-column::after { content: ""; position: absolute; z-index: 0; top: 50px; bottom: -15px; left: 50%; width: 2px; border-radius: 2px; background: var(--line-strong); transform: translateX(-50%); }
.avatar-column .avatar { position: relative; z-index: 1; }
.post-body { min-width: 0; }
.post-head { display: flex; align-items: center; gap: 5px; min-width: 0; min-height: 28px; }
.post-head strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.verified { width: 16px; height: 16px; flex: 0 0 auto; color: #1388e8; }
.handle-time { color: var(--muted); font-size: 13px; white-space: nowrap; }
.head-spacer { flex: 1; }
.follow-button { min-width: 66px; height: 44px; padding: 0 13px; border: 1px solid var(--line-strong); border-radius: 9px; color: var(--text); background: var(--surface); font-size: 13px; font-weight: 700; }
.follow-button.following { color: var(--muted); background: var(--surface-2); }
.more-button { width: 44px; height: 44px; margin-right: -8px; border: 0; border-radius: 50%; display: grid; place-items: center; color: var(--muted); background: transparent; }
.more-button:hover { color: var(--text); background: var(--surface-2); }
.more-button svg { width: 18px; height: 18px; }
.post-text { margin: 5px 0 11px; white-space: pre-wrap; overflow-wrap: anywhere; }
.post-text a { color: inherit; font-weight: 650; text-decoration: underline; text-decoration-color: var(--line-strong); text-underline-offset: 2px; }
.image-grid { display: grid; grid-template-columns: 1.2fr .8fr; gap: 3px; margin: 10px 0 6px; overflow: hidden; border: 1px solid var(--line); border-radius: 15px; background: var(--surface-2); }
.image-grid .main-image { grid-row: span 2; min-height: 255px; }
.image-grid .side-image { min-height: 126px; }
.image-grid svg { width: 100%; height: 100%; }
.quote-card { margin: 9px 0 7px; padding: 12px; border: 1px solid var(--line-strong); border-radius: 15px; background: var(--surface); }
.quote-head { display: flex; align-items: center; gap: 7px; font-size: 13px; }
.quote-card p { margin: 7px 0 0; font-size: 14px; }
.post-actions { min-height: 44px; margin-top: 5px; display: flex; align-items: center; gap: 1px; }
.post-action { min-width: 47px; height: 44px; padding: 0 7px; border: 0; border-radius: 999px; display: flex; align-items: center; gap: 5px; color: var(--muted); background: transparent; font-size: 12px; transition: color .18s,background .18s; }
.post-action:hover { color: var(--text); background: var(--surface-2); }
.post-action svg { width: 20px; height: 20px; }
.post-action.liked { color: var(--danger); }
.post-action.liked svg, .post-action.reposted svg { fill: currentColor; }
.post-action.reposted { color: var(--success); }
.post-action.share { margin-left: auto; }
.reply-preview { margin-top: 3px; padding: 9px 0 3px; display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 13px; }
.stacked-avatars { display: flex; align-items: center; min-width: 54px; }
.stacked-avatars .avatar + .avatar { margin-left: -10px; }
.reply-form { display: none; padding: 10px 0 4px; gap: 8px; }
.reply-form.open { display: flex; }
.reply-form input { flex: 1; min-width: 0; height: 44px; padding: 0 14px; border: 1px solid var(--line); border-radius: 999px; color: var(--text); background: var(--surface-2); font-size: 16px; }
.reply-send { width: 44px; height: 44px; border: 0; border-radius: 50%; display: grid; place-items: center; color: var(--accent-on); background: var(--accent); }
.reply-send svg { width: 18px; height: 18px; }
.reply-bubble { margin: 8px 0 2px; padding: 10px 12px; border-radius: 12px; background: var(--surface-2); font-size: 14px; }
.reply-bubble strong { display: block; margin-bottom: 2px; }
.post-menu { position: absolute; z-index: 20; top: 53px; right: 14px; width: 210px; padding: 7px; display: none; border: 1px solid var(--line); border-radius: 14px; background: var(--surface); box-shadow: 0 14px 40px rgba(0,0,0,.16); }
.post-menu.open { display: block; }
.post-menu button { width: 100%; min-height: 44px; padding: 0 11px; border: 0; border-radius: 9px; display: flex; align-items: center; gap: 9px; background: transparent; text-align: left; }
.post-menu button:hover { background: var(--surface-2); }
.post-menu svg { width: 18px; height: 18px; }
.empty-state { display: none; padding: 45px 20px; text-align: center; }
.empty-state svg { width: 38px; height: 38px; margin: 0 auto 12px; color: var(--muted); }
.empty-state h2 { margin: 0 0 5px; }
.empty-state p { margin: 0; color: var(--muted); }
.right-column { position: sticky; top: calc(var(--df-generated-header-height, 0px) + var(--header-h) + 22px); display: grid; gap: 12px; }
.side-card { padding: 16px; border-radius: 20px; background: var(--surface); border: 1px solid var(--line); }
.side-card h2 { margin: 0 0 12px; font-size: 16px; }
.profile-summary { display: flex; align-items: center; gap: 10px; }
.profile-copy { min-width: 0; flex: 1; }
.profile-copy strong, .profile-copy span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.profile-copy span { color: var(--muted); font-size: 13px; }
.profile-stats { margin-top: 13px; padding-top: 12px; border-top: 1px solid var(--line); display: flex; justify-content: space-around; text-align: center; }
.profile-stats strong { display: block; }
.profile-stats span { color: var(--muted); font-size: 11px; }
.suggest-row { min-height: 58px; display: flex; align-items: center; gap: 9px; }
.suggest-copy { min-width: 0; flex: 1; }
.suggest-copy strong, .suggest-copy span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.suggest-copy strong { font-size: 13px; }
.suggest-copy span { color: var(--muted); font-size: 12px; }
.topic { min-height: 64px; padding: 8px 0; border-top: 1px solid var(--line); }
.topic:first-of-type { border-top: 0; }
.topic span { color: var(--muted); font-size: 11px; }
.topic strong { display: block; margin: 2px 0; font-size: 14px; }
.topic small { color: var(--muted); }
.side-footer { padding: 2px 8px; color: var(--muted); font-size: 11px; line-height: 1.7; }
.side-footer a { color: inherit; text-decoration: none; margin-right: 7px; }
.overlay { position: fixed; z-index: 110; inset: 0; padding: 18px; display: grid; place-items: start center; background: rgba(0,0,0,.38); backdrop-filter: blur(3px); opacity: 0; visibility: hidden; transition: opacity .2s,visibility .2s; }
.overlay.open { opacity: 1; visibility: visible; }
.compose-modal { width: min(620px,100%); margin-top: 8vh; border: 1px solid var(--line); border-radius: 24px; background: var(--surface); box-shadow: 0 24px 80px rgba(0,0,0,.24); transform: translateY(10px) scale(.98); transition: transform .2s; }
.overlay.open .compose-modal { transform: translateY(0) scale(1); }
.modal-head { min-height: 62px; padding: 0 14px; display: flex; align-items: center; justify-content: space-between; border-bottom: 1px solid var(--line); }
.modal-head h2 { margin: 0; font-size: 16px; }
.close-button { width: 44px; height: 44px; border: 0; border-radius: 50%; display: grid; place-items: center; background: transparent; }
.close-button:hover { background: var(--surface-2); }
.close-button svg { width: 20px; height: 20px; }
.modal-body { padding: 17px; }
.modal-compose { display: grid; grid-template-columns: 46px 1fr; gap: 11px; }
.modal-textarea { width: 100%; min-height: 140px; padding: 5px 0; resize: vertical; border: 0; outline: 0; color: var(--text); background: transparent; font-size: 17px; line-height: 1.55; }
.modal-textarea::placeholder { color: var(--muted); }
.modal-footer { min-height: 62px; padding-top: 12px; display: flex; align-items: center; justify-content: space-between; border-top: 1px solid var(--line); }
.composer-tools { display: flex; gap: 1px; }
.tool-button { width: 44px; height: 44px; border: 0; border-radius: 50%; display: grid; place-items: center; color: var(--muted); background: transparent; }
.tool-button:hover { color: var(--text); background: var(--surface-2); }
.tool-button svg { width: 20px; height: 20px; }
.modal-actions { display: flex; align-items: center; gap: 10px; }
.char-count { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.char-count.warn { color: var(--danger); }
.modal-publish { min-width: 78px; height: 44px; border: 0; border-radius: 999px; color: var(--accent-on); background: var(--accent); font-weight: 700; }
.modal-publish:disabled { opacity: .4; cursor: not-allowed; }
.panel { position: fixed; z-index: 100; top: calc(var(--df-generated-header-height, 0px) + var(--header-h) + 8px); left: 50%; width: min(580px,calc(100vw - 24px)); max-height: calc(100dvh - var(--df-generated-header-height, 0px) - var(--header-h) - 20px); overflow: auto; padding: 15px; border: 1px solid var(--line); border-radius: 20px; background: var(--surface); box-shadow: 0 18px 55px rgba(0,0,0,.2); opacity: 0; visibility: hidden; transform: translate(-50%,-8px); transition: opacity .18s,visibility .18s,transform .18s; }
.panel.open { opacity: 1; visibility: visible; transform: translate(-50%,0); }
.panel-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.panel-head h2 { margin: 0; font-size: 19px; }
.panel-search { position: relative; }
.panel-search svg { position: absolute; left: 14px; top: 50%; width: 18px; height: 18px; color: var(--muted); transform: translateY(-50%); }
.panel-search input { width: 100%; height: 46px; padding: 0 14px 0 42px; border: 1px solid var(--line); border-radius: 14px; color: var(--text); background: var(--surface-2); font-size: 16px; }
.search-hints { padding: 16px 5px 4px; color: var(--muted); font-size: 13px; }
.activity-row { min-height: 68px; padding: 8px 3px; display: flex; align-items: center; gap: 10px; border-top: 1px solid var(--line); }
.activity-row:first-of-type { border-top: 0; }
.activity-copy { flex: 1; }
.activity-copy p { margin: 0; font-size: 13px; }
.activity-copy time { color: var(--muted); font-size: 11px; }
.toast { position: fixed; z-index: 160; left: 50%; bottom: 25px; padding: 11px 16px; border-radius: 12px; color: var(--accent-on); background: var(--accent); box-shadow: 0 14px 38px rgba(0,0,0,.2); opacity: 0; visibility: hidden; transform: translate(-50%,12px); transition: opacity .18s,visibility .18s,transform .18s; }
.toast.show { opacity: 1; visibility: visible; transform: translate(-50%,0); }
.mobile-nav { display: none; }
.mobile-header { display: none; }
@media (max-width: 920px) {
.page-shell { grid-template-columns: minmax(0,640px); width: min(640px,calc(100% - 24px)); }
.right-column { display: none; }
}
@media (max-width: 680px) {
:root { --header-h: 58px; }
body { padding-bottom: calc(60px + env(safe-area-inset-bottom)); }
.topbar { display: none; }
.mobile-header { position: fixed; z-index: 75; inset: var(--df-generated-header-height, 0px) 0 auto; height: var(--header-h); padding: max(4px,env(safe-area-inset-top)) 14px 4px; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; background: color-mix(in srgb,var(--page) 91%,transparent); backdrop-filter: blur(16px); border-bottom: 1px solid var(--line); }
.mobile-header .weave-mark { width: 32px; height: 32px; }
.mobile-header strong { font-size: 17px; }
.mobile-header .round-button { justify-self: end; }
.page-shell { width: 100%; padding: calc(var(--header-h) + 8px) 0 15px; display: block; }
.feed-head { padding-inline: 13px; }
.feed-head h1 { display: none; }
.feed-filter { margin-left: auto; }
.composer-card { margin: 0 8px 9px; border-radius: 18px; box-shadow: none; grid-template-columns: 42px 1fr; }
.composer-card .publish-inline { display: none; }
.feed-tabs { margin: 0 8px 8px; }
.thread-card { margin: 0 0 8px; padding: 15px 13px 8px; border-inline: 0; border-radius: 0; box-shadow: none; }
.thread-row { grid-template-columns: 42px 1fr; gap: 9px; }
.avatar-lg { width: 44px; height: 44px; }
.post-head { flex-wrap: nowrap; }
.handle-time { max-width: 92px; overflow: hidden; text-overflow: ellipsis; }
.image-grid .main-image { min-height: 210px; }
.image-grid .side-image { min-height: 103px; }
.post-action { min-width: 44px; padding: 0 6px; }
.mobile-nav { position: fixed; z-index: 76; inset: auto 0 0; height: calc(58px + env(safe-area-inset-bottom)); padding: 3px 8px max(4px,env(safe-area-inset-bottom)); display: grid; grid-template-columns: repeat(5,1fr); background: color-mix(in srgb,var(--page) 94%,transparent); border-top: 1px solid var(--line); backdrop-filter: blur(16px); }
.mobile-nav button { min-height: 50px; border: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; color: var(--muted); background: transparent; font-size: 10px; }
.mobile-nav button.active { color: var(--text); }
.mobile-nav svg { width: 22px; height: 22px; }
.mobile-create { width: 42px; height: 32px; border: 1px solid var(--line-strong); border-radius: 11px; display: grid; place-items: center; color: var(--accent-on); background: var(--accent); }
.mobile-create svg { width: 18px; height: 18px; }
.overlay { padding: 0; }
.compose-modal { min-height: 100dvh; margin: 0; border: 0; border-radius: 0; }
.panel { top: calc(var(--df-generated-header-height, 0px) + var(--header-h) + 5px); }
.toast { bottom: calc(70px + env(safe-area-inset-bottom)); }
}
@media (max-width: 390px) {
.thread-card { padding-inline: 10px; }
.post-action .action-count { font-size: 10px; }
.post-text { font-size: 15px; }
.handle-time { max-width: 70px; }
.follow-button { min-width: 58px; padding-inline: 9px; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { scroll-behavior: auto !important; animation: none !important; transition: none !important; }
}
.header-actions { padding-right: 54px; }
.settings-trigger { position: fixed; z-index: 180; top: calc(var(--df-generated-header-height, 0px) + 12px); right: 18px; width: 46px; height: 46px; border: 1px solid var(--line-strong); border-radius: 50%; display: grid; place-items: center; color: var(--text); background: color-mix(in srgb,var(--surface) 92%,transparent); box-shadow: 0 8px 24px rgba(15,20,25,.14); backdrop-filter: blur(12px); transition: transform .18s,background .18s; }
.settings-trigger:hover { background: var(--surface-2); transform: rotate(12deg); }
.settings-trigger svg { width: 21px; height: 21px; }
.settings-overlay { position: fixed; z-index: 220; inset: 0; padding: 30px; display: grid; place-items: center; background: rgba(2,8,18,.76); backdrop-filter: blur(8px); opacity: 0; visibility: hidden; transition: opacity .2s,visibility .2s; }
.settings-overlay.open { opacity: 1; visibility: visible; }
body.settings-open > :not(.settings-overlay):not(svg) { visibility: hidden !important; }
.settings-modal { width: min(1280px,100%); height: min(790px,calc(100dvh - 60px)); display: grid; grid-template-rows: auto 1fr auto; overflow: hidden; border: 1px solid #2a6382; border-radius: 14px; color: #e8f3ff; background: #071321; box-shadow: 0 30px 100px rgba(0,0,0,.52); }
.settings-head, .settings-body, .settings-foot { background: #071321; }
.settings-head { min-height: 82px; padding: 16px 24px; display: flex; align-items: center; gap: 14px; border-bottom: 1px solid #21455d; }
.settings-head-copy { flex: 1; }
.settings-kicker { display: block; margin-bottom: 3px; color: #35b8ff; font-size: 13px; font-weight: 800; letter-spacing: .1em; }
.settings-head h2 { margin: 0; color: #f7fbff; font-size: 25px; }
.settings-close { width: 46px; height: 46px; border: 1px solid #2e708f; border-radius: 9px; display: grid; place-items: center; color: #f2f8ff; background: #0b1d30; }
.settings-close:hover { background: #12304b; }
.settings-close svg { width: 22px; height: 22px; }
.settings-body { min-height: 0; padding: 18px 24px; display: grid; grid-template-columns: 255px minmax(0,1fr); gap: 18px; }
.module-tabs { min-height: 0; overflow: auto; }
.module-tabs h3 { margin: 0 0 10px; color: #8fa9bf; font-size: 13px; font-weight: 650; }
.module-tab { width: 100%; min-height: 58px; margin-bottom: 7px; padding: 9px 12px; border: 1px solid #1d4660; border-radius: 9px; display: block; color: #b7cada; background: #0a1929; text-align: left; }
.module-tab:hover { background: #0d2338; }
.module-tab.active { border-color: #25adf2; color: #fff; background: #0d2a42; box-shadow: inset 3px 0 #28b6ff; }
.module-tab strong,.module-tab span { display: block; }
.module-tab span { margin-top: 2px; color: #7e9aae; font-size: 11px; }
.editor-pane { min-width: 0; min-height: 0; display: grid; grid-template-rows: auto 1fr auto; }
.editor-title { min-height: 37px; display: flex; align-items: flex-start; justify-content: space-between; color: #8fa9bf; font-size: 12px; }
.editor-title strong { color: #eef8ff; font-size: 16px; }
.json-editor { width: 100%; min-height: 0; padding: 16px; resize: none; border: 1px solid #28526b; border-radius: 10px; outline: 0; color: #d6f1ff; background: #020a12; font: 14px/1.62 ui-monospace,SFMono-Regular,Consolas,"Liberation Mono",monospace; tab-size: 2; }
.json-editor:focus { border-color: #28b6ff; box-shadow: 0 0 0 3px rgba(40,182,255,.16); }
.editor-hint { min-height: 40px; padding-top: 9px; display: flex; justify-content: space-between; gap: 12px; color: #7894aa; font-size: 12px; }
.json-status { font-weight: 750; }
.json-status.valid { color: #48d8a0; }
.json-status.invalid { color: #ff7189; }
.settings-foot { min-height: 74px; padding: 13px 24px; display: flex; align-items: center; justify-content: flex-end; gap: 10px; border-top: 1px solid #21455d; }
.editor-button { min-height: 44px; padding: 0 17px; border: 1px solid #2d7292; border-radius: 9px; color: #e5f4ff; background: #0b1e30; font-weight: 700; }
.editor-button:hover { background: #12334f; }
.editor-button.primary { border-color: #2ab8ff; color: #03131e; background: #33b9fa; }
.editor-button.primary:hover { background: #67caff; }
@media (max-width: 680px) {
.settings-trigger { top: calc(var(--df-generated-header-height, 0px) + 7px); right: 60px; width: 40px; height: 40px; }
.settings-overlay { padding: 0; }
.settings-modal { width: 100%; height: 100dvh; border: 0; border-radius: 0; }
.settings-head { min-height: 68px; padding: 10px 14px; }
.settings-head h2 { font-size: 20px; }
.settings-body { padding: 12px; grid-template-columns: 1fr; grid-template-rows: auto minmax(0,1fr); }
.module-tabs { display: flex; gap: 7px; overflow-x: auto; }
.module-tabs h3 { display: none; }
.module-tab { width: auto; min-width: 118px; margin: 0; }
.settings-foot { padding: 10px 12px; flex-wrap: wrap; }
.editor-button { flex: 1; padding-inline: 10px; }
}
.skip-link { transform: translateY(calc(-100% - var(--df-generated-header-height, 0px) - 24px)); }
.skip-link:focus { transform: translateY(0); }
.overlay, .panel { z-index: 1200; }
.settings-overlay { z-index: 1300; }
</style>
</head>
<body>
<a class="skip-link" href="#feed">跳到动态</a>
<svg aria-hidden="true" width="0" height="0" style="position:absolute">
<symbol id="i-home" viewBox="0 0 24 24"><path d="m3 10 9-7 9 7v10a1 1 0 0 1-1 1h-5v-7H9v7H4a1 1 0 0 1-1-1Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
<symbol id="i-search" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7" fill="none" stroke="currentColor" stroke-width="2"/><path d="m16.2 16.2 4.2 4.2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
<symbol id="i-plus" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round"/></symbol>
<symbol id="i-heart" viewBox="0 0 24 24"><path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.7l-1.1-1.1a5.5 5.5 0 0 0-7.8 7.8l1.1 1.1L12 21l7.8-7.5 1.1-1.1a5.5 5.5 0 0 0-.1-7.8Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
<symbol id="i-user" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4" fill="none" stroke="currentColor" stroke-width="2"/><path d="M4 21a8 8 0 0 1 16 0" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
<symbol id="i-menu" viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
<symbol id="i-moon" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 2v2m0 16v2M4.9 4.9l1.5 1.5m11.2 11.2 1.5 1.5M2 12h2m16 0h2M4.9 19.1l1.5-1.5m11.2-11.2 1.5-1.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
<symbol id="i-chevron" viewBox="0 0 24 24"><path d="m8 10 4 4 4-4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-more" viewBox="0 0 24 24"><circle cx="5" cy="12" r="1.7" fill="currentColor"/><circle cx="12" cy="12" r="1.7" fill="currentColor"/><circle cx="19" cy="12" r="1.7" fill="currentColor"/></symbol>
<symbol id="i-verified" viewBox="0 0 24 24"><path d="m12 2 2.2 2.1 3-.4.9 2.9 2.7 1.4-1.3 2.8 1.3 2.8-2.7 1.4-.9 2.9-3-.4L12 22l-2.2-2.1-3 .4-.9-2.9L3.2 16l1.3-2.8-1.3-2.8L5.9 9l.9-2.9 3 .4Z" fill="currentColor"/><path d="m8.5 12 2.2 2.2 4.8-5" fill="none" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-comment" viewBox="0 0 24 24"><path d="M21 12a8.5 8.5 0 0 1-9 8.5 9 9 0 0 1-3.7-.8L4 21l1.2-3.8A8.5 8.5 0 1 1 21 12Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
<symbol id="i-repost" viewBox="0 0 24 24"><path d="m17 3 4 4-4 4M3 7h18M7 21l-4-4 4-4m14 4H3" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-share" viewBox="0 0 24 24"><path d="M12 16V3m0 0L7 8m5-5 5 5M5 13v7h14v-7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-bookmark" viewBox="0 0 24 24"><path d="M6 3h12a1 1 0 0 1 1 1v17l-7-4-7 4V4a1 1 0 0 1 1-1Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
<symbol id="i-eye-off" viewBox="0 0 24 24"><path d="M3 3l18 18M10.6 10.6A2 2 0 0 0 13.4 13.4M9.9 4.2A10.5 10.5 0 0 1 21 12s-1.4 3-4.3 5.1M6.2 6.2C4.1 7.6 3 10 3 12c0 0 3 6 9 6 1 0 2-.2 2.8-.5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="i-image" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="8.5" cy="9" r="1.5" fill="currentColor"/><path d="m4 17 5-5 4 4 2-2 5 4" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/></symbol>
<symbol id="i-smile" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/><path d="M8 14s1.5 2 4 2 4-2 4-2M9 9h.01M15 9h.01" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
<symbol id="i-link" viewBox="0 0 24 24"><path d="M10 13a5 5 0 0 0 7.5.5l3-3a5 5 0 0 0-7-7l-1.7 1.7M14 11a5 5 0 0 0-7.5-.5l-3 3a5 5 0 0 0 7 7l1.7-1.7" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
<symbol id="i-close" viewBox="0 0 24 24"><path d="m6 6 12 12M18 6 6 18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></symbol>
<symbol id="i-send" viewBox="0 0 24 24"><path d="m22 2-7 20-4-9-9-4Z" fill="none" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><path d="M22 2 11 13" fill="none" stroke="currentColor" stroke-width="2"/></symbol>
<symbol id="i-settings" viewBox="0 0 24 24"><path d="M12 15.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7Z" fill="none" stroke="currentColor" stroke-width="2"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.9l.1.1-2.8 2.8-.1-.1a1.7 1.7 0 0 0-1.9-.3 1.7 1.7 0 0 0-1 1.6v.2h-4V21a1.7 1.7 0 0 0-1-1.6 1.7 1.7 0 0 0-1.9.3l-.1.1L4.2 17l.1-.1a1.7 1.7 0 0 0 .3-1.9A1.7 1.7 0 0 0 3 14H2.8v-4H3a1.7 1.7 0 0 0 1.6-1 1.7 1.7 0 0 0-.3-1.9L4.2 7 7 4.2l.1.1a1.7 1.7 0 0 0 1.9.3A1.7 1.7 0 0 0 10 3V2.8h4V3a1.7 1.7 0 0 0 1 1.6 1.7 1.7 0 0 0 1.9-.3l.1-.1L19.8 7l-.1.1a1.7 1.7 0 0 0-.3 1.9 1.7 1.7 0 0 0 1.6 1h.2v4H21a1.7 1.7 0 0 0-1.6 1Z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></symbol>
</svg>
<header class="topbar"><a class="brand" id="brandLink" href="#feed"><span class="weave-mark"></span><span id="brandText">Threads</span></a><nav class="desktop-nav" aria-label="主导航"><button class="nav-button active" aria-label="首页"><svg><use href="#i-home"/></svg></button><button class="nav-button" data-panel="searchPanel" aria-label="搜索"><svg><use href="#i-search"/></svg></button><button class="nav-button" data-open-composer aria-label="创建动态"><svg><use href="#i-plus"/></svg></button><button class="nav-button" data-panel="activityPanel" aria-label="动态"><svg><use href="#i-heart"/></svg></button><button class="nav-button" aria-label="个人主页"><svg><use href="#i-user"/></svg></button></nav><div class="header-actions"><button class="round-button" id="themeToggle" aria-label="切换主题"><svg><use href="#i-moon"/></svg></button><button class="round-button" aria-label="菜单"><svg><use href="#i-menu"/></svg><span class="notification-dot"></span></button></div></header>
<header class="mobile-header"><span id="mobileUser"></span><span class="weave-mark"></span><button class="round-button" id="mobileTheme" aria-label="切换主题"><svg><use href="#i-moon"/></svg></button></header>
<button class="settings-trigger" id="openSettings" aria-label="编辑页面 JSON" title="编辑页面 JSON"><svg><use href="#i-settings"/></svg></button>
<main class="page-shell" id="feed">
<section class="feed-column" aria-label="对话动态">
<div class="feed-head"><h1 id="feedTitle">首页</h1><button class="feed-filter"><span id="feedFilter">为你推荐</span> <svg><use href="#i-chevron"/></svg></button></div>
<section class="card composer-card"><span id="composerUser"></span><button class="composer-button" id="composerButton" data-open-composer></button><button class="publish-inline" id="inlinePublish" data-open-composer></button></section>
<div class="feed-tabs" id="feedTabs"></div>
<div id="threadList"></div>
<section class="card empty-state" id="emptyState"><svg><use href="#i-search"/></svg><h2 id="emptyTitle"></h2><p id="emptyText"></p></section>
</section>
<aside class="right-column" aria-label="推荐内容">
<section class="side-card" id="profileSummary"></section>
<section class="side-card"><h2 id="followTitle"></h2><div id="suggestions"></div></section>
<section class="side-card"><h2 id="topicTitle"></h2><div id="topics"></div></section>
<footer class="side-footer" id="sideFooter"></footer>
</aside>
</main>
<nav class="mobile-nav" id="mobileNav" aria-label="移动端导航"></nav>
<div class="overlay" id="composeOverlay" aria-hidden="true"><section class="compose-modal" role="dialog" aria-modal="true" aria-labelledby="composeTitle"><header class="modal-head"><button class="close-button" id="closeCompose" aria-label="关闭发帖窗口"><svg><use href="#i-close"/></svg></button><h2 id="composeTitle"></h2><span style="width:44px"></span></header><div class="modal-body"><div class="modal-compose"><span id="modalUser"></span><div><strong id="modalUserName"></strong><label class="sr-only" for="composeText">串聊内容</label><textarea id="composeText" class="modal-textarea"></textarea></div></div><footer class="modal-footer"><div class="composer-tools"><button class="tool-button" aria-label="添加图片"><svg><use href="#i-image"/></svg></button><button class="tool-button" aria-label="添加表情"><svg><use href="#i-smile"/></svg></button><button class="tool-button" aria-label="添加链接"><svg><use href="#i-link"/></svg></button></div><div class="modal-actions"><span class="char-count" id="charCount"></span><button class="modal-publish" id="modalPublish" disabled></button></div></footer></div></section></div>
<section class="panel" id="searchPanel" aria-hidden="true"><header class="panel-head"><h2>搜索</h2><button class="close-button" data-close-panel aria-label="关闭搜索"><svg><use href="#i-close"/></svg></button></header><label class="panel-search"><span class="sr-only">搜索串聊</span><svg><use href="#i-search"/></svg><input id="searchInput" type="search" autocomplete="off" /></label><div class="search-hints"><strong>试试搜索</strong><p id="searchHints"></p></div></section>
<section class="panel" id="activityPanel" aria-hidden="true"><header class="panel-head"><h2 id="activityTitle"></h2><button class="close-button" data-close-panel aria-label="关闭动态"><svg><use href="#i-close"/></svg></button></header><div id="activityList"></div></section>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<div class="settings-overlay" id="settingsOverlay" aria-hidden="true"><section class="settings-modal" role="dialog" aria-modal="true" aria-labelledby="settingsTitle"><header class="settings-head"><div class="settings-head-copy"><span class="settings-kicker">THREADS TEMPLATE CONTROL</span><h2 id="settingsTitle">JSON 编辑器</h2></div><button class="settings-close" id="closeSettings" aria-label="关闭 JSON 编辑器"><svg><use href="#i-close"/></svg></button></header><div class="settings-body"><nav class="module-tabs" id="moduleTabs" aria-label="JSON 模块"><h3>页面模块</h3></nav><div class="editor-pane"><div class="editor-title"><strong id="editorModuleTitle">站点信息</strong><span>只编辑当前模块</span></div><textarea class="json-editor" id="jsonEditor" spellcheck="false" aria-label="当前模块 JSON"></textarea><div class="editor-hint"><span>修改后先校验,再应用到页面。</span><span class="json-status valid" id="jsonStatus">JSON 有效</span></div></div></div><footer class="settings-foot"><button class="editor-button" id="resetJson">恢复初始</button><button class="editor-button" id="copyJson">复制 JSON</button><button class="editor-button" id="downloadJson">下载 JSON</button><button class="editor-button primary" id="applyJson">应用并渲染</button></footer></section></div>
<script type="application/json" id="threadsPageData">__THREADS_PAGE_DATA__</script>
<script>__THREADS_PAGE_RUNTIME__</script>
</body>
</html>