Files
SpineParticlesWeb/src/views/HelpDialog.vue
T
2026-11-10 11:11:09 +08:00

448 lines
26 KiB
Vue

<template>
<div v-if="show" class="help-overlay" role="presentation" @click.self="close">
<section class="help-dialog" data-matomo-section="help" role="dialog" aria-modal="true" aria-labelledby="help-title">
<header class="help-head">
<nav class="help-tabs" :aria-label="$t('help.tabsLabel')">
<button
id="help-title"
type="button"
class="help-tab"
:class="{ active: activeTab === 'guide' }"
:aria-pressed="activeTab === 'guide'"
aria-controls="help-guide-panel"
@click="activeTab = 'guide'"
>
<strong>{{ $t('help.title') }}</strong>
<small>{{ $t('help.subtitle') }}</small>
</button>
<button
type="button"
class="help-tab"
:class="{ active: activeTab === 'updates' }"
:aria-pressed="activeTab === 'updates'"
aria-controls="help-updates-panel"
@click="activeTab = 'updates'"
>
<strong>{{ $t('help.updates') }}</strong>
<small>{{ $t('help.updatesSubtitle') }}</small>
</button>
</nav>
<button class="help-close" :aria-label="$t('help.close')" :title="$t('help.closeShort')" @click="close">✕</button>
</header>
<div class="help-body">
<div v-show="activeTab === 'guide'" id="help-guide-panel">
<section class="help-section help-start">
<h3>{{ $t('help.quickStart') }}</h3>
<ol>
<li>{{ $t('help.stepCreate') }}</li>
<li>{{ $t('help.stepEdit') }}</li>
<li>{{ $t('help.stepPreview') }}</li>
<li>{{ $t('help.stepExport') }}</li>
</ol>
<p class="help-note">{{ $t('help.quickNote') }}</p>
</section>
<div class="help-grid">
<section class="help-section">
<h3>{{ $t('help.commonOps') }}</h3>
<dl class="help-list">
<div><dt>{{ $t('help.eye') }}</dt><dd>{{ $t('help.eyeDesc') }}</dd></div>
<div><dt>+Copy</dt><dd>{{ $t('help.copyDesc') }}</dd></div>
<div><dt>{{ $t('help.sceneClipboard') }}</dt><dd>{{ $t('help.sceneClipboardDesc') }}</dd></div>
<div><dt>{{ $t('toolbar.background') }}</dt><dd>{{ $t('help.backgroundDesc') }}</dd></div>
<div><dt>{{ $t('toolbar.settings') }}</dt><dd>{{ $t('help.settingsDesc') }}</dd></div>
<div><dt>{{ $t('help.undoShortcut') }}</dt><dd>{{ $t('help.undoDesc') }}</dd></div>
<div><dt>Spine Bone</dt><dd>{{ $t('help.spineBoneDesc') }}</dd></div>
</dl>
</section>
<section class="help-section">
<h3>{{ $t('help.shortcuts') }}</h3>
<div class="shortcut-list">
<div><kbd>Ctrl/⌘</kbd><span>+</span><kbd>Z</kbd><em>{{ $t('help.undoShortcut') }}</em></div>
<div><kbd>Ctrl/⌘</kbd><span>+</span><kbd>S</kbd><em>{{ $t('help.saveShortcut') }}</em></div>
<div><kbd>Q</kbd><em>{{ $t('help.panShortcut') }}</em></div>
<div><kbd>W</kbd><em>{{ $t('help.translateShortcut') }}</em></div>
<div><kbd>E</kbd><em>{{ $t('help.rotateShortcut') }}</em></div>
<div><kbd>R</kbd><em>{{ $t('help.scaleShortcut') }}</em></div>
<div><kbd>D</kbd><em>{{ $t('help.playShortcut') }}</em></div>
<div><kbd>S</kbd><em>{{ $t('help.startShortcut') }}</em></div>
</div>
<p class="help-note">{{ $t('help.shortcutNote') }}</p>
</section>
</div>
<div class="help-doc-title">{{ $t('help.modules') }}</div>
<section class="help-section help-module" :class="{ open: openModules[0] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[0] ? 'true' : 'false'" @click="openModules[0] = !openModules[0]">
<span class="mnum">1</span><span class="mtitle">{{ $t('help.configTitle') }}</span><span class="caret">{{ openModules[0] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[0]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('config.save') }}</dt><dd>{{ $t('help.saveConfigDesc') }}</dd></div>
<div><dt>{{ $t('config.load') }}</dt><dd>{{ $t('help.loadConfigDesc') }}</dd></div>
<div><dt>{{ $t('config.selectPreset') }}</dt><dd>{{ $t('help.presetDesc') }}</dd></div>
<div><dt>{{ $t('help.configScope') }}</dt><dd>{{ $t('help.configScopeDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[1] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[1] ? 'true' : 'false'" @click="openModules[1] = !openModules[1]">
<span class="mnum">2</span><span class="mtitle">{{ $t('help.sceneTitle') }}</span><span class="caret">{{ openModules[1] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[1]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('scene.particle') }}</dt><dd>{{ $t('help.particleDesc') }}</dd></div>
<div><dt>{{ $t('scene.collision') }}</dt><dd>{{ $t('help.colliderDesc') }}</dd></div>
<div><dt>{{ $t('scene.path') }}</dt><dd>{{ $t('help.pathDesc') }}</dd></div>
<div><dt>Spine</dt><dd>{{ $t('help.spineDesc') }}</dd></div>
<div><dt>{{ $t('help.commonOps') }}</dt><dd>{{ $t('help.sceneCommonDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[2] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[2] ? 'true' : 'false'" @click="openModules[2] = !openModules[2]">
<span class="mnum">3</span><span class="mtitle">{{ $t('emission.title') }}</span><span class="caret">{{ openModules[2] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[2]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('emission.stream') }}</dt><dd>{{ $t('help.emissionDesc') }}</dd></div>
<div><dt>{{ $t('emission.burst') }}</dt><dd>{{ $t('help.burstDesc') }}</dd></div>
<div><dt>{{ $t('emission.delay') }}</dt><dd>{{ $t('help.delayDesc') }}</dd></div>
<div><dt>{{ $t('modifiers.showShape') }}</dt><dd>{{ $t('help.loopNote') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[3] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[3] ? 'true' : 'false'" @click="openModules[3] = !openModules[3]">
<span class="mnum">4</span><span class="mtitle">{{ $t('emission.shapeTitle') }}</span><span class="caret">{{ openModules[3] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[3]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('emission.shape') }}</dt><dd>{{ $t('help.shapeDesc') }}</dd></div>
<div><dt>{{ $t('emission.emissionAngle') }}</dt><dd>{{ $t('help.angleDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[4] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[4] ? 'true' : 'false'" @click="openModules[4] = !openModules[4]">
<span class="mnum">5</span><span class="mtitle">{{ $t('attributes.title') }}</span><span class="caret">{{ openModules[4] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[4]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('attributes.initialParams') }}</dt><dd>{{ $t('help.initialDesc') }}</dd></div>
<div><dt>{{ $t('attributes.lifecycleTitle') }}</dt><dd>{{ $t('help.overLifeDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[5] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[5] ? 'true' : 'false'" @click="openModules[5] = !openModules[5]">
<span class="mnum">6</span><span class="mtitle">{{ $t('appearance.title') }}</span><span class="caret">{{ openModules[5] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[5]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('appearance.opacity') }}</dt><dd>{{ $t('help.alphaDesc') }}</dd></div>
<div><dt>{{ $t('appearance.imageResources') }}</dt><dd>{{ $t('help.imageDesc') }}</dd></div>
<div><dt>{{ $t('image.sequence') }}</dt><dd>{{ $t('help.sequenceDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[6] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[6] ? 'true' : 'false'" @click="openModules[6] = !openModules[6]">
<span class="mnum">7</span><span class="mtitle">{{ $t('modifiers.title') }}</span><span class="caret">{{ openModules[6] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[6]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('modifiers.enableNoise') }}</dt><dd>{{ $t('help.noiseDesc') }}</dd></div>
<div><dt>{{ $t('modifiers.enableGravity') }} / {{ $t('modifiers.enableWind') }}</dt><dd>{{ $t('help.gravityDesc') }}</dd></div>
<div><dt>{{ $t('modifiers.enableForceField') }} / {{ $t('modifiers.enableVortex') }} / {{ $t('modifiers.enableAttraction') }}</dt><dd>{{ $t('help.forceDesc') }}</dd></div>
<div><dt>{{ $t('modifiers.enableTrail') }}</dt><dd>{{ $t('help.trailDesc') }}</dd></div>
<div><dt>{{ $t('modifiers.enableFollow') }}</dt><dd>{{ $t('help.followDesc') }}</dd></div>
<div><dt>{{ $t('modifiers.enableCollision') }} / {{ $t('modifiers.damping') }}</dt><dd>{{ $t('help.collisionDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[7] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[7] ? 'true' : 'false'" @click="openModules[7] = !openModules[7]">
<span class="mnum">8</span><span class="mtitle">{{ $t('export.title') }}</span><span class="caret">{{ openModules[7] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[7]" class="help-module-body">
<dl class="help-list">
<div><dt>{{ $t('export.imagesPath') }}</dt><dd>{{ $t('help.exportDesc') }}</dd></div>
<div><dt>{{ $t('export.spineVersion') }}</dt><dd>3.8 / 4.0 / 4.1 / 4.2 / 4.3</dd></div>
<div><dt>{{ $t('export.keyframeCurve') }}</dt><dd>{{ $t('export.bezierHelp') }}</dd></div>
<div><dt>{{ $t('export.fps') }}</dt><dd>{{ $t('export.fpsHelp') }}</dd></div>
<div><dt>{{ $t('export.title') }}</dt><dd>{{ $t('help.exportButtonsDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module help-connector" :class="{ open: openModules[8] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[8] ? 'true' : 'false'" @click="openModules[8] = !openModules[8]">
<span class="mnum">9</span><span class="mtitle">{{ $t('help.connectorTitle') }}</span><span class="caret">{{ openModules[8] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[8]" class="help-module-body">
<p class="connector-intro">{{ $t('help.connectorIntro') }}</p>
<dl class="help-list">
<div><dt>{{ $t('help.prerequisite') }}</dt><dd>{{ $t('help.prerequisiteDesc') }}</dd></div>
<div><dt>{{ $t('help.download') }}</dt><dd>
<a class="dl-link" href="/downloads/connector/SpineParticleConnector-windows-x64.exe" data-matomo-category="使用说明" data-matomo-action="点击下载" data-matomo-name="下载 Windows 连接器" download>Windows<br><small>SpineParticleConnector-windows-x64.exe</small></a>
<a class="dl-link" href="/downloads/connector/SpineParticleConnector-macos-universal.zip" data-matomo-category="使用说明" data-matomo-action="点击下载" data-matomo-name="下载 macOS 连接器" download>macOS (Universal)<br><small>SpineParticleConnector-macos-universal.zip</small></a>
</dd></div>
<div><dt>{{ $t('help.webSide') }}</dt><dd>{{ $t('help.webSideDesc') }}</dd></div>
<div><dt>{{ $t('help.authorization') }}</dt><dd>{{ $t('help.authorizationDesc') }}</dd></div>
<div><dt>{{ $t('help.pathSetup') }}</dt><dd>{{ $t('help.pathSetupDesc') }}</dd></div>
<div><dt>{{ $t('help.downloadResult') }}</dt><dd>{{ $t('help.downloadResultDesc') }}</dd></div>
<div><dt>{{ $t('help.version') }}</dt><dd>{{ $t('help.versionDesc') }}</dd></div>
<div><dt>{{ $t('help.security') }}</dt><dd>{{ $t('help.securityDesc') }}</dd></div>
</dl>
</div>
</section>
<section class="help-section help-module" :class="{ open: openModules[9] }">
<button type="button" class="help-module-head" :aria-expanded="openModules[9] ? 'true' : 'false'" @click="openModules[9] = !openModules[9]">
<span class="mnum">10</span><span class="mtitle">{{ $t('help.embedTitle') }}</span><span class="caret">{{ openModules[9] ? '▾' : '▸' }}</span>
</button>
<div v-show="openModules[9]" class="help-module-body">
<p class="embed-intro">{{ $t('help.embedIntro') }}</p>
<pre class="embed-code"><code>{{ embedCode }}</code></pre>
</div>
</section>
<section class="help-section help-export">
<h3>{{ $t('help.differenceTitle') }}</h3>
<p>{{ $t('help.differenceDesc') }}</p>
</section>
</div>
<div v-show="activeTab === 'updates'" id="help-updates-panel" class="help-updates">
<section
v-for="(release, index) in releases"
:key="release.title"
class="help-section release-card"
:class="{ open: openRelease === index }"
>
<button
type="button"
class="release-head"
:aria-expanded="openRelease === index"
@click="openRelease = openRelease === index ? null : index"
>
<time :datetime="release.date">{{ release.date }}</time>
<span>{{ $t(release.title) }}</span>
<b>{{ openRelease === index ? '▾' : '▸' }}</b>
</button>
<div v-show="openRelease === index" class="release-body">
<p>{{ $t(release.heading) }}</p>
<ol>
<li v-for="update in release.updates" :key="update">{{ $t(update) }}</li>
</ol>
</div>
</section>
</div>
</div>
</section>
</div>
</template>
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
defineProps<{ show: boolean }>()
const emit = defineEmits<{ (event: 'close'): void }>()
const activeTab = ref<'guide' | 'updates'>('guide')
// 功能模块详解:默认全部收起,点击标题栏展开/收起单个模块。
const openModules = ref<boolean[]>(Array.from({ length: 10 }, () => false))
const embedCode = `<iframe style="width: 75%;height: 80%;border: 10px solid #ccc;border-radius: 10px;display: block;margin: 0 auto;"
src="https://spineparticles.yeomai.site/#/editor"
title="SpineParticlesEditor"
allow="clipboard-read; clipboard-write; fullscreen"
allowfullscreen
referrerpolicy="strict-origin-when-cross-origin"
></iframe>`
const releases = [
{
date: '2026-11-09',
title: 'help.releaseSummaryV11109',
heading: 'help.releaseHeadingV11109',
updates: [
'help.releaseSceneClipboard',
'help.releaseConfigAppend',
'help.releaseTimelineScroll',
'help.releaseCanvasBlendFix',
'help.releaseConnectorUpdate',
'help.releaseColorThemes',
],
},
{
date: '2026-11-07',
title: 'help.releaseSummaryV11107',
heading: 'help.releaseHeadingV11107',
updates: ['help.releaseSafariConnector'],
},
{
date: '2026-11-06',
title: 'help.releaseSummaryV11106',
heading: 'help.releaseHeadingV11106',
updates: ['help.releaseMenuLayerFix', 'help.releaseSequenceStart', 'help.releaseSaveDialog'],
},
{
date: '2026-11-05',
title: 'help.releaseSummaryV11105',
heading: 'help.releaseHeadingV11105',
updates: ['help.releaseWindowFix'],
},
{
date: '2026-11-04',
title: 'help.releaseSummaryV11104',
heading: 'help.releaseHeadingV11104',
updates: ['help.releaseLanguageUpdate', 'help.releaseFollowUpdate'],
},
]
const openRelease = ref<number | null>(0)
function close() {
emit('close')
}
function onKeydown(event: KeyboardEvent) {
if (event.key === 'Escape') close()
}
onMounted(() => window.addEventListener('keydown', onKeydown))
onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
</script>
<style scoped>
.help-overlay {
position: absolute; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center; padding: 72px 24px 28px;
box-sizing: border-box; background: var(--ui-backdrop); backdrop-filter: blur(3px);
}
.help-dialog {
width: min(820px, 100%); height: 100%; max-height: 100%; display: flex; flex-direction: column; overflow: hidden;
border: 1px solid var(--ui-border-strong); border-radius: 14px; background: var(--ui-surface); color: var(--ui-text-body);
box-shadow: 0 22px 70px rgba(0, 0, 0, .62);
}
.help-head {
position: relative; display: flex; align-items: flex-end; min-height: 82px; padding: 14px 52px 0 18px;
border-bottom: 1px solid var(--ui-border-subtle); background: linear-gradient(135deg, var(--ui-surface-raised), var(--ui-surface-soft));
}
.help-tabs { display: grid; width: 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.help-tab {
display: flex; min-width: 0; flex-direction: column; align-items: flex-start; justify-content: center; gap: 4px;
padding: 11px 14px 10px; border: 1px solid transparent; border-bottom: 0; border-radius: 9px 9px 0 0;
background: transparent; color: var(--ui-text-faint); font: inherit; text-align: left; cursor: pointer;
}
.help-tab strong { color: inherit; font-size: 19px; }
.help-tab small { overflow: hidden; width: 100%; color: inherit; font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.help-tab:hover { color: var(--ui-text-body); }
.help-tab.active { border-color: var(--ui-border-strong); background: var(--ui-surface); color: var(--ui-accent-text-soft); }
.help-tab:focus-visible { outline: 2px solid var(--ui-focus); outline-offset: -2px; }
.help-close {
position: absolute; top: 18px; right: 18px; width: 28px; height: 28px; border: 1px solid var(--ui-border-button); border-radius: 6px;
background: var(--ui-control-hover); color: var(--ui-text-body); cursor: pointer;
}
.help-close:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.help-body {
min-height: 0; overflow: auto; padding: 18px 20px 21px;
scrollbar-width: thin; scrollbar-color: var(--ui-scrollbar) transparent;
}
.help-body::-webkit-scrollbar { width: 6px; }
.help-body::-webkit-scrollbar-track { background: transparent; }
.help-body::-webkit-scrollbar-thumb { border-radius: 3px; background: var(--ui-scrollbar); }
.help-body::-webkit-scrollbar-thumb:hover { background: var(--ui-scrollbar-hover); }
.help-section { padding: 14px 15px; border: 1px solid var(--ui-border-strong); border-radius: 10px; background: var(--ui-surface-soft); }
.help-section h3 { margin: 0 0 11px; color: var(--ui-accent-text-muted); font-size: 13px; }
.help-start ol { margin: 0; padding-left: 21px; color: var(--ui-text-body); font-size: 12px; line-height: 1.75; }
.help-start li::marker { color: var(--ui-accent-strong); font-weight: 700; }
.help-section b { color: var(--ui-text-strong); }
.help-grid { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(250px, .85fr); gap: 12px; margin-top: 12px; }
.help-list { display: grid; gap: 0; margin: 0; }
.help-list > div { display: grid; grid-template-columns: 78px 1fr; gap: 9px; padding: 7px 0; border-bottom: 1px solid var(--ui-border-subtle); }
.help-list > div:last-child { border-bottom: 0; }
.help-list dt { color: var(--ui-text-strong); font-size: 11px; font-weight: 700; }
.help-list dd { margin: 0; color: var(--ui-text-faint); font-size: 11px; line-height: 1.5; }
.shortcut-list { display: grid; gap: 7px; }
.shortcut-list > div { display: flex; align-items: center; min-height: 25px; gap: 5px; }
.shortcut-list kbd {
min-width: 24px; box-sizing: border-box; padding: 3px 6px; border: 1px solid var(--ui-border-strong); border-bottom-width: 2px;
border-radius: 5px; background: var(--ui-control-deep); color: var(--ui-text-strong); font: 10px/1.2 ui-monospace, SFMono-Regular, Menlo, monospace; text-align: center;
}
.shortcut-list span { color: var(--ui-text-faint); font-size: 10px; }
.shortcut-list em { margin-left: auto; color: var(--ui-text-secondary); font-size: 11px; font-style: normal; }
.help-note { margin: 11px 0 0; padding-top: 9px; border-top: 1px solid var(--ui-border-subtle); color: var(--ui-text-faint); font-size: 10px; line-height: 1.55; }
.help-export { margin-top: 12px; }
.help-export p { margin: 0; color: var(--ui-text-faint); font-size: 11px; line-height: 1.65; }
.help-updates { display: grid; gap: 10px; }
.release-card { padding: 0; overflow: hidden; }
.release-head {
display: flex; width: 100%; align-items: center; gap: 11px; padding: 14px 15px; border: 0;
background: transparent; color: var(--ui-text-strong); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
.release-head time {
flex: 0 0 auto; padding: 3px 7px; border-radius: 5px; background: var(--ui-accent-soft);
color: var(--ui-accent-text-soft); font-size: 10px; font-weight: 700;
}
.release-head span { flex: 1; min-width: 0; font-weight: 700; }
.release-head b { color: var(--ui-text-faint); font-size: 12px; font-weight: 400; }
.release-head:hover, .release-card.open .release-head { background: var(--ui-nav-hover); color: var(--ui-text-primary); }
.release-card.open .release-head b { color: var(--ui-accent-text-muted); }
.release-body { margin: 0 15px; padding: 12px 0 14px; border-top: 1px solid var(--ui-border-subtle); }
.release-body p { margin: 0; color: var(--ui-text-faint); font-size: 12px; line-height: 1.7; }
.release-body ol { display: grid; gap: 7px; margin: 8px 0 0; padding-left: 21px; color: var(--ui-text-faint); font-size: 12px; line-height: 1.7; }
.release-body li::marker { color: var(--ui-accent-text-muted); font-weight: 700; }
.help-doc-title { margin: 16px 2px 2px; color: var(--ui-accent-text-muted); font-size: 13px; font-weight: 700; letter-spacing: .5px; }
.help-module { margin-top: 12px; }
.help-module-head {
display: flex; align-items: center; gap: 8px; width: 100%; padding: 0; border: 0; background: transparent;
color: var(--ui-accent-text-muted); font: inherit; font-size: 13px; font-weight: 700; text-align: left; cursor: pointer;
}
.help-module-head:hover { color: var(--ui-text-primary); }
.help-module-head .mtitle { flex: 1; min-width: 0; }
.help-module-head .caret { flex: 0 0 auto; color: var(--ui-text-faint); font-size: 12px; }
.help-module.open .help-module-head { color: var(--ui-text-primary); }
.help-module.open .help-module-head .caret { color: var(--ui-accent-text-muted); }
.help-module .mnum {
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
width: 22px; height: 22px; border-radius: 6px;
background: linear-gradient(135deg, var(--ui-accent-button), var(--ui-accent-button)); color: #fff; font-size: 12px; font-weight: 700;
}
.help-module.help-connector { border-color: var(--ui-accent-soft); background: linear-gradient(135deg, var(--ui-accent-soft), var(--ui-surface-soft)); }
.help-module.help-connector .help-module-head { color: var(--ui-accent-text-soft); }
.help-module .connector-intro { margin: 0 0 10px; color: var(--ui-text-body); font-size: 11px; line-height: 1.6; }
.help-module .connector-intro b { color: var(--ui-text-strong); }
.help-module .embed-intro { margin: 0 0 10px; color: var(--ui-text-body); font-size: 11px; line-height: 1.6; }
.help-module .embed-code {
margin: 0; padding: 11px 12px; overflow-x: auto; border: 1px solid var(--ui-border-strong); border-radius: 7px;
background: var(--ui-control-deep); color: var(--ui-text-body); font: 10px/1.65 ui-monospace, SFMono-Regular, Menlo, monospace;
user-select: text; white-space: pre; tab-size: 2;
}
.help-module .dl-link {
display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px; margin: 0 10px 6px 0; padding: 6px 12px;
border: 1px solid var(--ui-accent-button); border-radius: 6px; background: var(--ui-accent-bg); color: #fff; font-size: 12px; font-weight: 700; text-decoration: none;
}
.help-module .dl-link:hover { border-color: var(--ui-accent-bright); background: var(--ui-accent-bg-hover); }
.help-module .dl-link small { color: var(--ui-accent-text-soft); font-weight: 500; font-size: 9px; }
.help-module-body { padding-top: 10px; }
@media (max-width: 760px) {
.help-overlay { padding: 66px 12px 14px; }
.help-grid { grid-template-columns: 1fr; }
.help-head { padding-left: 10px; padding-right: 48px; }
.help-tab { padding: 9px 10px; }
.help-tab strong { font-size: 15px; }
.help-tab small { font-size: 9px; }
}
</style>