dsh-background-by-model 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -1
- package/CHANGELOG.zh.md +12 -1
- package/README.md +35 -18
- package/README.zh.md +35 -18
- package/lib/client.js +651 -47
- package/lib/client.js.map +1 -1
- package/lib/index.js +86 -8
- package/package.json +3 -2
package/lib/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":["BG_MODES","clamp","clamp","Component","useState","createPortal","useRef","memo","useRef","useState","useCallback","toHex","useState","useRef","toHex","useRef","useState","useCallback","useState","useRef","useCallback","useState","useRef","useRef","useState","useRef"],"sources":["../src/client/runtime.ts","../src/client/i18n.ts","../src/holiday.ts","../src/schema.ts","../src/client/state.ts","../src/client/rotation.ts","../src/client/repaint.ts","../src/client/rpc.ts","../src/client/utils/color.ts","../src/client/components/ui.css.ts","../src/client/wallpaper.ts","../src/client/modelbg.ts","../src/client/components/icons.tsx","../src/client/components/ErrorBoundary.tsx","../src/client/components/Portal.tsx","../src/client/components/LiveSlider.tsx","../src/client/components/pages/InterfacePage.tsx","../src/client/utils/image.ts","../src/client/components/ColorWheel.tsx","../src/client/components/ColorInputs.tsx","../src/client/components/ColorPicker.tsx","../src/client/components/BgEditor.tsx","../src/client/components/pages/ModelBgPage.tsx","../src/client/components/pages/ProfilePage.tsx","../src/client/components/ThemeSection.tsx","../src/client/index.tsx"],"sourcesContent":["/**\r\n * Harness-version-agnostic access to the client runtime.\r\n *\r\n * Before dsh 0.1.2 the store primitive lived on the composite package\r\n * `@deepseek-ai/dsh-client-runtime` (the `/client` subpath). The new harness\r\n * split it into `@deepseek-ai/dsh-client-store`. Both specifiers are kept\r\n * external so they resolve against the host client-module table; a missing\r\n * table entry on one side throws (the \"missed the module table\" error) and is\r\n * caught, falling through to the other package. This lets one bundle load on\r\n * both the old npm release and the new source.\r\n *\r\n * The host's synchronous `require` is injected by the loader into the bundle\r\n * factory; tsdown keeps these two bare specifiers as external CJS requires so\r\n * they bind to that factory `require`.\r\n */\r\n\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\ninterface StoreModule {\r\n defineStore: any\r\n}\r\n\r\nfunction resolveStore(): StoreModule {\r\n try {\r\n // New harness (dsh >= 0.1.2): dedicated store package after the runtime\r\n // was split. Missing here means the loader table has no such row → throw.\r\n return require('@deepseek-ai/dsh-client-store') as StoreModule\r\n } catch {\r\n /* fall through to the legacy composite runtime below */\r\n }\r\n // Legacy harness (npm release): composite runtime, /client subpath.\r\n return require('@deepseek-ai/dsh-client-runtime/client') as StoreModule\r\n}\r\n\r\nexport const defineStore: any = resolveStore().defineStore","export const NS = 'settings.anyBg'\r\n\r\nexport const zh: Record<string, string> = {\r\n nav: '模型背景', brandTag: '按模型换背景',\r\n pageInterface: '界面', pageModelBg: '模型背景', pageProfile: '配置',\r\n descInterface: '为主界面的各个区域单独调节透明度与模糊,营造空间层次感。这里的设置对所有模型生效',\r\n descModelBg: '每条规则 = 一个匹配串 + 一组背景图与外观。切换模型时,从上往下找第一条匹配串出现在模型名里的规则;都没中就使用第 1 条。一条规则可以放多张图,按你设的节奏轮换',\r\n descProfile: '把当前全部规则连同图片导出备份,或从文件一键恢复',\r\n\r\n uiTitle: '主界面',\r\n uiOpacity: '透明度', uiBlur: '模糊度',\r\n uiOpacityBg: '主背景', uiOpacitySide: '左侧栏', uiOpacityCard: '卡片与菜单面板', uiOpacityInput: '输入框与控件',\r\n uiSop: '设置界面透明度', uiChatRegion: '对话文本框', uiTrajectory: '轨迹页',\r\n uiPreview: '右侧栏',\r\n\r\n // Only the diagnostics survive: the model/rule readout they used to sit under\r\n // is gone (the match tester at the top of the page answers the same question).\r\n statusUnknownHint: '检测不到时一律使用第 1 条可用规则;切换一次模型或稍等片刻会自动重试',\r\n statusSourceDefaultHint: '只读到宿主默认模型,它不是本会话当前选择的模型;本会话的模型选择可用后会自动纠正',\r\n statusNoteNoService: '仍未拿到会话服务(会话控制器晚于本插件加载),正在自动重试',\r\n statusNoteNoSession: '会话服务已就绪,但还没有当前会话 id',\r\n statusNoteNoProjection: '拿不到本会话的模型选择投影(binding / projections 不可用)',\r\n statusNoteEmptySelection: '本会话的模型选择投影还没有值(切一次模型即可写入)',\r\n\r\n // Shown only when the running host process predates multi-image: the panel works\r\n // but holds its writes, and the user has to restart DSH to make them land.\r\n hostStaleHint: '检测到 DSH 主进程仍在运行旧版插件:新版配置格式它还读不懂,为避免丢规则,本次只改界面不写入配置。重启 DSH 后多图与轮换即可正常保存',\r\n tryoutTitle: '匹配试跑',\r\n tryoutPlaceholder: '输入模型名,如 deepseek-flash',\r\n tryoutUseCurrent: '填入当前模型',\r\n tryoutHit: '命中规则',\r\n tryoutFallback: '无匹配 · 走兜底规则',\r\n tryoutNone: '没有可用规则(规则需要启用,并且有图片或主题色)',\r\n tryoutEmpty: '输入模型名即可试跑',\r\n autoExtract: '选图后自动取主题色',\r\n ruleAdd: '新增规则',\r\n ruleFallbackBadge: '兜底',\r\n ruleMatchPlaceholder: '如 flash / glm(忽略大小写,留空则不参与匹配)',\r\n ruleEnabled: '启用',\r\n ruleUp: '上移', ruleDown: '下移', ruleRemove: '删除规则',\r\n ruleNoImage: '尚未选择图片',\r\n ruleFromUrl: '从网址', ruleUrlPlaceholder: '粘贴图片网址 https://…',\r\n ruleUrlApply: '应用', ruleUrlCancel: '取消', ruleUrlApplying: '加载中…',\r\n ruleUrlBadHttp: '仅支持 http/https 图片网址', ruleUrlFail: '获取图片失败',\r\n ruleImageRemove: '移除',\r\n ruleEmptyHint: '这条规则还没有图片,也没有自己的主题色:没有可显示的内容,匹配和兜底都会跳过它',\r\n // The other no-image state — the rule kept its own color, so it DOES paint.\r\n ruleColorOnlyHint: '这条规则还没有图片:不会铺壁纸,界面只用这个主题色',\r\n // Images exist but the selected one has no bytes (deleted outside DSH, or still\r\n // being read): saying \"this rule has no image\" there was simply wrong.\r\n ruleImagePendingHint: '这张图片还没有取到内容,稍后会自己出现(也可以直接替换它)',\r\n ruleColor: '主题色',\r\n ruleColorNone: '跟随系统主题',\r\n ruleColorNoneHint: '未设颜色时跟随系统主题:界面用宿主的配色,壁纸与各部位的透明度、模糊照旧生效',\r\n // Shown where a rule has NO color yet: pressing it picks a color, which is the\r\n // opposite of what the button above does, so it must not borrow that label.\r\n ruleColorPick: '自定义颜色',\r\n ruleColorPickHint: '优先从本图取色,取不到就用默认色',\r\n // Same button, but there is no image to extract from: promising an extraction\r\n // next to a disabled \"extract\" button is the one thing this hint cannot say.\r\n ruleColorNoImageHint: '这条规则还没有图片,取不到色:选一个颜色可以只铺主题色,或先添加图片',\r\n // …and its sibling: there IS an image, it just has no bytes yet. Saying \"this\r\n // rule has no image\" here would contradict the strip right above it.\r\n ruleColorPendingImageHint: '这张图片还没有取到内容,暂时取不了色:可以直接选一个颜色,或等它加载完',\r\n ruleColorExtract: '从本图提取',\r\n // Which of the two things the color controls below edit. A theme color belongs\r\n // to an image, so the same wheel means different things depending on the strip,\r\n // and a section that silently retargets is how \"I changed it and nothing\r\n // happened\" starts.\r\n ruleColorTargetImage: '作用于选中的图片:',\r\n ruleColorTargetRule: '作用于本规则(它还没有图片)',\r\n ruleLayout: '布局模式',\r\n ruleFramingEdit: '编辑位置',\r\n ruleOpacity: '背景透明度',\r\n ruleBlur: '背景模糊',\r\n ruleBlurHint: '背景模糊作用于壁纸层;界面页里的模糊作用于界面各区域,两者互不影响',\r\n\r\n // ── 多图轮换 ──────────────────────────────────────────────────────────────\r\n // 默认关闭:轮换会真的花流量、内存和电,不能靠\"默认\"偷偷替用户做主。\r\n rotTitle: '多图轮换',\r\n rotEnable: '轮换这组图',\r\n rotNeedTwo: '至少两张图才能轮换',\r\n rotEvery: '每张停留',\r\n rotCustom: '自定义秒数',\r\n rotSeconds: '秒',\r\n rotOrder: '换图顺序',\r\n rotOrderSeq: '按顺序',\r\n rotOrderShuffle: '随机',\r\n rotOnSwitch: '切换模型时也换一张',\r\n rotNext: '下一张',\r\n rotNextInactive: '只有正在生效的规则能换画面上的图',\r\n rotPos: '第',\r\n rotShowing: '正在显示',\r\n rotAddImage: '添加',\r\n // Replacing keeps the image's position in the rotation, so it is a different\r\n // action from adding and must not borrow that label.\r\n rotReplaceImage: '替换',\r\n rotDragHint: '拖动排序',\r\n rotDblHint: '双击切换',\r\n rotEvery10s: '10 秒', rotEvery30s: '30 秒', rotEvery1m: '1 分钟',\r\n rotEvery5m: '5 分钟', rotEvery30m: '30 分钟', rotEvery1h: '1 小时',\r\n\r\n\r\n bgModeFit: '适应', bgModeFill: '填充', bgModeStretch: '拉伸', bgModeTile: '平铺', bgModeCenter: '居中',\r\n editorTitle: '背景编辑器', editorHint: '拖动移动画面,滚轮缩放大小',\r\n editorCommit: '确认', editorCancel: '取消', editorReset: '重置',\r\n\r\n extracting: '取色中…',\r\n extractDone: '已应用图片配色',\r\n extractFail: '未在这张图里找到鲜明的颜色,请换一张',\r\n eyedropper: '从图片取色',\r\n pickerTitle: '从图片取色',\r\n pickerHint: '移动鼠标预览颜色,点击图片选取为主题色',\r\n pickerClose: '关闭',\r\n\r\n crashTitle: '界面渲染出错',\r\n crashDesc: '设置面板遇到问题,点击下方按钮重置后重试',\r\n crashReset: '重置面板',\r\n\r\n exportTheme: '导出配置', importTheme: '导入配置',\r\n exportCardTitle: '导出配置',\r\n exportCardDesc: '把全部规则、每条规则的颜色/布局/透明度/模糊与图片打包为 dsh-background-by-model-theme.json',\r\n importCardTitle: '导入配置',\r\n importCardDesc: '从之前导出的 JSON 文件一键恢复全部规则(会覆盖当前规则与图片)',\r\n toastExportDone: '配置文件已开始下载',\r\n importDone: '已导入配置',\r\n importFail: '导入失败,文件格式不正确',\r\n footerTag: '按模型换背景插件',\r\n\r\n // ── 节日特殊背景(默认开启;界面上只有一行开关)───────────────────────────\r\n holidayTitle: '节日特殊背景',\r\n holidayEnable: '启用节日特殊背景(中秋当天、国庆 10 月 1–7 日)',\r\n}\r\n\r\nexport const en: Record<string, string> = {\r\n nav: 'Model background', brandTag: 'Per-model wallpaper',\r\n pageInterface: 'Interface', pageModelBg: 'Model background', pageProfile: 'Profile',\r\n descInterface: 'Tune opacity and blur per surface to build depth. These settings are global and apply to every model',\r\n descModelBg: 'Each rule is a match string plus a set of wallpapers and one look. On a model switch the list is scanned top-down for the first match string contained in the model name; if nothing hits, rule 1 is used. A rule can hold several images and rotate through them on a rhythm you set',\r\n descProfile: 'Back up every rule together with its image, or restore one from a file',\r\n\r\n uiTitle: 'Interface',\r\n uiOpacity: 'Opacity', uiBlur: 'Blur',\r\n uiOpacityBg: 'Main background', uiOpacitySide: 'Left panel', uiOpacityCard: 'Cards & menus', uiOpacityInput: 'Input & controls',\r\n uiSop: 'Settings interface opacity', uiChatRegion: 'Conversation text frame', uiTrajectory: 'Trajectory view',\r\n uiPreview: 'Right panel',\r\n\r\n // Only the diagnostics survive: the model/rule readout they used to sit under\r\n // is gone (the match tester at the top of the page answers the same question).\r\n statusUnknownHint: 'Without a detected model rule 1 is always used; switching the model once or waiting a moment retries automatically',\r\n statusSourceDefaultHint: 'Only the host-wide default model could be read — that is not necessarily this session\\'s selection. It self-corrects once this session\\'s model selection is available.',\r\n statusNoteNoService: 'The sessions service is not available yet (the session controller loads after this plugin); retrying automatically',\r\n statusNoteNoSession: 'The sessions service is up but reports no current session yet',\r\n statusNoteNoProjection: 'This session\\'s model-selection projection is unreachable (no binding / projections)',\r\n statusNoteEmptySelection: 'The model-selection projection exists but carries no value yet (selecting a model once writes it)',\r\n\r\n // Shown only when the running host process predates multi-image: the panel works\r\n // but holds its writes, and the user has to restart DSH to make them land.\r\n hostStaleHint: 'The DSH host process is still running the older plugin, which cannot read the new config shape. To avoid dropping rules, this session changes the interface but holds every config write — restart DSH and multi-image plus rotation will save normally',\r\n tryoutTitle: 'Match test',\r\n tryoutPlaceholder: 'Type a model name, e.g. deepseek-flash',\r\n tryoutUseCurrent: 'Use current model',\r\n tryoutHit: 'matches rule',\r\n tryoutFallback: 'no match · fallback rule',\r\n tryoutNone: 'No usable rule (a rule needs to be enabled and carry an image or a theme color)',\r\n tryoutEmpty: 'Type a model name to test the list',\r\n autoExtract: 'Extract the theme color when an image is chosen',\r\n ruleAdd: 'Add rule',\r\n ruleFallbackBadge: 'fallback',\r\n ruleMatchPlaceholder: 'e.g. flash / glm (case-insensitive, empty never matches)',\r\n ruleEnabled: 'Enabled',\r\n ruleUp: 'Move up', ruleDown: 'Move down', ruleRemove: 'Remove rule',\r\n ruleNoImage: 'No image yet',\r\n ruleFromUrl: 'From URL', ruleUrlPlaceholder: 'Paste an image URL https://…',\r\n ruleUrlApply: 'Apply', ruleUrlCancel: 'Cancel', ruleUrlApplying: 'Loading…',\r\n ruleUrlBadHttp: 'Only http/https image URLs are supported', ruleUrlFail: 'Could not fetch the image',\r\n ruleImageRemove: 'Remove',\r\n ruleEmptyHint: 'This rule has no image and no theme color of its own: it has nothing to show, so matching and the fallback both skip it',\r\n // The other no-image state — the rule kept its own color, so it DOES paint.\r\n ruleColorOnlyHint: 'No image in this rule yet: no wallpaper is shown, and the interface is painted from this theme color alone',\r\n // Images exist but the selected one has no bytes (deleted outside DSH, or still\r\n // being read): saying \"this rule has no image\" there was simply wrong.\r\n ruleImagePendingHint: 'This image has no content yet — it appears once it loads; you can also replace it',\r\n ruleColor: 'Theme color',\r\n ruleColorNone: 'Follow system theme',\r\n ruleColorNoneHint: 'Without a color this rule follows the system theme: the host palette paints the interface while the wallpaper and every opacity/blur slider keep working',\r\n // Shown where a rule has NO color yet: pressing it picks a color, which is the\r\n // opposite of what the button above does, so it must not borrow that label.\r\n ruleColorPick: 'Custom color',\r\n ruleColorPickHint: 'Extracts from this image when it can, otherwise uses a default color',\r\n // Same button, but there is no image to extract from: promising an extraction\r\n // next to a disabled \"extract\" button is the one thing this hint cannot say.\r\n ruleColorNoImageHint: 'This rule has no image to take a color from: pick a color to tint the interface alone, or add an image first',\r\n // …and its sibling: there IS an image, it just has no bytes yet. Saying \"this\r\n // rule has no image\" here would contradict the strip right above it.\r\n ruleColorPendingImageHint: 'This image has no content yet, so there is nothing to extract from: pick a color directly, or wait for it to load',\r\n ruleColorTargetImage: 'Applies to the selected image:',\r\n ruleColorTargetRule: 'Applies to this rule (it has no image yet)',\r\n ruleColorExtract: 'Extract from image',\r\n ruleLayout: 'Layout mode',\r\n ruleFramingEdit: 'Edit position',\r\n ruleOpacity: 'Background opacity',\r\n ruleBlur: 'Background blur',\r\n ruleBlurHint: 'Background blur affects the wallpaper layer; the blur on the Interface page affects interface surfaces — they are independent',\r\n\r\n // ── Multi-image rotation ──────────────────────────────────────────────────\r\n // Off by default: rotating really does spend bandwidth, memory and battery,\r\n // and no default should quietly decide that for the user.\r\n rotTitle: 'Image rotation',\r\n rotEnable: 'Rotate these images',\r\n rotNeedTwo: 'At least two images are needed to rotate',\r\n rotEvery: 'Dwell time per image',\r\n rotCustom: 'Custom seconds',\r\n rotSeconds: 's',\r\n rotOrder: 'Order',\r\n rotOrderSeq: 'In order',\r\n rotOrderShuffle: 'Shuffle',\r\n rotOnSwitch: 'Also step on a model switch',\r\n rotNext: 'Next image',\r\n rotNextInactive: 'Only the active rule can step the background',\r\n rotPos: 'Image',\r\n rotShowing: 'On screen',\r\n rotAddImage: 'Add',\r\n // Replacing keeps the image's position in the rotation, so it is a different\r\n // action from adding and must not borrow that label.\r\n rotReplaceImage: 'Replace',\r\n rotDragHint: 'drag to reorder',\r\n rotDblHint: 'double-click to show',\r\n rotEvery10s: '10 s', rotEvery30s: '30 s', rotEvery1m: '1 min',\r\n rotEvery5m: '5 min', rotEvery30m: '30 min', rotEvery1h: '1 h',\r\n\r\n\r\n bgModeFit: 'Fit', bgModeFill: 'Fill', bgModeStretch: 'Stretch', bgModeTile: 'Tile', bgModeCenter: 'Center',\r\n editorTitle: 'Background editor', editorHint: 'Drag to move, scroll to zoom',\r\n editorCommit: 'Confirm', editorCancel: 'Cancel', editorReset: 'Reset',\r\n\r\n extracting: 'Extracting…',\r\n extractDone: 'Image colors applied',\r\n extractFail: 'No vivid color found in this image, try another',\r\n eyedropper: 'Eyedropper',\r\n pickerTitle: 'Pick from image',\r\n pickerHint: 'Hover to preview, click to pick as the theme color',\r\n pickerClose: 'Close',\r\n\r\n crashTitle: 'Section crashed',\r\n crashDesc: 'The panel hit an error. Reset below to recover.',\r\n crashReset: 'Reset panel',\r\n\r\n exportTheme: 'Export', importTheme: 'Import',\r\n exportCardTitle: 'Export profile',\r\n exportCardDesc: 'Bundle every rule — color, layout, opacity, blur — and its image into dsh-background-by-model-theme.json',\r\n importCardTitle: 'Import profile',\r\n importCardDesc: 'Restore every rule and image from a previously exported JSON file (replaces the current set)',\r\n toastExportDone: 'Export started',\r\n importDone: 'Profile imported',\r\n importFail: 'Import failed — invalid file',\r\n footerTag: 'Per-model wallpaper plugin',\r\n\r\n // ── Holiday overrides (on by default; one switch, no cards) ───────────────\r\n holidayTitle: 'Holiday backgrounds',\r\n holidayEnable: 'Enable holiday backgrounds (Mid-Autumn day, Oct 1–7)',\r\n}\r\n","/**\n * The built-in holiday calendar behind the \"holiday background\" override.\n *\n * Imported by BOTH halves — the node half only reads `HOLIDAYS` (the fixed slot\n * ids and the bundled asset names), the browser half does the date maths — so\n * nothing here may touch the DOM, Node or the Cordis context, and every\n * `Intl` formatter is built lazily so the node half never constructs one.\n *\n * Both holidays are evaluated in **Asia/Shanghai**, not in the machine's own\n * zone: 中秋 is a lunar date, and the lunar day rolls over at Beijing midnight,\n * so reading \"today\" from a UTC or UTC-8 clock puts the festival on the wrong\n * day for most of the planet.\n *\n * mid-autumn 农历八月十五 — moves across the Gregorian calendar\n * (2024-09-17, 2025-10-06, 2026-09-25, 2027-09-15 …)\n * national-day 公历 10 月 1–7 日 — the fixed National Day holiday window\n */\n\nexport type HolidayId = 'mid-autumn' | 'national-day'\n\nexport interface HolidayDef {\n id: HolidayId\n /**\n * Image slot holding this holiday's wallpaper. Fixed, and namespaced with an\n * `h-` prefix so it can never collide with a rule slot (`nextSlot` only ever\n * hands out `m<n>`, and slots are what reach the filesystem).\n */\n slot: string\n /** Wallpaper bundled inside the package under `holiday/`. */\n asset: string\n /**\n * The theme color this holiday paints with, as `#RRGGBB`.\n *\n * Fixed, and fixed HERE — beside the slot and the art — rather than derived\n * from the wallpaper: the palette of a festival is a design decision, and\n * decoding a 3456×1920 photo to re-derive the same hue was both slower and\n * less predictable than naming it. ./schema turns this into the `[h, s, l]`\n * triple the rule shape stores, and takes it from the definition rather than\n * from disk, so a config can never paint a festival in a color it does not\n * have.\n */\n color: string\n /** How the window is computed — also drives the \"next occurrence\" scan. */\n kind: 'lunar' | 'gregorian'\n}\n\nexport const HOLIDAYS: readonly HolidayDef[] = [\n { id: 'mid-autumn', slot: 'h-midautumn', asset: 'mid-autumn.webp', color: '#384A77', kind: 'lunar' },\n { id: 'national-day', slot: 'h-nationalday', asset: 'national-day.webp', color: '#FFF6EB', kind: 'gregorian' },\n]\n\n/** 中秋 always falls between these two Gregorian days, so a scan can skip the rest. */\nconst MID_AUTUMN_FROM = { m: 9, d: 7 }\nconst MID_AUTUMN_TO = { m: 10, d: 8 }\n\nexport function holidayDef(id: string): HolidayDef | null {\n return HOLIDAYS.find(h => h.id === id) ?? null\n}\n\nexport function isHolidayId(id: string): id is HolidayId {\n return HOLIDAYS.some(h => h.id === id)\n}\n\n/** The slot a holiday's wallpaper lives in; '' for an unknown id. */\nexport function holidaySlot(id: string): string {\n return holidayDef(id)?.slot ?? ''\n}\n\n// ── Calendar primitives ────────────────────────────────────────────────────\n// Both formatters are optional: a build without full ICU (a small-icu Node, an\n// exotic browser) simply cannot answer, and every caller degrades to \"no\n// holiday\" instead of throwing inside a render.\n\nconst TZ = 'Asia/Shanghai'\n\nlet civilFormatter: Intl.DateTimeFormat | null | undefined\nfunction civilFmt(): Intl.DateTimeFormat | null {\n if (civilFormatter === undefined) {\n try {\n civilFormatter = new Intl.DateTimeFormat('en-US', {\n timeZone: TZ, year: 'numeric', month: 'numeric', day: 'numeric',\n })\n } catch {\n civilFormatter = null\n }\n }\n return civilFormatter\n}\n\nlet lunarFormatter: Intl.DateTimeFormat | null | undefined\nfunction lunarFmt(): Intl.DateTimeFormat | null {\n if (lunarFormatter === undefined) {\n try {\n lunarFormatter = new Intl.DateTimeFormat('en-u-ca-chinese', {\n timeZone: TZ, year: 'numeric', month: 'numeric', day: 'numeric',\n })\n } catch {\n lunarFormatter = null\n }\n }\n return lunarFormatter\n}\n\nfunction partsOf(fmt: Intl.DateTimeFormat, date: Date): Record<string, string> | null {\n try {\n const out: Record<string, string> = {}\n for (const p of fmt.formatToParts(date)) {\n if (p.type !== 'literal') out[p.type] = p.value\n }\n return out\n } catch {\n return null\n }\n}\n\n/** The civil (Gregorian) date in Asia/Shanghai, or null when ICU cannot answer. */\nexport function shanghaiDate(date: Date): { y: number; m: number; d: number } | null {\n const fmt = civilFmt()\n if (fmt === null) return null\n const p = partsOf(fmt, date)\n if (p === null) return null\n const y = Number(p.year)\n const m = Number(p.month)\n const d = Number(p.day)\n if (!isFinite(y) || !isFinite(m) || !isFinite(d)) return null\n return { y, m, d }\n}\n\n/** `YYYY-MM-DD` of one Asia/Shanghai civil date. */\nexport function civilKey(date: { y: number; m: number; d: number }): string {\n return `${date.y}-${String(date.m).padStart(2, '0')}-${String(date.d).padStart(2, '0')}`\n}\n\n/**\n * The Chinese-calendar month and day in Asia/Shanghai.\n *\n * ICU marks a **leap** month by suffixing `bis` — a leap fourth month reads\n * `4bis`, a leap eighth month would read `8bis`. 中秋 is the FIFTEENTH DAY OF THE\n * REGULAR EIGHTH MONTH, so the exact `month === '8'` test below is what keeps a\n * leap eighth month (which does occur, roughly once every few decades) from\n * dragging the festival a month late.\n */\nexport function lunarMonthDay(date: Date): { month: string; day: string } | null {\n const fmt = lunarFmt()\n if (fmt === null) return null\n const p = partsOf(fmt, date)\n if (p === null || p.month === undefined || p.day === undefined) return null\n return { month: p.month, day: p.day }\n}\n\n// ── The two windows ────────────────────────────────────────────────────────\n\n/** 农历八月十五, in the regular eighth month — i.e. 中秋 itself. */\nexport function isMidAutumn(date: Date = new Date()): boolean {\n const lunar = lunarMonthDay(date)\n return lunar !== null && lunar.month === '8' && lunar.day === '15'\n}\n\n/** 公历 10 月 1–7 日 — the National Day holiday period. */\nexport function isNationalDay(date: Date = new Date()): boolean {\n const civil = shanghaiDate(date)\n return civil !== null && civil.m === 10 && civil.d >= 1 && civil.d <= 7\n}\n\n/**\n * The holiday whose window contains `date`, or null.\n *\n * 中秋 wins the overlap: it is a single precise day, while National Day is a\n * seven-day window, and the two do collide (2025-10-06 was both). On a tie the\n * rarer, more specific answer is the better one.\n */\nexport function activeHoliday(date: Date = new Date()): HolidayId | null {\n if (isMidAutumn(date)) return 'mid-autumn'\n if (isNationalDay(date)) return 'national-day'\n return null\n}\n\n/**\n * The next Asia/Shanghai civil date on which `id` starts, as `YYYY-MM-DD`, or\n * null when the calendar is unavailable.\n *\n * The scan is anchored at 04:00 UTC — noon in Beijing, and Shanghai has no DST —\n * so stepping a whole day at a time can never skip or repeat a civil date. Days\n * outside the possible window of a lunar holiday are skipped before the\n * (expensive) lunar lookup, which is what keeps this cheap enough to run while\n * the settings page renders.\n */\nexport function nextHolidayStart(id: HolidayId, from: Date = new Date()): string | null {\n const start = shanghaiDate(from)\n if (start === null) return null\n const anchor = Date.UTC(start.y, start.m - 1, start.d, 4)\n for (let i = 0; i < 400; i++) {\n const probe = new Date(anchor + i * 86_400_000)\n const civil = shanghaiDate(probe)\n if (civil === null) return null\n // A day that cannot hold this holiday is skipped BEFORE the lunar lookup,\n // which is what makes a year-long scan cheap enough to run while the\n // settings page renders.\n if (holidayDef(id)?.kind === 'lunar' && !inMidAutumnRange(civil)) continue\n if (activeHoliday(probe) === id) return civilKey(civil)\n }\n return null\n}\n\nfunction inMidAutumnRange(civil: { m: number; d: number }): boolean {\n if (civil.m === MID_AUTUMN_FROM.m) return civil.d >= MID_AUTUMN_FROM.d\n if (civil.m === MID_AUTUMN_TO.m) return civil.d <= MID_AUTUMN_TO.d\n return false\n}\n\n// ── Which holiday overrides the rules right now ────────────────────────────\n\n/**\n * The bits of a holiday entry the picker needs. Structural on purpose: the\n * persisted shape lives in ./schema, and this module importing THAT would close a\n * cycle, since ./schema imports `HOLIDAYS` from here.\n *\n * The image LIST (rather than one slot) is what a rule owns since 0.7, and this\n * mirrors just enough of it to ask the picker's only question: \"is there anything\n * to paint?\". A holiday's own list is always the single packaged image (see\n * `defaultHolidayRule`), so the shape stays a formality for it — and a rule that\n * happens to be passed in answers through the same field.\n */\nexport interface HolidayCandidate {\n id: string\n enabled: boolean\n images: readonly { slot: string }[]\n}\n\n/**\n * The holiday the background must follow right now, or null.\n *\n * Four gates, every one of them deliberate:\n *\n * 1. the master switch — an override that discards the user's rule list must\n * never happen without being asked for;\n * 2. a built-in holiday whose window contains today;\n * 3. that holiday's own switch;\n * 4. actual bytes in its slot.\n *\n * The last one matters most, and it is the reason this is not a one-liner at the\n * call site: a switched-on holiday with no image at all has to fall through to\n * the model rules, not blank the wallpaper.\n *\n * It lives here, as a pure function, so the decision is covered by\n * `scripts/holiday-check.ts` instead of hiding inside the plugin's apply closure\n * where nothing can reach it.\n */\nexport function pickHoliday<T extends HolidayCandidate>(\n master: boolean,\n items: readonly T[],\n todayId: HolidayId | null,\n hasImage: (slot: string) => boolean,\n): T | null {\n if (!master || todayId === null) return null\n const item = items.find(i => i.id === todayId)\n if (item === undefined || !item.enabled) return null\n return item.images.some(image => hasImage(image.slot)) ? item : null\n}\n","/**\n * The persisted configuration shape — declared exactly ONCE, for both halves.\n *\n * This shape used to be written out twice: the node half owns persistence and\n * sanitizes every write, the browser half owns the UI and its own reading of the\n * same file. A field added to only one side was silently dropped by the other\n * side's sanitizer — the matching slider stayed live in memory, `writeConfig`\n * wrote a config without it, and the next load fell back to the default.\n * `blurs.rightbar` / `rightbarOpacity` in 0.3.2 was exactly that bug, and the key\n * lists were duplicated 6 times across the two halves, so it was due to happen.\n *\n * The types, the key lists, the defaults and the pure normalizers therefore live\n * here and both halves import them: adding a field means editing this file, and\n * the two halves cannot disagree about the shape. The host additionally logs one\n * warning per unknown key while sanitizing a write (see `warnUnknownConfigKeys`\n * in `src/index.ts`), so a field that reaches the node half without being\n * declared here shows up in the host log instead of quietly disappearing.\n *\n * Nothing in this module may touch the DOM, Node or the Cordis context: it is\n * imported by the browser bundle and by the node half alike.\n */\n\nimport { HOLIDAYS } from './holiday'\nimport type { HolidayDef } from './holiday'\n\n/** Placement state of one background image (zoom + fractional center + intrinsic size). */\nexport interface BgState { zoom: number; x: number; y: number; iw: number; ih: number }\n\nexport const DEFAULT_BG_STATE: BgState = { zoom: 1, x: 0, y: 0, iw: 0, ih: 0 }\n\n/**\n * One image of a rule: its slot, plus everything that belongs to THAT image —\n * its framing and its theme color.\n *\n * The framing is per image rather than per rule because a crop is a property of\n * a picture: two wallpapers with different aspect ratios share the rule's\n * `bgMode`, opacity and blur, but a single `fit` framing computed for one of\n * them is simply wrong for the other.\n *\n * The theme color is per image for the same reason one step further out: a rule\n * is a rotation through several pictures, and pictures that were collected for\n * different moods do not share one accent. A rule's own `color` therefore means\n * something narrower than it used to (see `BgRule.color`) — it is what a rule\n * with no image left paints.\n */\nexport interface BgImage {\n /** Image slot; the bytes live in `modelbg-<slot>` under the data dir. */\n slot: string\n /** This image's framing (zoom + fractional center + intrinsic size). */\n bgState: BgState\n /**\n * This image's own theme color as `[h, s, l]`, or null for \"follow the system\n * theme while THIS image is on screen\".\n *\n * Null is an opinion, not an absence: it is the state the clear button puts an\n * image in, and it is deliberately NOT the rule's color — an image's color is\n * the image's, which is what makes a rotation through a green, a red and a\n * system-themed picture expressible at all. The rule's own color only applies\n * when the rule has no image to speak for it.\n *\n * Written by every release from 0.7.1 on. An entry that predates the field has\n * no `color` KEY at all, which is exactly how `normalizeImage` tells \"this\n * image never had a color of its own\" from \"this image was explicitly cleared\"\n * — and why the rule's color is lifted onto such an entry on read rather than\n * being quietly dropped.\n */\n color: [number, number, number] | null\n}\n\n/** Adaptive placement of a background image. */\nexport type BgMode = 'fit' | 'fill' | 'stretch' | 'tile' | 'center'\n\n/** Every accepted `bgMode`, in UI order. */\nexport const BG_MODES: readonly BgMode[] = ['fit', 'fill', 'stretch', 'tile', 'center']\n\n// ── Multi-image rotation ───────────────────────────────────────────────────\n\n/** How a rule walks its own image list. */\nexport type RotateOrder = 'order' | 'shuffle'\n\n/** Every accepted `rotate.order`, in UI order. */\nexport const ROTATE_ORDERS: readonly RotateOrder[] = ['order', 'shuffle']\n\n/** Fastest allowed dwell time — below this the cross-fade never settles. */\nexport const ROTATE_MIN_MS = 5_000\n/** Slowest allowed dwell time (24 h): one image per day is still \"rotation\". */\nexport const ROTATE_MAX_MS = 24 * 60 * 60 * 1000\n/** Longest allowed cross-fade; 0 is a hard cut. */\nexport const ROTATE_FADE_MAX_MS = 3_000\n\n/**\n * Multi-image rotation, per rule.\n *\n * OFF by default, and that is a deliberate product decision: switching images by\n * itself costs memory, bandwidth and CPU on a wallpaper that nobody asked to\n * animate. `intervalMs` is the dwell time, `order` picks the next image, and\n * `advanceOnSwitch` also steps once when the model switch lands on this rule —\n * so a model can have \"a different picture every time\" without any timer at all.\n */\nexport interface BgRotation {\n enabled: boolean\n /** Dwell time per image, ms (`ROTATE_MIN_MS`..`ROTATE_MAX_MS`). */\n intervalMs: number\n /** `order` walks the list top-down; `shuffle` never repeats the current image. */\n order: RotateOrder\n /** Step once when this rule becomes the active one. */\n advanceOnSwitch: boolean\n /** Cross-fade duration in ms (0 = hard cut, max `ROTATE_FADE_MAX_MS`). */\n fadeMs: number\n}\n\n/** Everything off: the shipped default, and what a config predating this feature gets. */\nexport const DEFAULT_ROTATION: BgRotation = {\n enabled: false,\n intervalMs: 60_000,\n order: 'order',\n advanceOnSwitch: false,\n fadeMs: 320,\n}\n\n/** A fresh rotation block (never hand out the shared default object). */\nexport function defaultRotation(): BgRotation { return { ...DEFAULT_ROTATION } }\n\n/**\n * Main interface opacities (0..1), global (Interface page):\n * `bg` main background (`--dsw-alias-bg-base`)\n * `sidebar` sidebar (`--dsw-specific-sidebar-fill`)\n * `card` cards/panels (`--dsw-alias-bg-layer-1/2/3`, `--dsw-specific-menu`\n * and its 0.1.7 alias `--dsw-menu-surface-fill`)\n * `input` input/control surfaces (`--dsw-specific-input-major`)\n */\nexport const PART_OPACITY_KEYS = ['bg', 'sidebar', 'card', 'input'] as const\n\n/** Per-part main interface opacities (0..1), keyed BY the list above. */\nexport type PartOpacities = Record<(typeof PART_OPACITY_KEYS)[number], number>\n\nexport const DEFAULT_PART_OPACITIES: PartOpacities = { bg: 0.85, sidebar: 0.93, card: 1, input: 1 }\n\n/**\n * Interface blur (px, 0..60), global (Interface page):\n * `bg` main background (AppFrame grid)\n * `sidebar` sidebar column\n * `card` cards/panels (center + details columns, dialog option panels)\n * `settings` settings panel\n * `chat` conversation text region (message column of the chat view)\n * `trajectory` trajectory view surface\n * `rightbar` file-preview panel — the right sidebar a file click opens\n * `input` input/control surfaces ([data-composer-card], [data-cordis-panel])\n */\nexport const PART_BLUR_KEYS = ['bg', 'sidebar', 'card', 'settings', 'chat', 'trajectory', 'rightbar', 'input'] as const\n\n/** Per-part interface blur (px, 0..60), keyed BY the list above. */\nexport type PartBlurs = Record<(typeof PART_BLUR_KEYS)[number], number>\n\nexport const DEFAULT_PART_BLURS: PartBlurs = {\n bg: 0, sidebar: 0, card: 0, settings: 0, chat: 0, trajectory: 0, rightbar: 0, input: 0,\n}\n\n/**\n * One model rule: a match string plus everything the background needs while it\n * is the active rule. Every appearance field lives HERE rather than globally —\n * the settings UI edits a rule, and the render layer follows whichever rule the\n * current model selected.\n */\nexport interface BgRule {\n /** Stable id; also the render key. */\n id: string\n /**\n * Case-insensitive substring tested against the current model text (provider,\n * model id and display name joined with spaces). An EMPTY string never matches\n * on its own — that rule then only ever serves as the fallback.\n */\n match: string\n /**\n * The rule's images, in order. `images[0]` is the one painted when no rotation\n * is running. The list may legitimately be EMPTY (every picture removed): the\n * rule then paints its own theme color alone, or nothing at all when it has no\n * color either — see `ruleCanPaint`, which is what matching asks.\n *\n * This replaced the single `slot`/`bgState` pair in 0.7.0. A config written by\n * an earlier version is lifted to `[{ slot, bgState }]` on read (see\n * `normalizeRule`), so both shapes live on ONE in-memory shape and only the new\n * one is ever written back — the same \"declare it once\" rule as this file's\n * header.\n */\n images: BgImage[]\n /** Disabled rules are skipped by matching AND by the fallback pick. */\n enabled: boolean\n /**\n * The theme color of the rule ITSELF: what an image-less rule paints the\n * interface from. Null = that rule falls back to the system theme.\n *\n * It is not a default for the rule's images — each of those carries its own\n * (`BgImage.color`) and never inherits this one at paint time. The only\n * inheritance that exists is a one-shot LIFT at read time for configs written\n * before per-image colors, so a rule that was themed before 0.7.1 comes back\n * looking exactly the same (see `normalizeImage`).\n */\n color: [number, number, number] | null\n bgMode: BgMode\n /** Wallpaper layer opacity (0..1). */\n wallpaperOpacity: number\n /** Wallpaper layer blur (px, 0..60) — NOT the interface part blur. */\n blur: number\n /** How the rule cycles `images`; off by default. */\n rotate: BgRotation\n}\n\n/** Every slot a rule owns, in order. The one thing the render and store layers\n * ask of the image list, so a rule's slots are never enumerated ad hoc. */\nexport function ruleSlots(rule: BgRule): string[] {\n return rule.images.map(i => i.slot)\n}\n\n/**\n * Whether a rule has anything to show at all: an image, or a theme color of its\n * own. Used by matching (`usable` in ./client/modelbg) and by the panel's copy.\n *\n * An image is the obvious way a rule paints, and until 0.7 it was the ONLY one —\n * which stopped being true the moment the last image became removable. A\n * rule-level theme color is the second: it recolors the interface through the\n * token palette with no wallpaper involved, so a rule whose pictures were all\n * removed still paints, and treating it as unusable made every control left on\n * its card (the wheel, the swatches, the clear-to-system-theme button) dead — the\n * one state where the panel was confidently showing a lie. It also silently\n * handed the model to the NEXT rule, so clearing the default rule's images put\n * another model's wallpaper on the screen.\n *\n * Note that a per-image color (0.7.1) does not enter this question at all: an\n * image is already enough, so the answer here is about the IMAGE LIST being\n * non-empty, never about what those images are painted in.\n *\n * A rule with no image and no color of its own paints nothing: the system theme\n * is not a paint of this rule's own, so such a rule is skipped by matching, which\n * is what makes a freshly added rule (empty, colorless) invisible until the user\n * gives it something.\n */\nexport function ruleCanPaint(rule: BgRule): boolean {\n return rule.enabled && (ruleSlots(rule).length > 0 || rule.color !== null)\n}\n\n/**\n * One built-in holiday override.\n *\n * Deliberately the SAME shape as a rule — an alias rather than an extension: the\n * render layer resolves whatever `ruleById` returns, so making a holiday a rule\n * is what lets the wallpaper, the theme color, the layout mode and the framing\n * all work without a second code path. `id` and `slot` are fixed by `HOLIDAYS` —\n * the sanitizer overwrites them from the definition, so a hand-edited config can\n * never point a holiday at another rule's slot.\n *\n * There is deliberately nothing here about the IMAGE. A holiday's wallpaper is\n * the one bundled in the package (under `holiday/`), the node half serves it\n * straight out of there, and a holiday slot is read-only — no entry point takes\n * bytes for it. The feature is an easter egg, not a thing to configure.\n *\n * Its theme colors are forced from the definition for the same reason, one level\n * deeper: a holiday's color belongs to it, so `normalizeHolidayRule` rewrites both\n * the rule's color and every image's. That is also what makes a future holiday\n * with SEVERAL pictures (a rotation through festival art, each piece with its own\n * palette) a change to `HOLIDAYS` and its assets alone, rather than a second code\n * path in the render layer.\n */\nexport type HolidayRule = BgRule\n\n/** The holiday override: one master switch plus one entry per built-in holiday. */\nexport interface HolidaysConfig {\n /**\n * While on, a holiday whose window contains today replaces the rule the model\n * resolved to. On unless it is explicitly turned off — the switch on the Config\n * page is an off-ramp, not an opt-in.\n */\n enabled: boolean\n /** One entry per `HOLIDAYS` definition, in that order. */\n items: HolidayRule[]\n}\n\n/** The persisted plugin configuration. */\nexport interface ThemeConfig { /** Ordered rules: matching runs top→bottom, rule 1 doubles as the fallback. */\n rules: BgRule[]\n /** Global per-part opacities (Interface page). */\n opacities: PartOpacities\n /** Global per-part blur (Interface page). */\n blurs: PartBlurs\n /** Settings-panel opacity (0..1). */\n settingsOpacity: number\n /** Translucent tint over the conversation text region (0 = none, 1 = solid). */\n chatTextOpacity: number\n /** Translucent tint over the trajectory view surface (0 = none, 1 = solid). */\n trajectoryOpacity: number\n /**\n * Surface opacity of the file-preview panel (0..1). `null` = never touched, so\n * the panel keeps following `opacities.bg`: the panel's only surface IS\n * `--dsw-alias-bg-base`, which the main-background slider already re-emits, so\n * an untouched card must stay indistinguishable from the interface behind it.\n */\n rightbarOpacity: number | null\n /**\n * Extract a rule's theme color from its own image when the rule has none yet.\n * Only ever FILLS an empty color — a color the user picked or that an earlier\n * extraction produced is never overwritten, so this cannot fight the user.\n */\n autoExtract: boolean\n /** Built-in holiday overrides (中秋 / 国庆), switched off as a whole. */\n holidays: HolidaysConfig\n}\n\n/** 100% = untouched host surface; zero would blank the page by default. */\nexport const DEFAULT_SETTINGS_OPACITY = 1\nexport const DEFAULT_CHAT_TEXT_OPACITY = 0\n/** 100% = untouched host surface; zero would blank the page by default. */\nexport const DEFAULT_TRAJECTORY_OPACITY = 1\n/** `null` = the file-preview panel still follows the main background. */\nexport const DEFAULT_RIGHTBAR_OPACITY: number | null = null\n/** Picking an image should just work; the toggle is there for people who don't want it. */\nexport const DEFAULT_AUTO_EXTRACT = true\n/**\n * Holiday overrides are ON out of the box: the point is that the background\n * changes by itself on the day and changes back the next morning. The single\n * switch on the Config page is the off-ramp, so only an explicit `false` turns\n * the feature off.\n */\nexport const DEFAULT_HOLIDAYS_ENABLED = true\n\n/**\n * `#RRGGBB` → the `[h, s, l]` triple every rule stores (`s` and `l` in 0..1), or\n * null when the string is not a hex color.\n *\n * A holiday names its color as hex because that is how a color is quoted, and a\n * hand-converted triple is a magic number nothing downstream can check. The\n * conversion lives here rather than in ./holiday because `[h, s, l]` is this\n * module's own rule shape.\n */\nexport function hexToHsl(hex: string): [number, number, number] | null {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim())\n if (m === null) return null\n const n = parseInt(m[1]!, 16)\n const r = ((n >> 16) & 0xff) / 255\n const g = ((n >> 8) & 0xff) / 255\n const b = (n & 0xff) / 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n const l = (max + min) / 2\n const d = max - min\n // Grey: no hue to name, and the saturation formula below would divide by zero.\n if (d === 0) return [0, 0, l]\n const s = d / (1 - Math.abs(2 * l - 1))\n let h: number\n if (max === r) h = 60 * (((g - b) / d) % 6)\n else if (max === g) h = 60 * ((b - r) / d + 2)\n else h = 60 * ((r - g) / d + 4)\n if (h < 0) h += 360\n // Clamped like every other color this module stores: the float arithmetic\n // above lands a hair outside the range on a saturated input (a pure #FFF6EB\n // gives s = 1.0000000000000008), and that would travel into the token\n // generator as an out-of-range channel.\n return [clamp(h, 0, 360, 0), clamp01(s, 0), clamp01(l, 0.5)]\n}\n\n/**\n * One holiday's appearance, untouched.\n *\n * Holidays default to `fill` rather than a rule's `fit`: these are full-bleed\n * festival wallpapers, and `fit` would letterbox them on every aspect ratio the\n * art was not cut for.\n */\nexport function defaultHolidayRule(def: HolidayDef): HolidayRule {\n // The definition's own color, never an extracted one — see hexToHsl. It is\n // written BOTH on the rule (what an image-less festival would paint) and on the\n // image (what actually paints today), because those are two different slots in\n // the shape now and a holiday that only filled one of them would look themed or\n // unthemed depending on which branch the render layer happened to read.\n const color = hexToHsl(def.color)\n return {\n id: def.id,\n // Exactly one image: a holiday's art is the package's, so there is nothing\n // for a second entry to point at and nothing for a rotation to walk.\n images: [{ slot: def.slot, bgState: { ...DEFAULT_BG_STATE }, color }],\n match: '',\n enabled: true,\n color,\n bgMode: 'fill',\n wallpaperOpacity: 1,\n blur: 0,\n rotate: defaultRotation(),\n }\n}\n\n/** Every built-in holiday at its default, in `HOLIDAYS` order. */\nexport function defaultHolidayRules(): HolidayRule[] {\n return HOLIDAYS.map(defaultHolidayRule)\n}\n\n/** A default config with independent nested objects (never hand out the shared ones). */\nexport function freshThemeConfig(): ThemeConfig {\n return {\n rules: [],\n opacities: { ...DEFAULT_PART_OPACITIES },\n blurs: { ...DEFAULT_PART_BLURS },\n settingsOpacity: DEFAULT_SETTINGS_OPACITY,\n chatTextOpacity: DEFAULT_CHAT_TEXT_OPACITY,\n trajectoryOpacity: DEFAULT_TRAJECTORY_OPACITY,\n rightbarOpacity: DEFAULT_RIGHTBAR_OPACITY,\n autoExtract: DEFAULT_AUTO_EXTRACT,\n holidays: { enabled: DEFAULT_HOLIDAYS_ENABLED, items: defaultHolidayRules() },\n }\n}\n\n// ── Sanitizers ─────────────────────────────────────────────────────────────\n// Pure coercions from a possibly-old / possibly-hand-edited JSON value into the\n// shape above. Both halves run THESE, so a clamp can never differ between what\n// the UI shows and what lands on disk.\n\n/** Slot names reach the filesystem, so they are strictly whitelisted. */\nexport const SLOT_RE = /^[A-Za-z0-9_-]{1,32}$/\n\n/**\n * The persisted SHAPE this build writes: 4 = a theme color belongs to an IMAGE\n * (`images[].color`), and a rule's own color is what an image-less rule paints.\n *\n * Declared here, with the shape itself, and published by the node half on every\n * `read`. The browser half compares it before it writes anything: a client bundle\n * from a newer release can be served to a page whose host process is still\n * running an OLDER node half (update the package, then just refresh the page),\n * and that older sanitizer would silently drop every rule it does not understand.\n * Knowing the shape up front is what lets the client hold its writes and say so\n * instead.\n *\n * Both bumps so far were of that kind, not cosmetic. 2 → 3 was \"an empty image\n * list is legal\": a schema-2 host refuses one, so once this bundle could PRODUCE\n * an empty rule, every write was at risk of erasing the user's rule list — the\n * failure mode is data loss, and it arrived on the first slider drag after\n * emptying a rule. 3 → 4 is `images[].color`: the field is unknown to a schema-3\n * sanitizer, which REBUILDS each image entry from the keys it knows, so a color\n * the user set would survive in memory until the next reload and then be gone —\n * a silent, per-image loss that no warning would accompany. The check is a plain\n * `>=`, so an older host lands in the hold-writes path automatically.\n */\nexport const SCHEMA_VERSION = 4\n\nexport function clamp(n: unknown, lo: number, hi: number, def: number): number {\n return typeof n === 'number' && isFinite(n) ? Math.min(hi, Math.max(lo, n)) : def\n}\n\nexport const clamp01 = (n: unknown, def: number): number => clamp(n, 0, 1, def)\n\nexport function normalizeBgState(s: Partial<BgState> | undefined): BgState {\n const v = s ?? {}\n return {\n zoom: clamp(v.zoom, 0.1, 10, 1),\n x: typeof v.x === 'number' && isFinite(v.x) ? v.x : 0,\n y: typeof v.y === 'number' && isFinite(v.y) ? v.y : 0,\n iw: typeof v.iw === 'number' && v.iw > 0 ? v.iw : 0,\n ih: typeof v.ih === 'number' && v.ih > 0 ? v.ih : 0,\n }\n}\n\n/** One `[h, s, l]` triple, or null when the value is not a complete finite triple. */\nexport function normalizeHsl(raw: unknown): [number, number, number] | null {\n if (!Array.isArray(raw) || raw.length !== 3) return null\n if (!raw.every(n => typeof n === 'number' && isFinite(n))) return null\n return [clamp(raw[0], 0, 360, 220), clamp(raw[1], 0, 1, 0.55), clamp(raw[2], 0, 1, 0.25)]\n}\n\n/** Coerce one persisted rotation block; a config without one gets the shipped default. */\nexport function normalizeRotation(raw: unknown): BgRotation {\n const r = (raw ?? {}) as Partial<BgRotation>\n const d = DEFAULT_ROTATION\n return {\n // Only an explicit `true` turns rotation on: it is the one setting here that\n // spends the user's bandwidth and CPU, so it never becomes on by accident.\n enabled: r.enabled === true,\n intervalMs: clamp(r.intervalMs, ROTATE_MIN_MS, ROTATE_MAX_MS, d.intervalMs),\n order: ROTATE_ORDERS.includes(r.order as RotateOrder) ? (r.order as RotateOrder) : d.order,\n advanceOnSwitch: r.advanceOnSwitch === true,\n // 0 is a legal value (a hard cut), so it must not be treated as \"absent\".\n fadeMs: clamp(r.fadeMs, 0, ROTATE_FADE_MAX_MS, d.fadeMs),\n }\n}\n\n/** Own-property test for values that may be anything at all (a raw JSON entry). */\nfunction hasOwn(o: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(o, key)\n}\n\n/**\n * Coerce one persisted image entry, or null when it lacks a usable slot.\n *\n * `inherit` is the RULE's own color, and it is applied only to an entry that has\n * no `color` key at all — the shape every release before 0.7.1 wrote, where a\n * rule's color was the only color there was. Lifting it here, once, is what makes\n * an upgrade a no-op on screen: a themed wallpaper keeps its theme instead of\n * silently dropping to the system palette, and it happens in the shared sanitizer\n * so both halves lift identically.\n *\n * The KEY's presence is the whole distinction, which is why `null` is not the\n * same as absent: an entry with `color: null` is an image the user explicitly set\n * to \"follow the system theme\", and re-inheriting the rule's color over that\n * would undo a deliberate choice on every load.\n */\nexport function normalizeImage(raw: unknown, inherit: [number, number, number] | null = null): BgImage | null {\n const i = (raw ?? {}) as Partial<BgImage>\n if (typeof i.slot !== 'string' || !SLOT_RE.test(i.slot)) return null\n return {\n slot: i.slot,\n bgState: normalizeBgState(i.bgState as Partial<BgState> | undefined),\n color: hasOwn(i, 'color') ? normalizeHsl(i.color) : inherit,\n }\n}\n\n/**\n * Coerce one persisted rule, or null when it names no image AT ALL.\n *\n * Accepts BOTH image shapes: the 0.7 list (`images`), and the single\n * `slot`/`bgState` pair every earlier version wrote — the latter is lifted to a\n * one-entry list here rather than at a dozen call sites, which is what keeps the\n * rest of the codebase free of \"old config\" branches. Duplicate slots inside one\n * rule are dropped: two entries pointing at the same bytes would only make the\n * rotation look stuck.\n *\n * The rule's color is resolved FIRST and handed to every image entry, because it\n * is what an entry written before 0.7.1 inherits (`normalizeImage`). The rule keeps\n * it as well: it is not a default for its images at paint time any more, but it\n * is still what the rule paints once its last picture is gone.\n *\n * An EMPTY list is a legitimate rule, not a broken one: removing a rule's last\n * picture has to be expressible, and forcing an entry back in is what produced a\n * phantom blank image that took slot 1 and could never be deleted again (the next\n * upload landed at position 2 and the rule kept painting nothing). What such a\n * rule then does is `ruleCanPaint`'s business: with a color of its own it paints\n * the interface, with neither it is skipped by matching — which the card's own\n * hint says in so many words. Only a rule that names no image anywhere — no list,\n * no legacy slot, or a slot that could never be a filename — is dropped.\n */\nexport function normalizeRule(raw: unknown): BgRule | null {\n const r = (raw ?? {}) as Partial<BgRule> & { slot?: unknown; bgState?: unknown }\n const id = typeof r.id === 'string' && r.id !== '' ? r.id : null\n if (id === null) return null\n const color = normalizeHsl(r.color)\n const images: BgImage[] = []\n const seen = new Set<string>()\n const hadList = Array.isArray(r.images)\n if (hadList) {\n for (const entry of r.images as unknown[]) {\n const image = normalizeImage(entry, color)\n if (image === null || seen.has(image.slot)) continue\n seen.add(image.slot)\n images.push(image)\n }\n }\n const legacySlot = typeof r.slot === 'string' && SLOT_RE.test(r.slot) ? r.slot : null\n if (images.length === 0 && legacySlot !== null) {\n // Synthesized, not read: the pre-0.7 pair has no image entry of its own, so\n // the rule's color is what this image starts out with (the same lift as\n // above, for the shape that has no `color` key to be absent from).\n images.push({ slot: legacySlot, bgState: normalizeBgState(r.bgState as Partial<BgState> | undefined), color })\n }\n // Nothing usable anywhere: a pre-0.7 rule whose slot was empty or malformed.\n if (images.length === 0 && !hadList) return null\n const mode: BgMode = BG_MODES.includes(r.bgMode as BgMode) ? (r.bgMode as BgMode) : 'fit'\n return {\n id,\n images,\n match: typeof r.match === 'string' ? r.match : '',\n enabled: r.enabled !== false,\n color,\n bgMode: mode,\n wallpaperOpacity: clamp01(r.wallpaperOpacity, 1),\n blur: clamp(r.blur, 0, 60, 0),\n rotate: normalizeRotation(r.rotate),\n }\n}\n\n/**\n * Coerce one persisted holiday entry.\n *\n * `id`, `images` and every theme color (the rule's and each image's) come from\n * the DEFINITION, never from disk: a holiday's slot is the only thing tying it to\n * its bytes, and its theme color is a fixed part of what that holiday looks like —\n * so a stale or hand-edited value would either orphan the wallpaper, point the\n * holiday at a rule's image, or paint a festival in a color it does not have.\n * Everything else is sanitized exactly like a rule's field — except the image\n * list and the rotation, which stay the definition's own single image and stay\n * off, so a festival can never be swapped or cycled.\n */\nexport function normalizeHolidayRule(def: HolidayDef, raw: unknown): HolidayRule {\n const r = (raw ?? {}) as Partial<HolidayRule> & { bgState?: unknown }\n const base = defaultHolidayRule(def)\n return {\n ...base,\n // Only an explicit `false` disables the entry, so a config written before\n // this feature existed starts with every holiday usable.\n enabled: r.enabled !== false,\n bgMode: BG_MODES.includes(r.bgMode as BgMode) ? (r.bgMode as BgMode) : base.bgMode,\n wallpaperOpacity: clamp01(r.wallpaperOpacity, base.wallpaperOpacity),\n blur: clamp(r.blur, 0, 60, base.blur),\n // A holiday's own framing is still the user's: which part of the festival art\n // fills the screen is a taste question, and the editor allows it. Its COLOR is\n // not — it comes from `base` (the definition), like the slot beside it, so the\n // `hasOwn` lift in normalizeImage can never reach a holiday and a hand-edited\n // per-image color cannot repaint a festival.\n images: base.images.map(image => ({\n slot: image.slot,\n bgState: normalizeBgState((r.images?.[0]?.bgState ?? r.bgState) as Partial<BgState> | undefined),\n color: image.color,\n })),\n }\n}\n\n/** Coerce the whole holiday block; unknown ids are dropped, missing ones defaulted. */\nexport function normalizeHolidays(raw: unknown): HolidaysConfig {\n const r = (raw ?? {}) as Partial<HolidaysConfig>\n const stored = new Map<string, unknown>()\n if (Array.isArray(r.items)) {\n for (const item of r.items) {\n const id = (item as { id?: unknown } | null | undefined)?.id\n if (typeof id === 'string') stored.set(id, item)\n }\n }\n return {\n // Only an explicit `false` turns the feature off — the same \"absent means\n // on\" rule the per-item switch uses, so a config predating the feature (or\n // one whose hidden panel was never opened) keeps working.\n enabled: r.enabled !== false,\n items: HOLIDAYS.map(def => normalizeHolidayRule(def, stored.get(def.id))),\n }\n}\n\n/** Coerce an unknown persisted value into a valid ThemeConfig, falling back per-field. */\nexport function normalizeConfig(raw: unknown): ThemeConfig {\n const r = (raw ?? {}) as Partial<ThemeConfig>\n const rules = Array.isArray(r.rules)\n ? r.rules.map(normalizeRule).filter((x): x is BgRule => x !== null)\n : []\n const ops = (r.opacities ?? {}) as Partial<PartOpacities>\n const bl = (r.blurs ?? {}) as Partial<PartBlurs>\n const blurs = {} as PartBlurs\n for (const k of PART_BLUR_KEYS) {\n blurs[k] = clamp(bl[k], 0, 60, DEFAULT_PART_BLURS[k])\n }\n const opacities = {} as PartOpacities\n for (const k of PART_OPACITY_KEYS) {\n opacities[k] = clamp01(ops[k], DEFAULT_PART_OPACITIES[k])\n }\n return {\n rules,\n opacities,\n blurs,\n settingsOpacity: clamp01(r.settingsOpacity, DEFAULT_SETTINGS_OPACITY),\n chatTextOpacity: clamp01(r.chatTextOpacity, DEFAULT_CHAT_TEXT_OPACITY),\n trajectoryOpacity: clamp01(r.trajectoryOpacity, DEFAULT_TRAJECTORY_OPACITY),\n // Anything but a real number means \"not owned yet\" — including the absent\n // field of a config written before this option existed.\n rightbarOpacity: typeof r.rightbarOpacity === 'number' && isFinite(r.rightbarOpacity)\n ? clamp01(r.rightbarOpacity, 1)\n : DEFAULT_RIGHTBAR_OPACITY,\n // Only an explicit `false` turns it off, so a config written before this\n // option existed starts with the helpful default.\n autoExtract: r.autoExtract !== false,\n holidays: normalizeHolidays(r.holidays),\n }\n}\n","import type { BgImage, BgRule, BgState, BgMode, HolidayRule, ThemeConfig, PartOpacities, PartBlurs } from './types'\n// The persisted shape, its key lists, its defaults and its sanitizers all live in\n// ../schema, shared verbatim with the node half — a field declared on one side\n// only used to be silently dropped by the other side's sanitizer.\nimport {\n DEFAULT_BG_STATE, DEFAULT_CHAT_TEXT_OPACITY, DEFAULT_PART_BLURS, DEFAULT_PART_OPACITIES,\n DEFAULT_SETTINGS_OPACITY, DEFAULT_TRAJECTORY_OPACITY, PART_BLUR_KEYS, PART_OPACITY_KEYS,\n clamp, clamp01, defaultRotation, freshThemeConfig, normalizeConfig, normalizeRotation, normalizeRule,\n ruleSlots,\n} from '../schema'\n\nexport { DEFAULT_BG_STATE, normalizeRule, ruleSlots }\n\nconst PALETTE: Array<[number, number, number]> = [\n [356, 0.72, 0.55], [24, 0.78, 0.55], [44, 0.8, 0.55], [152, 0.62, 0.5],\n [174, 0.68, 0.48], [208, 0.72, 0.55], [252, 0.68, 0.6], [300, 0.64, 0.58],\n]\nexport { PALETTE }\n\n/** The defaults every accessor falls back to; the shape itself lives in ../schema. */\nexport const DEFAULT_CONFIG: ThemeConfig = freshThemeConfig()\n\n// In-memory mirror of the file-backed store; the UI reads and mutates this and\n// it is synced to disk via the RPC layer.\nexport let cfg: ThemeConfig = freshThemeConfig()\n\n// ── Image cache (slot → data URL) ──────────────────────────────────────────\n// Rule images are fetched lazily per slot; only the active rule's bytes are\n// needed to paint, the rest are loaded when their card is expanded.\n//\n// Two URLs are kept per slot: the DATA URL is what gets persisted and embedded\n// in an export, while the DISPLAY URL is an object URL derived from it. Painting\n// goes through the display URL because `background-image: url(data:…)` is\n// re-decoded on every assignment — a visible stall on every model switch for a\n// multi-megabyte wallpaper — whereas a blob URL is served from the browser's\n// memory cache after the first load.\nconst images = new Map<string, string>()\nconst displayUrls = new Map<string, string>()\n\nfunction revokeDisplay(slot: string): void {\n const url = displayUrls.get(slot)\n if (url === undefined) return\n displayUrls.delete(slot)\n // Deferred on purpose: the wallpaper layer may still be painting this URL\n // while the replacement fades in over it, and revoking it mid-fade would blank\n // the wallpaper behind the incoming image for a frame.\n window.setTimeout(() => {\n try { URL.revokeObjectURL(url) } catch { /* not a live object URL (e.g. fallback) */ }\n }, 2000)\n}\n\nexport function setImage(slot: string, url: string | null): void {\n revokeDisplay(slot)\n if (url === null) images.delete(slot)\n else images.set(slot, url)\n}\n/** Persisted data URL (RPC / export). Use `displayImageOf` to paint it. */\nexport function imageOf(slot: string): string | null { return images.get(slot) ?? null }\n\n/** Paintable URL for one slot, created on first use and cached; falls back to\n * the data URL when no object URL can be built. */\nexport function displayImageOf(slot: string): string | null {\n const cached = displayUrls.get(slot)\n if (cached !== undefined) return cached\n const data = images.get(slot)\n if (data === undefined) return null\n const made = toObjectUrl(data)\n if (made === null) return data\n displayUrls.set(slot, made)\n return made\n}\n\nfunction toObjectUrl(dataUrl: string): string | null {\n try {\n if (typeof URL === 'undefined' || typeof URL.createObjectURL !== 'function') return null\n const comma = dataUrl.indexOf(',')\n if (comma < 0) return null\n const meta = dataUrl.slice(0, comma)\n if (!/;base64$/i.test(meta)) return null\n const mime = meta.slice(5, -7) || 'image/jpeg'\n const bin = atob(dataUrl.slice(comma + 1))\n const bytes = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i)\n return URL.createObjectURL(new Blob([bytes], { type: mime }))\n } catch {\n return null\n }\n}\n\nexport function clearImages(): void {\n for (const slot of Array.from(displayUrls.keys())) revokeDisplay(slot)\n images.clear()\n}\n\n// ── Active rule (what the render layer follows) ────────────────────────────\nexport let activeRuleId: string | null = null\nexport let activeMatched = false\nexport let modelLabel = ''\n\n/**\n * Which image of the ACTIVE rule is painted right now.\n *\n * Deliberately NOT persisted: a background that comes back on image 3 of 7 after\n * a reload, with no way to say why, is worse than one that starts at the first\n * image every time. Clamped to the rule's own length on every read, so an index\n * left over from a longer list can never point at nothing.\n */\nlet rotIndex = 0\n\nexport function setActive(ruleId: string | null, matched: boolean): void {\n // Every switch starts at the rule's FIRST image. Without this, a model switch\n // from a 7-image rule to a 2-image one would land on whatever index survived.\n if (ruleId !== activeRuleId) rotIndex = 0\n activeRuleId = ruleId\n activeMatched = matched\n}\nexport function setModelLabel(label: string): void { modelLabel = label }\n\n/** The image index the render layer is on, clamped into `rule`'s own range. */\nexport function imageIndexOf(rule: BgRule): number {\n if (rule.images.length === 0) return 0\n const i = Math.floor(rotIndex)\n return i >= 0 && i < rule.images.length ? i : 0\n}\n\n/** Point the active rule at another of its images (the rotation's one mutator). */\nexport function setRotIndex(i: number): void { rotIndex = Math.floor(i) }\n\n/** The image the active rule is painting now, or null when it has none. */\nexport function activeImage(): BgImage | null {\n const rule = activeRule()\n if (rule === null) return null\n return rule.images[imageIndexOf(rule)] ?? null\n}\n\n/** Slot of the active rule's current image; '' when there is nothing to paint. */\nexport function activeSlot(): string { return activeImage()?.slot ?? '' }\n\n/**\n * The theme color in force right now, or null for \"follow the system theme\".\n *\n * Two rungs, in this order and no others:\n * 1. the color of the IMAGE that is on screen, when the rule has one;\n * 2. the rule's own color, which is all an image-less rule has to paint with.\n *\n * There is deliberately no third rung where an image INHERITS its rule's color:\n * a rule's color is not a default for its pictures (see `BgRule.color`). If it\n * were, a rotation through a green picture, a red one and a system-themed one\n * could not be expressed at all — clearing a picture's color would only hand it\n * back to the rule's, and the clear button would look broken. Images that predate\n * per-image colors get the rule's color LIFTED onto them at read time instead\n * (`normalizeImage`), so nothing loses its theme on upgrade.\n *\n * The image is the one being PAINTED (`imageIndexOf`), not the one the panel has\n * selected — the panel's selection is an editing cursor and must not repaint the\n * interface while the user is fixing another picture's framing.\n */\nexport function activeColor(): [number, number, number] | null {\n const rule = activeRule()\n if (rule === null) return null\n if (rule.images.length === 0) return rule.color\n return activeImage()?.color ?? null\n}\n\n/**\n * One rule by id — from the USER's list first, then from the holiday overrides.\n *\n * Every render accessor (`rWp` / `rColor` / `rBgMode` / `rBgState` …) resolves\n * through here, so teaching this one function about holidays is what makes an\n * active holiday paint through the entire existing pipeline instead of needing a\n * parallel one.\n */\nexport function ruleById(id: string): BgRule | null {\n return cfg.rules.find(r => r.id === id)\n ?? cfg.holidays.items.find(r => r.id === id)\n ?? null\n}\nexport function activeRule(): BgRule | null {\n return activeRuleId === null ? null : ruleById(activeRuleId)\n}\n\n/** One holiday override entry, or null for an unknown id. */\nexport function holidayById(id: string): HolidayRule | null {\n return cfg.holidays.items.find(r => r.id === id) ?? null\n}\n\n// ── Rule factories / allocation ────────────────────────────────────────────\n/**\n * A fresh rule, holding NO image yet.\n *\n * It used to be born with an allocated slot and an empty entry, which is what put\n * a blank tile at position 1 of a new rule's strip — and, worse, stopped the\n * picture the user added next from being the first one (a rule paints its first\n * image). A rule with no pictures is a valid state: `ruleCanPaint` (./schema) skips\n * it — it has no image and no color yet — until either arrives, and the slot is\n * allocated when the first picture does.\n */\nexport function newRule(id: string): BgRule {\n return {\n id,\n images: [],\n match: '', enabled: true, color: null,\n bgMode: 'fit', wallpaperOpacity: 1, blur: 0,\n rotate: defaultRotation(),\n }\n}\n\n/** Every slot any rule owns — the user's rules and the holiday entries alike. */\nexport function takenSlots(): Set<string> {\n const taken = new Set<string>()\n for (const rule of cfg.rules) for (const slot of ruleSlots(rule)) taken.add(slot)\n for (const rule of cfg.holidays.items) for (const slot of ruleSlots(rule)) taken.add(slot)\n return taken\n}\n\n/**\n * First free image slot (`m1`, `m2`, …).\n *\n * Scans EVERY slot in the config, not just the primary one of each rule: with\n * several images per rule, \"the slots this file already uses\" is the only set\n * that can be safely handed out, and a collision here would silently point two\n * cards at the same bytes (and let one card's delete orphan the other).\n */\nexport function nextSlot(): string {\n const taken = takenSlots()\n for (let i = 1; i < 1000; i++) {\n const slot = `m${i}`\n if (!taken.has(slot)) return slot\n }\n return `m${Date.now()}`\n}\n\n/** Unique rule id (independent from the slot so removals never renumber). */\nexport function nextRuleId(): string {\n const taken = new Set(cfg.rules.map(r => r.id))\n for (let i = 1; i < 10000; i++) {\n const id = `r${i}`\n if (!taken.has(id)) return id\n }\n return `r${Date.now()}`\n}\n\n/** Patch one rule's rotation block, through the shared sanitizer so a live edit\n * can never hold a value the next load would clamp differently. */\nexport function patchRotation(rule: BgRule, patch: Partial<BgRule['rotate']>): void {\n rule.rotate = normalizeRotation({ ...rule.rotate, ...patch })\n}\n\n/** Re-sanitize one rule in place, so what the UI holds equals what would persist. */\nexport function normalizeRuleInPlace(rule: BgRule): void {\n const normalized = normalizeRule(rule)\n if (normalized !== null) Object.assign(rule, normalized)\n}\n\n// ── Accessors used by the render layer (they follow the ACTIVE rule) ───────\nexport function rHasColor(): boolean { return activeColor() !== null }\nexport function rColor(): [number, number, number] { return activeColor() ?? [220, 0.55, 0.25] }\nexport function rBgMode(): BgMode { return activeRule()?.bgMode ?? 'fit' }\nexport function rWop(): number { return clamp01(activeRule()?.wallpaperOpacity, 1) }\nexport function rBl(): number { return clamp(activeRule()?.blur, 0, 60, 0) }\n/** Framing of the CURRENT image (per image, see BgImage). */\nexport function rBgState(): BgState { return activeImage()?.bgState ?? DEFAULT_BG_STATE }\n/** Rotation of the active rule; the shipped default when nothing is active. */\nexport function rRotation(): BgRule['rotate'] { return activeRule()?.rotate ?? defaultRotation() }\n/** Cross-fade duration the active rule asks for, in ms (0 = hard cut). */\nexport function rFadeMs(): number { return rRotation().fadeMs }\n/** Paintable URL of the active rule's CURRENT image, or null when it has none. */\nexport function rWp(): string | null {\n const slot = activeSlot()\n return slot === '' ? null : displayImageOf(slot)\n}\nexport function rOps(): PartOpacities {\n const o = cfg.opacities ?? {}\n const out = {} as PartOpacities\n for (const k of PART_OPACITY_KEYS) {\n out[k] = clamp01(o[k], DEFAULT_PART_OPACITIES[k])\n }\n return out\n}\nexport function rBlurs(): PartBlurs {\n const b = cfg.blurs ?? {}\n const out = {} as PartBlurs\n for (const k of PART_BLUR_KEYS) {\n out[k] = clamp(b[k], 0, 60, DEFAULT_PART_BLURS[k])\n }\n return out\n}\nexport function rSop(): number { return clamp01(cfg.settingsOpacity, DEFAULT_SETTINGS_OPACITY) }\nexport function rChatTextOpacity(): number { return clamp01(cfg.chatTextOpacity, DEFAULT_CHAT_TEXT_OPACITY) }\nexport function rTrajectoryOpacity(): number { return clamp01(cfg.trajectoryOpacity, DEFAULT_TRAJECTORY_OPACITY) }\n/** Own opacity of the file-preview panel; while unowned it IS the main background's. */\nexport function rRightbarOpacity(): number {\n const own = cfg.rightbarOpacity\n return typeof own === 'number' && isFinite(own) ? clamp01(own, 1) : rOps().bg\n}\n\n// ── Normalization ──────────────────────────────────────────────────────────\n// The sanitizers are the shared ones from ../schema (the same code the node half\n// runs before writing to disk), so what the UI shows and what is persisted can\n// never be clamped differently.\n\n/** Move a possibly-absent partial config into the shape the UI reads. */\nexport function adoptConfig(raw: unknown): void {\n cfg = normalizeConfig(raw)\n // A rule that vanished (import/removal) must not stay active — and a holiday\n // that is still in `cfg.holidays.items` legitimately stays active, which is\n // why this asks `ruleById` instead of scanning `cfg.rules` directly.\n if (activeRuleId !== null && ruleById(activeRuleId) === null) {\n activeRuleId = null\n activeMatched = false\n }\n // The list this index belonged to is gone (an import can replace it wholesale),\n // so the first image is the only index that is certainly valid.\n rotIndex = 0\n}\n\nexport function resetConfig(): void {\n cfg = freshThemeConfig()\n clearImages()\n activeRuleId = null\n activeMatched = false\n modelLabel = ''\n rotIndex = 0\n}\n","/**\n * Multi-image rotation: which image comes next, and how often.\n *\n * Pure and dependency-free on purpose — the timer that calls this lives in the\n * plugin's apply closure (where nothing can reach it), but the DECISION lives\n * here so `scripts/rotation-check.ts` can pin it down: a picker that walks off\n * the end of the list, or that \"shuffles\" onto the image it is already showing,\n * looks exactly like a rotation that has stopped, and neither shows up as an\n * error anywhere.\n */\nimport type { RotateOrder } from './types'\n\n/** Dwell-time presets the settings UI offers, in ms. */\nexport const ROTATE_PRESETS: ReadonlyArray<{ ms: number; key: string }> = [\n { ms: 10_000, key: 'rotEvery10s' },\n { ms: 30_000, key: 'rotEvery30s' },\n { ms: 60_000, key: 'rotEvery1m' },\n { ms: 5 * 60_000, key: 'rotEvery5m' },\n { ms: 30 * 60_000, key: 'rotEvery30m' },\n { ms: 60 * 60_000, key: 'rotEvery1h' },\n]\n\n/**\n * The index to paint after the current one, or null when there is nowhere to go\n * (fewer than two images — the caller must not start a timer at all then).\n *\n * `order` walks the list and wraps; `shuffle` picks uniformly among every index\n * EXCEPT the current one, because landing on the same image reads as a missed\n * tick. `current` outside the list is treated as 0 rather than trusted: it comes\n * from the UI as often as from the timer, and a stale index must not be able to\n * index past the end.\n *\n * `rand` is injectable so the shuffle branch is testable without stubbing a\n * global.\n */\nexport function nextIndex(\n len: number,\n order: RotateOrder,\n current: number,\n rand: () => number = Math.random,\n): number | null {\n if (!Number.isFinite(len) || len < 2) return null\n const count = Math.floor(len)\n const cur = Number.isFinite(current) && current >= 0 && current < count ? Math.floor(current) : 0\n if (order === 'shuffle') {\n // Uniform over the count-1 candidates, skipping `cur`. `rand() === 1` (which\n // a caller-supplied generator may return) would otherwise land on `count`.\n const roll = Math.min(Math.floor(Math.max(rand(), 0) * (count - 1)), count - 2)\n return roll >= cur ? roll + 1 : roll\n }\n return (cur + 1) % count\n}\n\n/**\n * Whether a rotation is worth running: two images, the switch on, and a positive\n * dwell time. Kept here (rather than at the call site) so the UI's \"rotating\"\n * badge and the timer agree by construction — a badge that says \"rotating\" while\n * no timer exists is the one failure this feature can produce silently.\n */\nexport function isRotating(len: number, enabled: boolean, intervalMs: number): boolean {\n return enabled && len >= 2 && Number.isFinite(intervalMs) && intervalMs > 0\n}\n","/**\n * The repaint decision, as a pure function.\n *\n * Every edit to a rule ends with the same question: does the interface have to be\n * repainted, or is refreshing the panel's readout enough? Repainting is the\n * expensive half (the theme skin is re-registered, the wallpaper layer is\n * rewritten, the host's theme is switched), so it must not be done for a rule\n * that is not the one on screen — but it MUST be done the moment the edit\n * changes what should be on screen.\n *\n * The naive test — \"is the edited rule the active one?\" — is wrong in exactly the\n * case that kept being reported as \"更新的不太及时,只有我动调色盘或者切模型的时候\n * 才出现\": an edit that CREATES the winner. Uploading a rule's first picture, or\n * an auto-extracted color landing on a rule that had none, makes that rule\n * paintable *through that very edit* (see `ruleCanPaint`), so the rule is not the\n * active one at the moment of the check; the wallpaper and the skin then only\n * showed up later, when an unrelated drag or model switch happened to re-run the\n * resolution.\n *\n * Sampling the winner on BOTH sides of the edit is what makes such a change land\n * at once, and `editedId === winnerAfter` additionally covers the edit that does\n * not move the resolution but changes the look of the rule that IS painting (a\n * color, a slider, a framing).\n *\n * `null` is \"nothing of ours is painting\" (the interface falls back to the host's\n * own look), which is a winner like any other id.\n *\n * Kept free of imports on purpose: `scripts/repaint-check.ts` exercises it on\n * plain node, the same way `rotation.ts` is exercised. A rule's `color`/`match`\n * are the inputs that make the resolution move, which is why they are the fields\n * whose write paths all end here.\n */\nexport function shouldRepaint(\n editedId: string,\n winnerBefore: string | null,\n winnerAfter: string | null\n): boolean {\n return winnerAfter === editedId || winnerAfter !== winnerBefore\n}\n","import type { FetchResult, RpcResultLike } from './types'\nimport { cfg } from './state'\n// The shape this bundle writes, and the one the host announces on `read`.\nimport { SCHEMA_VERSION } from '../schema'\n\nexport const RPC_CHANNEL = '/dsh-background-by-model'\nconst RPC_NS = 'dshBackgroundByModel'\nconst rpcEndpoint = (method: string): string => `${RPC_NS}/${method}`\n\n/**\n * What the host process said about the config shape it writes.\n *\n * `unknown` — the RPC never answered (offline/broken): writes are allowed, and\n * the ordinary failure paths deal with it.\n * `legacy` — it answered WITHOUT a schema, i.e. it is running a node half from\n * before multi-image. Its sanitizer drops any rule whose image list\n * it does not understand, so writing our config would erase the\n * user's rule list; every config write is held instead.\n * `current` — same shape as this bundle.\n */\nexport type HostShape = 'unknown' | 'legacy' | 'current'\n\nlet hostShape: HostShape = 'unknown'\nlet warnedLegacy = false\n\n/** Whether this bundle may write its config to the host it is talking to. */\nexport function canWriteConfig(): boolean { return hostShape !== 'legacy' }\n\n/** Whether the running host process is older than this client bundle. */\nexport function hostIsLegacy(): boolean { return hostShape === 'legacy' }\n\nfunction holdWrite(): void {\n if (warnedLegacy) return\n warnedLegacy = true\n console.warn(\n 'dsh-background-by-model: the running host is an older build that cannot read the multi-image ' +\n 'config shape — holding config writes so its sanitizer cannot drop this profile\\'s rules. ' +\n 'Restart DSH to load the new node half.',\n )\n}\n\nlet rpcCallFn: ((endpoint: string, payload: unknown) => Promise<RpcResultLike | undefined>) | null = null\n\nexport function initRpc(call: (endpoint: string, payload: unknown) => Promise<RpcResultLike | undefined>): void {\n rpcCallFn = call\n}\n\nasync function rpcCall(method: string, payload: unknown): Promise<unknown> {\n if (!rpcCallFn) return undefined\n try {\n const res = await rpcCallFn(rpcEndpoint(method), payload)\n if (res && res.ok === true) return res.value\n console.warn(`dsh-background-by-model: rpc \"${method}\" failed`, res?.error)\n return undefined\n } catch (e) {\n console.warn(`dsh-background-by-model: rpc \"${method}\" threw`, e)\n return undefined\n }\n}\n\n/** Raw call for the few places that need the host's error message. */\nasync function rpcRaw(method: string, payload: unknown): Promise<RpcResultLike | undefined> {\n if (!rpcCallFn) return undefined\n try {\n return await rpcCallFn(rpcEndpoint(method), payload)\n } catch {\n return undefined\n }\n}\n\n// Slider drags fire dozens of events per second; coalesce writes to a trailing\n// debounce and flush the last pending write on pagehide so a quick close never\n// loses it.\nconst SAVE_DEBOUNCE_MS = 250\nlet saveTimer: number | undefined\n\nexport function saveConfig(): void {\n if (!canWriteConfig()) { holdWrite(); return }\n if (saveTimer !== undefined) window.clearTimeout(saveTimer)\n saveTimer = window.setTimeout(() => {\n saveTimer = undefined\n void rpcCall('writeConfig', { config: cfg })\n }, SAVE_DEBOUNCE_MS)\n}\n\nexport function flushSave(): void {\n if (saveTimer === undefined) return\n window.clearTimeout(saveTimer)\n saveTimer = undefined\n // Deliberately checked AFTER the timer is dropped: a held write must not stay\n // queued and fire on the next flush either.\n if (!canWriteConfig()) { holdWrite(); return }\n void rpcCall('writeConfig', { config: cfg })\n}\n\n/** Persist the current config immediately (no debounce). */\nexport function persistConfig(): void {\n if (!canWriteConfig()) { holdWrite(); return }\n void rpcCall('writeConfig', { config: cfg })\n}\n\nexport interface Persisted {\n config: unknown\n /**\n * Every image slot the store holds. Reported for diagnostics and asserted by\n * `scripts/node-half-check.mjs`; the plugin no longer HYDRATES from it — boot\n * reads the slots the config actually references, because a slot nothing points\n * at has no card to appear on and pulling its bytes costs a full-size transfer.\n */\n slots: string[]\n /** The config shape the host writes; null when it predates this field. */\n schema: number | null\n}\n\n/** Load the persisted config plus the list of stored image slots. */\nexport async function loadPersisted(): Promise<Persisted | null> {\n const data = await rpcCall('read', {})\n if (data === null || typeof data !== 'object') return null\n const d = data as { config?: unknown; slots?: unknown; schema?: unknown }\n const slots = Array.isArray(d.slots) ? d.slots.filter((s): s is string => typeof s === 'string') : []\n const schema = typeof d.schema === 'number' && isFinite(d.schema) ? d.schema : null\n // The one place the answer arrives, so the one place it is recorded: a host that\n // answered without a schema is a pre-0.7 node half (see HostShape).\n hostShape = schema === null ? 'legacy' : (schema >= SCHEMA_VERSION ? 'current' : 'legacy')\n if (hostShape === 'legacy') holdWrite()\n return { config: d.config, slots, schema }\n}\n\n/** Read one rule image as a data URL (null when the slot is empty). */\nexport async function readImage(slot: string): Promise<string | null> {\n const data = await rpcCall('readImage', { slot })\n if (data === null || typeof data !== 'object') return null\n const url = (data as { dataUrl?: unknown }).dataUrl\n return typeof url === 'string' ? url : null\n}\n\n/** Persist (or clear) one rule image; one-shot, no debounce. */\nexport async function writeImage(slot: string, dataUrl: string | null): Promise<boolean> {\n const res = await rpcCall('writeImage', { slot, dataUrl })\n return res === true\n}\n\n/** Remove one rule image from disk. */\nexport async function deleteImage(slot: string): Promise<boolean> {\n const res = await rpcCall('deleteImage', { slot })\n return res === true\n}\n\n/** Download an image from a network URL into one slot, replacing its bytes. */\nexport async function fetchImageUrl(slot: string, url: string): Promise<FetchResult> {\n const res = await rpcRaw('fetchImageUrl', { slot, url })\n if (!res) return { ok: false, error: 'no response' }\n if (res.ok !== true) {\n const err = (res as { error?: { message?: string } }).error\n return { ok: false, error: err?.message ?? 'request failed' }\n }\n const v = res.value as FetchResult | undefined\n return v?.ok === true\n ? { ok: true, dataUrl: v.dataUrl ?? null }\n : { ok: false, error: v?.error ?? 'failed' }\n}\n\n/** Host default model — used only when the per-session services are absent. */\nexport async function readDefaultModel(): Promise<string | null> {\n const data = await rpcCall('defaultModel', {})\n if (data === null || typeof data !== 'object') return null\n const d = data as { provider?: unknown; model?: unknown }\n const parts = [d.provider, d.model].filter((s): s is string => typeof s === 'string' && s !== '')\n return parts.length > 0 ? parts.join(' ') : null\n}\n","import type { BgState, ColorPalette } from '../types'\r\n\r\n// The wheel works in HSV end to end; storage and genTokens expect HSL, so\r\n// setColor converts HSV → HSL at the boundary and sectionInject converts the\r\n// stored HSL → HSV for the initial wheel props. Conversions never stack.\r\n\r\nexport function hsvToHsl(h: number, s: number, v: number): [number, number, number] {\r\n const l = v * (1 - s / 2)\r\n const sl = l === 0 || l === 1 ? 0 : (v - l) / Math.min(l, 1 - l)\r\n return [h, sl, l]\r\n}\r\n\r\nexport function hslToHsv(h: number, s: number, l: number): [number, number, number] {\r\n const v = l + s * Math.min(l, 1 - l)\r\n const sv = v === 0 ? 0 : 2 * (1 - l / v)\r\n return [h, sv, v]\r\n}\r\n\r\nlet tokensCacheKey = ''\r\nlet tokensCache: { colorScheme: 'light' | 'dark'; tokens: Record<string, string> } | null = null\r\n\r\n/**\r\n * Memoized token generation: the same (hue, sat, lit) input always yields the\r\n * same token set, and applyWp / applyCustomTokens / applySettingsOverrides call\r\n * this repeatedly (slider drags, viewport re-applies), so cache the last result\r\n * and skip the 30+ hsl() string builds when nothing changed.\r\n */\r\nexport function genTokens(hue: number, sat: number, lit: number): { colorScheme: 'light' | 'dark'; tokens: Record<string, string> } {\r\n const key = `${hue}|${sat}|${lit}`\r\n if (tokensCacheKey === key && tokensCache) return tokensCache\r\n tokensCacheKey = key\r\n tokensCache = buildTokens(hue, sat, lit)\r\n return tokensCache\r\n}\r\n\r\nfunction buildTokens(hue: number, sat: number, lit: number): { colorScheme: 'light' | 'dark'; tokens: Record<string, string> } {\r\n const dark = lit < 0.55\r\n const h = (d: number) => ((hue + d) % 360 + 360) % 360\r\n const s = (d: number) => Math.max(0, Math.min(1, sat + d))\r\n const l = (d: number) => Math.max(0, Math.min(1, lit + d))\r\n const hsl = (hh: number, ss: number, ll: number) => `hsl(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%)`\r\n const rgba = (hh: number, ss: number, ll: number, a: number) =>\r\n `hsla(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%,${a})`\r\n // Ink for anything painted ON the brand fill. One verdict feeds both\r\n // spellings of it: brand-text (which the host defines but never uses) and\r\n // label-primary-foreground, which the HOST's own primary buttons label\r\n // themselves with on --dsw-alias-button-primary-fill — the same color as\r\n // --dsw-alias-brand-primary below. It has to flip with the fill: the dark\r\n // branch deliberately keeps that fill at 50%+ lightness, so a hard-coded white\r\n // label is white on white. The host's own dark scheme is only readable because\r\n // it flips brand-primary AND label-primary-foreground together.\r\n const onBrand = l(0.2) > 0.6 ? '#000' : '#fff'\r\n\r\n if (dark) {\r\n // dsh 0.1.7 splits the menu surface in two: the shared MenuSurface material\r\n // paints `--dsw-menu-surface-fill`, and every other overlay paints\r\n // `--dsw-specific-menu`, which the host aliases to the former\r\n // (`--dsw-specific-menu: var(--dsw-menu-surface-fill)`). Both are generated\r\n // from this one expression so the plugin's override of either can never let\r\n // the pair drift apart — see OPACITY_VARS in wallpaper.ts.\r\n const menuFill = hsl(h(0), s(0), l(0.08))\r\n return {\r\n colorScheme: 'dark',\r\n tokens: {\r\n '--dsw-alias-bg-base': hsl(h(0), s(0), l(-0.04)),\r\n '--dsw-alias-bg-layer-1': hsl(h(0), s(0), l(0.02)),\r\n '--dsw-alias-bg-layer-2': hsl(h(0), s(0), l(0.07)),\r\n '--dsw-alias-bg-layer-3': hsl(h(0), s(-0.05), l(0.12)),\r\n '--dsw-alias-bg-overlay': hsl(h(0), s(-0.05), l(0.12)),\r\n '--dsw-alias-bg-module-platform': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-bg-multi-select': hsl(h(0), s(0), l(0.1)),\r\n '--dsw-alias-bg-skeleton': 'rgba(255,255,255,0.08)',\r\n '--dsw-alias-border-l1': rgba(h(0), s(-0.1), l(0.18), 0.12),\r\n '--dsw-alias-border-l2': rgba(h(0), s(-0.1), l(0.22), 0.22),\r\n '--dsw-alias-border-l3': 'rgba(255,255,255,0.16)',\r\n '--dsw-alias-border-l4': 'rgba(255,255,255,0.2)',\r\n '--dsw-alias-border-inverted': 'rgba(255,255,255,0.06)',\r\n '--dsw-alias-label-primary': hsl(0, 0, 1),\r\n '--dsw-alias-label-secondary': 'rgba(255,255,255,0.85)',\r\n '--dsw-alias-label-tertiary': 'rgba(255,255,255,0.7)',\r\n // Placeholder/dim hint — deliberately weaker than the text tiers so a\r\n // placeholder reads as a hint, never as real input.\r\n '--dsw-alias-label-caption': 'rgba(255,255,255,0.5)',\r\n '--dsw-alias-label-dimmed': 'rgba(255,255,255,0.35)',\r\n '--dsw-alias-label-quaternary': 'rgba(255,255,255,0.25)',\r\n '--dsw-alias-label-primary-dimmed': 'rgba(255,255,255,0.92)',\r\n '--dsw-alias-label-primary-foreground': onBrand,\r\n // Inverted label sits on a light brand/contrast/badge surface in dark\r\n // mode, so it must be dark ink, not white.\r\n '--dsw-alias-label-primary-inverted': hsl(h(0), s(0.08), Math.min(l(0.06), 0.16)),\r\n '--dsw-alias-label-primary-bluish': hsl(0, 0, 1),\r\n '--dsw-alias-brand-primary': hsl(h(0), s(0.1), Math.max(l(0.2), 0.5)),\r\n '--dsw-alias-brand-text': onBrand,\r\n '--dsw-alias-button-primary-fill': hsl(h(0), s(0.1), Math.max(l(0.2), 0.5)),\r\n '--dsw-alias-button-primary-hover': hsl(h(0), s(0.1), Math.max(l(0.28), 0.58)),\r\n '--dsw-alias-button-primary-dimmed': hsl(h(0), s(0), l(0.07)),\r\n '--dsw-alias-button-elevated-fill': hsl(h(0), s(0), l(0.04)),\r\n '--dsw-alias-button-floating-fill': hsl(h(0), s(0), l(0.02)),\r\n '--dsw-alias-button-floating-hover': hsl(h(0), s(0), l(0.1)),\r\n '--dsw-alias-button-tool-bar-fill': 'rgba(255,255,255,0.08)',\r\n '--dsw-alias-button-tool-bar-hover': 'rgba(255,255,255,0.12)',\r\n '--dsw-alias-button-ghost-active-fill': hsl(h(0), s(0), l(0.06)),\r\n '--dsw-alias-button-ghost-active-border': 'rgba(255,255,255,0.16)',\r\n '--dsw-alias-button-ghost-active-hover': hsl(h(0), s(0), l(0.09)),\r\n '--dsw-alias-button-info-fill': '#679efe',\r\n '--dsw-alias-button-info-hover': '#4176e6',\r\n '--dsw-alias-button-contrast-fill': hsl(0, 0, 1),\r\n '--dsw-alias-interactive-bg-hover': rgba(h(0), s(0), Math.max(l(0.15), 0.4), 0.12),\r\n '--dsw-alias-interactive-bg-hover-solid': rgba(h(0), s(0), Math.max(l(0.15), 0.4), 0.16),\r\n '--dsw-alias-interactive-bg-hover-accent': 'rgba(255,255,255,0.24)',\r\n '--dsw-alias-interactive-bg-hover-danger': 'rgba(242,90,90,0.15)',\r\n '--dsw-alias-interactive-bg-active': rgba(h(0), s(0), Math.max(l(0.15), 0.4), 0.2),\r\n '--dsw-alias-markdown-code-block': hsl(h(0), s(0), l(-0.06)),\r\n '--dsw-alias-markdown-code-block-banner': hsl(h(0), s(0), l(-0.02)),\r\n '--dsw-alias-markdown-inline-code': hsl(h(0), s(0), l(0.04)),\r\n '--dsw-alias-markdown-placeholder': hsl(h(0), s(0), l(-0.02)),\r\n '--dsw-alias-markdown-tag': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-markdown-citation': hsl(h(0), s(0), l(0.06)),\r\n '--dsw-alias-markdown-code-segment-selected': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-markdown-code-segment-unselected': hsl(h(0), s(0), l(-0.05)),\r\n '--dsw-alias-state-error-primary': '#ff5c72',\r\n '--dsw-alias-state-error-secondary': '#ff8aa0',\r\n '--dsw-alias-state-success-primary': '#3ddc84',\r\n '--dsw-alias-state-success-secondary': '#69eea4',\r\n // Badge tertiary tokens are the static dark surfaces the UI draws\r\n // over (trajectory tool/context badges, connection pill, plan chip):\r\n // aligning them with the native dark 800/900 steps keeps light fix label\r\n // text readable instead of tint-same-as-background (issue #9).\r\n '--dsw-alias-state-success-tertiary': '#233c2c',\r\n '--dsw-alias-state-warn-primary': '#ffb347',\r\n '--dsw-alias-state-warn-secondary': '#ffc980',\r\n '--dsw-alias-state-warn-tertiary': '#27241f',\r\n '--dsw-alias-state-warn-label': '#dd8629',\r\n '--dsw-alias-state-business-primary': '#679efe',\r\n '--dsw-alias-state-business-tertiary': '#34415b',\r\n '--dsw-specific-sidebar-fill': hsl(h(0), s(0), l(-0.06)),\r\n '--dsw-specific-sidebar-nav-item-active': hsl(h(0), s(0), l(0.04)),\r\n '--dsw-specific-sidebar-nav-item-hover': hsl(h(0), s(0), l(0)),\r\n '--dsw-specific-input-major': hsl(h(0), s(0), l(0.02)),\r\n '--dsw-specific-menu': menuFill,\r\n '--dsw-menu-surface-fill': menuFill,\r\n '--dsw-specific-bubble': hsl(h(0), s(0), l(0.03)),\r\n '--dsw-specific-bubble-highlight': hsl(h(0), s(0), l(0.08)),\r\n '--dsw-specific-selector': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-specific-login-input': hsl(h(0), s(0), l(0.03)),\r\n '--dsw-specific-tip': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-toast-bg': hsl(h(0), s(0), l(0.08)),\r\n '--dsw-alias-tooltip-bg': hsl(h(0), s(0), l(0.08)),\r\n '--dsw-alias-scrollbar-bg-l1': hsl(h(0), s(-0.05), l(0.12)),\r\n '--dsw-alias-scrollbar-bg-l2': hsl(h(0), s(-0.05), l(0.16)),\r\n '--dsw-alias-scrollbar-hover-l1': hsl(h(0), s(-0.05), l(0.22)),\r\n '--dsw-alias-scrollbar-hover-l2': hsl(h(0), s(-0.05), l(0.22)),\r\n },\r\n }\r\n }\r\n // Same one-expression contract as the dark branch above.\r\n const menuFill = hsl(h(0), s(-0.12), l(0.15))\r\n return {\r\n colorScheme: 'light',\r\n tokens: {\r\n '--dsw-alias-bg-base': hsl(h(0), s(-0.08), l(0.03)),\r\n '--dsw-alias-bg-layer-1': hsl(h(0), s(-0.12), l(0.07)),\r\n '--dsw-alias-bg-layer-2': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-alias-bg-layer-3': hsl(h(0), s(-0.08), l(-0.09)),\r\n '--dsw-alias-bg-overlay': hsl(h(0), s(-0.12), l(0.08)),\r\n '--dsw-alias-border-l1': rgba(h(0), s(-0.15), l(-0.35), 0.18),\r\n '--dsw-alias-border-l2': rgba(h(0), s(-0.15), l(-0.35), 0.3),\r\n '--dsw-alias-label-primary': hsl(0, 0, 0),\r\n '--dsw-alias-label-secondary': 'rgba(0,0,0,0.85)',\r\n '--dsw-alias-label-tertiary': 'rgba(0,0,0,0.7)',\r\n // Placeholder/dim hint — deliberately weaker than the text tiers so a\r\n // placeholder reads as a hint, never as real input.\r\n '--dsw-alias-label-caption': 'rgba(0,0,0,0.5)',\r\n '--dsw-alias-label-dimmed': 'rgba(0,0,0,0.35)',\r\n '--dsw-alias-label-quaternary': 'rgba(0,0,0,0.25)',\r\n // Mirror of the dark branch: this branch always paints its brand fill dark\r\n // (45% lightness or less), so the ink ON it is white. Re-emitted rather\r\n // than inherited so the plugin's own palette owns the pair — the plugin's\r\n // settings UI paints every primary button/chip/tile label from this token.\r\n '--dsw-alias-label-primary-inverted': '#fff',\r\n '--dsw-alias-brand-primary': hsl(h(0), s(0.05), Math.min(l(-0.18), 0.45)),\r\n '--dsw-alias-brand-text': '#fff',\r\n '--dsw-alias-button-primary-hover': hsl(h(0), s(0.05), Math.min(l(-0.12), 0.5)),\r\n '--dsw-alias-button-primary-dimmed': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-alias-button-elevated-fill': hsl(h(0), s(-0.1), l(0.1)),\r\n '--dsw-alias-button-floating-hover': hsl(h(0), s(-0.1), l(0.16)),\r\n '--dsw-alias-interactive-bg-hover': rgba(h(0), s(0), l(-0.3), 0.08),\r\n '--dsw-alias-interactive-bg-active': rgba(h(0), s(0), l(-0.3), 0.14),\r\n '--dsw-alias-markdown-code-block': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-alias-markdown-inline-code': hsl(h(0), s(-0.08), l(0.04)),\r\n '--dsw-specific-sidebar-fill': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-specific-sidebar-nav-item-active': hsl(h(0), s(-0.08), l(0.05)),\r\n '--dsw-specific-sidebar-nav-item-hover': hsl(h(0), s(-0.12), l(0)),\r\n '--dsw-specific-input-major': hsl(h(0), s(-0.12), l(0.1)),\r\n '--dsw-specific-menu': menuFill,\r\n '--dsw-menu-surface-fill': menuFill,\r\n '--dsw-alias-scrollbar-bg-l1': hsl(h(0), s(-0.1), l(-0.08)),\r\n '--dsw-alias-scrollbar-bg-l2': hsl(h(0), s(-0.08), l(-0.12)),\r\n '--dsw-alias-scrollbar-hover-l1': hsl(h(0), s(-0.08), l(-0.16)),\r\n '--dsw-alias-scrollbar-hover-l2': hsl(h(0), s(-0.08), l(-0.16)),\r\n },\r\n }\r\n}\r\n\r\nexport function toRgba(c: string, a: number): string {\r\n const hx = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(c.trim())\r\n if (hx) { let d = hx[1]!; if (d.length === 3) d = d.split('').map(x => x + x).join(''); const n = parseInt(d, 16); return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${a})` }\r\n const rgb = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*,\\s*([\\d.]+))?\\s*\\)$/i.exec(c.trim())\r\n if (rgb) return `rgba(${rgb[1]},${rgb[2]},${rgb[3]},${a})`\r\n const hsl = /^hsla?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)%\\s*,\\s*([\\d.]+)%/i.exec(c.trim())\r\n if (hsl) return `hsla(${hsl[1]},${hsl[2]}%,${hsl[3]}%,${a})`\r\n return c.trim()\r\n}\r\n\r\nexport function rgbToHsl(r: number, g: number, b: number): [number, number, number] {\r\n const rn = r / 255, gn = g / 255, bn = b / 255\r\n const max = Math.max(rn, gn, bn), min = Math.min(rn, gn, bn)\r\n const l = (max + min) / 2\r\n if (max === min) return [0, 0, l]\r\n const d = max - min\r\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\r\n let h: number\r\n if (max === rn) h = ((gn - bn) / d) % 6\r\n else if (max === gn) h = (bn - rn) / d + 2\r\n else h = (rn - gn) / d + 4\r\n h *= 60\r\n if (h < 0) h += 360\r\n return [h, s, l]\r\n}\r\n\r\n// Wallpaper color extraction: decode the cached data URL → crop the visible\r\n// (framed) region → downsample to a 64×64 canvas → quantize pixels into 4-bit\r\n// RGB buckets → discard near-gray / near-black / near-white pixels → pick the\r\n// most populous vivid bucket (count × saturation bias) → average its members →\r\n// RGB→HSL → clamp lightness into a band that keeps the light/dark scheme\r\n// decision unambiguous. Purely client-side and memory-bounded.\r\n\r\nconst EXTRACT_SIDE = 64\r\n\r\ninterface Bucket { count: number; r: number; g: number; b: number; s: number }\r\n\r\nfunction bucketsToHsl(b: Bucket): [number, number, number] {\r\n return rgbToHsl(b.r / b.count, b.g / b.count, b.b / b.count)\r\n}\r\n\r\nfunction extractWallpaperPalette(dataUrl: string, bgState: BgState): Promise<ColorPalette | null> {\r\n return new Promise(resolve => {\r\n const img = new Image()\r\n img.onerror = () => resolve(null)\r\n img.onload = () => {\r\n try {\r\n const iw = img.naturalWidth || img.width\r\n const ih = img.naturalHeight || img.height\r\n const bg = bgState\r\n let sx = 0, sy = 0, sw = iw, sh = ih\r\n if (bg.iw === iw && bg.ih === ih && bg.iw > 0) {\r\n const fit = Math.min(window.innerWidth / iw, window.innerHeight / ih)\r\n const w = iw * fit * bg.zoom\r\n const h = ih * fit * bg.zoom\r\n sx = Math.max(0, bg.x * window.innerWidth - w / 2)\r\n sy = Math.max(0, bg.y * window.innerHeight - h / 2)\r\n sw = Math.min(iw - sx, w)\r\n sh = Math.min(ih - sy, h)\r\n if (sw <= 0 || sh <= 0) { sx = 0; sy = 0; sw = iw; sh = ih }\r\n }\r\n const c = document.createElement('canvas')\r\n c.width = EXTRACT_SIDE; c.height = EXTRACT_SIDE\r\n const g = c.getContext('2d', { willReadFrequently: true })!\r\n g.drawImage(img, sx, sy, sw, sh, 0, 0, EXTRACT_SIDE, EXTRACT_SIDE)\r\n const px = g.getImageData(0, 0, EXTRACT_SIDE, EXTRACT_SIDE).data\r\n const counts = new Uint32Array(4096)\r\n const sums = new Float64Array(4096 * 3)\r\n let totalLum = 0\r\n let sampled = 0\r\n for (let i = 0; i < px.length; i += 4) {\r\n const r = px[i], gg = px[i + 1], b = px[i + 2]\r\n const max = Math.max(r, gg, b), min = Math.min(r, gg, b)\r\n const v = max / 255\r\n const s = max === 0 ? 0 : (max - min) / max\r\n // Include all non-extreme pixels in luminance; only vivid pixels in\r\n // palette buckets so we don't theme around gray/black/white.\r\n // Rec.709 luma — the measure a display reads as brightness, and the one\r\n // the light/dark band below is decided with. The HSV value used here\r\n // before counts every saturated pixel as bright (pure blue: v = 1.0,\r\n // luma = 0.072), which pushed dark saturated wallpapers into the light\r\n // band and built a light palette over a dark picture.\r\n totalLum += (0.2126 * r + 0.7152 * gg + 0.0722 * b) / 255\r\n sampled++\r\n if (s < 0.08 || v < 0.12 || v > 0.97) continue\r\n const key = ((r >> 4) << 8) | ((gg >> 4) << 4) | (b >> 4)\r\n counts[key]++\r\n sums[key * 3] += r; sums[key * 3 + 1] += gg; sums[key * 3 + 2] += b\r\n }\r\n const buckets: Bucket[] = []\r\n for (let k = 0; k < 4096; k++) {\r\n if (counts[k] === 0) continue\r\n buckets.push({\r\n count: counts[k],\r\n r: sums[k * 3],\r\n g: sums[k * 3 + 1],\r\n b: sums[k * 3 + 2],\r\n s: (Math.max(sums[k * 3], sums[k * 3 + 1], sums[k * 3 + 2]) - Math.min(sums[k * 3], sums[k * 3 + 1], sums[k * 3 + 2])) / Math.max(sums[k * 3], sums[k * 3 + 1], sums[k * 3 + 2]) || 0,\r\n })\r\n }\r\n if (buckets.length === 0) { resolve(null); return }\r\n // Sort by vivid-weighted count.\r\n buckets.sort((a, b) => b.count * (0.5 + b.s) - a.count * (0.5 + a.s))\r\n const primary = bucketsToHsl(buckets[0]!)\r\n const primaryHue = primary[0]\r\n // Secondary: next bucket that is reasonably separated from primary.\r\n let secondary = primary\r\n for (const b of buckets.slice(1)) {\r\n const [h] = bucketsToHsl(b)\r\n const sep = Math.abs(((h - primaryHue + 540) % 360) - 180)\r\n if (sep > 30) { secondary = bucketsToHsl(b); break }\r\n }\r\n // Tertiary: complementary-ish hue based on primary if no good secondary.\r\n let tertiary: [number, number, number] = [((primaryHue + 180) % 360), Math.min(0.7, primary[1]), Math.min(0.7, primary[2])]\r\n for (const b of buckets.slice(1)) {\r\n const [h] = bucketsToHsl(b)\r\n const sep = Math.abs(((h - primaryHue + 540) % 360) - 180)\r\n if (sep > 90 && sep < 150) { tertiary = bucketsToHsl(b); break }\r\n }\r\n // Surface: neutralized primary (very low saturation).\r\n const surface: [number, number, number] = [primaryHue, Math.min(0.06, primary[1] * 0.3), primary[2]]\r\n // Auto light/dark: use the average luminance of the whole image so a\r\n // bright wallpaper naturally drives a light scheme and vice-versa.\r\n const luminance = sampled > 0 ? totalLum / sampled : primary[2]\r\n // Snap primary lightness out of the ambiguous middle band.\r\n const autoDark = luminance < 0.5\r\n const lc = autoDark ? Math.min(0.44, Math.max(0.2, primary[2])) : Math.max(0.6, Math.min(0.82, primary[2]))\r\n primary[2] = lc\r\n resolve({\r\n primary: [primary[0], Math.min(0.9, Math.max(0.15, primary[1])), primary[2]],\r\n secondary: [secondary[0], Math.min(0.85, Math.max(0.2, secondary[1])), Math.min(0.75, Math.max(0.35, secondary[2]))],\r\n tertiary: [tertiary[0], Math.min(0.8, Math.max(0.2, tertiary[1])), Math.min(0.7, Math.max(0.35, tertiary[2]))],\r\n surface,\r\n luminance,\r\n })\r\n } catch {\r\n resolve(null)\r\n }\r\n }\r\n img.src = dataUrl\r\n })\r\n}\r\n\r\n/** Backward-compatible single-color extraction: returns the primary HSL. */\r\nexport async function extractWallpaperColor(dataUrl: string, bgState: BgState): Promise<[number, number, number] | null> {\r\n const palette = await extractWallpaperPalette(dataUrl, bgState)\r\n return palette ? palette.primary : null\r\n}\r\n\r\n// One-shot frame brightness analysis: called only when a generated background\r\n// is switched (from its captured snapshot), never from the animation loop.\r\n// Decode the frame, downsample to a 32×32 canvas, average Rec.709 luma.\r\n// Dark frame → light fonts, light frame → dark fonts.\r\n\r\nconst ANALYZE_SIDE = 32\r\n\r\n/** Analyze a captured frame's average luminance. Resolves true when the frame\r\n * reads dark (use white fonts), false when light (use black fonts), or null\r\n * when the frame cannot be decoded. */\r\nexport function analyzeFrameDark(dataUrl: string): Promise<boolean | null> {\r\n return new Promise(resolve => {\r\n const img = new Image()\r\n img.onerror = () => resolve(null)\r\n img.onload = () => {\r\n try {\r\n const c = document.createElement('canvas')\r\n c.width = ANALYZE_SIDE; c.height = ANALYZE_SIDE\r\n const g = c.getContext('2d', { willReadFrequently: true })!\r\n g.drawImage(img, 0, 0, ANALYZE_SIDE, ANALYZE_SIDE)\r\n const px = g.getImageData(0, 0, ANALYZE_SIDE, ANALYZE_SIDE).data\r\n let lum = 0\r\n const count = px.length / 4\r\n for (let i = 0; i < px.length; i += 4) {\r\n lum += 0.2126 * px[i]! + 0.7152 * px[i + 1]! + 0.0722 * px[i + 2]!\r\n }\r\n resolve(lum / count / 255 < 0.5)\r\n } catch {\r\n resolve(null)\r\n }\r\n }\r\n img.src = dataUrl\r\n })\r\n}\r\n\r\n/** HSL (h 0-360, s/l 0-1) → RGB (0-255 integers). */\r\nexport function hslToRgb(h: number, s: number, l: number): [number, number, number] {\r\n const c = (1 - Math.abs(2 * l - 1)) * s\r\n const hp = h / 60\r\n const x = c * (1 - Math.abs((hp % 2) - 1))\r\n let r = 0, g = 0, b = 0\r\n if (hp < 1) { r = c; g = x }\r\n else if (hp < 2) { r = x; g = c }\r\n else if (hp < 3) { g = c; b = x }\r\n else if (hp < 4) { g = x; b = c }\r\n else if (hp < 5) { r = x; b = c }\r\n else { r = c; b = x }\r\n const m = l - c / 2\r\n return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)]\r\n}\r\n","/**\r\n * dsh-background-by-model — settings UI design system.\r\n *\r\n * The section is styled entirely through these scoped classes instead of the\r\n * host's inline-style approach: animations (page transitions, staggered\r\n * reveals, the rotating orb ring) and pseudo-element effects cannot be\r\n * expressed as React inline styles. Every color reads the host's\r\n * --dsw-alias-* tokens so the panel follows the user's custom theme color and\r\n * light/dark scheme automatically; `color-mix` tints carry a plain-token\r\n * fallback first for older engines.\r\n */\r\nexport const NAV_ITEM_H = 38\r\nexport const NAV_GAP = 4\r\n\r\nexport const UI_CSS = `\r\n/* The section is rendered INLINE inside the host settings dialog's content\r\n * column: the host provides the modal chrome (backdrop, centering, closing).\r\n * These classes style only the embedded shell; transient fixed layers (toast,\r\n * color picker, background editor) escape through Portals on <html>. */\r\n.dab-root{position:relative;color:var(--dsw-alias-label-primary);animation:dab-fade-in .35s ease both;container-type:inline-size;display:flex;flex-direction:column;align-items:center;width:100%;min-width:0;--dab-mono:ui-monospace,\"Cascadia Mono\",\"SF Mono\",Consolas,\"Courier New\",monospace}\r\n.dab-root *,.dab-root *::before,.dab-root *::after{box-sizing:border-box}\r\n.dab-root button{font-family:inherit}\r\n\r\n/* ── shell: nav rail + page body ─────────────────────────────────────────── */\r\n.dab-shell{display:grid;grid-template-columns:158px minmax(0,1fr);gap:26px;align-items:start;padding-bottom:8px;width:100%;max-width:980px;margin:0 auto}\r\n.dab-nav{position:sticky;top:0;display:flex;flex-direction:column;gap:18px}\r\n.dab-brand{display:flex;align-items:center;gap:10px;padding:2px 6px}\r\n.dab-brand-tile{width:30px;height:30px;flex:none;border-radius:9px;display:grid;place-items:center;color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-brand-primary);box-shadow:0 4px 14px -4px var(--dsw-alias-brand-primary)}\r\n.dab-brand-name{font-size:13px;font-weight:650;letter-spacing:.01em;line-height:1.25}\r\n.dab-brand-tag{font-size:9px;letter-spacing:.16em;font-weight:600;color:var(--dsw-alias-label-quaternary,var(--dsw-alias-label-tertiary));text-transform:uppercase}\r\n.dab-nav-list{position:relative;display:flex;flex-direction:column;gap:${NAV_GAP}px}\r\n.dab-nav-ind{position:absolute;left:0;right:0;top:0;height:${NAV_ITEM_H}px;border-radius:11px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 13%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-brand-primary) 25%,transparent);transition:transform .38s cubic-bezier(.22,1,.36,1)}\r\n.dab-nav-item{position:relative;z-index:1;display:flex;align-items:center;gap:10px;height:${NAV_ITEM_H}px;padding:0 12px;border:0;background:none;border-radius:11px;color:var(--dsw-alias-label-tertiary);font-size:13px;cursor:pointer;text-align:left;transition:color .22s ease}\r\n.dab-nav-item:hover{color:var(--dsw-alias-label-primary)}\r\n.dab-nav-item.is-active{color:var(--dsw-alias-brand-primary);font-weight:600}\r\n.dab-nav-item svg{flex:none;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}\r\n.dab-nav-item:hover svg{transform:scale(1.14) rotate(-5deg)}\r\n\r\n/* ── page chrome ─────────────────────────────────────────────────────────── */\r\n.dab-page{animation:dab-page-in .4s cubic-bezier(.22,1,.36,1) both;min-width:0;display:flex;flex-direction:column;gap:13px}\r\n.dab-head{margin:2px 0 5px}\r\n.dab-overline{font-size:10.5px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--dsw-alias-brand-primary);opacity:.9}\r\n.dab-h1{margin:4px 0 0;font-size:21px;font-weight:700;letter-spacing:-.01em}\r\n.dab-desc{margin:6px 0 0;font-size:12.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);max-width:56ch}\r\n.dab-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:16px;padding:18px}\r\n.dab-card-hover{transition:transform .28s ease,box-shadow .28s ease,border-color .28s ease}\r\n.dab-card-hover:hover{transform:translateY(-2px);box-shadow:0 10px 28px -12px rgba(0,0,0,.28)}\r\n.dab-rise{animation:dab-rise-in .55s cubic-bezier(.22,1,.36,1) both;animation-delay:calc(var(--d,0) * 62ms)}\r\n\r\n/* ── accent hero (color orb) ─────────────────────────────────────────────── */\r\n.dab-hero-accent{display:flex;align-items:center;gap:24px;flex-wrap:wrap}\r\n.dab-orb-wrap{position:relative;width:118px;height:118px;flex:none}\r\n.dab-orb{position:absolute;inset:11px;border-radius:50%;background:radial-gradient(circle at 32% 28%,rgba(255,255,255,.5),rgba(255,255,255,0) 44%),var(--c,#888);box-shadow:0 16px 36px -10px var(--c-soft,transparent),inset 0 -10px 20px rgba(0,0,0,.16);animation:dab-orb-in .7s cubic-bezier(.22,1,.36,1) both}\r\n.dab-orb-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,transparent 0 30%,var(--c,#888) 46%,transparent 62%,transparent 76%,var(--c,#888) 90%,transparent 100%);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 3.5px),#000 calc(100% - 2.5px));mask:radial-gradient(farthest-side,transparent calc(100% - 3.5px),#000 calc(100% - 2.5px));animation:dab-spin 7s linear infinite;opacity:.9}\r\n.dab-hex{font-family:var(--dab-mono);font-size:24px;font-weight:600;letter-spacing:.02em;line-height:1.2;margin-top:2px}\r\n.dab-hsl-row{display:flex;gap:16px;margin-top:7px;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-hsl-row b{font-weight:600;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n\r\n/* ── swatches ────────────────────────────────────────────────────────────── */\r\n.dab-swatch-title{font-size:12px;font-weight:600;margin-bottom:10px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-swatches{display:flex;flex-wrap:wrap;gap:9px}\r\n.dab-swatch{width:25px;height:25px;border-radius:50%;border:0;padding:0;cursor:pointer;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1);transition:transform .22s cubic-bezier(.34,1.56,.64,1),box-shadow .22s ease}\r\n.dab-swatch:hover{transform:scale(1.2)}\r\n.dab-swatch.is-on{box-shadow:0 0 0 2px var(--dsw-alias-bg-layer-1),0 0 0 4px var(--dsw-alias-brand-primary)}\r\n\r\n/* ── wheel card ──────────────────────────────────────────────────────────── */\r\n.dab-wheel-card{position:relative;display:flex;align-items:center;justify-content:center;gap:28px;flex-wrap:wrap;padding:24px 18px}\r\n.dab-wheel-glow{position:absolute;width:230px;height:230px;border-radius:50%;filter:blur(48px);opacity:.2;background:var(--c,#888);pointer-events:none;transition:background .4s ease}\r\n.dab-wheel{position:relative;cursor:crosshair;border-radius:50%;box-shadow:0 12px 32px -14px rgba(0,0,0,.4)}\r\n.dab-hint{font-size:11.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);padding:0 4px}\r\n/* The \"your edits are being held\" notice: it reports a state the user has to act\r\n on, so it is tinted like a warning rather than left as grey hint text. */\r\n.dab-stale{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 35%,transparent);border-radius:9px;padding:8px 10px}\r\n\r\n/* ── precise color inputs ────────────────────────────────────────────────── */\r\n.dab-inputs{display:flex;flex-direction:column;gap:10px;min-width:172px}\r\n.dab-field{display:flex;align-items:center;gap:8px}\r\n.dab-field-label{width:14px;text-align:center;font-family:var(--dab-mono);font-size:11px;font-weight:600;color:var(--dsw-alias-label-tertiary)}\r\n.dab-num{flex:1;min-width:0;height:30px;padding:0 10px;border-radius:9px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-family:var(--dab-mono);font-size:12px;outline:none;transition:border-color .2s,box-shadow .2s}\r\n.dab-num:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}\r\n.dab-num::-webkit-outer-spin-button,.dab-num::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\r\n.dab-num{-moz-appearance:textfield;appearance:textfield}\r\n.dab-urlinput{flex:1;min-width:180px;height:34px;padding:0 12px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:12.5px;outline:none;transition:border-color .2s}\r\n.dab-urlinput::placeholder{color:var(--dsw-alias-label-quaternary)}\r\n.dab-urlinput:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}\r\n/* Prints the current hex on the color itself. Without the value this was an\r\n * empty bordered rectangle sitting in the same column as the H/S/L number\r\n * fields, which made it read as one more — blank — text input; nothing is ever\r\n * typed here, so nothing may look typable. The hover scale went with that\r\n * reading: it advertised an interaction this field does not have. */\r\n.dab-swatch-lg{display:flex;align-items:center;justify-content:center;height:38px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);box-shadow:inset 0 0 14px rgba(0,0,0,.1);font-family:var(--dab-mono);font-size:12.5px;font-weight:600;letter-spacing:.06em;user-select:all}\r\n\r\n/* ── buttons & chips ─────────────────────────────────────────────────────── */\r\n/* Text/icon painted ON --dsw-alias-brand-primary reads\r\n * --dsw-alias-label-primary-inverted, never --dsw-alias-brand-text. The host's\r\n * brand-primary is a CONTRAST ink, not a hue: black in its light scheme and\r\n * near-white (#f9fafb) in its dark one, with brand-text equal to it in BOTH\r\n * (and unused by the host's own CSS). Following the system theme therefore made\r\n * every brand-filled control a filled box with an invisible label — a white\r\n * primary button and a white active chip on a dark dialog. It was only ever\r\n * readable while the plugin owned the palette and generated its own brand pair.\r\n * label-primary-inverted is the host's answer for ink on a brand/contrast fill\r\n * (its sidebar build badge paints exactly this pair) and it flips with the\r\n * scheme: #fff on the light scheme's black fill, #353638 on the dark scheme's\r\n * white one. */\r\n.dab-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:34px;padding:0 14px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:550;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease,opacity .18s ease,background .18s ease}\r\n.dab-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 14px -6px rgba(0,0,0,.32)}\r\n.dab-btn:active:not(:disabled){transform:translateY(0) scale(.97);box-shadow:none}\r\n.dab-btn:disabled{opacity:.5;cursor:not-allowed}\r\n.dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted);border-color:transparent}\r\n.dab-btn-danger{color:var(--dsw-alias-state-error-primary)}\r\n.dab-btn-ghost{background:transparent;border-color:transparent;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-btn-ghost:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2);box-shadow:none}\r\n.dab-btn:focus-visible,.dab-nav-item:focus-visible,.dab-seg-item:focus-visible,.dab-swatch:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\r\n.dab-chip-row{display:flex;flex-wrap:wrap;gap:8px}\r\n.dab-chip{height:30px;padding:0 14px;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary));font-size:12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:all .22s ease}\r\n.dab-chip:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary)}\r\n.dab-chip.is-active{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted);border-color:transparent}\r\n\r\n/* ── sliders ─────────────────────────────────────────────────────────────── */\r\n.dab-slider-block{display:flex;flex-direction:column;gap:6px}\r\n.dab-slider-block + .dab-slider-block{margin-top:13px}\r\n.dab-slider-label{font-size:12px;font-weight:550;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-slider-val{font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);min-width:44px;text-align:right}\r\n.dab-slider{-webkit-appearance:none;appearance:none;flex:1;min-width:0;height:4px;border-radius:99px;outline:none;cursor:pointer;margin:5px 0;background:linear-gradient(to right,var(--dsw-alias-brand-primary) calc(var(--pct,50) * 1%),var(--dsw-alias-border-l2) calc(var(--pct,50) * 1%));transition:height .15s ease}\r\n.dab-slider:hover{height:5px}\r\n.dab-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:15px;height:15px;border-radius:50%;background:var(--dsw-alias-button-elevated-fill,#fff);border:2px solid var(--dsw-alias-brand-primary);box-shadow:0 1px 5px rgba(0,0,0,.28);transition:transform .16s cubic-bezier(.34,1.56,.64,1)}\r\n.dab-slider:hover::-webkit-slider-thumb,.dab-slider:focus-visible::-webkit-slider-thumb{transform:scale(1.22)}\r\n.dab-slider:active::-webkit-slider-thumb{transform:scale(1.34)}\r\n.dab-slider::-moz-range-thumb{width:13px;height:13px;border-radius:50%;background:var(--dsw-alias-button-elevated-fill,#fff);border:2px solid var(--dsw-alias-brand-primary)}\r\n\r\n/* ── interface part cards ────────────────────────────────────────────────── */\r\n.dab-grid-parts{display:grid;grid-template-columns:repeat(auto-fill,minmax(256px,1fr));gap:13px}\r\n.dab-part-head{display:flex;align-items:center;gap:11px;margin-bottom:14px}\r\n.dab-part-ico{width:32px;height:32px;flex:none;border-radius:10px;display:grid;place-items:center;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 12%,transparent)}\r\n.dab-part-name{font-size:13.5px;font-weight:600}\r\n.dab-part-badge{margin-left:auto;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:99px;padding:3px 9px}\r\n\r\n/* ── segmented control ───────────────────────────────────────────────────── */\r\n.dab-seg{position:relative;display:inline-flex;padding:3px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:11px}\r\n.dab-seg-thumb{position:absolute;top:3px;bottom:3px;left:3px;width:var(--w,96px);border-radius:8px;background:var(--dsw-alias-button-elevated-fill);box-shadow:0 2px 8px -2px rgba(0,0,0,.28);transition:transform .32s cubic-bezier(.22,1,.36,1)}\r\n.dab-seg-item{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;width:var(--w,96px);height:30px;border:0;background:none;border-radius:8px;color:var(--dsw-alias-label-tertiary);font-size:12.5px;cursor:pointer;transition:color .25s ease}\r\n.dab-seg-item.is-active{color:var(--dsw-alias-label-primary);font-weight:600}\r\n\r\n/* ── toggle switch ───────────────────────────────────────────────────────── */\r\n.dab-toggle{position:relative;width:42px;height:24px;flex:none;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;padding:0;transition:background .28s ease,border-color .28s ease}\r\n.dab-toggle-knob{position:absolute;top:2.5px;left:2.5px;width:17px;height:17px;border-radius:50%;background:var(--dsw-alias-label-secondary,#999);box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .28s cubic-bezier(.22,1,.36,1),background .28s ease}\r\n.dab-toggle.is-on{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}\r\n.dab-toggle.is-on .dab-toggle-knob{transform:translateX(18px);background:var(--dsw-alias-label-primary-inverted)}\r\n\r\n/* ── background preview hero ─────────────────────────────────────────────── */\r\n.dab-hero{position:relative;border-radius:16px;overflow:hidden;aspect-ratio:16/9;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2)}\r\n.dab-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .5s cubic-bezier(.22,1,.36,1)}\r\n.dab-hero:hover .dab-hero-img{transform:scale(1.03)}\r\n.dab-hero-empty{position:absolute;inset:6px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:var(--dsw-alias-label-tertiary);font-size:12.5px;border:1.5px dashed var(--dsw-alias-border-l2);border-radius:12px;cursor:pointer;background:transparent;transition:border-color .25s,color .25s,background .25s;width:auto;height:auto}\r\n.dab-hero-empty:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}\r\n.dab-hero-empty.is-over{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent)}\r\n.dab-hero-badge{position:absolute;top:10px;left:10px;display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 11px;border-radius:99px;background:rgba(0,0,0,.45);color:#fff;font-size:11px;backdrop-filter:blur(6px);pointer-events:none}\r\n.dab-hero-veil{position:absolute;left:0;right:0;bottom:0;padding:34px 12px 12px;display:flex;align-items:flex-end;justify-content:flex-end;gap:8px;background:linear-gradient(to top,rgba(0,0,0,.55),rgba(0,0,0,0));opacity:0;transform:translateY(6px);transition:opacity .3s ease,transform .3s ease}\r\n.dab-hero:hover .dab-hero-veil{opacity:1;transform:none}\r\n.dab-hero-veil .dab-btn{background:rgba(255,255,255,.94);color:#14161a;border-color:transparent;height:30px;font-size:12px}\r\n.dab-hero-veil .dab-btn-danger{color:#dc2626}\r\n\r\n/* ── profile page ────────────────────────────────────────────────────────── */\r\n.dab-profile-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(238px,1fr));gap:13px}\r\n.dab-profile-ico{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;margin-bottom:13px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 12%,transparent)}\r\n.dab-profile-title{font-size:14px;font-weight:650}\r\n.dab-profile-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);line-height:1.55;margin:5px 0 15px}\r\n.dab-footer{margin-top:6px;padding:14px 4px 0;border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;font-size:11px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-footer-mono{font-family:var(--dab-mono);letter-spacing:.02em}\r\n\r\n/* ── toast ───────────────────────────────────────────────────────────────── */\r\n.dab-toast{position:fixed;left:50%;bottom:30px;transform:translateX(-50%);display:flex;align-items:center;gap:8px;height:38px;padding:0 16px;border-radius:99px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-bg-layer-2));border:1px solid var(--dsw-alias-border-l2);box-shadow:0 10px 30px -8px rgba(0,0,0,.38);font-size:12.5px;z-index:10001;animation:dab-toast-in .32s cubic-bezier(.22,1,.36,1) both}\r\n.dab-toast-ok{color:var(--dsw-alias-brand-primary);display:grid;place-items:center}\r\n.dab-toast-err{color:var(--dsw-alias-state-error-primary);display:grid;place-items:center}\r\n\r\n/* ── modals (editor / eyedropper / crash) ────────────────────────────────── */\r\n/* Pin to the viewport explicitly with vw/vh so ancestor padding/margins on\r\n * body cannot shift or clip the overlay; keep it above host sidebar chrome.\r\n * pointer-events:auto re-enables interaction: these overlays render inside a\r\n * Portal root that is pointer-events:none so it never blocks the page alone. */\r\n.dab-overlay{position:fixed;left:0;top:0;width:100vw;height:100vh;z-index:999999;background:rgba(8,10,14,.62);backdrop-filter:blur(8px);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;animation:dab-fade-in .25s ease both;pointer-events:auto}\r\n.dab-overlay-title{color:#fff;font-size:15px;font-weight:600}\r\n.dab-overlay-hint{color:rgba(255,255,255,.62);font-size:12px}\r\n.dab-modal-card{animation:dab-zoom-in .3s cubic-bezier(.22,1,.36,1) both;max-width:calc(100vw - 40px);max-height:calc(100vh - 120px);overflow:auto}\r\n.dab-overlay .dab-btn{background:rgba(255,255,255,.94);color:#14161a;border-color:transparent}\r\n.dab-overlay .dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted)}\r\n.dab-crash{display:flex;flex-direction:column;gap:10px;align-items:center;padding:28px 18px;border:1px solid var(--dsw-alias-border-l2);border-radius:16px}\r\n.dab-crash-title{font-size:15px;font-weight:650}\r\n.dab-crash-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);text-align:center;line-height:1.5}\r\n\r\n/* ── model rules ─────────────────────────────────────────────────────────── */\r\n.dab-rules{display:flex;flex-direction:column;gap:12px}\r\n.dab-rule{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:16px;padding:14px;transition:border-color .25s,box-shadow .25s,opacity .25s}\r\n.dab-rule.is-active{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 16%,transparent)}\r\n.dab-rule.is-off{opacity:.55}\r\n.dab-rule-head{display:flex;align-items:center;gap:9px;flex-wrap:wrap}\r\n.dab-rule-num{font-family:var(--dab-mono);font-size:11px;font-weight:700;color:var(--dsw-alias-label-tertiary);min-width:16px}\r\n.dab-rule-badge{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 14%,transparent);border-radius:99px;padding:2px 8px}\r\n.dab-rule-match{flex:1;min-width:150px;height:32px;padding:0 11px;border-radius:9px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-family:var(--dab-mono);font-size:12.5px;outline:none;transition:border-color .2s,box-shadow .2s}\r\n.dab-rule-match::placeholder{color:var(--dsw-alias-label-quaternary)}\r\n.dab-rule-match:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}\r\n.dab-icon-btn{width:28px;height:28px;flex:none;display:grid;place-items:center;border-radius:8px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;transition:color .2s,border-color .2s,background .2s}\r\n.dab-icon-btn:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}\r\n.dab-icon-btn:disabled{opacity:.35;cursor:not-allowed}\r\n.dab-icon-btn-danger:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}\r\n.dab-rule-body{margin-top:13px;display:flex;flex-direction:column;gap:13px}\r\n.dab-rule-thumb{position:relative;border-radius:12px;overflow:hidden;aspect-ratio:16/9;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2)}\r\n.dab-rule-thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}\r\n.dab-rule-thumb-empty{position:absolute;inset:5px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;border:1.5px dashed var(--dsw-alias-border-l2);border-radius:9px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-align:center;padding:0 10px}\r\n/* The empty tile is the upload button while the rule has no picture at all, so\r\n it is a real <button> (focusable, keyboard-reachable) reset down to the box the\r\n plain preview occupies — a button brings its own padding, font and border. The\r\n dashed frame it looks like is .dab-rule-thumb-empty, which is why the hover and\r\n the drag highlight have to reach it through a descendant selector too. */\r\n.dab-rule-thumb-add{display:block;width:100%;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;-webkit-appearance:none;appearance:none;transition:border-color .2s,background .2s}\r\n.dab-rule-thumb-add:hover,.dab-rule-thumb-add.is-over{border-color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 6%,var(--dsw-alias-bg-layer-2))}\r\n.dab-rule-thumb-add:hover .dab-rule-thumb-empty,.dab-rule-thumb-add.is-over .dab-rule-thumb-empty{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}\r\n.dab-rule-thumb-add:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\r\n.dab-rule-cols{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:18px;align-items:start}\r\n.dab-rule-section-title{font-size:12px;font-weight:600;margin-bottom:9px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n\r\n/* ── image strip (multi-image rules) ─────────────────────────────────────── */\r\n/* A horizontally scrolling row of thumbnails: the one open for editing is\r\n ringed, and the one the wallpaper is actually painting carries a live dot —\r\n but deliberately NO ring of its own. Two tiles ringed at once read as \"two\r\n things are selected\", which is the one question a row of near-identical\r\n thumbnails must not leave open: being on screen is the dot, and nothing\r\n else. FILES dropped here are added, which is why the container's border\r\n reacts to a drag; a TILE dragged across the row reorders it instead, and that\r\n is what the is-dragging / dab-strip-bar pair below is for. */\r\n.dab-strip{display:flex;gap:7px;margin-top:9px;padding:7px;border-radius:12px;border:1.5px dashed var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);overflow-x:auto;scrollbar-width:thin}\r\n.dab-strip.is-over{border-color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent)}\r\n.dab-strip-item{position:relative;flex:none;width:62px;height:44px;padding:0;border-radius:8px;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);cursor:grab;user-select:none;transition:border-color .2s,box-shadow .2s,transform .18s}\r\n.dab-strip-item img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}\r\n.dab-strip-item:hover{transform:translateY(-1px);border-color:var(--dsw-alias-brand-primary)}\r\n.dab-strip-item.is-sel{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-brand-primary) 40%,transparent)}\r\n/* The tile being dragged out of the row, and the 2px bar that says where it will\r\n land. The bar is drawn INSIDE the tile it precedes (at its left edge) or inside\r\n the last tile (at its right edge, for a drop past the end): a bar as its own flex\r\n item would push the tiles sideways, and a target that slides away as the pointer\r\n approaches it is how a drop ends up one slot off. */\r\n.dab-strip-item.is-dragging{cursor:grabbing;opacity:.45;transform:none;border-style:dashed}\r\n.dab-strip-bar{position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--dsw-alias-brand-primary);z-index:2}\r\n.dab-strip-bar.is-end{left:auto;right:0}\r\n.dab-strip-wait{position:absolute;inset:0;background:repeating-linear-gradient(45deg,transparent 0 4px,color-mix(in srgb,var(--dsw-alias-label-tertiary) 14%,transparent) 4px 8px)}\r\n.dab-strip-num{position:absolute;left:3px;bottom:2px;font-family:var(--dab-mono);font-size:9.5px;line-height:1;padding:1px 4px;border-radius:5px;background:rgba(0,0,0,.45);color:#fff}\r\n.dab-strip-live{position:absolute;right:3px;top:3px;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px rgba(0,0,0,.35);animation:dab-pulse 1.8s ease-in-out infinite}\r\n/* Each image's OWN theme color, when it has one. It shares the right edge with\r\n the live dot but sits at the bottom, where nothing else is: the item number is\r\n bottom-LEFT. Two rings (dark outside, light inside) keep the swatch readable\r\n over a dark and a light thumbnail alike. */\r\n.dab-strip-dot{position:absolute;right:3px;bottom:3px;width:8px;height:8px;border-radius:50%;box-shadow:0 0 0 1.5px rgba(0,0,0,.45),inset 0 0 0 1px rgba(255,255,255,.35)}\r\n.dab-strip-add{flex:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;width:62px;height:44px;border-radius:8px;border:1.5px dashed var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);font-size:9.5px;line-height:1.15;cursor:pointer;transition:border-color .2s,color .2s}\r\n.dab-strip-add:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}\r\n.dab-strip-pos{display:inline-flex;align-items:center;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);padding:0 4px}\r\n\r\n/* ── rotation panel ──────────────────────────────────────────────────────── */\r\n.dab-rot-panel{margin-top:10px;padding:12px;border-radius:12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2)}\r\n.dab-num-sec{flex:none;width:88px;min-width:0}\r\n\r\n@container (max-width:760px){.dab-rule-cols{grid-template-columns:1fr}}\r\n\r\n/* ── host self-check ─────────────────────────────────────────────────────── */\r\n.dab-verdict{display:flex;flex-direction:column;gap:14px;position:relative;overflow:hidden}\r\n.dab-verdict::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;background:linear-gradient(120deg,transparent 55%,color-mix(in srgb,var(--dab-verdict-tone,transparent) 26%,transparent))}\r\n.dab-verdict-ok{--dab-verdict-tone:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 38%,var(--dsw-alias-border-l2))}\r\n.dab-verdict-partial,.dab-verdict-broken{--dab-verdict-tone:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,var(--dsw-alias-border-l2))}\r\n.dab-verdict-unknown{--dab-verdict-tone:var(--dsw-alias-label-tertiary)}\r\n.dab-verdict-head{display:flex;align-items:center;gap:13px;flex-wrap:wrap}\r\n.dab-verdict-ico{width:34px;height:34px;flex:none;border-radius:11px;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}\r\n.dab-verdict-ico-ok{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 14%,transparent)}\r\n.dab-verdict-ico-partial,.dab-verdict-ico-broken{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent)}\r\n.dab-verdict-text{flex:1;min-width:170px}\r\n.dab-verdict-title{font-size:14.5px;font-weight:650}\r\n.dab-verdict-sub{margin-top:4px;font-size:12px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-verdict-actions{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}\r\n.dab-facts{display:flex;flex-wrap:wrap;gap:8px;position:relative;z-index:1}\r\n.dab-fact{display:inline-flex;align-items:center;gap:7px;height:27px;padding:0 11px;border-radius:99px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);max-width:100%}\r\n.dab-fact.is-bad{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}\r\n.dab-fact-k{font-size:10.5px;font-weight:650;letter-spacing:.06em;text-transform:uppercase;color:var(--dsw-alias-label-tertiary);white-space:nowrap}\r\n.dab-fact-v{font-family:var(--dab-mono);font-size:11.5px;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:32ch}\r\n.dab-check-group-title{display:flex;align-items:center;gap:9px;font-size:12.5px;font-weight:650;margin-bottom:11px}\r\n.dab-check-group-count{margin-left:auto;font-family:var(--dab-mono);font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:99px;padding:3px 9px}\r\n.dab-checks{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}\r\n.dab-check{display:flex;gap:10px;padding:9px 10px;border-radius:11px;transition:background .2s ease}\r\n.dab-check:hover{background:var(--dsw-alias-bg-layer-2)}\r\n.dab-check-ico{width:19px;height:19px;flex:none;margin-top:1px;border-radius:50%;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}\r\n.dab-check-ico-pass{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 15%,transparent)}\r\n.dab-check-ico-fail{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 15%,transparent)}\r\n.dab-check-dot{width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.65}\r\n.dab-check-body{min-width:0;flex:1;display:flex;flex-direction:column;gap:3px}\r\n.dab-check-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}\r\n.dab-check-label{font-size:12.5px;font-weight:600}\r\n.dab-check-status{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:1px 7px;border-radius:99px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary)}\r\n.dab-check-status-pass{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 14%,transparent)}\r\n.dab-check-status-fail{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent)}\r\n.dab-check-target{font-family:var(--dab-mono);font-size:10.5px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:6px;padding:1px 6px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\r\n.dab-check-detail{font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);line-height:1.5;overflow-wrap:anywhere}\r\n.dab-check-reason{display:flex;flex-direction:column;gap:5px;font-size:12px;line-height:1.55;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-check-symptom{color:var(--dsw-alias-state-error-primary)}\r\n.dab-check-where{display:flex;gap:7px;align-items:baseline;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-check-where code{font-family:var(--dab-mono);font-size:10.5px;overflow-wrap:anywhere}\r\n.dab-check-note{margin:12px 0 0;font-size:11.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);position:relative;z-index:1}\r\n\r\n/* ── holiday override (Profile page) ─────────────────────────────────────── */\r\n/* Only a label: the whole feature is one switch, and dab-toggle already exists.\r\n The per-holiday cards that used to live here are gone by design. */\r\n.dab-holiday-label{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary)}\r\n\r\n/* ── keyframes ───────────────────────────────────────────────────────────── */\r\n@keyframes dab-fade-in{from{opacity:0}to{opacity:1}}\r\n@keyframes dab-page-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}\r\n@keyframes dab-rise-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}\r\n@keyframes dab-orb-in{from{opacity:0;transform:scale(.82)}to{opacity:1;transform:none}}\r\n@keyframes dab-spin{to{transform:rotate(360deg)}}\r\n@keyframes dab-rotate{to{transform:rotate(360deg)}}\r\n@keyframes dab-toast-in{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}\r\n@keyframes dab-zoom-in{from{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:none}}\r\n@keyframes dab-flow{to{background-position:300% 50%}}\r\n/* The strip's \"this is the image on screen\" dot. It is the only marker that says\r\n the rotation is alive, so it breathes rather than merely sitting there. */\r\n@keyframes dab-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.72)}}\r\n\r\n/* ── responsive & motion preferences ─────────────────────────────────────── */\r\n@container (max-width:620px){\r\n .dab-shell{grid-template-columns:1fr;gap:14px}\r\n .dab-nav{position:static;flex-direction:row;align-items:center;justify-content:space-between;gap:10px}\r\n .dab-nav-list{flex-direction:row;overflow-x:auto;scrollbar-width:none}\r\n .dab-nav-list::-webkit-scrollbar{display:none}\r\n .dab-nav-ind{display:none}\r\n .dab-nav-item{flex:none;padding:0 10px}\r\n .dab-nav-item.is-active{background:var(--dsw-alias-bg-layer-2)}\r\n .dab-types{grid-template-columns:1fr}\r\n .dab-verdict-actions{margin-left:0;width:100%}\r\n .dab-verdict-actions .dab-btn{flex:1}\r\n}\r\n@container (min-width:621px){\r\n .dab-shell{grid-template-columns:158px minmax(0,1fr);gap:26px}\r\n}\r\n@media (prefers-reduced-motion:reduce){\r\n .dab-root *,.dab-root *::before,.dab-root *::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}\r\n}\r\n`\r\n\r\nconst CSS_ID = 'dab-ui-css'\r\n\r\n/**\r\n * The attribute that marks a `<style>` element as OURS.\r\n *\r\n * The host's own CSS modules also set `data-plugin` on their `<style>` elements\r\n * (every one of them), so `data-plugin` cannot distinguish this plugin's sheets\r\n * from the host's — and the host-contract probe has to make exactly that\r\n * distinction: a token this plugin re-emits must never be allowed to make a\r\n * *host* check pass. This attribute is the honest marker, and it is set on every\r\n * stylesheet this plugin injects.\r\n */\r\nexport const OWN_SHEET_ATTR = 'data-dab-side'\r\n\r\n/** Mark a stylesheet this plugin injected, so the host probe can tell it apart. */\r\nexport function markOwnSheet(el: HTMLStyleElement): HTMLStyleElement {\r\n el.setAttribute(OWN_SHEET_ATTR, 'own')\r\n return el\r\n}\r\n\r\n/** Inject the design-system stylesheet once per document (HMR-safe). */\r\nexport function ensureUiCss(): void {\r\n if (typeof document === 'undefined') return\r\n let el = document.getElementById(CSS_ID) as HTMLStyleElement | null\r\n if (!el) {\r\n el = document.createElement('style')\r\n el.id = CSS_ID\r\n markOwnSheet(el)\r\n document.head.appendChild(el)\r\n }\r\n if (el.textContent !== UI_CSS) el.textContent = UI_CSS\r\n}\r\n","import { rWp, rBgState, rBl, rWop, rOps, rSop, rColor, rHasColor, rBlurs, rBgMode, rChatTextOpacity, rTrajectoryOpacity, rRightbarOpacity, rFadeMs } from './state'\r\nimport type { PartOpacities, PartBlurs } from './types'\r\nimport { genTokens, toRgba } from './utils/color'\r\nimport { markOwnSheet } from './components/ui.css'\r\n\r\n/**\r\n * `data-ds-dark-theme` value the plugin writes while it forces its own dark\r\n * palette. The host treats the attribute as a boolean (`toggleAttribute`), so a\r\n * plugin-specific value still matches every `body[data-ds-dark-theme]` rule\r\n * while staying distinguishable from the host's own write — which is what lets\r\n * `releaseOwnScheme` hand the flag back without clobbering the host's scheme.\r\n */\r\nexport const OWN_SCHEME = 'dsh-background-by-model'\r\nconst DARK_ATTR = 'data-ds-dark-theme'\r\n\r\n/**\r\n * Marker on <html> while the plugin owns a palette. The dialog/trajectory rules\r\n * below redirect NO-fallback tokens (`--dsw-alias-bg-layer-*`) to plugin-owned\r\n * variables, so they may only match while those variables are actually written:\r\n * without the gate a palette-less state would leave them reading a\r\n * guaranteed-invalid value (transparent panels) instead of handing the surface\r\n * back to the host untouched.\r\n */\r\nconst THEMED_ATTR = 'data-dab-themed'\r\n\r\nlet wpEl: HTMLDivElement | null = null\r\nlet appliedTokenNames: string[] = []\r\nlet tokenStyleEl: HTMLStyleElement | null = null\r\n\r\nfunction ensureTokenStyle(): HTMLStyleElement {\r\n if (tokenStyleEl?.isConnected) return tokenStyleEl\r\n tokenStyleEl = document.createElement('style')\r\n tokenStyleEl.dataset.plugin = 'dsh-background-by-model-tokens'\r\n markOwnSheet(tokenStyleEl)\r\n document.head.appendChild(tokenStyleEl)\r\n return tokenStyleEl\r\n}\r\n\r\nfunction clearCustomTokens(): void {\r\n if (tokenStyleEl) tokenStyleEl.textContent = ''\r\n for (const name of appliedTokenNames) document.body.style.removeProperty(name)\r\n appliedTokenNames = []\r\n // Whatever follows must repaint from scratch: the fingerprints that guard the\r\n // token rule and the part opacities describe a stylesheet that no longer exists.\r\n baseTokenKey = ''\r\n lastBgKey = ''\r\n}\r\n\r\n/** Drop every surface the plugin owns: the variables the scoped\r\n * dialog/trajectory rules read, and the inline backgrounds written onto the\r\n * AppFrame columns. Used when no palette is available and at teardown — without\r\n * it the last color's surfaces outlive the color that produced them. */\r\nfunction clearOwnedSurfaces(): void {\r\n discoverParts()\r\n const root = document.documentElement\r\n for (const name of OWNED_SURFACE_VARS) root.style.removeProperty(name)\r\n for (const el of [frameEl, centerEl, detailsEl]) el?.style.removeProperty('background')\r\n}\r\n\r\n// Solid surface tokens grouped by which interface-opacity slider owns them.\r\n// Every member is re-emitted with per-part alpha so surfaces over the wallpaper\r\n// (composer input, elevated buttons, menu panels) can go translucent — not just\r\n// the layered bg/sidebar tokens. The two menu fills are owned by the card slider\r\n// and must always travel together: --dsw-specific-menu is what overlays paint\r\n// (dropdowns, slash-trigger menu, popovers around the dialog) and\r\n// --dsw-menu-surface-fill is what the shared MenuSurface material paints, which\r\n// dsh 0.1.7 aliases the former to. Re-emitting only one of them leaves a menu\r\n// panel on one fill and its sticky group headings on the other — the solid band\r\n// across the model selector's provider rows. The Cordis panel shares\r\n// --dsw-specific-menu but is re-scoped to the input slider via INPUT_BLUR_RULE.\r\nconst OPACITY_TOKEN_GROUPS: Array<{ part: keyof PartOpacities; names: string[] }> = [\r\n { part: 'bg', names: ['--dsw-alias-bg-base'] },\r\n { part: 'sidebar', names: ['--dsw-specific-sidebar-fill'] },\r\n { part: 'card', names: ['--dsw-alias-bg-layer-1', '--dsw-alias-bg-layer-2', '--dsw-alias-bg-layer-3', '--dsw-specific-menu', '--dsw-menu-surface-fill'] },\r\n { part: 'input', names: ['--dsw-specific-input-major'] },\r\n]\r\n\r\n// Plugin-owned variables the opacity-bearing tokens read from. They live as\r\n// inline custom props on <html>, so a slider drag rewrites only those few values\r\n// instead of re-parsing/re-matching the whole body token rule on every tick —\r\n// the difference is critical when a large wallpaper sits under the interface.\r\nconst OPACITY_VARS: Record<string, string> = {\r\n '--dsw-alias-bg-base': '--dsh-any-op-bg',\r\n '--dsw-specific-sidebar-fill': '--dsh-any-op-sidebar',\r\n '--dsw-alias-bg-layer-1': '--dsh-any-op-card-1',\r\n '--dsw-alias-bg-layer-2': '--dsh-any-op-card-2',\r\n '--dsw-alias-bg-layer-3': '--dsh-any-op-card-3',\r\n '--dsw-specific-input-major': '--dsh-any-op-input',\r\n // The MenuSurface material under a menu panel and the overlay fill its sticky\r\n // headings paint are the same value on a 0.1.7 host, so they read the same\r\n // plugin-owned variable — one slider, one alpha, no seam between them.\r\n '--dsw-specific-menu': '--dsh-any-op-menu',\r\n '--dsw-menu-surface-fill': '--dsh-any-op-menu',\r\n}\r\n\r\n// Fingerprint of the non-alpha token base (palette source + color pick +\r\n// scheme verdict). The static body rule is only rebuilt when it changes; a drag\r\n// never touches it.\r\nlet baseTokenKey = ''\r\n\r\n// ── Palette source ────────────────────────────────────────────────────────────\r\n// Every surface is painted from ONE palette at a time:\r\n// * a rule WITH a color → the plugin's generated token set;\r\n// * a rule WITHOUT a color → the host's own alias tokens, read back out of the\r\n// live cascade, so \"follow the system theme\" keeps the wallpaper showing and\r\n// the Interface-page sliders working instead of dropping every surface back\r\n// to the host as an opaque plate.\r\n// Both feed the same writers (the body token rule, the per-part alpha variables,\r\n// the dialog/trajectory scoping), so there is never a state where one surface is\r\n// painted from one palette and another from the other one.\r\nconst HOST_SURFACE_TOKENS: string[] = Object.keys(OPACITY_VARS)\r\n\r\n/** Plugin-owned variables the scoped dialog/trajectory rules read. */\r\nconst SETTINGS_SURFACE_VARS = [\r\n '--dsh-any-bg-settings-surface',\r\n '--dsh-any-bg-settings-layer-1',\r\n '--dsh-any-bg-settings-layer-2',\r\n '--dsh-any-bg-settings-layer-3',\r\n]\r\nconst TRAJECTORY_SURFACE_VARS = [\r\n '--dsh-any-traj-layer-1',\r\n '--dsh-any-traj-layer-2',\r\n '--dsh-any-traj-layer-3',\r\n]\r\nconst OWNED_SURFACE_VARS = [...SETTINGS_SURFACE_VARS, ...TRAJECTORY_SURFACE_VARS]\r\n\r\ninterface Palette {\r\n /** True while the palette is the plugin's own (the rule carries a color). */\r\n own: boolean\r\n tokens: Record<string, string>\r\n}\r\n\r\nlet hostProbe: HTMLElement | null = null\r\n\r\n/** Resolve any color the engine understands (hex, rgb()/hsl(), a var() chain,\r\n * color-mix(), …) to its USED value: only a used color can be re-emitted with\r\n * an alpha. Returns null when the engine rejects the value. */\r\nfunction resolveCssColor(raw: string): string | null {\r\n const value = raw.trim()\r\n if (value === '') return null\r\n if (hostProbe === null) {\r\n hostProbe = document.createElement('span')\r\n hostProbe.setAttribute('aria-hidden', 'true')\r\n hostProbe.style.cssText = 'position:absolute;width:0;height:0;pointer-events:none'\r\n }\r\n if (!hostProbe.isConnected) document.body.appendChild(hostProbe)\r\n // Reset first: a rejected value must not be mistaken for the previous one.\r\n hostProbe.style.color = ''\r\n hostProbe.style.color = value\r\n if (hostProbe.style.color === '') return null\r\n return getComputedStyle(hostProbe).color || null\r\n}\r\n\r\n/** Read the host's own surface colors out of the live cascade. */\r\nfunction readHostPalette(): Palette | null {\r\n const sheet = tokenStyleEl\r\n // Our token rule re-emits the very names being asked for, so it has to be\r\n // muted while reading or the readback would return the palette we are leaving.\r\n // No paint can happen in between: the flag is set and cleared in one task.\r\n const muted = sheet !== null && sheet.isConnected && !sheet.disabled\r\n if (muted) sheet!.disabled = true\r\n try {\r\n const computed = getComputedStyle(document.body)\r\n const tokens: Record<string, string> = {}\r\n for (const name of HOST_SURFACE_TOKENS) {\r\n const used = resolveCssColor(computed.getPropertyValue(name))\r\n if (used !== null) tokens[name] = used\r\n }\r\n // Without a base surface there is no palette to paint from: the caller hands\r\n // every surface back to the host instead.\r\n return tokens['--dsw-alias-bg-base'] === undefined ? null : { own: false, tokens }\r\n } finally {\r\n if (muted) sheet!.disabled = false\r\n }\r\n}\r\n\r\n// The readback costs a style recalculation and applyWp runs on every viewport\r\n// frame, so the last result is reused briefly. The theme-reset watch drops it on\r\n// any scheme change; the TTL covers a host palette rewritten without one.\r\nlet hostPaletteCache: { at: number; palette: Palette | null } | null = null\r\nconst HOST_PALETTE_TTL_MS = 1000\r\n\r\nexport function invalidateHostPalette(): void { hostPaletteCache = null }\r\n\r\nfunction hostPalette(): Palette | null {\r\n const now = Date.now()\r\n if (hostPaletteCache !== null && now - hostPaletteCache.at < HOST_PALETTE_TTL_MS) return hostPaletteCache.palette\r\n const read = readHostPalette()\r\n hostPaletteCache = { at: now, palette: read }\r\n return read\r\n}\r\n\r\n/** The palette every surface is currently painted from. */\r\nfunction palette(): Palette | null {\r\n if (!rHasColor()) return hostPalette()\r\n const [h, s, l] = rColor()\r\n return { own: true, tokens: genTokens(h, s, l).tokens }\r\n}\r\n\r\n/** A resolved color with a new alpha. The plugin's own tokens are `hsl()` and\r\n * the host's alias tokens resolve to hex, both of which `toRgba` parses; a host\r\n * publishing an already-composited value (`color(…)`, `oklab(…)`, …) cannot be\r\n * parsed there, and emitting it unchanged would paint an OPAQUE surface — the\r\n * one outcome the transparent-surface design must never fall back to. Those go\r\n * through `color-mix` instead. */\r\nfunction withAlpha(color: string, alpha: number): string {\r\n const converted = toRgba(color, alpha)\r\n if (/^(rgb|hsl)a?\\(/i.test(converted)) return converted\r\n const pct = Math.round(Math.max(0, Math.min(1, alpha)) * 100)\r\n return `color-mix(in srgb, ${color} ${pct}%, transparent)`\r\n}\r\n\r\n/**\r\n * The color scheme the HOST's own preference resolves to, pushed in by the\r\n * browser half (the theme service knows it, custom themes included). `null`\r\n * means \"unknown\", which is the only case where the plugin falls back to the\r\n * preference the host's boot script published and to the OS query itself.\r\n */\r\nlet hostSchemeDark: boolean | null = null\r\n\r\nexport function setHostScheme(dark: boolean | null): void { hostSchemeDark = dark }\r\n\r\nfunction resolveHostDark(): boolean {\r\n if (typeof hostSchemeDark === 'boolean') return hostSchemeDark\r\n // The host's boot script publishes the preference it resolved\r\n // (`html[data-ds-theme-source]`) before any plugin runs.\r\n const source = document.documentElement.dataset.dsThemeSource\r\n if (source === 'dark') return true\r\n if (source === 'light') return false\r\n try { return window.matchMedia('(prefers-color-scheme: dark)').matches } catch { return false }\r\n}\r\n\r\n/**\r\n * Keep `data-ds-dark-theme` in the HOST's own form (a boolean attribute) while\r\n * the plugin does not own a palette.\r\n *\r\n * The plugin overwrites that flag whenever it owns a palette — including\r\n * REMOVING it to force a light one — and the host only re-projects the flag on a\r\n * theme change. So a flag the plugin dropped can stick: the host keeps painting\r\n * its light palette on a dark system, the readback then hands those light\r\n * surfaces back to the plugin, and the interface stays light until some\r\n * unrelated event happens to re-run an apply. Restoring the flag from the\r\n * resolved scheme closes that hole, and the write is skipped when it already\r\n * matches so this never churns the theme observer.\r\n */\r\nexport function adoptHostScheme(): void {\r\n const dark = resolveHostDark()\r\n const current = document.body.getAttribute(DARK_ATTR)\r\n if (dark) {\r\n if (current !== '') document.body.setAttribute(DARK_ATTR, '')\r\n } else if (current !== null) {\r\n document.body.removeAttribute(DARK_ATTR)\r\n }\r\n}\r\n\r\n/** Re-read the host palette and repaint from it when it moved. Called while a\r\n * color-less rule is active (the host can re-project its palette at any time,\r\n * with no event of ours to hang a repaint on). */\r\nexport function refreshSystemTheme(): void {\r\n adoptHostScheme()\r\n invalidateHostPalette()\r\n applyCustomTokens(rOps())\r\n}\r\n\r\n// Coalesce slider-driven token updates to one rAF: a single drag fires several\r\n// input events per frame, and every full re-apply repaints expensive regions\r\n// over a large wallpaper. Batching keeps at most one update per frame.\r\nlet pendingOps: PartOpacities | null = null\r\nlet tokensRaf: number | null = null\r\n\r\nexport function applyCustomTokens(ops: PartOpacities): void {\r\n pendingOps = ops\r\n if (tokensRaf !== null) return\r\n tokensRaf = requestAnimationFrame(() => {\r\n tokensRaf = null\r\n if (pendingOps === null) return\r\n const o = pendingOps\r\n pendingOps = null\r\n applyCustomTokensNow(o)\r\n })\r\n}\r\n\r\n// Only the main-bg slider retints the center/details columns; keys on\r\n// baseTokenKey + ops.bg so a sidebar/card/input drag never rewrites them.\r\nlet lastBgKey = ''\r\n\r\nfunction applyCustomTokensNow(ops: PartOpacities): void {\r\n const src = palette()\r\n if (src === null) {\r\n // Nothing to paint from: drop the token rule too, then hand every\r\n // plugin-owned surface — and the scheme flag — back to the host rather than\r\n // leaving the previous palette's values in place.\r\n clearCustomTokens()\r\n clearOwnedSurfaces()\r\n adoptHostScheme()\r\n return\r\n }\r\n const { own, tokens } = src\r\n const [h, s, l] = rColor()\r\n try {\r\n const forceDark = own && l < 0.55\r\n // The fingerprint carries the source, so switching between the two palettes\r\n // always rewrites the rule, even when the numbers happen to coincide.\r\n const key = own\r\n ? `own:${h}|${s}|${l}`\r\n : `host:${HOST_SURFACE_TOKENS.map(n => tokens[n] ?? '').join('|')}`\r\n if (key !== baseTokenKey) {\r\n // Drive the base-palette switch with a plugin-specific value so the\r\n // gradient rule never matches a host dark-mode flag; color-scheme makes\r\n // native controls (select popups) follow the forced palette. Both ride the\r\n // stylesheet (not inline styles) so the host presenter clearing body\r\n // inline styles on boot can't drop them, and the !important rule survives\r\n // that clearing too.\r\n if (own) {\r\n if (forceDark) document.body.setAttribute(DARK_ATTR, OWN_SCHEME)\r\n else document.body.removeAttribute(DARK_ATTR)\r\n } else {\r\n adoptHostScheme()\r\n }\r\n const decls: string[] = own ? [`color-scheme:${forceDark ? 'dark' : 'light'}`] : []\r\n for (const [name, value] of Object.entries(tokens)) {\r\n const opVar = OPACITY_VARS[name]\r\n decls.push(`${name}:${opVar !== undefined ? `var(${opVar})` : value}!important`)\r\n }\r\n ensureTokenStyle().textContent = `body{${decls.join(';')}}`\r\n if (own) {\r\n // Drop inline tokens left by earlier builds so the stylesheet is the single source of truth.\r\n for (const name of appliedTokenNames) document.body.style.removeProperty(name)\r\n appliedTokenNames = Object.keys(tokens)\r\n }\r\n // Recorded only once the rule is in: a write that threw must be retried by\r\n // the next apply instead of being skipped by this fingerprint forever.\r\n baseTokenKey = key\r\n }\r\n // Cheap per-drag update: only the surface alpha vars move on <html>.\r\n const root = document.documentElement\r\n for (const g of OPACITY_TOKEN_GROUPS) {\r\n for (const name of g.names) {\r\n root.style.setProperty(OPACITY_VARS[name], withAlpha(tokens[name] ?? '#000', ops[g.part]))\r\n }\r\n }\r\n // The Cordis panel keeps its own input-slider alpha (see INPUT_BLUR_RULE).\r\n root.style.setProperty('--dsh-any-op-menu-cordis', withAlpha(tokens['--dsw-specific-menu'] ?? '#000', ops.input))\r\n const bgKey = `${baseTokenKey}|${ops.bg}`\r\n if (bgKey !== lastBgKey) { lastBgKey = bgKey; applyPartOpacities(ops) }\r\n } catch {\r\n // ignore\r\n }\r\n}\r\n\r\n// ── Settings panel opacity ─────────────────────────────────────────────────────\r\n// The settings modal is the only aria-modal dialog identifying itself with\r\n// aria-labelledby, so this selector scopes translucency to the settings panel.\r\n// The surface (--dsw-alias-bg-layer-2) is re-emitted with an alpha through a\r\n// plugin-owned variable so the panel keeps its color while fading.\r\n\r\nconst SETTINGS_PANEL_SEL = '[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]'\r\nexport const SETTINGS_STYLE_RULE =\r\n `${SETTINGS_PANEL_SEL}{` +\r\n `background:var(--dsh-any-bg-settings-surface,var(--dsw-alias-bg-layer-2));` +\r\n `backdrop-filter:var(--dsh-any-blur-settings,none);` +\r\n `}` +\r\n // Re-scope the dialog's layer tokens to plugin-owned variables so every\r\n // surface inside the dialog follows the settings opacity slider only. Gated on\r\n // the plugin owning a palette (see THEMED_ATTR): these three declarations have\r\n // no host fallback, so they may only be live while `applySettingsOverrides`\r\n // writes the variables they read.\r\n `html[${THEMED_ATTR}] ${SETTINGS_PANEL_SEL}{` +\r\n `--dsw-alias-bg-layer-1:var(--dsh-any-bg-settings-layer-1);` +\r\n `--dsw-alias-bg-layer-2:var(--dsh-any-bg-settings-layer-2);` +\r\n `--dsw-alias-bg-layer-3:var(--dsh-any-bg-settings-layer-3)}` +\r\n // Option-panel blur inside the dialog, owned by the card blur slider.\r\n `${SETTINGS_PANEL_SEL} .dab-card{backdrop-filter:var(--dsh-any-blur-card-panels,none);-webkit-backdrop-filter:var(--dsh-any-blur-card-panels,none)}`\r\n\r\n// Input/control surface blur. The composer card and the Cordis panel expose\r\n// stable host data attributes ([data-composer-card], [data-cordis-panel]), so\r\n// the backdrop is attached via a stylesheet rule rather than element discovery.\r\n// The Cordis panel shares the --dsw-specific-menu token with the dialog's\r\n// option boxes, but it stays owned by the input slider — the re-scope below\r\n// keeps it there now that the menu token itself follows the card slider. Note\r\n// the input slider must NOT drive the button-elevated-fill /\r\n// button-floating-hover tokens: the settings panel's own controls (slider\r\n// thumbs, .dab-btn, segmented thumb) are painted from those same tokens, so\r\n// tinting them would bleach the panel's own UI.\r\nexport const INPUT_BLUR_RULE =\r\n '[data-composer-card],[data-cordis-panel]{' +\r\n '-webkit-backdrop-filter:var(--dsh-any-input-blur,none);' +\r\n 'backdrop-filter:var(--dsh-any-input-blur,none)}' +\r\n '[data-cordis-panel]{--dsw-specific-menu:var(--dsh-any-op-menu-cordis)!important}'\r\n\r\nfunction applyInputBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-input-blur', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-input-blur')\r\n}\r\n\r\n// Placeholder/hint text inside the composer and the plugin's own input\r\n// surfaces: rendered with the weak caption token (distinct from real input)\r\n// plus italic, so an empty box is never mistaken for typed content.\r\nexport const PLACEHOLDER_RULE =\r\n '[data-composer-card] textarea::placeholder,' +\r\n '[data-composer-card] input::placeholder,' +\r\n '[data-composer-card] [contenteditable]::placeholder,' +\r\n '[data-cordis-panel] input::placeholder,' +\r\n '[data-cordis-panel] textarea::placeholder,' +\r\n '.dab-input::placeholder,' +\r\n '.dab-input textarea::placeholder,' +\r\n '.dab-input input::placeholder' +\r\n '{color:var(--dsh-any-placeholder,var(--dsw-alias-label-caption,#8a8f98))!important;font-style:italic;opacity:.85}'\r\n\r\nexport function applySettingsOverrides(op: number): void {\r\n // Follows whichever palette is in force: the rule's own tokens, or the host's\r\n // own surfaces while the rule follows the system theme. A token the palette\r\n // does not carry has its variable REMOVED — leaving the previous color's value\r\n // behind is exactly the stale surface this used to show.\r\n const tokens = palette()?.tokens ?? {}\r\n const root = document.documentElement\r\n const write = (name: string, token: string): void => {\r\n const value = tokens[token]\r\n if (value === undefined) root.style.removeProperty(name)\r\n else root.style.setProperty(name, withAlpha(value, op))\r\n }\r\n // Always written explicitly (including 100%) — removing them would make\r\n // SETTINGS_STYLE_RULE fall back to the body layer tokens that\r\n // applyCustomTokens rewrites with the homepage card alpha.\r\n write('--dsh-any-bg-settings-surface', '--dsw-alias-bg-layer-2')\r\n // Dialog-scoped layer overrides consumed by SETTINGS_STYLE_RULE; opacity\r\n // follows the settings slider only (the card slider reaches panels via blur).\r\n write('--dsh-any-bg-settings-layer-1', '--dsw-alias-bg-layer-1')\r\n write('--dsh-any-bg-settings-layer-2', '--dsw-alias-bg-layer-2')\r\n write('--dsh-any-bg-settings-layer-3', '--dsw-alias-bg-layer-3')\r\n}\r\n\r\n// ── Trajectory view opacity ──────────────────────────────────────────────\r\n// The trajectory view's own panels fully cover the root, so retinting only the\r\n// root background is invisible. Re-scope the view root's layer tokens to\r\n// plugin-owned variables so every surface follows the trajectory slider.\r\nexport const TRAJECTORY_STYLE_RULE =\r\n // Gated like the settings re-scope: see THEMED_ATTR.\r\n `html[${THEMED_ATTR}] [data-conversation-composer-overlay]{` +\r\n // No fallback inside var(): a self-referential fallback would be a cycle.\r\n '--dsw-alias-bg-layer-1:var(--dsh-any-traj-layer-1);' +\r\n '--dsw-alias-bg-layer-2:var(--dsh-any-traj-layer-2);' +\r\n '--dsw-alias-bg-layer-3:var(--dsh-any-traj-layer-3)}'\r\n\r\nexport function applyTrajectoryOverrides(op: number): void {\r\n // Always written explicitly so the view stays owned by this slider at 100%,\r\n // and removed per token the palette lacks (see applySettingsOverrides).\r\n const tokens = palette()?.tokens ?? {}\r\n const root = document.documentElement\r\n const write = (name: string, token: string): void => {\r\n const value = tokens[token]\r\n if (value === undefined) root.style.removeProperty(name)\r\n else root.style.setProperty(name, withAlpha(value, op))\r\n }\r\n write('--dsh-any-traj-layer-1', '--dsw-alias-bg-layer-1')\r\n write('--dsh-any-traj-layer-2', '--dsw-alias-bg-layer-2')\r\n write('--dsh-any-traj-layer-3', '--dsw-alias-bg-layer-3')\r\n}\r\n\r\n// ── File-preview panel (right sidebar) ────────────────────────────────────\r\n// Clicking a file opens the host's right panel, whose visible surface is painted\r\n// from `background: var(--dsw-alias-bg-base)` — the exact token the\r\n// main-background slider re-emits with its own alpha. The panel was therefore a\r\n// second, unnamed copy of the main background with no control of its own; this\r\n// card takes it over, on whichever element the host paints that surface.\r\n//\r\n// dsh 0.1.7 moved the paint off the panel: the container lost its background and\r\n// became the slide / fullscreen viewport, and it stays mounted at its full width\r\n// for the whole session — collapsing it only slides the dock out (`transform` +\r\n// `visibility`, never `display`). A surface (plus a backdrop-filter) written on\r\n// that container therefore covers the empty right half of the frame even with\r\n// the panel closed, which is the permanent frosted plate 0.1.7 shows. The dock's\r\n// own tab hosts are what the host paints now, so the card follows them:\r\n//\r\n// 0.1.7+ the dock's tab hosts — `[data-dockkit-content]` (and the\r\n// `[data-dockkit-empty]` seat of an empty pane), painted by the host\r\n// from the same token and hidden with `visibility`, so the card rides\r\n// the host's own open/close and slide transitions for free. Floating\r\n// panes are excluded exactly as the host excludes them.\r\n// older the panel itself, which used to carry that background on its hashed\r\n// class. `:has()` keeps the two apart, so the alpha is never painted\r\n// twice over on a 0.1.7 host.\r\n//\r\n// The selectors use data attributes (not the hashed CSS-module classes) and\r\n// `!important` outranks the host's class rule. The `var()` fallback keeps the\r\n// host's own value until a rule with a color supplies one, so a color-less rule\r\n// changes nothing here.\r\n//\r\n// backdrop-filter stays on the container — that is where this card has always\r\n// put it, and it keeps the panel to a single filter pass — but only while the\r\n// panel is open: an always-on filter is what turned the collapsed panel into a\r\n// plate.\r\nexport const RIGHTBAR_STYLE_RULE =\r\n 'div[data-sidebar-right-panel]:not(:has([data-dockkit-content],[data-dockkit-empty]))[data-sidebar-right-open],' +\r\n 'div[data-sidebar-right-panel] [data-dockkit-content]:not([data-dockkit-float]),' +\r\n 'div[data-sidebar-right-panel] [data-dockkit-empty]{' +\r\n 'background:var(--dsh-any-bg-rightbar,var(--dsw-alias-bg-base))!important}' +\r\n 'div[data-sidebar-right-panel][data-sidebar-right-open]{' +\r\n '-webkit-backdrop-filter:var(--dsh-any-blur-rightbar,none);' +\r\n 'backdrop-filter:var(--dsh-any-blur-rightbar,none)}'\r\n\r\n/** Paint the file-preview panel's surface from its own slider. */\r\nexport function applyRightbarOverrides(op: number): void {\r\n const root = document.documentElement\r\n // The panel is painted from the palette in force like every other surface;\r\n // only when there is no palette at all (a host publishing none of the tokens\r\n // we re-emit) does it keep the host's own --dsw-alias-bg-base.\r\n const base = palette()?.tokens['--dsw-alias-bg-base']\r\n if (base === undefined) { root.style.removeProperty('--dsh-any-bg-rightbar'); return }\r\n root.style.setProperty('--dsh-any-bg-rightbar', withAlpha(base, op))\r\n}\r\n\r\n/** Extra backdrop frost for the file-preview panel (0 = no frost of its own). */\r\nfunction applyRightbarBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-blur-rightbar', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-blur-rightbar')\r\n}\r\n\r\n// ── Per-part interface blur ───────────────────────────────────────────────────\r\n// The AppFrame columns use hashed CSS-module classes, so parts are located\r\n// structurally: the shell overlay carries a stable data attribute and the\r\n// sidebar/center/details columns are its three preceding siblings.\r\n//\r\n// backdrop-filter must NEVER go directly on a host part: it turns the element\r\n// into a containing block for fixed-positioned descendants, which would trap\r\n// the host's settings dialog inside the column. Each blurred part carries an\r\n// isolated ::before underlay holding the backdrop-filter instead.\r\nlet frameEl: HTMLElement | null = null\r\nlet sidebarEl: HTMLElement | null = null\r\nlet centerEl: HTMLElement | null = null\r\nlet detailsEl: HTMLElement | null = null\r\n\r\nconst PART_BLUR_CLASS = 'dab-part-blur'\r\nconst PART_UNDERLAY_CLASS = 'dab-part-underlay'\r\nconst PART_BLUR_RULE =\r\n `${PART_BLUR_CLASS}{isolation:isolate}` +\r\n `.${PART_UNDERLAY_CLASS}{position:absolute;inset:0;z-index:-1;pointer-events:none;border-radius:inherit;` +\r\n `backdrop-filter:var(--dsh-any-part-blur,none);-webkit-backdrop-filter:var(--dsh-any-part-blur,none)}`\r\n\r\nlet partBlurStyleEl: HTMLStyleElement | null = null\r\n\r\nfunction ensurePartBlurStyle(): void {\r\n if (partBlurStyleEl?.isConnected) return\r\n partBlurStyleEl = document.createElement('style')\r\n partBlurStyleEl.dataset.plugin = 'dsh-background-by-model-parts'\r\n markOwnSheet(partBlurStyleEl)\r\n partBlurStyleEl.textContent = PART_BLUR_RULE\r\n document.head.appendChild(partBlurStyleEl)\r\n}\r\n\r\nfunction discoverParts(): void {\r\n const overlay = document.querySelector<HTMLElement>('[data-shell-overlay]')\r\n if (overlay === null) return\r\n const frame = overlay.parentElement\r\n if (frame === null) return\r\n frameEl = frame\r\n const idx = Array.from(frame.children).indexOf(overlay)\r\n sidebarEl = (frame.children[idx - 3] as HTMLElement | undefined) ?? null\r\n centerEl = (frame.children[idx - 2] as HTMLElement | undefined) ?? null\r\n detailsEl = (frame.children[idx - 1] as HTMLElement | undefined) ?? null\r\n}\r\n\r\nfunction setBlur(el: HTMLElement | null, px: number): void {\r\n if (el === null) return\r\n const underlay = el.querySelector<HTMLDivElement>(`:scope > .${PART_UNDERLAY_CLASS}`)\r\n if (px > 0) {\r\n ensurePartBlurStyle()\r\n // The underlay is position:absolute and needs a positioned host: static\r\n // columns get relative (a layout no-op for flex items) that is restored on\r\n // clear; parts the host already positions keep their own scheme.\r\n if (!el.classList.contains(PART_BLUR_CLASS) && getComputedStyle(el).position === 'static') {\r\n el.style.position = 'relative'\r\n el.setAttribute('data-dab-pos-patched', '1')\r\n }\r\n el.classList.add(PART_BLUR_CLASS)\r\n if (underlay === null) {\r\n const node = document.createElement('div')\r\n node.className = PART_UNDERLAY_CLASS\r\n el.prepend(node)\r\n }\r\n el.style.setProperty('--dsh-any-part-blur', `blur(${px}px)`)\r\n } else {\r\n el.classList.remove(PART_BLUR_CLASS)\r\n el.style.removeProperty('--dsh-any-part-blur')\r\n underlay?.remove()\r\n if (el.getAttribute('data-dab-pos-patched') === '1') {\r\n el.style.removeProperty('position')\r\n el.removeAttribute('data-dab-pos-patched')\r\n }\r\n }\r\n}\r\n\r\nfunction applySettingsBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-blur-settings', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-blur-settings')\r\n}\r\n\r\n/** Apply the main-background opacity to the center/details columns instead of\r\n * the frame. The frame's translucent bg-base sits UNDER the sidebar, so\r\n * reducing the main-bg opacity stacked a second alpha onto the sidebar; moving\r\n * the alpha onto the columns keeps the sidebar owned by its own slider. */\r\nfunction applyPartOpacities(ops: PartOpacities): void {\r\n discoverParts()\r\n if (frameEl === null) return\r\n const base = palette()?.tokens['--dsw-alias-bg-base']\r\n if (base === undefined) {\r\n // No palette to paint from: hand the columns back to the host instead of\r\n // leaving the last color's inline background on them.\r\n for (const el of [frameEl, centerEl, detailsEl]) el?.style.removeProperty('background')\r\n return\r\n }\r\n frameEl.style.background = 'transparent'\r\n if (centerEl !== null) centerEl.style.background = withAlpha(base, ops.bg)\r\n if (detailsEl !== null) detailsEl.style.background = withAlpha(base, ops.bg)\r\n}\r\n\r\n/** Blur of the option panels inside the settings dialog (.dab-card), owned by\r\n * the \"dialog option panel\" (card) blur slider. Written as a plugin-owned\r\n * variable consumed by SETTINGS_STYLE_RULE — deliberately NOT applied to the\r\n * homepage center/details columns, which this slider must never touch. */\r\nfunction applyCardPanelsBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-blur-card-panels', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-blur-card-panels')\r\n}\r\n\r\n/** Apply per-part interface blur to the AppFrame columns + settings panel. */\r\nexport function applyPartBlurs(blurs: PartBlurs): void {\r\n discoverParts()\r\n // The bg blur frosts the wallpaper behind the main content columns (center +\r\n // details); the frame itself stays unblurred so the sidebar is never\r\n // double-frosted by both the bg and sidebar sliders.\r\n setBlur(frameEl, 0)\r\n setBlur(sidebarEl, blurs.sidebar)\r\n setBlur(centerEl, blurs.bg)\r\n setBlur(detailsEl, blurs.bg)\r\n applyCardPanelsBlur(blurs.card)\r\n applySettingsBlur(blurs.settings)\r\n applyInputBlur(blurs.input)\r\n applyRightbarBlur(blurs.rightbar)\r\n applyViewCards()\r\n}\r\n\r\n/** Live per-part blur update during slider drag (no full re-apply). */\r\nexport function setPartBlur(part: keyof PartBlurs, v: number): void {\r\n if (part === 'settings') { applySettingsBlur(v); return }\r\n if (part === 'card') { applyCardPanelsBlur(v); return }\r\n if (part === 'input') { applyInputBlur(v); return }\r\n if (part === 'rightbar') { applyRightbarBlur(v); return }\r\n if (part === 'chat' || part === 'trajectory') { applyViewCards(); return }\r\n discoverParts()\r\n if (part === 'bg') { setBlur(centerEl, v); setBlur(detailsEl, v) }\r\n else setBlur(sidebarEl, v)\r\n}\r\n\r\n// ── Conversation view treatments ────────────────────────────────────\r\n// The chat message column is styled as a real card (layer-1 surface + border +\r\n// 16px radius + 18px padding); the trajectory view gets NO card decoration —\r\n// its own panels fully cover the view root, so its opacity slider re-scopes the\r\n// layer tokens inside the view and its blur frosts the backdrop through the\r\n// standard root underlay.\r\n//\r\n// Host structure (deepseek-harness ui-conversation / ui-trajectory):\r\n// ConversationRoot\r\n// header — title + tabs, OUTSIDE the scrollport\r\n// [data-conversation-scroll] — the single scrollport\r\n// [data-chat-flow] ← chat column (flow content, NOT scrollable)\r\n// [data-conversation-composer-overlay] ← trajectory view root\r\n// [data-composer-seat] — sticky composer, a sibling\r\n// Cards are ALWAYS styled once their host exists — sliders at zero only turn\r\n// surface/border transparent, so the layout never reflows and the view cannot\r\n// jump when a slider leaves zero. Removal happens only at plugin teardown.\r\ninterface ViewCardSpec {\r\n sel: string\r\n mark: string\r\n /** Dataset key prefix holding the stashed pre-card inline values. */\r\n prev: string\r\n opacity: () => number\r\n blur: () => number\r\n /** Generic heuristic fallback (chat card only, hosts without the marker). */\r\n fallback?: boolean\r\n /** No card decoration — surfaces follow scoped layer tokens; only the blur\r\n * underlay is attached to the host element. */\r\n plain?: boolean\r\n}\r\n\r\nconst VIEW_CARDS: ViewCardSpec[] = [\r\n { sel: '[data-chat-flow]', mark: 'data-dab-chat-card', prev: 'dabChatPrev', opacity: rChatTextOpacity, blur: () => rBlurs().chat, fallback: true },\r\n { sel: '[data-conversation-composer-overlay]', mark: 'data-dab-traj-card', prev: 'dabTrajPrev', opacity: rTrajectoryOpacity, blur: () => rBlurs().trajectory, plain: true },\r\n]\r\n\r\nconst viewTargets: Array<HTMLElement | null> = VIEW_CARDS.map(() => null)\r\n\r\nfunction isScrollableY(el: HTMLElement): boolean {\r\n const oy = getComputedStyle(el).overflowY\r\n // 'overlay' covers Chromium's non-standard overflow value.\r\n return oy === 'auto' || oy === 'scroll' || oy === 'overlay'\r\n}\r\n\r\n/** Whether the subtree hosts the chat input (textarea / contenteditable /\r\n * textbox role) — used to keep the card off the input row. */\r\nfunction containsChatEditor(el: HTMLElement): boolean {\r\n return el.querySelector('textarea,[contenteditable=\"true\"],[contenteditable=\"\"],[contenteditable=\"plaintext-only\"],[role=\"textbox\"]') !== null\r\n}\r\n\r\n/** Walk down from a coarse candidate toward the actual message column. */\r\nfunction refineMessageColumn(start: HTMLElement): HTMLElement {\r\n let cur = start\r\n for (let depth = 0; depth < 10; depth++) {\r\n if (isScrollableY(cur)) break\r\n const kids = Array.from(cur.children).filter((k): k is HTMLElement => k instanceof HTMLElement)\r\n if (kids.length === 0) break\r\n const tallest = kids.reduce((a, b) => (b.clientHeight > a.clientHeight ? b : a))\r\n if (containsChatEditor(cur)) {\r\n const candidates = kids.filter(k => !containsChatEditor(k) && k.clientHeight >= cur.clientHeight * 0.4)\r\n if (candidates.length === 0) break\r\n cur = candidates.reduce((a, b) => (b.clientHeight > a.clientHeight ? b : a))\r\n continue\r\n }\r\n if (kids.length > 1 && tallest.clientHeight >= cur.clientHeight * 0.85) { cur = tallest; continue }\r\n break\r\n }\r\n return cur\r\n}\r\n\r\nfunction discoverViewTarget(idx: number, spec: ViewCardSpec): HTMLElement | null {\r\n if (centerEl === null || !document.body.contains(centerEl)) { viewTargets[idx] = null; return null }\r\n // The host marker always wins over a cached fallback (the view may not be\r\n // mounted yet when the plugin applies early).\r\n const marked = centerEl.querySelector<HTMLElement>(spec.sel)\r\n const cached = viewTargets[idx]\r\n if (marked !== null) {\r\n if (cached !== null && cached !== marked) { setBlur(cached, 0); restoreCardHost(cached, spec.mark, spec.prev, spec.plain === true) }\r\n viewTargets[idx] = marked\r\n return marked\r\n }\r\n if (cached !== null && centerEl.contains(cached)) return cached\r\n viewTargets[idx] = null\r\n if (spec.fallback !== true) return null\r\n // On the harness, an absent [data-chat-flow] just means the chat view is not\r\n // mounted (hero phase, trajectory tab) — settling on the whole scrollport\r\n // there would wrap the entire page in the card.\r\n if (centerEl.querySelector('[data-conversation-scroll]') !== null) return null\r\n // Marker-less hosts keep their layout until a slider moves.\r\n if (spec.opacity() <= 0 && spec.blur() <= 0) return null\r\n let best: HTMLElement | null = null\r\n let bestArea = 0\r\n for (const el of Array.from(centerEl.querySelectorAll<HTMLElement>('*'))) {\r\n if (!isScrollableY(el)) continue\r\n if (el.clientHeight < centerEl.clientHeight * 0.35) continue\r\n const area = el.clientWidth * el.clientHeight\r\n if (area > bestArea) { bestArea = area; best = el }\r\n }\r\n if (best === null) {\r\n for (const el of Array.from(centerEl.children)) {\r\n if (!(el instanceof HTMLElement)) continue\r\n if (el.clientHeight < centerEl.clientHeight * 0.5) continue\r\n if (el.clientHeight > (best?.clientHeight ?? 0)) best = el\r\n }\r\n }\r\n const refined = best !== null ? refineMessageColumn(best) : null\r\n viewTargets[idx] = refined\r\n return refined\r\n}\r\n\r\n/** Stash the host's own inline values so teardown restores them exactly. */\r\nfunction stashCardPrev(el: HTMLElement, prev: string, plain: boolean): void {\r\n const ds = el.dataset as Record<string, string | undefined>\r\n ds[prev + 'Bg'] = el.style.getPropertyValue('background')\r\n if (plain) return\r\n ds[prev + 'Border'] = el.style.getPropertyValue('border')\r\n ds[prev + 'Radius'] = el.style.getPropertyValue('border-radius')\r\n ds[prev + 'Padding'] = el.style.getPropertyValue('padding')\r\n}\r\n\r\n/** Undo the inline styling, restoring the host's previous inline values. */\r\nfunction restoreCardHost(el: HTMLElement, mark: string, prev: string, plain: boolean): void {\r\n if (!el.hasAttribute(mark)) return\r\n const ds = el.dataset as Record<string, string | undefined>\r\n const restore = (prop: string, v: string | undefined): void => {\r\n if (v !== undefined && v !== '') el.style.setProperty(prop, v)\r\n else el.style.removeProperty(prop)\r\n }\r\n restore('background', ds[prev + 'Bg'])\r\n if (!plain) {\r\n restore('border', ds[prev + 'Border'])\r\n restore('border-radius', ds[prev + 'Radius'])\r\n restore('padding', ds[prev + 'Padding'])\r\n delete ds[prev + 'Border']; delete ds[prev + 'Radius']; delete ds[prev + 'Padding']\r\n }\r\n delete ds[prev + 'Bg']\r\n el.removeAttribute(mark)\r\n}\r\n\r\n/** Teardown only: strip every view treatment and hand the hosts back untouched. */\r\nfunction removeViewCards(): void {\r\n VIEW_CARDS.forEach((spec, i) => {\r\n const el = viewTargets[i]\r\n if (el !== null) { setBlur(el, 0); restoreCardHost(el, spec.mark, spec.prev, spec.plain === true) }\r\n viewTargets[i] = null\r\n })\r\n}\r\n\r\n// ── Wide markdown tables ──────────────────────────────────────────────────────\r\n// DSH intentionally lets `.md-table-wide` bleed outside the text column. That\r\n// bleed only becomes visible once the chat surface gains a visible border, i.e.\r\n// when the chat region opacity or blur is non-zero. Under that same condition,\r\n// pull the table back inside the column and let it scroll horizontally.\r\nconst TABLE_FIX_RULE = [\r\n '.md-table-wide {',\r\n ' --dsh-table-spare: 0px !important;',\r\n ' --dsh-table-lead: 0px !important;',\r\n ' box-sizing: border-box !important;',\r\n ' width: 100% !important;',\r\n ' max-width: 100% !important;',\r\n ' margin-left: 0 !important;',\r\n ' padding-left: 0 !important;',\r\n ' padding-bottom: 0 !important;',\r\n ' overflow-x: auto !important;',\r\n '}',\r\n].join('\\n')\r\nlet tableFixStyleEl: HTMLStyleElement | null = null\r\n\r\n/** Toggle the wide-table clamp according to the chat region's opacity & blur. */\r\nfunction syncTableFix(): void {\r\n const needed = rChatTextOpacity() > 0 || rBlurs().chat > 0\r\n if (!needed) {\r\n if (tableFixStyleEl !== null) { tableFixStyleEl.remove(); tableFixStyleEl = null }\r\n return\r\n }\r\n if (tableFixStyleEl === null) {\r\n tableFixStyleEl = document.createElement('style')\r\n tableFixStyleEl.dataset.plugin = 'dsh-background-by-model-table-fix'\r\n markOwnSheet(tableFixStyleEl)\r\n tableFixStyleEl.textContent = TABLE_FIX_RULE\r\n }\r\n if (!tableFixStyleEl.isConnected) document.head.appendChild(tableFixStyleEl)\r\n}\r\n\r\n/** Re-derive the conversation view cards from the current config. */\r\nexport function applyViewCards(): void {\r\n discoverParts()\r\n if (centerEl === null) return\r\n // The chat card is tinted from the palette in force, so a color-less rule gets\r\n // the host's own surface instead of the seed color's fallback tint.\r\n const surface = palette()?.tokens['--dsw-alias-bg-layer-1']\r\n VIEW_CARDS.forEach((spec, i) => {\r\n const target = discoverViewTarget(i, spec)\r\n if (target === null) return\r\n const plain = spec.plain === true\r\n const opacity = spec.opacity()\r\n const blurPx = spec.blur()\r\n if (!plain) {\r\n if (!target.hasAttribute(spec.mark)) stashCardPrev(target, spec.prev, false)\r\n // Mirrors .dab-card (layer-1 background, border, 16px radius, 18px\r\n // padding), written inline so it wins over host stylesheets; the opacity\r\n // slider drives surface alpha and fades the border with it.\r\n const borderAlpha = opacity > 0 ? Math.min(1, opacity * 1.5) : (blurPx > 0 ? 0.35 : 0)\r\n target.style.background = surface !== undefined ? withAlpha(surface, opacity) : 'transparent'\r\n target.style.border = surface !== undefined ? `1px solid ${withAlpha(surface, borderAlpha)}` : '1px solid transparent'\r\n target.style.borderRadius = '16px'\r\n target.style.padding = '18px'\r\n }\r\n // Plain views write no inline styles — only the blur underlay is hosted here.\r\n target.setAttribute(spec.mark, '1')\r\n setBlur(target, blurPx)\r\n })\r\n syncTableFix()\r\n}\r\n\r\nlet partsObserver: MutationObserver | null = null\r\n\r\n/** Watch for the AppFrame mounting so persisted blurs land even when the shell\r\n * renders after this plugin's apply. */\r\nexport function watchParts(): void {\r\n if (partsObserver !== null || typeof MutationObserver === 'undefined') return\r\n partsObserver = new MutationObserver(() => {\r\n if (frameEl !== null && sidebarEl !== null && centerEl !== null && detailsEl !== null && document.body.contains(frameEl)\r\n // Keep re-applying while any card host is absent or was swapped by the host.\r\n && viewTargets.every(el => el !== null && document.body.contains(el))) return\r\n applyPartBlurs(rBlurs())\r\n applyPartOpacities(rOps())\r\n })\r\n partsObserver.observe(document.body, { childList: true, subtree: true })\r\n}\r\n\r\nexport function stopWatchingParts(): void {\r\n partsObserver?.disconnect()\r\n partsObserver = null\r\n}\r\n\r\n// ── Theme-reset watchdog ──────────────────────────────────────────────────\r\n// The host re-asserts its own :root/body scheme rules on mount, on settings\r\n// adoption and after the plugin's startup assertion, toggling the\r\n// `data-ds-dark-theme` attribute off / to a host value — which would paint a\r\n// frame of light surfaces. Watch that flag and, whenever the plugin's own\r\n// value disappears, re-set it and re-emit the token stylesheet within the same\r\n// frame.\r\nlet themeObserver: MutationObserver | null = null\r\nlet themeRaf = 0\r\n\r\nfunction reassertScheme(): void {\r\n const [, , l] = rColor()\r\n if (l < 0.55) document.body.setAttribute(DARK_ATTR, OWN_SCHEME)\r\n else document.body.removeAttribute(DARK_ATTR)\r\n applyCustomTokens(rOps())\r\n}\r\n\r\n/** Re-assert the plugin's forced scheme whenever the host strips it, so a\r\n * refresh / cold-load / set-change never flashes a light frame. Also the point\r\n * where a host-side scheme flip is noticed while a color-less rule runs: that\r\n * rule paints from the host palette, so the readback is dropped and the\r\n * surfaces are re-emitted from the new one. */\r\nexport function watchThemeResets(): () => void {\r\n if (themeObserver !== null || typeof MutationObserver === 'undefined') return () => undefined\r\n themeObserver = new MutationObserver(() => {\r\n invalidateHostPalette()\r\n if (document.body.getAttribute(DARK_ATTR) === OWN_SCHEME) return\r\n if (!rHasColor()) {\r\n // Nothing to re-assert, but the host's own surfaces just changed under us.\r\n applyCustomTokens(rOps())\r\n return\r\n }\r\n if (themeRaf !== 0) return\r\n themeRaf = requestAnimationFrame(() => {\r\n themeRaf = 0\r\n if (document.body.getAttribute(DARK_ATTR) === OWN_SCHEME) return\r\n reassertScheme()\r\n })\r\n })\r\n themeObserver.observe(document.body, { attributes: true, attributeFilter: [DARK_ATTR] })\r\n themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: [DARK_ATTR] })\r\n return () => {\r\n themeObserver?.disconnect()\r\n themeObserver = null\r\n }\r\n}\r\n\r\n// ── Wallpaper layer: two stacked layers, cross-faded on a rule switch ───────\r\n// The incoming image fades in ON TOP of the outgoing one at full opacity.\r\n// Fading the old one out at the same time would drop the composite below full\r\n// alpha at the midpoint — both images half transparent — and the interface\r\n// behind would flash through.\r\n//\r\n// A layer addresses its image by OBJECT URL (see displayImageOf in state):\r\n// assigning a `url(data:…)` background re-decodes the photo on every switch,\r\n// which is where a large wallpaper's stall comes from, while a blob URL is\r\n// served from the browser's memory cache after the first load.\r\n//\r\n// The duration is the ACTIVE rule's own (`rotate.fadeMs`, default 320 ms — see\r\n// DEFAULT_ROTATION in ./schema), so a rule that cycles through images can ask for\r\n// a slower blend than a model switch, and 0 means a hard cut.\r\ninterface WpLayer {\r\n el: HTMLDivElement\r\n /** Display URL of the image painted on this layer; null when empty. */\r\n url: string | null\r\n}\r\n\r\nlet layers: [WpLayer, WpLayer] | null = null\r\n/** Index of the layer the user is looking at. */\r\nlet front = 0\r\n/** Index of the layer fading in right now, if any. */\r\nlet pending: 0 | 1 | null = null\r\nlet fadeTimer: number | null = null\r\n\r\nfunction createLayer(): WpLayer {\r\n const el = document.createElement('div')\r\n el.dataset.dabWpLayer = ''\r\n el.style.cssText = 'position:absolute;inset:0;opacity:0;background-repeat:no-repeat;background-position:center;'\r\n return { el, url: null }\r\n}\r\n\r\nfunction ensureWpContainer(): void {\r\n if (wpEl !== null && layers !== null && document.body.contains(wpEl)) return\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n const a = createLayer()\r\n const b = createLayer()\r\n wpEl = document.createElement('div')\r\n wpEl.dataset.dabWp = ''\r\n wpEl.style.cssText = 'position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden;'\r\n wpEl.append(a.el, b.el)\r\n layers = [a, b]\r\n front = 0\r\n pending = null\r\n document.body.prepend(wpEl)\r\n}\r\n\r\n/** Drop the whole wallpaper layer (no rule carries an image). */\r\nfunction dropWpContainer(): void {\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n front = 0\r\n layers = null\r\n wpEl?.remove()\r\n wpEl = null\r\n}\r\n\r\n/** Release one layer's image — the layer is fully covered when this is called. */\r\nfunction clearLayer(l: WpLayer): void {\r\n if (l.url === null) return\r\n l.url = null\r\n l.el.style.backgroundImage = ''\r\n l.el.style.backgroundSize = ''\r\n l.el.style.backgroundPosition = ''\r\n}\r\n\r\n/** Intrinsic-size cache for the center mode (native pixels of the current image). */\r\nlet imgNat: { url: string; w: number; h: number } | null = null\r\nfunction imageNatSize(url: string, cb: (w: number, h: number) => void): void {\r\n if (imgNat !== null && imgNat.url === url) { cb(imgNat.w, imgNat.h); return }\r\n const img = new Image()\r\n img.onload = () => {\r\n imgNat = { url, w: img.naturalWidth, h: img.naturalHeight }\r\n cb(img.naturalWidth, img.naturalHeight)\r\n }\r\n img.onerror = () => cb(0, 0)\r\n img.src = url\r\n}\r\n\r\n/** Paint one layer's image and its placement. The placement always follows the\r\n * ACTIVE rule: the incoming layer is painted right after a switch, and a\r\n * repaint of the same URL (framing edit, viewport resize) must use the rule's\r\n * current framing. */\r\nfunction paintLayer(l: WpLayer, url: string): void {\r\n const el = l.el\r\n l.url = url\r\n const bg = rBgState()\r\n const mode = rBgMode()\r\n const next = `url(\"${url}\")`\r\n // Skip re-setting the same URL — a redundant assignment can flash the layer\r\n // blank for a frame while it is re-resolved.\r\n if (el.style.backgroundImage !== next) {\r\n el.style.backgroundImage = next\r\n }\r\n if (mode === 'fit') {\r\n el.style.backgroundRepeat = 'no-repeat'\r\n if (bg.iw > 0) {\r\n // Contain-fit at zoom with the image center pinned to the committed\r\n // fractional viewport point, so the framed region survives viewport changes.\r\n const fit = Math.min(window.innerWidth / bg.iw, window.innerHeight / bg.ih)\r\n const w = bg.iw * fit * bg.zoom\r\n const h = bg.ih * fit * bg.zoom\r\n el.style.backgroundSize = `${w}px ${h}px`\r\n el.style.backgroundPosition = `${bg.x * window.innerWidth - w / 2}px ${bg.y * window.innerHeight - h / 2}px`\r\n } else {\r\n // Fresh image: match the editor's initial centered contain view.\r\n el.style.backgroundSize = 'contain'\r\n el.style.backgroundPosition = 'center'\r\n }\r\n } else if (mode === 'fill') {\r\n el.style.backgroundRepeat = 'no-repeat'\r\n el.style.backgroundSize = 'cover'\r\n el.style.backgroundPosition = 'center'\r\n } else if (mode === 'stretch') {\r\n el.style.backgroundRepeat = 'no-repeat'\r\n el.style.backgroundSize = '100% 100%'\r\n el.style.backgroundPosition = 'center'\r\n } else if (mode === 'tile') {\r\n el.style.backgroundRepeat = 'repeat'\r\n // background-size:auto resolves the intrinsic size per tile.\r\n el.style.backgroundSize = 'auto'\r\n el.style.backgroundPosition = '0px 0px'\r\n } else {\r\n // Center: native size, centered. The intrinsic size needs an async decode;\r\n // 'contain' keeps a sensible frame until it lands.\r\n el.style.backgroundRepeat = 'no-repeat'\r\n el.style.backgroundSize = 'contain'\r\n el.style.backgroundPosition = 'center'\r\n imageNatSize(url, (w, h) => {\r\n if (l.url !== url || el.style.backgroundImage !== next || rBgMode() !== 'center') return\r\n if (w > 0 && h > 0) {\r\n el.style.backgroundSize = `${w}px ${h}px`\r\n el.style.backgroundPosition = 'center'\r\n }\r\n })\r\n }\r\n}\r\n\r\n/** Whether a switch should animate: nothing to fade from, an invisible\r\n * wallpaper and a reduced-motion preference all switch instantly. */\r\nfunction canFade(from: WpLayer): boolean {\r\n if (from.url === null) return false\r\n if (rWop() <= 0.01) return false\r\n const mm = typeof window.matchMedia === 'function' ? window.matchMedia('(prefers-reduced-motion: reduce)') : null\r\n return mm === null || !mm.matches\r\n}\r\n\r\n/** End an in-flight fade: promote the incoming layer, free the one under it. */\r\nfunction finishFade(idx: 0 | 1): void {\r\n if (layers === null || pending !== idx) return\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n front = idx\r\n const el = layers[idx].el\r\n // Re-asserted so a fade whose frames never ran (background tab) still ends on\r\n // the visible image.\r\n el.style.opacity = '1'\r\n el.style.willChange = ''\r\n // Covered from here on: drop its bytes so a second full-resolution image is\r\n // never left decoded behind the visible one.\r\n clearLayer(layers[idx === 0 ? 1 : 0])\r\n}\r\n\r\n/** Land an in-flight fade on its end state at once (another switch arrived). */\r\nfunction settleFade(): void {\r\n if (layers === null || pending === null) return\r\n const idx = pending\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n front = idx\r\n const el = layers[idx].el\r\n el.style.transition = 'none'\r\n el.style.opacity = '1'\r\n el.style.willChange = ''\r\n clearLayer(layers[idx === 0 ? 1 : 0])\r\n}\r\n\r\n/** Abandon an in-flight fade: the layer it was leaving holds the wanted image. */\r\nfunction cancelFade(): void {\r\n if (layers === null || pending === null) return\r\n const idx = pending\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n const el = layers[idx].el\r\n el.style.transition = 'none'\r\n el.style.opacity = '0'\r\n el.style.willChange = ''\r\n clearLayer(layers[idx])\r\n}\r\n\r\n/** Show `url` on the wallpaper layer, cross-fading from what it paints now. */\r\nfunction applyImageWp(url: string): void {\r\n ensureWpContainer()\r\n const ls = layers!\r\n if (pending !== null) {\r\n // A → B → A inside one fade: keep whichever layer already paints the wanted\r\n // image instead of queueing a third one.\r\n if (ls[pending].url === url) { paintLayer(ls[pending], url); applyWpEffects(); return }\r\n if (ls[front].url === url) { cancelFade(); paintLayer(ls[front], url); applyWpEffects(); return }\r\n settleFade()\r\n }\r\n if (ls[front].url === url) { paintLayer(ls[front], url); applyWpEffects(); return }\r\n const from = ls[front]\r\n const idx: 0 | 1 = front === 0 ? 1 : 0\r\n const target = ls[idx]\r\n const el = target.el\r\n // Rewind the incoming layer before its bytes land, so a stale image from an\r\n // earlier switch can never flash through while the new one rasterizes.\r\n el.style.transition = 'none'\r\n el.style.opacity = '0'\r\n el.style.zIndex = '1'\r\n from.el.style.zIndex = '0'\r\n paintLayer(target, url)\r\n applyWpEffects()\r\n const fadeMs = rFadeMs()\r\n if (!canFade(from) || fadeMs <= 0) {\r\n el.style.opacity = '1'\r\n front = idx\r\n clearLayer(from)\r\n return\r\n }\r\n // will-change promotes the layer in this frame, so the fade itself is a pure\r\n // compositor animation that survives the main-thread work a switch triggers\r\n // (theme re-registration, token rewrite, settings-panel re-render).\r\n el.style.willChange = 'opacity'\r\n pending = idx\r\n requestAnimationFrame(() => {\r\n if (pending !== idx || layers === null) return\r\n el.style.transition = `opacity ${fadeMs}ms ease`\r\n el.style.opacity = '1'\r\n })\r\n fadeTimer = window.setTimeout(() => finishFade(idx), fadeMs + 160)\r\n}\r\n\r\nfunction applyWpEffects(): void {\r\n if (wpEl === null || layers === null) return\r\n wpEl.style.opacity = String(rWop())\r\n // The blur sits on each LAYER rather than on the container: with the filter on\r\n // the parent, every frame of an opacity fade would re-run a full-screen blur\r\n // instead of just re-compositing the blurred surface.\r\n const blur = rBl()\r\n const filter = blur > 0 ? `blur(${blur}px)` : ''\r\n layers[0].el.style.filter = filter\r\n layers[1].el.style.filter = filter\r\n}\r\n\r\n/** Repaint the wallpaper layer, the token palette and every interface part from\r\n * the ACTIVE rule. This is the single entry point a rule switch goes through. */\r\nexport function applyWp(): void {\r\n const url = rWp()\r\n if (url) {\r\n applyImageWp(url)\r\n } else if (wpEl !== null) {\r\n // No background: tear down the layer but keep tokens/blur intact.\r\n dropWpContainer()\r\n }\r\n // A rule without a saved color follows the system theme: the plugin owns no\r\n // color of its own, so the surfaces come from the host's palette (see\r\n // `palette`) with the user's opacities applied — the wallpaper keeps showing\r\n // and the Interface sliders keep doing something, which is what \"follow the\r\n // system theme\" is expected to mean. THREE things have to be true before the\r\n // readback, or it answers with the wrong palette:\r\n // 1. our own body rule is out of the way (it re-emits the tokens being read);\r\n // 2. the scheme flag is the host's own again (we force/remove it while we own\r\n // a palette, and the host only re-projects on a theme change);\r\n // 3. the cached palette is dropped once, on the way in.\r\n if (!rHasColor() && !baseTokenKey.startsWith('host:')) {\r\n clearCustomTokens()\r\n invalidateHostPalette()\r\n }\r\n if (!rHasColor()) adoptHostScheme()\r\n const src = palette()\r\n // Marker for the no-fallback re-scope rules: they may only be live while the\r\n // variables they read are written (see THEMED_ATTR).\r\n document.documentElement.toggleAttribute(THEMED_ATTR, src !== null)\r\n if (src === null) {\r\n // No palette at all (a host publishing none of the surfaces we re-emit):\r\n // give every surface back to the host untouched instead of leaving ours.\r\n clearCustomTokens()\r\n clearOwnedSurfaces()\r\n }\r\n applyCustomTokens(rOps())\r\n applySettingsOverrides(rSop())\r\n applyTrajectoryOverrides(rTrajectoryOpacity())\r\n applyRightbarOverrides(rRightbarOpacity())\r\n applyPartBlurs(rBlurs())\r\n}\r\n\r\nexport function teardownWp(): void {\r\n dropWpContainer()\r\n clearCustomTokens()\r\n tokenStyleEl?.remove(); tokenStyleEl = null\r\n removeViewCards()\r\n document.documentElement.removeAttribute(THEMED_ATTR)\r\n document.body.style.removeProperty('color-scheme')\r\n // Every plugin-owned surface, including the AppFrame columns' inline\r\n // backgrounds and the palette readback that described them; the scheme flag is\r\n // handed back in the host's own form.\r\n clearOwnedSurfaces()\r\n adoptHostScheme()\r\n invalidateHostPalette()\r\n document.documentElement.style.removeProperty('--dsh-any-blur-settings')\r\n document.documentElement.style.removeProperty('--dsh-any-blur-card-panels')\r\n document.documentElement.style.removeProperty('--dsh-any-input-blur')\r\n document.documentElement.style.removeProperty('--dsh-any-bg-rightbar')\r\n document.documentElement.style.removeProperty('--dsh-any-blur-rightbar')\r\n for (const v of Object.values(OPACITY_VARS)) document.documentElement.style.removeProperty(v)\r\n if (tokensRaf !== null) { cancelAnimationFrame(tokensRaf); tokensRaf = null }\r\n pendingOps = null\r\n tableFixStyleEl?.remove(); tableFixStyleEl = null\r\n setBlur(frameEl, 0); setBlur(sidebarEl, 0); setBlur(centerEl, 0); setBlur(detailsEl, 0)\r\n stopWatchingParts()\r\n}\r\n\r\n/** Live wallpaper-opacity updates during slider drag (no full re-apply). */\r\nexport function setWpOpacity(v: number): void {\r\n if (wpEl) wpEl.style.opacity = String(v)\r\n}\r\n\r\n/** Live wallpaper-blur updates during slider drag (no full re-apply). */\r\nexport function setWpBlur(v: number): void {\r\n if (layers === null) return\r\n const filter = v > 0 ? `blur(${v}px)` : ''\r\n layers[0].el.style.filter = filter\r\n layers[1].el.style.filter = filter\r\n}\r\n","/**\n * Model → rule resolution.\n *\n * Two halves:\n * 1. `matchRule` — a pure function over the ordered rule list.\n * 2. `watchModel` — reports the current model whenever the session's durable\n * model selection changes.\n *\n * Sources, in the order they are consulted:\n *\n * a. **Which session is current** (`resolveMainSessionId` below) — the model is\n * read per session, so this hop answers before any other can. 0.1.7 moved it:\n * `sessions.list` stopped carrying a single `current` id, and the main view's\n * session is published by the `uiSession` service and marked by the list row\n * retained by `mainView`.\n * b. **The session's own durable model selection** —\n * `ctx.sessions.binding(id).session.projections.faceOf('modelSelection')`,\n * the same `{ lastUsed, next }` value the composer model seat and the\n * /model popup read. This is the authoritative per-session answer.\n * c. **`ctx.modelDirectories`** — the shared per-session directory\n * (ui-model-selection). It adds the provider-group catalog, so it is the\n * only source that can supply a display name, but it lives in that plugin's\n * own scope on some builds and is then invisible from here, hence optional.\n * d. **The host default model** — resolved by the CALLER as a last resort\n * (see index.tsx). It is a global default, NOT this session's selection, so\n * it is reported as `default` and the settings page says so.\n *\n * TIMING is load-bearing. `sessions` is published by the api-session-controller\n * client plugin, which this deployment loads AFTER this plugin's client bundle,\n * so `ctx.get('sessions')` is normally still undefined when `apply()` runs.\n * Giving up there — returning a no-op disposer — left the model pinned to the\n * host default for the whole session with nothing to retry it. The service is\n * now polled for until it appears, and `uiSession` (which can mount even later)\n * is picked up by the same poll because the session id is re-resolved on every\n * tick. Every hop reports a `note` when it cannot answer, so the settings page\n * can name the failing one instead of silently showing a value that is not this\n * session's model.\n */\nimport type {\n BgRule, Ctx, ModelDirectoryLike, ModelDirectoryResolverLike, ModelSelectionProjectionLike,\n ObservableFaceLike, SessionListSnapshotLike, SessionsServiceLike, UiSessionLike,\n} from './types'\n// Whether a rule can paint AT ALL is the shared shape's business, not this\n// module's: `ruleCanPaint` is the one answer (enabled, and carrying an image or a\n// theme color), so matching and the panel's copy cannot drift apart.\nimport { ruleCanPaint } from '../schema'\n\n/** Rules that can actually paint: see `ruleCanPaint` (./schema). */\nfunction usable(rules: readonly BgRule[]): BgRule[] {\n return rules.filter(ruleCanPaint)\n}\n\n/**\n * Resolve the rule for one model text.\n *\n * Top→bottom, first case-insensitive substring hit wins; an empty `match` never\n * hits on its own. When nothing hits, the FIRST usable rule is the fallback\n * (rule 1 deliberately doubles as both a matcher and the fallback).\n *\n * \"Usable\" is `ruleCanPaint` — an image, or a theme color of its own — so a rule\n * whose pictures were all removed still holds the models it matches (and paints\n * its color alone) instead of quietly handing them to the next rule.\n */\nexport function matchRule(\n rules: readonly BgRule[],\n modelText: string,\n): { rule: BgRule | null; matched: boolean } {\n const list = usable(rules)\n if (list.length === 0) return { rule: null, matched: false }\n const hay = modelText.toLowerCase()\n if (hay.trim() !== '') {\n for (const rule of list) {\n const needle = rule.match.trim().toLowerCase()\n if (needle === '') continue\n if (hay.includes(needle)) return { rule, matched: true }\n }\n }\n return { rule: list[0]!, matched: false }\n}\n\n/** Human-readable label of the model text an active rule matched against. */\nexport function modelLabelOf(text: string): string {\n const parts = text.split(/\\s+/).filter(p => p !== '')\n // The display name (last token, when the catalog provided one) reads best.\n return parts.length > 0 ? parts[parts.length - 1]! : ''\n}\n\n/** Look the current model's display name up in the shared catalog. */\nfunction displayNameOf(state: {\n groups?: ReadonlyArray<{ id?: string; models?: ReadonlyArray<{ id?: string; name?: string }> }>\n} | undefined, provider: string, model: string): string {\n if (model === '' || !Array.isArray(state?.groups)) return ''\n for (const group of state!.groups!) {\n if (group.id !== provider) continue\n for (const entry of group.models ?? []) {\n if (entry.id === model) return typeof entry.name === 'string' ? entry.name : ''\n }\n }\n return ''\n}\n\n/** Where the reported model text came from. */\nexport type ModelSource = 'session' | 'default'\n\n/**\n * Which hop could not answer when no per-session model was found. Surfaced in\n * the settings readout: without it, a broken hop is indistinguishable from\n * \"this session really is on the host default\".\n */\nexport type ModelNote = '' | 'no-service' | 'no-session' | 'no-projection' | 'empty-selection'\n\n/** How often to look for the sessions service that mounts after this plugin. */\nconst ATTACH_RETRY_MS = 400\n/** Stop looking after this many tries (~2 minutes). */\nconst ATTACH_RETRY_LIMIT = 300\n/** Safety re-read of every source, so a missed notification cannot pin a stale model. */\nconst POLL_MS = 1500\n\n/** One selection out of a `modelSelection` projection value. */\nfunction selectionOf(value: ModelSelectionProjectionLike | undefined): { provider: string; model: string } | null {\n const pick = value?.next ?? value?.lastUsed ?? null\n if (pick === null || typeof pick !== 'object') return null\n const provider = typeof pick.provider === 'string' ? pick.provider : ''\n const model = typeof pick.model === 'string' ? pick.model : ''\n if (provider === '' && model === '') return null\n return { provider, model }\n}\n\n/** A non-empty string id, or null. */\nfunction asId(value: unknown): string | null {\n return typeof value === 'string' && value !== '' ? value : null\n}\n\n/**\n * The id of the session the main view is showing.\n *\n * The model is read per session, so this hop has to answer before any of the\n * others can. 0.1.7 moved the answer: `sessions.list` stopped publishing a single\n * `current` id in favour of a row table (`ids` / `byId` / `phase`), and the main\n * view's session is now whatever holds a `mainView` retention — the same row the\n * host's own `uiSession.current` binding source is built from. Reading only\n * `list.current` therefore finds nothing on 0.1.7, and a plugin with no session\n * id can only ever fall back to rule 1: the background stops following the model.\n *\n * The hops are tried in order of authority and every one is optional, so this\n * answers on both host generations — and while `uiSession` is still mounting.\n */\nexport function resolveMainSessionId(\n uiCurrent: { key?: string } | undefined,\n snapshot: SessionListSnapshotLike | undefined,\n): string | null {\n // 0.1.7: the host's own answer, already resolved from list + retention.\n const fromUiSession = asId(uiCurrent?.key)\n if (fromUiSession !== null) return fromUiSession\n // ≤0.1.6: the list published the current id directly.\n const legacy = asId(snapshot?.current)\n if (legacy !== null) return legacy\n // 0.1.7 without `uiSession` yet: derive it from the retention the host uses.\n const byId = snapshot?.byId\n if (byId !== undefined && byId !== null) {\n for (const row of Object.values(byId)) {\n if ((row?.retainedBy?.mainView ?? 0) > 0) {\n const id = asId(row?.id)\n if (id !== null) return id\n }\n }\n }\n return null\n}\n\n/** Read `uiSession.current` (if that service is on this host) and resolve. */\nfunction mainSessionId(ctx: Ctx, list: ObservableFaceLike<SessionListSnapshotLike> | null): string | null {\n let uiCurrent: { key?: string } | undefined\n try {\n const ui = ctx.get('uiSession') as UiSessionLike | undefined\n uiCurrent = ui?.current?.getSnapshot?.()\n } catch {\n // Service absent (or not mounted yet) — the list retention below still answers.\n }\n return resolveMainSessionId(uiCurrent, list?.getSnapshot())\n}\n\n/**\n * Watch the current session's model selection.\n *\n * @param ctx - client root context.\n * @param onChange - called with the match text (provider + id + display name),\n * the best available label, which source answered, and — when nothing could be\n * read — the hop that failed.\n * @returns disposer.\n */\nexport function watchModel(\n ctx: Ctx,\n onChange: (text: string, label: string, source: ModelSource, note: ModelNote) => void,\n): () => void {\n let service: SessionsServiceLike | null = null\n let list: ObservableFaceLike<SessionListSnapshotLike> | null = null\n let offList: (() => void) | null = null\n let sessionId: string | null = null\n let directory: ModelDirectoryLike | null = null\n let offDirectory: (() => void) | null = null\n /** The session's own `modelSelection` projection face. */\n let projected: ObservableFaceLike<ModelSelectionProjectionLike> | null = null\n let offProjected: (() => void) | null = null\n let lastKey = '\\u0000'\n let poll: number | null = null\n let retry: number | null = null\n let retries = 0\n\n const release = (): void => {\n if (offDirectory !== null) { offDirectory(); offDirectory = null }\n if (offProjected !== null) { offProjected(); offProjected = null }\n directory = null\n projected = null\n }\n\n /** Bind the session's own durable model selection (the authoritative source). */\n const bindProjection = (id: string): void => {\n const svc = service\n if (svc === null) return\n try {\n let binding = typeof svc.binding === 'function' ? svc.binding(id) : undefined\n if (binding === undefined && typeof svc.scope === 'function') {\n // Materialize the scope, then resolve again: a session that is merely\n // listed has no binding yet.\n svc.scope(id)\n binding = typeof svc.binding === 'function' ? svc.binding(id) : undefined\n }\n const face = binding?.session?.projections?.faceOf?.('modelSelection')\n if (face === undefined || typeof face.subscribe !== 'function' || typeof face.getSnapshot !== 'function') return\n projected = face\n offProjected = face.subscribe(() => { emit(false) })\n } catch {\n projected = null\n offProjected = null\n }\n }\n\n const note = (): ModelNote => {\n if (service === null) return 'no-service'\n if (sessionId === null) return 'no-session'\n if (projected === null && directory === null) return 'no-projection'\n return 'empty-selection'\n }\n\n const emit = (force: boolean): void => {\n const state = directory?.store.getSnapshot()\n const fromDirectory = state?.current ?? null\n const sel = fromDirectory !== null\n ? { provider: fromDirectory.provider ?? '', model: fromDirectory.model ?? '' }\n : (() => {\n try { return selectionOf(projected?.getSnapshot()) } catch { return null }\n })()\n const provider = sel?.provider ?? ''\n const model = sel?.model ?? ''\n const name = displayNameOf(state, provider, model)\n const text = [provider, model, name].filter(p => p !== '').join(' ').trim()\n const noteValue: ModelNote = text === '' ? note() : ''\n const key = `${text}\\u0001${name}\\u0001${noteValue}`\n if (!force && key === lastKey) return\n lastKey = key\n onChange(text, name !== '' ? name : (model !== '' ? model : provider), 'session', noteValue)\n }\n\n const bind = (): void => {\n const id = mainSessionId(ctx, list)\n // Already bound to this session and holding at least one live source: only\n // refresh the value. A missing source keeps retrying on the poll below.\n if (id === sessionId && (directory !== null || projected !== null)) { emit(false); return }\n release()\n sessionId = id\n if (id !== null) {\n bindProjection(id)\n if (directory === null) {\n const directories = ctx.get('modelDirectories') as ModelDirectoryResolverLike | undefined\n if (directories !== undefined && typeof directories.directoryFor === 'function') {\n try {\n directory = directories.directoryFor(id)\n offDirectory = directory.store.subscribe(() => { emit(false) })\n // The advisory catalog (display names) loads lazily; a failure only\n // costs us the pretty name, never the match.\n const pending = directory.load?.()\n if (pending !== undefined && pending !== null && typeof (pending as Promise<unknown>).catch === 'function') {\n void (pending as Promise<unknown>).catch(() => undefined)\n }\n } catch {\n directory = null\n offDirectory = null\n }\n }\n }\n }\n // Forced: the sources may have appeared without the text changing (the host\n // default was showing and the session now agrees with it), and the settings\n // page must be able to correct its badge and its note.\n emit(true)\n }\n\n const stopRetry = (): void => {\n if (retry === null) return\n window.clearInterval(retry)\n retry = null\n }\n\n const tick = (): void => {\n if (list === null) return\n if (mainSessionId(ctx, list) !== sessionId || (directory === null && projected === null)) bind()\n else emit(false)\n }\n\n /**\n * Look the sessions service up. It arrives after this plugin's bundle on this\n * deployment, so the first attempt usually fails — which is exactly why this\n * is a retry loop rather than a one-shot lookup.\n */\n const attach = (): boolean => {\n const svc = ctx.get('sessions') as SessionsServiceLike | undefined\n if (svc === undefined || svc === null) return false\n const face = svc.list\n if (face === undefined || typeof face.subscribe !== 'function' || typeof face.getSnapshot !== 'function') return false\n service = svc\n list = face\n offList = face.subscribe(bind)\n if (poll === null) poll = window.setInterval(tick, POLL_MS)\n bind()\n return true\n }\n\n if (!attach()) {\n retry = window.setInterval(() => {\n retries++\n if (attach() || retries >= ATTACH_RETRY_LIMIT) stopRetry()\n }, ATTACH_RETRY_MS)\n }\n\n return () => {\n stopRetry()\n if (poll !== null) { window.clearInterval(poll); poll = null }\n if (offList !== null) { offList(); offList = null }\n service = null\n list = null\n release()\n }\n}\n","import type { ReactNode } from 'react'\r\n\r\n/** Sun glyph, migrated from @deepseek-ai/dsh-client-ui-primitives IconLightOutline16. */\r\nexport const SUN_PATHS = '<path d=\"M11.3496 8C11.3496 6.14985 9.85015 4.65039 8 4.65039C6.14985 4.65039 4.65039 6.14985 4.65039 8C4.65039 9.85015 6.14985 11.3496 8 11.3496C9.85015 11.3496 11.3496 9.85015 11.3496 8ZM12.6504 8C12.6504 10.5681 10.5681 12.6504 8 12.6504C5.43188 12.6504 3.34961 10.5681 3.34961 8C3.34961 5.43188 5.43188 3.34961 8 3.34961C10.5681 3.34961 12.6504 5.43188 12.6504 8Z\" fill=\"currentColor\"/><path d=\"M8.65039 0.5V2.5H7.34961V0.5H8.65039Z\" fill=\"currentColor\"/><path d=\"M8.65039 13.5V15.5H7.34961V13.5H8.65039Z\" fill=\"currentColor\"/><path d=\"M3.15808 2.24035L4.57229 3.65456L3.6525 4.57435L2.23829 3.16014L3.15808 2.24035Z\" fill=\"currentColor\"/><path d=\"M12.3505 11.4327L13.7647 12.8469L12.8449 13.7667L11.4307 12.3525L12.3505 11.4327Z\" fill=\"currentColor\"/><path d=\"M2.24537 12.8469L3.65958 11.4327L4.57937 12.3525L3.16516 13.7667L2.24537 12.8469Z\" fill=\"currentColor\"/><path d=\"M11.4377 3.65455L12.852 2.24033L13.7718 3.16012L12.3575 4.57434L11.4377 3.65455Z\" fill=\"currentColor\"/><path d=\"M0.5 7.35461H2.5V8.6554H0.5L0.5 7.35461Z\" fill=\"currentColor\"/><path d=\"M13.5 7.35461H15.5V8.6554H13.5V8.6554Z\" fill=\"currentColor\"/>'\r\n\r\nexport function SunIcon({ size = 16, className }: { size?: number; className?: string }) {\r\n return (\r\n <svg width={size} height={size} className={className} viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" dangerouslySetInnerHTML={{ __html: SUN_PATHS }} />\r\n )\r\n}\r\n\r\nfunction Glyph({ children, size = 16, className }: { children: ReactNode; size?: number; className?: string }) {\r\n return (\r\n <svg width={size} height={size} className={className} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\r\n {children}\r\n </svg>\r\n )\r\n}\r\n\r\nexport const DropletIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 1.9c2.4 2.8 4.3 5 4.3 7.1a4.3 4.3 0 1 1-8.6 0C3.7 6.9 5.6 4.7 8 1.9z\" /></Glyph>\r\n)\r\n\r\nexport const LayersIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 2.2 13.2 5 8 7.8 2.8 5 8 2.2z\" /><path d=\"M2.8 8.2 8 11l5.2-2.8\" /><path d=\"M2.8 11.2 8 14l5.2-2.8\" /></Glyph>\r\n)\r\n\r\nexport const PhotoIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2\" y=\"3.2\" width=\"12\" height=\"9.6\" rx=\"2\" /><circle cx=\"5.7\" cy=\"6.3\" r=\"0.9\" /><path d=\"M14 10.4l-2.8-2.8-4.8 4.8\" /></Glyph>\r\n)\r\n\r\nexport const VideoIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"1.5\" y=\"4.2\" width=\"8.8\" height=\"7.6\" rx=\"2\" /><path d=\"M10.3 6.9l4.2-2.4v7l-4.2-2.4\" /></Glyph>\r\n)\r\n\r\nexport const TextIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M3 4.2h10M3 8h10M3 11.8h6.5\" /></Glyph>\r\n)\r\n\r\nexport const TrajectoryIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M2.5 3.2h11M2.5 6.6h11M2.5 10h11\" /><circle cx=\"4.4\" cy=\"3.2\" r=\"1.1\" /><circle cx=\"8\" cy=\"6.6\" r=\"1.1\" /><circle cx=\"11.4\" cy=\"10\" r=\"1.1\" /></Glyph>\r\n)\r\n\r\nexport const SlidersIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M2.5 4.5h4.9M11.6 4.5h1.9M2.5 11.5h1.9M8.6 11.5h4.9\" /><circle cx=\"9.5\" cy=\"4.5\" r=\"1.7\" /><circle cx=\"5.5\" cy=\"11.5\" r=\"1.7\" /></Glyph>\r\n)\r\n\r\nexport const SparkleIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M7.2 1.8l1.2 3.1 3.1 1.2-3.1 1.2-1.2 3.1-1.2-3.1L2.9 6.1 6 4.9l1.2-3.1z\" /><path d=\"M12 10.5l.5 1.2 1.2.5-1.2.5-.5 1.2-.5-1.2-1.2-.5 1.2-.5.5-1.2z\" /></Glyph>\r\n)\r\n\r\nexport const RefreshIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M13.2 8A5.2 5.2 0 1 1 11.5 4.2\" /><path d=\"M13.4 1.8v2.9h-2.9\" /></Glyph>\r\n)\r\n\r\nexport const DownloadIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 2.2v8\" /><path d=\"M4.6 7l3.4 3.4L11.4 7\" /><path d=\"M2.8 13.8h10.4\" /></Glyph>\r\n)\r\n\r\nexport const UploadIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 10.4V2.6\" /><path d=\"M4.6 5.8L8 2.4l3.4 3.4\" /><path d=\"M2.8 13.8h10.4\" /></Glyph>\r\n)\r\n\r\nexport const LinkIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M6.6 9.4 9.4 6.6\" /><path d=\"M5.9 11.1l-1.4 1.4a2.6 2.6 0 0 1-3.7-3.7L3.5 6.8\" /><path d=\"M10.1 4.9l1.4-1.4a2.6 2.6 0 0 1 3.7 3.7l-2.1 2.1\" /></Glyph>\r\n)\r\n\r\nexport const LockIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"3.6\" y=\"7.2\" width=\"8.8\" height=\"6\" rx=\"1.4\" /><path d=\"M5.6 7.2V5.4a2.4 2.4 0 0 1 4.8 0v1.8\" /></Glyph>\r\n)\r\n\r\nexport const TrashIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M2.8 4.4h10.4\" /><path d=\"M6.4 4.4V2.9h3.2v1.5\" /><path d=\"M4.4 4.4l.5 8.6h6.2l.5-8.6\" /></Glyph>\r\n)\r\n\r\nexport const EditIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M9.5 4l2.5 2.5\" /><path d=\"M3 13l.8-3L10 3.8 12.2 6 6 12.2 3 13z\" /></Glyph>\r\n)\r\n\r\nexport const PipetteIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><circle cx=\"8\" cy=\"8\" r=\"4.2\" /><path d=\"M8 1.6v2.6M8 11.8v2.6M1.6 8h2.6M11.8 8h2.6\" /></Glyph>\r\n)\r\n\r\nexport const CheckIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M3.2 8.6l3 3L12.8 5\" /></Glyph>\r\n)\r\n\r\nexport const AlertIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 2.6l5.4 9.8H2.6L8 2.6z\" /><path d=\"M8 6.8v2.4M8 11.4v.01\" /></Glyph>\r\n)\r\n\r\nexport const CopyIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"5.4\" y=\"5.4\" width=\"7.6\" height=\"7.6\" rx=\"1.6\" /><path d=\"M10.6 5.4V4.2a1.6 1.6 0 0 0-1.6-1.6H4.2a1.6 1.6 0 0 0-1.6 1.6v4.8a1.6 1.6 0 0 0 1.6 1.6h1.2\" /></Glyph>\r\n)\r\n\r\nexport const CanvasIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"2.2\" width=\"11.6\" height=\"11.6\" rx=\"2\" /></Glyph>\r\n)\r\n\r\nexport const SidebarIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"2.2\" width=\"11.6\" height=\"11.6\" rx=\"2\" /><path d=\"M6.6 2.2v11.6\" /></Glyph>\r\n)\r\n\r\n/** Mirror of SidebarIcon: the file-preview panel docked to the right edge. */\r\nexport const PreviewIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"2.2\" width=\"11.6\" height=\"11.6\" rx=\"2\" /><path d=\"M9.4 2.2v11.6\" /><path d=\"M11 5.6h1.2M11 8h1.2\" /></Glyph>\r\n)\r\n\r\nexport const ChatIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M13.4 4.4v4.4a2 2 0 0 1-2 2H6.2l-3.6 3V4.4a2 2 0 0 1 2-2h6.8a2 2 0 0 1 2 2z\" /></Glyph>\r\n)\r\n\r\nexport const GearIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><circle cx=\"8\" cy=\"8\" r=\"2.1\" /><path d=\"M8 1.7v1.8M8 12.5v1.8M1.7 8h1.8M12.5 8h1.8M3.6 3.6l1.3 1.3M11.1 11.1l1.3 1.3M12.4 3.6l-1.3 1.3M4.9 11.1l-1.3 1.3\" /></Glyph>\r\n)\r\n\r\nexport const InputIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"4\" width=\"11.6\" height=\"8\" rx=\"2\" /><path d=\"M8 6.6v2M7 8h2\" /></Glyph>\r\n)\r\n\r\n","import { Component, type ReactNode } from 'react'\r\n\r\ninterface Props {\r\n t: (key: string) => string\r\n onReset?: () => void\r\n children: ReactNode\r\n}\r\n\r\ninterface State {\r\n error: Error | null\r\n}\r\n\r\n/**\r\n * Catches render errors from the theme section subtree (wheel, sliders, editor)\r\n * so a single bad state can never take down the whole settings panel. Shows a\r\n * compact fallback with a reset button; the reset re-renders the section with\r\n * the current saved config, which is enough to recover from most transient\r\n * failures (corrupt transient UI state, stale image decode, etc.).\r\n */\r\nexport class ErrorBoundary extends Component<Props, State> {\r\n override state: State = { error: null }\r\n\r\n static getDerivedStateFromError(error: Error): State {\r\n return { error }\r\n }\r\n\r\n override componentDidCatch(error: Error, info: { componentStack?: string | null }): void {\r\n console.error('dsh-background-by-model: section render crashed', error, info.componentStack)\r\n }\r\n\r\n private reset = (): void => {\r\n this.setState({ error: null })\r\n this.props.onReset?.()\r\n }\r\n\r\n override render() {\r\n if (this.state.error) {\r\n return (\r\n <div className=\"dab-crash\">\r\n <div className=\"dab-crash-title\">{this.props.t('crashTitle')}</div>\r\n <div className=\"dab-crash-desc\">{this.props.t('crashDesc')}</div>\r\n <button type=\"button\" className=\"dab-btn\" onClick={this.reset}>{this.props.t('crashReset')}</button>\r\n </div>\r\n )\r\n }\r\n return this.props.children\r\n }\r\n}\r\n","import { useEffect, useState } from 'react'\r\nimport type { ReactNode } from 'react'\r\nimport { createPortal } from 'react-dom'\r\n\r\n/**\r\n * Render children into a fixed root attached to document.documentElement.\r\n *\r\n * The host's sidebar is often implemented by translating the body or a wrapper\r\n * (margin-left / transform). A fixed element portaled to body would still be\r\n * captured by that transformed ancestor and shift with the sidebar. Attaching\r\n * the portal root directly to <html> escapes body-level transforms so the\r\n * overlay is always painted relative to the viewport and centered correctly.\r\n */\r\nexport function Portal({ children }: { children: ReactNode }) {\r\n const [target, setTarget] = useState<HTMLElement | null>(null)\r\n useEffect(() => {\r\n const el = document.createElement('div')\r\n el.dataset.dabPortal = '1'\r\n el.style.cssText = 'position:fixed;inset:0;pointer-events:none;z-index:999999'\r\n document.documentElement.appendChild(el)\r\n setTarget(el)\r\n return () => { el.remove() }\r\n }, [])\r\n return target ? createPortal(children, target) : null\r\n}\r\n","import { useEffect, useRef } from 'react'\r\nimport type { CSSProperties } from 'react'\r\n\r\n/**\r\n * Zero-lag slider: the thumb and value label update through DOM refs while\r\n * dragging (onInput) so the caller can mutate the live UI directly without a\r\n * React re-render; onChange commits the settled value. Double-click resets to\r\n * the canonical default. The track fill is a gradient driven by the --pct\r\n * custom property, updated imperatively alongside the thumb.\r\n */\r\nexport function LiveSlider({ min, max, step, def, fmt, label, onInput, onChange }: {\r\n min: number; max: number; step: number; def: number\r\n fmt: (v: number) => string; label?: string; onInput?: (v: number) => void; onChange: (v: number) => void\r\n}) {\r\n const inputRef = useRef<HTMLInputElement>(null)\r\n const valRef = useRef<HTMLSpanElement>(null)\r\n\r\n const paint = (el: HTMLInputElement, v: number): void => {\r\n el.style.setProperty('--pct', String(((v - min) / (max - min)) * 100))\r\n }\r\n\r\n // Controlled sync: keep the knob and label aligned with the canonical prop\r\n // so external updates (presets, regeneration, imports) never leave it stale.\r\n useEffect(() => {\r\n if (inputRef.current) {\r\n inputRef.current.value = String(def)\r\n paint(inputRef.current, def)\r\n }\r\n if (valRef.current) valRef.current.textContent = fmt(def)\r\n }, [def, fmt, min, max])\r\n\r\n const apply = (v: number): void => {\r\n if (inputRef.current) {\r\n inputRef.current.value = String(v)\r\n paint(inputRef.current, v)\r\n }\r\n if (valRef.current) valRef.current.textContent = fmt(v)\r\n onInput?.(v)\r\n onChange(v)\r\n }\r\n\r\n return (\r\n <div className=\"dab-slider-block\">\r\n {label ? <span className=\"dab-slider-label\">{label}</span> : null}\r\n <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>\r\n <input\r\n ref={inputRef} type=\"range\" className=\"dab-slider\"\r\n style={{ '--pct': ((def - min) / (max - min)) * 100 } as CSSProperties}\r\n min={min} max={max} step={step} defaultValue={def}\r\n title={label ? `${label} · ${fmt(def)}` : fmt(def)}\r\n onDoubleClick={() => apply(def)}\r\n onInput={e => {\r\n const el = e.target as HTMLInputElement\r\n const v = Number(el.value)\r\n paint(el, v)\r\n onInput?.(v)\r\n if (valRef.current) valRef.current.textContent = fmt(v)\r\n }}\r\n onChange={e => onChange(Number((e.target as HTMLInputElement).value))} />\r\n <span ref={valRef} className=\"dab-slider-val\">{fmt(def)}</span>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import type { CSSProperties, ComponentType } from 'react'\r\nimport type { ThemeSectionProps, PartOpacities, PartBlurs } from '../../types'\r\nimport { cfg, rOps, rSop, rBlurs, rChatTextOpacity, rTrajectoryOpacity, rRightbarOpacity } from '../../state'\r\nimport { saveConfig } from '../../rpc'\r\nimport { applyCustomTokens, applySettingsOverrides, setPartBlur, applyViewCards, applyTrajectoryOverrides, applyRightbarOverrides } from '../../wallpaper'\r\nimport { LiveSlider } from '../LiveSlider'\r\nimport { CanvasIcon, SidebarIcon, ChatIcon, GearIcon, TextIcon, TrajectoryIcon, PreviewIcon, InputIcon } from '../icons'\r\n\r\ninterface PartDef {\r\n labelKey: string\r\n Icon: ComponentType<{ size?: number }>\r\n /** Homepage part key; absent for the settings-panel part. */\r\n opKey?: keyof PartOpacities\r\n isSettings?: boolean\r\n /** Conversation text region: tint opacity + blur over the message column. */\r\n isChat?: boolean\r\n /** Trajectory view: tint opacity + blur over the whole view surface. */\r\n isTrajectory?: boolean\r\n /** File-preview panel: the right sidebar a file click opens. */\r\n isRightbar?: boolean\r\n}\r\n\r\nconst PARTS: PartDef[] = [\r\n { opKey: 'bg', labelKey: 'uiOpacityBg', Icon: CanvasIcon },\r\n { opKey: 'sidebar', labelKey: 'uiOpacitySide', Icon: SidebarIcon },\r\n { isRightbar: true, labelKey: 'uiPreview', Icon: PreviewIcon },\r\n { opKey: 'card', labelKey: 'uiOpacityCard', Icon: ChatIcon },\r\n { opKey: 'input', labelKey: 'uiOpacityInput', Icon: InputIcon },\r\n { isSettings: true, labelKey: 'uiSop', Icon: GearIcon },\r\n { isChat: true, labelKey: 'uiChatRegion', Icon: TextIcon },\r\n { isTrajectory: true, labelKey: 'uiTrajectory', Icon: TrajectoryIcon },\r\n]\r\n\r\nexport function InterfacePage({ p }: { p: ThemeSectionProps }) {\r\n const { t, setOps, setBlurs, setSop, setRightbarOpacity } = p\r\n\r\n return (\r\n <>\r\n <header className=\"dab-head dab-rise\" style={{ '--d': 0 } as CSSProperties}>\r\n <div className=\"dab-overline\">Surfaces</div>\r\n <h2 className=\"dab-h1\">{t('uiTitle')}</h2>\r\n <p className=\"dab-desc\">{t('descInterface')}</p>\r\n </header>\r\n\r\n <div className=\"dab-grid-parts\">\r\n {PARTS.map((part, i) => {\r\n const { labelKey, Icon, isSettings, isChat, isTrajectory, isRightbar } = part\r\n const opKey = part.opKey\r\n // Homepage parts (bg/sidebar/card/input) bind to their own part only;\r\n // the settings panel (isSettings) binds exclusively to the 'settings'\r\n // part (--dsh-any-blur-settings / --dsh-any-bg-settings-surface) and\r\n // must never fall back to a homepage part key — otherwise the dialog\r\n // panel would track the homepage center/card blur and the home-page\r\n // opacities. The chat region (isChat) and the trajectory view\r\n // (isTrajectory) own their own blur keys plus their own tint\r\n // opacities, and the file-preview panel (isRightbar) owns the right\r\n // column's backdrop through the same deal. Every homepage opKey is\r\n // also a PartBlurs key (input included), so the shared blur slider\r\n // dereferences it directly.\r\n const blurKey: keyof PartBlurs = isChat\r\n ? 'chat'\r\n : isTrajectory\r\n ? 'trajectory'\r\n : isRightbar\r\n ? 'rightbar'\r\n : isSettings ? 'settings' : opKey!\r\n const opacity = isChat\r\n ? rChatTextOpacity()\r\n : isTrajectory\r\n ? rTrajectoryOpacity()\r\n : isRightbar ? rRightbarOpacity() : isSettings ? rSop() : rOps()[opKey!]\r\n return (\r\n <section key={blurKey} className=\"dab-card dab-card-hover dab-rise\" style={{ '--d': i + 1 } as CSSProperties}>\r\n <div className=\"dab-part-head\">\r\n <div className=\"dab-part-ico\"><Icon size={16} /></div>\r\n <div className=\"dab-part-name\">{t(labelKey)}</div>\r\n <span className=\"dab-part-badge\">{Math.round(opacity * 100)}%</span>\r\n </div>\r\n\r\n <LiveSlider label={t('uiOpacity')} min={0} max={100} step={1} def={Math.round(opacity * 100)}\r\n fmt={v => `${v}%`}\r\n onInput={v => {\r\n const op = v / 100\r\n if (isChat) {\r\n cfg.chatTextOpacity = op\r\n applyViewCards()\r\n } else if (isTrajectory) {\r\n cfg.trajectoryOpacity = op\r\n applyTrajectoryOverrides(op)\r\n } else if (isRightbar) {\r\n // First drag is what detaches the panel from the main\r\n // background; from then on the card owns it.\r\n cfg.rightbarOpacity = op\r\n applyRightbarOverrides(op)\r\n } else if (isSettings) {\r\n cfg.settingsOpacity = op\r\n applySettingsOverrides(op)\r\n } else {\r\n const ops = { ...rOps() }\r\n ops[opKey!] = op\r\n cfg.opacities = ops\r\n applyCustomTokens(ops)\r\n }\r\n saveConfig()\r\n }}\r\n onChange={v => {\r\n const op = v / 100\r\n if (isChat) {\r\n cfg.chatTextOpacity = op\r\n applyViewCards()\r\n saveConfig()\r\n } else if (isTrajectory) {\r\n cfg.trajectoryOpacity = op\r\n applyTrajectoryOverrides(op)\r\n saveConfig()\r\n } else if (isRightbar) {\r\n setRightbarOpacity(op)\r\n } else if (isSettings) {\r\n setSop(op)\r\n } else {\r\n const ops = { ...rOps() }\r\n ops[opKey!] = op\r\n setOps(ops)\r\n }\r\n }} />\r\n\r\n <LiveSlider label={t('uiBlur')} min={0} max={60} step={1} def={rBlurs()[blurKey]}\r\n fmt={v => `${v}px`}\r\n onInput={v => {\r\n const blurs = { ...rBlurs() }\r\n blurs[blurKey] = v\r\n cfg.blurs = blurs\r\n setPartBlur(blurKey, v)\r\n saveConfig()\r\n }}\r\n onChange={v => {\r\n const blurs = { ...rBlurs() }\r\n blurs[blurKey] = v\r\n setBlurs(blurs)\r\n }} />\r\n </section>\r\n )\r\n })}\r\n </div>\r\n </>\r\n )\r\n}\r\n","/**\r\n * Read a chosen image file as a data URL WITHOUT re-encoding: the original\r\n * pixels are kept as-is (no canvas downscale / JPEG re-compression), so the\r\n * wallpaper is stored and displayed at full fidelity. The tradeoff is a larger\r\n * payload over the RPC channel and on disk for big images.\r\n */\r\nexport function readImg(file: File, cb: (url: string | null) => void): void {\r\n const r = new FileReader()\r\n r.onerror = () => cb(null)\r\n r.onload = () => cb(r.result as string)\r\n r.readAsDataURL(file)\r\n}\r\n","import { useRef, useState, useEffect, useCallback, memo } from 'react'\r\n\r\nconst WHEEL_SIZE = 220\r\nconst CX = WHEEL_SIZE / 2\r\nconst RING_OUTER = 106\r\nconst RING_INNER = 82\r\n// Square inscribed in the ring's inner circle: half-side = RING_INNER / √2,\r\n// so the four corners sit exactly on the inner edge of the hue ring. The\r\n// exact (un-rounded) value keeps the corners tangent to the ring — a rounded\r\n// half-side would push the diagonals past the ring's inner boundary.\r\nconst SQ_HALF = RING_INNER / Math.SQRT2\r\n\r\n/** Static hue ring cached once across all wheels. */\r\nlet ringCache: HTMLCanvasElement | null = null\r\nfunction getRingCache(): HTMLCanvasElement {\r\n if (ringCache) return ringCache\r\n const cvs = document.createElement('canvas')\r\n cvs.width = WHEEL_SIZE; cvs.height = WHEEL_SIZE\r\n const c = cvs.getContext('2d')!\r\n // Instead of 360 separate arc paths, use a single conic gradient clipped to\r\n // the ring. This removes per-frame path overhead and anti-aliasing gaps.\r\n const g = c.createConicGradient(0, CX, CX)\r\n for (let i = 0; i <= 360; i++) g.addColorStop(i / 360, `hsl(${i},100%,50%)`)\r\n c.beginPath()\r\n c.arc(CX, CX, RING_OUTER, 0, Math.PI * 2)\r\n c.arc(CX, CX, RING_INNER, 0, Math.PI * 2, true)\r\n c.fillStyle = g\r\n c.fill()\r\n ringCache = cvs\r\n return ringCache\r\n}\r\n\r\nfunction drawMarkers(ctx: CanvasRenderingContext2D, hue: number, sat: number, lit: number): void {\r\n // Hue marker on ring. Canvas math angles (0 = +x / \"3 o'clock\", positive =\r\n // toward +y) directly match the conic-gradient hue distribution drawn in\r\n // getRingCache (colorStop i/360 → hsl(i)), so NO extra ±90° shift is applied.\r\n // A shift would rotate the picker's indication 90° away from the rendered\r\n // gradient (e.g. picking the top of the wheel would report red while the\r\n // pixels there are blue). hue 0 sits at the right edge, +90° at the bottom.\r\n const hRad = hue * Math.PI / 180\r\n const hR = (RING_OUTER + RING_INNER) / 2\r\n const hmx = CX + Math.cos(hRad) * hR\r\n const hmy = CX + Math.sin(hRad) * hR\r\n ctx.beginPath(); ctx.arc(hmx, hmy, 8, 0, Math.PI * 2)\r\n ctx.fillStyle = 'rgba(0,0,0,0.25)'; ctx.fill()\r\n ctx.beginPath(); ctx.arc(hmx, hmy, 6.5, 0, Math.PI * 2)\r\n ctx.strokeStyle = '#fff'; ctx.lineWidth = 2; ctx.stroke()\r\n\r\n // SL marker (HSV coordinates)\r\n const gx = CX - SQ_HALF, gy = CX - SQ_HALF, sz = SQ_HALF * 2\r\n const smx = gx + sat * sz\r\n const smy = gy + (1 - lit) * sz\r\n ctx.beginPath(); ctx.arc(smx, smy, 7, 0, Math.PI * 2)\r\n ctx.fillStyle = 'rgba(0,0,0,0.25)'; ctx.fill()\r\n ctx.beginPath(); ctx.arc(smx, smy, 5.5, 0, Math.PI * 2)\r\n ctx.strokeStyle = '#fff'; ctx.lineWidth = 2; ctx.stroke()\r\n ctx.beginPath(); ctx.arc(smx, smy, 3.5, 0, Math.PI * 2)\r\n ctx.strokeStyle = '#000'; ctx.lineWidth = 1; ctx.stroke()\r\n}\r\n\r\nfunction drawSquare(c: CanvasRenderingContext2D, hue: number): void {\r\n const gx = CX - SQ_HALF, gy = CX - SQ_HALF, sz = SQ_HALF * 2\r\n c.clearRect(gx - 1, gy - 1, sz + 2, sz + 2)\r\n c.fillStyle = '#fff'; c.fillRect(gx, gy, sz, sz)\r\n const gh = c.createLinearGradient(gx, 0, gx + sz, 0)\r\n gh.addColorStop(0, 'rgba(255,255,255,1)'); gh.addColorStop(1, `hsl(${hue},100%,50%)`)\r\n c.fillStyle = gh; c.fillRect(gx, gy, sz, sz)\r\n const gv = c.createLinearGradient(0, gy, 0, gy + sz)\r\n gv.addColorStop(0, 'rgba(0,0,0,0)'); gv.addColorStop(1, 'rgba(0,0,0,1)')\r\n c.fillStyle = gv; c.fillRect(gx, gy, sz, sz)\r\n}\r\n\r\nfunction hitTest(x: number, y: number): 'ring' | 'square' | null {\r\n if (Math.abs(x - CX) <= SQ_HALF && Math.abs(y - CX) <= SQ_HALF) return 'square'\r\n const dx = x - CX, dy = y - CX\r\n const dist = Math.sqrt(dx * dx + dy * dy)\r\n if (dist >= RING_INNER - 4 && dist <= RING_OUTER + 4) return 'ring'\r\n return null\r\n}\r\n\r\nfunction pickHue(x: number, y: number): number {\r\n // Inverse of drawMarkers: no ±90° shift, matching the conic gradient exactly.\r\n let angle = Math.atan2(y - CX, x - CX) * 180 / Math.PI\r\n if (angle < 0) angle += 360\r\n return angle\r\n}\r\n\r\nfunction pickSL(x: number, y: number): [number, number] {\r\n const gx = CX - SQ_HALF, gy = CX - SQ_HALF, sz = SQ_HALF * 2\r\n return [\r\n Math.max(0, Math.min(1, (x - gx) / sz)),\r\n Math.max(0.02, Math.min(0.98, 1 - (y - gy) / sz)),\r\n ]\r\n}\r\n\r\nexport const ColorWheel = memo(function ColorWheel({ hue, sat, lit, onChange }: {\r\n hue: number; sat: number; lit: number\r\n onChange: (h: number, s: number, l: number) => void\r\n}) {\r\n const cvsRef = useRef<HTMLCanvasElement>(null)\r\n const [col, setCol] = useState({ hue, sat, lit })\r\n const colRef = useRef(col)\r\n colRef.current = col\r\n\r\n // Adopt external changes (e.g. section remount after theme restore).\r\n useEffect(() => {\r\n setCol(c => (c.hue === hue && c.sat === sat && c.lit === lit ? c : { hue, sat, lit }))\r\n }, [hue, sat, lit])\r\n\r\n // Redraw only what changed. The static ring is copied from cache; the square\r\n // only redraws when hue changes; markers redraw on every value change.\r\n useEffect(() => {\r\n const cvs = cvsRef.current\r\n if (!cvs) return\r\n const ctx = cvs.getContext('2d')!\r\n ctx.clearRect(0, 0, WHEEL_SIZE, WHEEL_SIZE)\r\n // Draw the square first, then the ring on top: the ring's opaque pixels\r\n // cover the square's four corners (which are tangent to the ring's inner\r\n // edge), so the corners no longer visually overlap the hue ring.\r\n drawSquare(ctx, col.hue)\r\n ctx.drawImage(getRingCache(), 0, 0)\r\n drawMarkers(ctx, col.hue, col.sat, col.lit)\r\n }, [col])\r\n\r\n // Batch pointer updates in a single rAF so rapid mousemove events do not\r\n // trigger a React state flush + onChange on every pixel.\r\n const pendingRef = useRef<{ h: number; s: number; l: number } | null>(null)\r\n const rafRef = useRef<number | null>(null)\r\n const flushPending = useCallback(() => {\r\n rafRef.current = null\r\n const p = pendingRef.current\r\n if (!p) return\r\n pendingRef.current = null\r\n setCol({ hue: p.h, sat: p.s, lit: p.l })\r\n onChange(p.h, p.s, p.l)\r\n }, [onChange])\r\n\r\n const schedule = useCallback((h: number, s: number, l: number) => {\r\n pendingRef.current = { h, s, l }\r\n if (rafRef.current === null) rafRef.current = requestAnimationFrame(flushPending)\r\n }, [flushPending])\r\n\r\n const onDown = useCallback((e: React.MouseEvent<HTMLCanvasElement>) => {\r\n const r = cvsRef.current!.getBoundingClientRect()\r\n const x = e.clientX - r.left, y = e.clientY - r.top\r\n const region = hitTest(x, y)\r\n if (!region) return\r\n if (region === 'ring') {\r\n schedule(pickHue(x, y), colRef.current.sat, colRef.current.lit)\r\n } else {\r\n const [s, l] = pickSL(x, y)\r\n schedule(colRef.current.hue, s, l)\r\n }\r\n const onMove = (ev: MouseEvent) => {\r\n const rr = cvsRef.current!.getBoundingClientRect()\r\n const mx = ev.clientX - rr.left, my = ev.clientY - rr.top\r\n if (region === 'ring') {\r\n const d = Math.sqrt((mx - CX) ** 2 + (my - CX) ** 2)\r\n if (d >= RING_INNER - 10 && d <= RING_OUTER + 10) schedule(pickHue(mx, my), colRef.current.sat, colRef.current.lit)\r\n } else {\r\n const [s, l] = pickSL(mx, my)\r\n schedule(colRef.current.hue, s, l)\r\n }\r\n }\r\n const onUp = () => { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp) }\r\n document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp)\r\n }, [schedule])\r\n\r\n return <canvas ref={cvsRef} width={WHEEL_SIZE} height={WHEEL_SIZE} className=\"dab-wheel\" onMouseDown={onDown} />\r\n})\r\n","import { useState, useEffect, useRef } from 'react'\r\nimport type { CSSProperties } from 'react'\r\nimport { hsvToHsl, hslToRgb, rgbToHsl, hslToHsv } from '../utils/color'\r\n\r\ntype Mode = 'hsl' | 'rgb'\r\n\r\nconst SEG_W = 66\r\n\r\nfunction clamp(v: number, min: number, max: number): number {\r\n return Math.min(max, Math.max(min, v))\r\n}\r\n\r\n/** '#rrggbb' for a 0-255 RGB triple, in the caller's case. */\r\nfunction toHex(rgb: [number, number, number]): string {\r\n return '#' + rgb.map(v => Math.round(v).toString(16).padStart(2, '0')).join('')\r\n}\r\n\r\n/**\r\n * A single numeric field that edits one color channel. Keeps its own text\r\n * while focused so typing never gets clobbered by the parent re-rendering the\r\n * canonical value; commits every valid keystroke live and re-normalizes on\r\n * blur. The value prop only pushes back in when the field is not focused\r\n * (wheel drags, wallpaper extraction, mode switches).\r\n */\r\nfunction NumField({ label, value, min, max, step, onChange }: {\r\n label: string; value: number; min: number; max: number; step: number\r\n onChange: (v: number) => void\r\n}) {\r\n const [text, setText] = useState(String(value))\r\n const focused = useRef(false)\r\n\r\n useEffect(() => {\r\n if (!focused.current) setText(String(value))\r\n }, [value])\r\n\r\n return (\r\n <label className=\"dab-field\">\r\n <span className=\"dab-field-label\">{label}</span>\r\n <input\r\n type=\"number\"\r\n min={min} max={max} step={step}\r\n value={text}\r\n className=\"dab-num\"\r\n onFocus={() => { focused.current = true }}\r\n onBlur={() => { focused.current = false; setText(String(value)) }}\r\n onChange={e => {\r\n setText(e.target.value)\r\n const v = Number(e.target.value)\r\n if (Number.isFinite(v)) onChange(clamp(v, min, max))\r\n }}\r\n />\r\n </label>\r\n )\r\n}\r\n\r\n/**\r\n * Precise color entry next to the wheel: a HSL/RGB segmented toggle plus three\r\n * numeric channel fields and a live preview field that prints its own hex. The\r\n * wheel is HSV end-to-end, so this panel converts at the boundary — HSL fields\r\n * map straight onto the stored HSL, RGB fields round-trip through rgbToHsl —\r\n * and both emit HSV via the same onChange the wheel uses, keeping one canonical\r\n * color.\r\n */\r\nexport function ColorInputs({ hue, sat, lit, onChange }: {\r\n hue: number; sat: number; lit: number\r\n onChange: (h: number, s: number, l: number) => void\r\n}) {\r\n const [mode, setMode] = useState<Mode>('hsl')\r\n const [h, s, l] = hsvToHsl(hue, sat, lit)\r\n const [r, g, b] = hslToRgb(h, s, l)\r\n const hex = toHex([r, g, b]).toUpperCase()\r\n // Ink for the hex printed ON the preview field. Rec.709 luma is the\r\n // brightness measure the wallpaper extractor already uses, so the two agree:\r\n // a light color gets dark ink and a dark one light ink, and the value never\r\n // disappears into its own fill.\r\n const ink = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.55 ? 'rgba(0,0,0,.78)' : 'rgba(255,255,255,.92)'\r\n\r\n const setHsl = (nh: number, ns: number, nl: number) => onChange(...hslToHsv(nh, ns, nl))\r\n const setRgb = (nr: number, ng: number, nb: number) => {\r\n const [nh, ns, nl] = rgbToHsl(nr, ng, nb)\r\n onChange(...hslToHsv(nh, ns, nl))\r\n }\r\n\r\n return (\r\n <div className=\"dab-inputs\">\r\n <div className=\"dab-seg\" style={{ '--w': `${SEG_W}px` } as CSSProperties}>\r\n <div className=\"dab-seg-thumb\" style={{ transform: `translateX(${mode === 'hsl' ? 0 : SEG_W}px)` }} />\r\n <button type=\"button\" className={`dab-seg-item${mode === 'hsl' ? ' is-active' : ''}`} onClick={() => setMode('hsl')}>HSL</button>\r\n <button type=\"button\" className={`dab-seg-item${mode === 'rgb' ? ' is-active' : ''}`} onClick={() => setMode('rgb')}>RGB</button>\r\n </div>\r\n <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>\r\n {mode === 'hsl' ? (\r\n <>\r\n <NumField label=\"H\" value={Math.round(h)} min={0} max={360} step={1} onChange={v => setHsl(v, s, l)} />\r\n <NumField label=\"S\" value={Math.round(s * 100)} min={0} max={100} step={1} onChange={v => setHsl(h, v / 100, l)} />\r\n <NumField label=\"L\" value={Math.round(l * 100)} min={0} max={100} step={1} onChange={v => setHsl(h, s, v / 100)} />\r\n </>\r\n ) : (\r\n <>\r\n <NumField label=\"R\" value={r} min={0} max={255} step={1} onChange={v => setRgb(v, g, b)} />\r\n <NumField label=\"G\" value={g} min={0} max={255} step={1} onChange={v => setRgb(r, v, b)} />\r\n <NumField label=\"B\" value={b} min={0} max={255} step={1} onChange={v => setRgb(r, g, v)} />\r\n </>\r\n )}\r\n </div>\r\n {/* Prints its own value. An empty colored rectangle sitting in the same\r\n column as the H/S/L fields reads as one more text input — and there is\r\n nothing to type into it, so the value it is showing has to be visible\r\n on it. Without the hex this was the one control in the panel that\r\n looked editable and was not. */}\r\n <div\r\n className=\"dab-swatch-lg\"\r\n style={{ background: `hsl(${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%)`, color: ink }}>\r\n {hex}\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import { useRef, useState, useEffect, useCallback } from 'react'\r\nimport { rgbToHsl, hslToHsv } from '../utils/color'\r\nimport { Portal } from './Portal'\r\n\r\nconst MAG_SIZE = 96\r\nconst MAG_ZOOM = 8\r\n\r\nfunction toHex(rgb: [number, number, number]): string {\r\n return '#' + rgb.map(v => v.toString(16).padStart(2, '0')).join('')\r\n}\r\n\r\n/**\r\n * Eyedropper modal: shows the wallpaper full-bleed (no drag/zoom) and lets the\r\n * user click any pixel to adopt it as the theme color. A magnifier circle\r\n * follows the cursor so small details can be picked precisely. The wallpaper\r\n * is a data URL, so sampling is CORS-free: draw it once to an offscreen-sized\r\n * canvas and read pixels via getImageData.\r\n */\r\nexport function ColorPicker({ url, t, onPick, onClose }: {\r\n url: string\r\n t: (key: string) => string\r\n onPick: (hsv: [number, number, number]) => void\r\n onClose: () => void\r\n}) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n const magRef = useRef<HTMLCanvasElement>(null)\r\n const imgRef = useRef<HTMLImageElement | null>(null)\r\n const [ready, setReady] = useState(false)\r\n const [hover, setHover] = useState<{ rgb: [number, number, number] } | null>(null)\r\n const [mag, setMag] = useState<{ x: number; y: number } | null>(null)\r\n\r\n useEffect(() => {\r\n const img = new Image()\r\n img.onload = () => { imgRef.current = img; setReady(true) }\r\n img.src = url\r\n }, [url])\r\n\r\n useEffect(() => {\r\n if (!ready || !canvasRef.current || !imgRef.current) return\r\n const canvas = canvasRef.current\r\n canvas.width = imgRef.current.naturalWidth\r\n canvas.height = imgRef.current.naturalHeight\r\n const ctx = canvas.getContext('2d')\r\n if (ctx) ctx.drawImage(imgRef.current, 0, 0)\r\n }, [ready])\r\n\r\n const sampleAt = useCallback((clientX: number, clientY: number) => {\r\n const canvas = canvasRef.current\r\n if (!canvas) return null\r\n const rect = canvas.getBoundingClientRect()\r\n if (rect.width === 0 || rect.height === 0) return null\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx) return null\r\n const sx = Math.round((clientX - rect.left) * (canvas.width / rect.width))\r\n const sy = Math.round((clientY - rect.top) * (canvas.height / rect.height))\r\n if (sx < 0 || sy < 0 || sx >= canvas.width || sy >= canvas.height) return null\r\n const d = ctx.getImageData(sx, sy, 1, 1).data\r\n return { sx, sy, rgb: [d[0], d[1], d[2]] as [number, number, number] }\r\n }, [])\r\n\r\n const drawMagnifier = useCallback((sx: number, sy: number) => {\r\n const mag = magRef.current\r\n const src = canvasRef.current\r\n if (!mag || !src) return\r\n const ctx = mag.getContext('2d')\r\n if (!ctx) return\r\n const half = MAG_SIZE / MAG_ZOOM / 2\r\n ctx.clearRect(0, 0, MAG_SIZE, MAG_SIZE)\r\n ctx.drawImage(src, sx - half, sy - half, half * 2, half * 2, 0, 0, MAG_SIZE, MAG_SIZE)\r\n ctx.strokeStyle = 'rgba(255,255,255,0.85)'\r\n ctx.lineWidth = 1\r\n ctx.beginPath()\r\n ctx.moveTo(MAG_SIZE / 2, 0); ctx.lineTo(MAG_SIZE / 2, MAG_SIZE)\r\n ctx.moveTo(0, MAG_SIZE / 2); ctx.lineTo(MAG_SIZE, MAG_SIZE / 2)\r\n ctx.stroke()\r\n }, [])\r\n\r\n const onMove = (e: React.MouseEvent) => {\r\n const s = sampleAt(e.clientX, e.clientY)\r\n if (!s) { setHover(null); setMag(null); return }\r\n setHover({ rgb: s.rgb })\r\n drawMagnifier(s.sx, s.sy)\r\n const off = 28\r\n let x = e.clientX + off\r\n let y = e.clientY + off\r\n if (x + MAG_SIZE > window.innerWidth) x = e.clientX - off - MAG_SIZE\r\n if (y + MAG_SIZE > window.innerHeight) y = e.clientY - off - MAG_SIZE\r\n setMag({ x, y })\r\n }\r\n\r\n const onClick = (e: React.MouseEvent) => {\r\n const s = sampleAt(e.clientX, e.clientY)\r\n if (!s) return\r\n const [h, sl, l] = rgbToHsl(s.rgb[0], s.rgb[1], s.rgb[2])\r\n onPick(hslToHsv(h, sl, l))\r\n }\r\n\r\n return (\r\n <Portal>\r\n <div className=\"dab-overlay\">\r\n <div className=\"dab-overlay-title\">{t('pickerTitle')}</div>\r\n <div className=\"dab-overlay-hint\">{t('pickerHint')}</div>\r\n <div className=\"dab-modal-card\" style={{\r\n maxWidth: 'min(90vw, 720px)', maxHeight: '60vh', overflow: 'hidden',\r\n borderRadius: 12, border: '2px solid rgba(255,255,255,0.3)', background: '#000', cursor: 'crosshair',\r\n }}>\r\n <canvas ref={canvasRef} style={{ display: 'block', maxWidth: '100%', maxHeight: '60vh', objectFit: 'contain' }}\r\n onMouseMove={onMove}\r\n onMouseLeave={() => { setHover(null); setMag(null) }}\r\n onClick={onClick} />\r\n </div>\r\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 260 }}>\r\n <div style={{ width: 28, height: 28, borderRadius: 8, border: '1px solid rgba(255,255,255,0.4)', background: hover ? toHex(hover.rgb) : 'transparent' }} />\r\n <div style={{ color: '#fff', fontSize: 13, fontFamily: 'var(--dab-mono, monospace)' }}>{hover ? `${toHex(hover.rgb)} · rgb(${hover.rgb.join(', ')})` : '—'}</div>\r\n </div>\r\n <div style={{ display: 'flex', gap: 10 }}>\r\n <button type=\"button\" className=\"dab-btn\" onClick={onClose}>{t('pickerClose')}</button>\r\n </div>\r\n <canvas ref={magRef} width={MAG_SIZE} height={MAG_SIZE}\r\n style={{\r\n position: 'fixed', width: MAG_SIZE, height: MAG_SIZE, borderRadius: '50%',\r\n border: '2px solid rgba(255,255,255,0.7)', boxShadow: '0 4px 16px rgba(0,0,0,0.5)',\r\n zIndex: 10000, background: '#000', pointerEvents: 'none', transition: 'opacity 0.08s',\r\n left: mag?.x ?? 0, top: mag?.y ?? 0, opacity: mag ? 1 : 0,\r\n }} />\r\n </div>\r\n </Portal>\r\n )\r\n}\r\n","import { useRef, useState, useEffect, useCallback } from 'react'\nimport type { BgState } from '../types'\nimport { Portal } from './Portal'\n\n/**\n * Framing editor for one rule's image.\n *\n * The placement state is passed IN rather than read from a global slot: every\n * rule owns its own framing, and editing rule B must never touch rule A.\n */\nexport function BgEditor({ url, state, t, onClose, onCommit }: {\n url: string\n /** The rule's own framing. */\n state: BgState\n t: (key: string) => string; onClose: () => void\n onCommit: (zoom: number, x: number, y: number, iw: number, ih: number) => void\n}) {\n const pw = Math.min(window.innerWidth * 0.75, 860)\n const ph = Math.round(pw * window.innerHeight / window.innerWidth)\n const saved = state\n const [zoom, setZoom] = useState(saved.iw > 0 ? saved.zoom : 1)\n const [pos, setPos] = useState(saved.iw > 0 ? { x: saved.x * pw, y: saved.y * ph } : { x: 0, y: 0 })\n const [imgSize, setImgSize] = useState({ w: 0, h: 0 })\n const containerRef = useRef<HTMLDivElement>(null)\n const imgRef = useRef<HTMLImageElement>(null)\n const dragRef = useRef({ active: false, sx: 0, sy: 0, spx: 0, spy: 0 })\n\n useEffect(() => {\n const img = new Image()\n img.onload = () => {\n const scale = Math.min(pw / img.width, ph / img.height)\n const w = img.width * scale, h = img.height * scale\n setImgSize({ w, h })\n const s = state\n if (s.iw > 0 && s.iw === img.width && s.ih === img.height) {\n setZoom(s.zoom)\n // Saved x, y are CENTER fractions of the preview: the image center\n // lands at (x·pw, y·ph), so the top-left comes from subtracting half\n // the displayed (zoom-scaled) image size.\n setPos({ x: s.x * pw - w * s.zoom / 2, y: s.y * ph - h * s.zoom / 2 })\n } else {\n setZoom(1)\n setPos({ x: (pw - w) / 2, y: (ph - h) / 2 })\n }\n }\n img.src = url\n }, [url, state, pw, ph])\n\n const onDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault()\n dragRef.current = { active: true, sx: e.clientX, sy: e.clientY, spx: pos.x, spy: pos.y }\n const onMove = (ev: MouseEvent) => {\n if (!dragRef.current.active) return\n setPos({ x: dragRef.current.spx + ev.clientX - dragRef.current.sx, y: dragRef.current.spy + ev.clientY - dragRef.current.sy })\n }\n const onUp = () => { dragRef.current.active = false; document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp) }\n document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp)\n }, [pos])\n\n const onWheelCb = useCallback((e: WheelEvent) => {\n e.preventDefault()\n const el = containerRef.current\n if (!el) return\n const rect = el.getBoundingClientRect()\n // Anchor the zoom at the preview center so the mouse position never\n // steers where the image grows/shrinks — the current view stays centered.\n const mx = rect.width / 2, my = rect.height / 2\n // 3% per wheel step (0.97 zoom-out / 1.03 zoom-in).\n const factor = e.deltaY > 0 ? 0.97 : 1.03\n const nz = Math.max(0.1, Math.min(10, zoom * factor))\n const nx = mx - (mx - pos.x) * (nz / zoom)\n const ny = my - (my - pos.y) * (nz / zoom)\n setZoom(nz); setPos({ x: nx, y: ny })\n }, [zoom, pos])\n\n useEffect(() => {\n const el = containerRef.current\n if (!el) return\n el.addEventListener('wheel', onWheelCb, { passive: false })\n return () => el.removeEventListener('wheel', onWheelCb)\n }, [onWheelCb])\n\n const resetView = useCallback(() => {\n if (imgSize.w === 0) return\n setZoom(1); setPos({ x: (pw - imgSize.w) / 2, y: (ph - imgSize.h) / 2 })\n }, [pw, ph, imgSize])\n\n return (\n <Portal>\n <div className=\"dab-overlay\" onClick={e => { if (e.target === e.currentTarget) onClose() }}>\n <div className=\"dab-overlay-title\">{t('editorTitle')}</div>\n <div ref={containerRef} className=\"dab-modal-card\" style={{\n position: 'relative', overflow: 'hidden', border: '2px solid rgba(255,255,255,0.3)',\n borderRadius: 12, background: '#000', cursor: 'grab', width: pw, height: ph,\n }} onMouseDown={onDown}>\n <img ref={imgRef} src={url} alt=\"\" draggable={false} style={{\n position: 'absolute', transformOrigin: '0 0', pointerEvents: 'none',\n width: imgSize.w, height: imgSize.h,\n transform: `translate(${pos.x}px,${pos.y}px) scale(${zoom})`,\n }} />\n </div>\n <div className=\"dab-overlay-hint\">{t('editorHint')}</div>\n <div style={{ display: 'flex', gap: 10 }}>\n <button type=\"button\" className=\"dab-btn\" onClick={resetView}>{t('editorReset')}</button>\n <button type=\"button\" className=\"dab-btn\" onClick={onClose}>{t('editorCancel')}</button>\n <button type=\"button\" className=\"dab-btn\" onClick={() => onCommit(zoom, (pos.x + imgSize.w * zoom / 2) / pw, (pos.y + imgSize.h * zoom / 2) / ph, imgRef.current?.naturalWidth ?? 0, imgRef.current?.naturalHeight ?? 0)}>{t('editorCommit')}</button>\n </div>\n </div>\n </Portal>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { CSSProperties, PointerEvent as ReactPointerEvent } from 'react'\nimport type { BgMode, BgRule, ThemeSectionProps, ThemeStoreState } from '../../types'\nimport { cfg, PALETTE } from '../../state'\nimport { matchRule } from '../../modelbg'\nimport { ROTATE_PRESETS } from '../../rotation'\nimport { readImg } from '../../utils/image'\nimport { hslToHsv, hsvToHsl, hslToRgb } from '../../utils/color'\nimport { ColorWheel } from '../ColorWheel'\nimport { ColorInputs } from '../ColorInputs'\nimport { ColorPicker } from '../ColorPicker'\nimport { BgEditor } from '../BgEditor'\nimport { LiveSlider } from '../LiveSlider'\nimport { DropletIcon, EditIcon, LinkIcon, PipetteIcon, SparkleIcon, SunIcon, TrashIcon, UploadIcon } from '../icons'\n\nconst BG_MODES: Array<{ mode: BgMode; key: string }> = [\n { mode: 'fit', key: 'bgModeFit' },\n { mode: 'fill', key: 'bgModeFill' },\n { mode: 'stretch', key: 'bgModeStretch' },\n { mode: 'tile', key: 'bgModeTile' },\n { mode: 'center', key: 'bgModeCenter' },\n]\n\n/** Seed color a rule starts from when the user picks one for the first time. */\nconst SEED_COLOR: [number, number, number] = [220, 0.55, 0.25]\n\n/**\n * Failing-hop codes the model watcher can report, mapped to their copy. Only\n * these are rendered: `waiting` and `fallback` already have their own hints.\n */\nconst MODEL_NOTE_KEYS: Record<string, string | undefined> = {\n 'no-service': 'statusNoteNoService',\n 'no-session': 'statusNoteNoSession',\n 'no-projection': 'statusNoteNoProjection',\n 'empty-selection': 'statusNoteEmptySelection',\n}\n\nfunction toHex(rgb: [number, number, number]): string {\n return '#' + rgb.map(v => Math.round(v).toString(16).padStart(2, '0')).join('')\n}\n\nexport function ModelBgPage({ p, notify }: { p: ThemeSectionProps; notify: (msg: string, ok?: boolean) => void }) {\n const { t, useStore } = p\n const store = useStore((s: ThemeStoreState) => s)\n const rules = cfg.rules\n\n // Match tester: the field follows the detected model until the user types\n // their own text, so the card is useful the moment it is looked at and never\n // fights the watcher once it is not. It replaced the old \"active now\" readout —\n // the same question (\"what does this model resolve to?\") one step earlier, and\n // it does not go stale between switches.\n const [text, setText] = useState('')\n const [touched, setTouched] = useState(false)\n useEffect(() => { if (!touched) setText(store.model) }, [store.model, touched])\n const probe = text.trim()\n const result = ((): string | null => {\n if (probe === '') return null\n const hit = matchRule(rules, probe)\n const rule = hit.rule\n if (rule === null) return null\n const n = rules.findIndex(r => r.id === rule.id) + 1\n return `${hit.matched ? t('tryoutHit') : t('tryoutFallback')} ${n}`\n })()\n\n return (\n <>\n <header className=\"dab-head dab-rise\" style={{ '--d': 0 } as CSSProperties}>\n <div className=\"dab-overline\">Rules</div>\n <h2 className=\"dab-h1\">{t('pageModelBg')}</h2>\n <p className=\"dab-desc\">{t('descModelBg')}</p>\n </header>\n\n <section className=\"dab-card dab-rise\" style={{ '--d': 1 } as CSSProperties}>\n {/* A host process from before multi-image cannot read this bundle's config\n shape, so writes are held (see canWriteConfig in ../../rpc). Saying it\n out loud is the whole point: edits that silently do not persist are\n worse than a line telling the user to restart DSH. */}\n {store.hostStale ? (\n <p className=\"dab-hint dab-stale\" style={{ marginBottom: 10 }}>{t('hostStaleHint')}</p>\n ) : null}\n <div className=\"dab-swatch-title\">{t('tryoutTitle')}</div>\n <div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>\n <input\n type=\"text\" className=\"dab-urlinput\" value={text}\n placeholder={t('tryoutPlaceholder')}\n onChange={e => { setTouched(true); setText(e.target.value) }} />\n {store.model !== '' ? (\n <button type=\"button\" className=\"dab-btn\" onClick={() => { setTouched(true); setText(store.model) }}>\n {t('tryoutUseCurrent')}\n </button>\n ) : null}\n </div>\n <p className=\"dab-hint\" style={{ marginTop: 9 }}>\n {probe === '' ? t('tryoutEmpty') : result === null ? t('tryoutNone') : result}\n </p>\n {/* Why the pre-filled value is what it is: without these, a host default\n passed off as this session's model, or a sessions service that simply\n is not up yet, is indistinguishable from a correct read. */}\n {store.model === '' ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('statusUnknownHint')}</p> : null}\n {store.model !== '' && store.modelSource === 'default'\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('statusSourceDefaultHint')}</p>\n : null}\n {MODEL_NOTE_KEYS[store.modelNote] !== undefined\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t(MODEL_NOTE_KEYS[store.modelNote]!)}</p>\n : null}\n </section>\n\n <section className=\"dab-rise\" style={{ '--d': 2 } as CSSProperties}>\n {/* No \"rules\" heading and no priority sentence above the list: the panel's\n own title already introduces the rules, and the two lines only pushed\n the first card further down. */}\n {/* Picking an image should just theme the rule; this is the off switch\n for people who want the color to be their own choice every time. */}\n <div className=\"dab-chip-row\" style={{ marginBottom: 12, alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${cfg.autoExtract ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={cfg.autoExtract} title={t('autoExtract')}\n onClick={() => p.setAutoExtract(!cfg.autoExtract)}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-hint\">{t('autoExtract')}</span>\n </div>\n\n <div className=\"dab-rules\">\n {rules.map((rule, i) => (\n <RuleCard\n key={rule.id} p={p} rule={rule} index={i} total={rules.length}\n // Which of THIS rule's images is on screen right now; -1 for every\n // rule that is not the one painting, so a card can never claim to be\n // showing something it is not.\n liveIndex={rule.id === store.activeRuleId ? store.rotIndex : -1}\n active={rule.id === store.activeRuleId} notify={notify} />\n ))}\n </div>\n\n <button type=\"button\" className=\"dab-btn dab-btn-primary\" style={{ marginTop: 12 }} onClick={() => { p.addRule() }}>\n + {t('ruleAdd')}\n </button>\n </section>\n </>\n )\n}\n\nfunction RuleCard({ p, rule, index, total, active, liveIndex, notify }: {\n p: ThemeSectionProps\n rule: BgRule\n index: number\n total: number\n active: boolean\n /** Index of the image on screen (only meaningful while `active`); -1 = none. */\n liveIndex: number\n notify: (msg: string, ok?: boolean) => void\n}) {\n const { t } = p\n // The active rule opens by default so the panel shows the live one first.\n const [open, setOpen] = useState(active)\n const [dragOver, setDragOver] = useState(false)\n // ── Dragging a TILE to reorder the row ─────────────────────────────────────\n // Pointer events with capture rather than HTML5 drag-and-drop: the strip already\n // spends that channel on dropped FILES, and a drag we run ourselves is also the\n // only one that can put the insertion bar where the tile will actually land.\n // A pointerdown is merely a CANDIDATE — a tile is a button and clicking it\n // selects it — so the drag only begins once the pointer has travelled a little.\n const pendingDrag = useRef<{ x: number; y: number; from: number; slot: string; id: number } | null>(null)\n /** Insertion slot of the drag in flight (index of the tile it goes BEFORE). */\n const dragAt = useRef<{ from: number; at: number } | null>(null)\n const [drop, setDrop] = useState<{ from: number; at: number } | null>(null)\n /** Set while a drag is real, so the click that ends it is not also a selection. */\n const draggedRef = useRef(false)\n const [urlOpen, setUrlOpen] = useState(false)\n const [urlVal, setUrlVal] = useState('')\n const [urlBusy, setUrlBusy] = useState(false)\n const [urlErr, setUrlErr] = useState<string | null>(null)\n const [editorOpen, setEditorOpen] = useState(false)\n const [pickerOpen, setPickerOpen] = useState(false)\n const [extracting, setExtracting] = useState(false)\n const [secDraft, setSecDraft] = useState<string | null>(null)\n /** Whether the next file picked replaces the selected image or is added. */\n const [replace, setReplace] = useState(false)\n const fileRef = useRef<HTMLInputElement>(null)\n\n // Which image this card is EDITING — deliberately independent of which image\n // the rule is PAINTING: picking image 3 in the strip to fix its framing must not\n // change the background under the dialog. Clamped on read, because removing an\n // image can leave the selection past the end.\n const [sel, setSel] = useState(0)\n const selIdx = rule.images.length === 0 ? 0 : Math.min(sel, rule.images.length - 1)\n const image = rule.images[selIdx]\n const url = image === undefined ? null : p.imageOf(image.slot)\n\n // ── What the theme-color section edits ─────────────────────────────────────\n // The color belongs to an IMAGE, so the wheel, the swatches, the extractor and\n // the eyedropper all address the image selected in the strip. A rule with no\n // image has only its own color left to offer, and that is not a special case\n // bolted on here: it is the one thing such a rule paints (see `ruleCanPaint`),\n // so the same controls edit it without a second code path.\n //\n // The two targets never mix: an image's color is never inherited from the\n // rule's, which is what makes a rotation through a green, a red and a\n // system-themed picture expressible.\n const ownColor = image === undefined ? rule.color : image.color\n const setColor = (color: [number, number, number] | null): void => {\n if (image === undefined) p.setRule(rule.id, { color })\n else p.setImageColor(rule.id, image.slot, color)\n }\n const [h, s, l] = ownColor ?? SEED_COLOR\n const wheel = hslToHsv(h, s, l)\n\n // Boot only reads a rule's FIRST image, so an expanded card pulls the rest in.\n useEffect(() => {\n if (open) void p.loadRuleImages(rule.id)\n // The count is in the deps on purpose: adding an image to an open card has to\n // hydrate it too (the bytes are already in memory then, so this is a no-op).\n }, [open, rule.id, rule.images.length, p])\n\n const onColor = (nh: number, ns: number, nl: number): void => {\n const [sh, ss, sl] = hsvToHsl(nh, ns, nl)\n setColor([sh, ss, sl])\n }\n\n const onFiles = (files: readonly File[]): void => {\n const list = files.filter(f => f.type.startsWith('image/'))\n if (list.length === 0) return\n // \"Replace\" swaps the SELECTED image's bytes in place, which is what keeps its\n // position in the rotation; \"add\" appends. One input serves both, and the mode\n // is decided by the button that opened it.\n if (replace) {\n const slot = rule.images[selIdx]?.slot\n if (slot !== undefined) readImg(list[0]!, d => { if (d !== null) p.setRuleImage(rule.id, slot, d) })\n return\n }\n // Read every file, then hand them over in one batch: adding N images one at a\n // time would persist a config that references slots whose bytes are still\n // being decoded, and each add repaints the whole interface.\n const out: string[] = []\n // What the card will EDIT once the batch lands: the first picture of it. Adding\n // pictures without moving the selection is what made an upload look like it had\n // gone nowhere — the preview stayed on whatever was selected before, and for a\n // rule that had just been emptied that was nothing at all.\n const first = rule.images.length\n let pending = list.length\n list.forEach((f, i) => {\n readImg(f, d => {\n if (d !== null) out[i] = d\n pending--\n if (pending === 0) {\n p.addRuleImages(rule.id, out.filter((x): x is string => typeof x === 'string'))\n setSel(first)\n }\n })\n })\n }\n\n const onDrop = (e: React.DragEvent): void => {\n e.preventDefault()\n setDragOver(false)\n const files = Array.from(e.dataTransfer.files ?? [])\n if (files.length > 0) onFiles(files)\n }\n\n const applyUrl = async (): Promise<void> => {\n // One URL per line: pasting a list is how people actually collect wallpapers,\n // and making them repeat the dialog once per picture is the kind of friction\n // that keeps a rotation at two images.\n const urls = urlVal.split(/\\s+/).map(u => u.trim()).filter(u => u !== '')\n if (urls.length === 0) { setUrlErr(t('ruleUrlBadHttp')); return }\n if (urls.some(u => !/^https?:\\/\\//i.test(u))) { setUrlErr(t('ruleUrlBadHttp')); return }\n setUrlBusy(true)\n setUrlErr(null)\n // Sequential: the node half downloads each one, and firing them all at once\n // would interleave N downloads with no useful progress to show.\n const first = rule.images.length\n for (const u of urls) {\n const res = await p.addRuleImageFromUrl(rule.id, u)\n if (!res.ok) {\n setUrlBusy(false)\n setUrlErr(res.error === 'invalid url' || res.error === 'unsupported scheme'\n ? t('ruleUrlBadHttp')\n : (res.error ?? t('ruleUrlFail')))\n return\n }\n }\n setUrlBusy(false)\n setUrlOpen(false)\n setUrlVal('')\n // Same rule as the file picker: show the user what they just added.\n setSel(first)\n }\n\n const onExtract = async (): Promise<void> => {\n if (url === null || extracting || image === undefined) return\n setExtracting(true)\n try {\n const ok = await p.extractColor(rule.id, image.slot)\n notify(ok ? t('extractDone') : t('extractFail'), ok)\n } catch {\n notify(t('extractFail'), false)\n } finally {\n setExtracting(false)\n }\n }\n\n /**\n * Leaving \"follow the system theme\" must not hand the user a color that has\n * nothing to do with the wallpaper they just picked, so this tries the image\n * first and only falls back to the seed. (`extractColor` is the same pass the\n * extract button runs and returns false when nothing vivid was found.)\n */\n const onPickColor = async (): Promise<void> => {\n if (url !== null && image !== undefined) {\n setExtracting(true)\n try {\n if (await p.extractColor(rule.id, image.slot)) return\n } catch {\n // fall through to the seed\n } finally {\n setExtracting(false)\n }\n }\n setColor(SEED_COLOR)\n }\n\n const cls = `dab-rule${active ? ' is-active' : ''}${rule.enabled ? '' : ' is-off'}`\n const rotatable = rule.images.length >= 2\n const preset = ROTATE_PRESETS.find(x => x.ms === rule.rotate.intervalMs)\n const selSlot = image?.slot ?? null\n\n // ── Reordering by dragging a tile ──────────────────────────────────────────\n /** How far the pointer must travel before a click turns into a drag. */\n const DRAG_SLOP = 5\n\n const tileDown = (i: number, slot: string) => (e: ReactPointerEvent<HTMLButtonElement>): void => {\n // Mouse and pen only: on a touch screen this same gesture is how the row is\n // scrolled, and taking it over would leave the strip unscrollable by finger.\n if (e.button !== 0 || e.pointerType === 'touch') return\n e.currentTarget.setPointerCapture(e.pointerId)\n pendingDrag.current = { x: e.clientX, y: e.clientY, from: i, slot, id: e.pointerId }\n draggedRef.current = false\n }\n\n const tileMove = (e: ReactPointerEvent<HTMLButtonElement>): void => {\n const pen = pendingDrag.current\n if (pen === null || pen.id !== e.pointerId) return\n const cur = dragAt.current\n if (cur === null) {\n if (Math.abs(e.clientX - pen.x) + Math.abs(e.clientY - pen.y) < DRAG_SLOP) return\n draggedRef.current = true\n }\n // Where the tile would land, read off the live rectangles: the insertion slot\n // is the first tile whose midpoint is to the RIGHT of the pointer, so the left\n // half of a tile means \"before it\" and the right half \"after it\".\n const strip = e.currentTarget.parentElement\n const list = strip === null ? [] : [...strip.querySelectorAll('.dab-strip-item')]\n let at = list.length\n for (let i = 0; i < list.length; i++) {\n const box = list[i]!.getBoundingClientRect()\n if (e.clientX < box.left + box.width / 2) { at = i; break }\n }\n if (cur !== null && cur.at === at) return\n dragAt.current = { from: pen.from, at }\n setDrop({ from: pen.from, at })\n }\n\n /** End a drag: commit the new order, or just forget it on a cancel. */\n const tileUp = (commit: boolean) => (e: ReactPointerEvent<HTMLButtonElement>): void => {\n const pen = pendingDrag.current\n pendingDrag.current = null\n if (pen !== null && e.currentTarget.hasPointerCapture(pen.id)) e.currentTarget.releasePointerCapture(pen.id)\n const end = dragAt.current\n dragAt.current = null\n setDrop(null)\n if (!commit || pen === null || end === null) return\n // `at` counts tiles whose midpoint is left of the pointer, which is an index in\n // the list AS IT IS. The image is lifted out before it is put back, so a drop\n // to the right of its own slot has to lose one — the difference between a drop\n // that feels right and one that lands a slot short.\n const to = end.at > pen.from ? end.at - 1 : end.at\n if (to === pen.from) return\n p.moveRuleImageTo(rule.id, pen.slot, to)\n // Keep the preview on the picture the user just moved, which is where the drag\n // left their attention — the selection is an index, so it has to follow.\n setSel(to)\n }\n const removeSel = (): void => {\n if (selSlot === null) return\n // Removing the LAST image is allowed: the rule simply becomes empty and paints\n // nothing until a picture arrives, which is what the hint under the preview\n // has always said. (Refusing it left a cleared entry behind — see\n // removeRuleImage in ../../index.)\n const at = selIdx\n p.removeRuleImage(rule.id, selSlot)\n setSel(Math.max(0, Math.min(at, rule.images.length - 2)))\n }\n /** Commit the custom dwell time the moment it is typed (seconds → ms). */\n const commitSeconds = (): void => {\n if (secDraft === null) return\n const secs = Number(secDraft.trim())\n setSecDraft(null)\n if (!Number.isFinite(secs) || secs <= 0) return\n // The shared sanitizer clamps to ROTATE_MIN_MS..ROTATE_MAX_MS, so this cannot\n // store a value the next load would rewrite.\n p.setRuleRotation(rule.id, { intervalMs: Math.round(secs * 1000) })\n }\n\n return (\n <section className={cls}>\n <div className=\"dab-rule-head\">\n <button type=\"button\" className=\"dab-icon-btn\" onClick={() => setOpen(o => !o)}\n title={open ? 'Collapse' : 'Expand'} aria-expanded={open}>\n {open ? '▾' : '▸'}\n </button>\n <span className=\"dab-rule-num\">{index + 1}</span>\n {index === 0 ? <span className=\"dab-rule-badge\">{t('ruleFallbackBadge')}</span> : null}\n <input\n className=\"dab-rule-match\" value={rule.match}\n placeholder={t('ruleMatchPlaceholder')}\n onChange={e => p.setRule(rule.id, { match: e.target.value })} />\n <button type=\"button\" className={`dab-toggle${rule.enabled ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={rule.enabled} title={t('ruleEnabled')}\n onClick={() => p.setRule(rule.id, { enabled: !rule.enabled })}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <button type=\"button\" className=\"dab-icon-btn\" disabled={index === 0}\n title={t('ruleUp')} onClick={() => p.moveRule(rule.id, -1)}>↑</button>\n <button type=\"button\" className=\"dab-icon-btn\" disabled={index === total - 1}\n title={t('ruleDown')} onClick={() => p.moveRule(rule.id, 1)}>↓</button>\n <button type=\"button\" className=\"dab-icon-btn dab-icon-btn-danger\"\n title={t('ruleRemove')} onClick={() => p.removeRule(rule.id)}>\n <TrashIcon size={13} />\n </button>\n </div>\n\n {open ? (\n <div className=\"dab-rule-body\">\n <div className=\"dab-rule-cols\">\n {/* ── image strip + layout ───────────────────────────────────── */}\n <div>\n {/* Big preview of the SELECTED image — the card used to show its\n only image here, so the panel keeps the same visual weight. It\n is deliberately inert: dropping onto the strip below ADDS,\n while \"replace\" stays an explicit action on the labelled\n button, and a preview that quietly swallowed a click was the\n one thing this card's users could not predict. */}\n {/* Big preview of the SELECTED image — and, while the rule holds no\n picture at all, the rule's upload target.\n\n With pictures present it is deliberately inert: dropping onto\n the strip below ADDS, while \"replace\" stays an explicit action on\n the labelled button, and a preview that quietly swallowed a click\n was the one thing this card's users could not predict.\n\n With NO picture there is nothing to replace, so the same box is\n the opposite: the one obvious thing to click (\"点这个上传\"), and\n the drop zone as well — the strip is hidden in that state (it\n would hold nothing but a second add tile), and taking drag &\n drop away from the state every rule starts in is not a trade this\n card should make. `dragOver` is shared with the strip on purpose:\n exactly one of the two is ever mounted. */}\n {url !== null ? (\n <div className=\"dab-rule-thumb\">\n <img src={url} alt=\"\" draggable={false} />\n </div>\n ) : rule.images.length === 0 ? (\n <button\n type=\"button\"\n className={`dab-rule-thumb dab-rule-thumb-add${dragOver ? ' is-over' : ''}`}\n title={t('rotAddImage')}\n onDragOver={e => { e.preventDefault(); setDragOver(true) }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n onClick={() => { setReplace(false); fileRef.current?.click() }}>\n <span className=\"dab-rule-thumb-empty\">\n <UploadIcon size={18} />\n <span>{t('rotAddImage')}</span>\n </span>\n </button>\n ) : (\n <div className=\"dab-rule-thumb\">\n <div className=\"dab-rule-thumb-empty\">\n <UploadIcon size={18} />\n <span>{t('ruleNoImage')}</span>\n </div>\n </div>\n )}\n\n {/* The strip. One item per image, in the order the rotation walks\n them; the edited one is ringed, the PAINTED one carries the dot\n while this rule is the live rule — and only the dot, so the\n strip never shows two rings at once. Dropping files anywhere on\n it adds them (several at once — a rotation is built in batches),\n and dragging a TILE along it reorders the rotation.\n\n Hidden while the rule has no picture: a strip holding nothing but\n its own add tile said the same thing as the upload target right\n above it, and a filmstrip is a list of pictures — it has no job\n in a state that has none. */}\n {rule.images.length > 0 ? (\n <div\n className={`dab-strip${dragOver ? ' is-over' : ''}`}\n onDragOver={e => { e.preventDefault(); setDragOver(true) }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}>\n {rule.images.map((img, i) => {\n const thumb = p.imageOf(img.slot)\n return (\n <button\n key={img.slot} type=\"button\"\n // No `is-live` modifier: being on screen is the dot\n // below and nothing more. Ringing this tile as well put\n // two rings in the strip at once — this one and the\n // previewed one — and read as \"two images selected\".\n className={`dab-strip-item${i === selIdx ? ' is-sel' : ''}${drop !== null && drop.from === i ? ' is-dragging' : ''}`}\n title={`${i + 1} / ${rule.images.length} · ${t('rotDragHint')} · ${t('rotDblHint')}`}\n onPointerDown={tileDown(i, img.slot)}\n onPointerMove={tileMove}\n onPointerUp={tileUp(true)}\n onPointerCancel={tileUp(false)}\n onClick={() => {\n // A drag ends with a click on the tile it started from,\n // and that click is not a selection.\n if (draggedRef.current) { draggedRef.current = false; return }\n setSel(i)\n }}\n // Double-click shows this picture: it is the one gesture that\n // says \"THIS one on screen\", which reordering deliberately\n // does not do. It changes no order and saves nothing — the\n // image being shown is runtime state, not a setting.\n onDoubleClick={() => {\n // Only the rule that is painting has a screen to change, and\n // the store no-ops for any other — so say why instead of\n // leaving a double-click that looks broken.\n if (!active) { notify(t('rotNextInactive')); return }\n p.showRuleImage(rule.id, img.slot)\n }}>\n {thumb !== null\n ? <img src={thumb} alt=\"\" draggable={false} />\n : <span className=\"dab-strip-wait\" />}\n <span className=\"dab-strip-num\">{i + 1}</span>\n {/* Where the tile in hand will land: a bar at this tile's\n LEFT edge, or at the last tile's right edge for a drop\n past the end of the row. */}\n {drop !== null && drop.at === i ? <span className=\"dab-strip-bar\" /> : null}\n {drop !== null && drop.at === rule.images.length && i === rule.images.length - 1\n ? <span className=\"dab-strip-bar is-end\" /> : null}\n {/* This image's own theme color, when it has one. The whole\n point of per-image colors is that they differ, and\n without this the only way to find out which pictures\n already carry one is to click through the strip and\n watch the wheel change. Hex on hover, like a swatch. */}\n {img.color !== null ? (\n <span\n className=\"dab-strip-dot\"\n title={toHex(hslToRgb(img.color[0], img.color[1], img.color[2])).toUpperCase()}\n style={{ background: `hsl(${img.color[0]} ${Math.round(img.color[1] * 100)}% ${Math.round(img.color[2] * 100)}%)` }} />\n ) : null}\n {liveIndex === i ? <span className=\"dab-strip-live\" title={t('rotShowing')} /> : null}\n </button>\n )\n })}\n <button type=\"button\" className=\"dab-strip-add\" title={t('rotAddImage')}\n onClick={() => { setReplace(false); fileRef.current?.click() }}>\n <UploadIcon size={16} />\n <span>{t('rotAddImage')}</span>\n </button>\n </div>\n ) : null}\n\n <div className=\"dab-chip-row\" style={{ marginTop: 10 }}>\n {/* No position readout for an empty rule: \"image 0 / 0\" would be a\n number about nothing — the upload target above is the whole\n story there. */}\n {rule.images.length > 0 ? (\n <span className=\"dab-strip-pos\">{t('rotPos')} {selIdx + 1} / {rule.images.length}</span>\n ) : null}\n <button type=\"button\" className=\"dab-btn\" onClick={() => { setReplace(false); fileRef.current?.click() }}>\n <UploadIcon size={13} />{t('rotAddImage')}\n </button>\n <button type=\"button\" className=\"dab-btn dab-btn-ghost\" onClick={() => setUrlOpen(o => !o)}>\n <LinkIcon size={13} />{t('ruleFromUrl')}\n </button>\n {/* Replacing keeps the image's POSITION in the rotation, which\n \"remove + add\" cannot do — and the two actions are labelled\n apart on purpose: the button above appends, this one swaps the\n selected image's bytes. */}\n {selSlot !== null ? (\n <button type=\"button\" className=\"dab-btn dab-btn-ghost\"\n onClick={() => { setReplace(true); fileRef.current?.click() }}>\n <UploadIcon size={13} />{t('rotReplaceImage')}\n </button>\n ) : null}\n {/* No step/first buttons any more: the strip IS the control for\n order. Dragging a tile is the same operation those two arrows\n and \"make first\" were, and a row of five tiles is a list you\n can see — a pair of arrows that nudges the selected one along\n it was a second, worse way to say \"put this one there\". */}\n {/* Always offered, including on the LAST image: the rule is then\n simply empty, and the empty strip above is the honest picture\n of that. Hiding this — the first cut of the feature did —\n left a cleared entry that could never be deleted again. Note\n that \"empty\" is not \"off\": a rule that kept its theme color\n still paints (see `ruleCanPaint`), which the hint above says. */}\n {selSlot !== null ? (\n <button type=\"button\" className=\"dab-btn dab-btn-ghost dab-btn-danger\"\n onClick={removeSel}>\n <TrashIcon size={13} />{t('ruleImageRemove')}\n </button>\n ) : null}\n </div>\n\n {urlOpen ? (\n <div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>\n <input\n type=\"text\" className=\"dab-urlinput\" value={urlVal}\n placeholder={t('ruleUrlPlaceholder')} autoFocus\n onChange={e => setUrlVal(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); void applyUrl() } }} />\n <button type=\"button\" className=\"dab-btn dab-btn-primary\" disabled={urlBusy} onClick={() => void applyUrl()}>\n {urlBusy ? t('ruleUrlApplying') : t('ruleUrlApply')}\n </button>\n <button type=\"button\" className=\"dab-btn\"\n onClick={() => { setUrlOpen(false); setUrlVal(''); setUrlErr(null) }}>\n {t('ruleUrlCancel')}\n </button>\n </div>\n ) : null}\n {urlErr !== null ? (\n <p style={{ marginTop: 8, color: 'var(--dsw-alias-state-error-primary)', fontSize: 12 }}>{urlErr}</p>\n ) : null}\n {/* Three states, three sentences — the old single test (`url ===\n null`) told a rule with no pictures and a rule whose picture\n simply has no bytes yet the same story, and only one of them\n was true. A rule with no image but a COLOR of its own is not\n skipped: it paints the interface from that color (see\n `ruleCanPaint`), and saying otherwise is what made its color\n controls look broken. */}\n {rule.images.length === 0 ? (\n <p className=\"dab-hint\" style={{ marginTop: 8 }}>\n {rule.color === null ? t('ruleEmptyHint') : t('ruleColorOnlyHint')}\n </p>\n ) : null}\n {rule.images.length > 0 && url === null ? (\n <p className=\"dab-hint\" style={{ marginTop: 8 }}>{t('ruleImagePendingHint')}</p>\n ) : null}\n\n {/* ── rotation ──────────────────────────────────────────────── */}\n <div style={{ marginTop: 14 }}>\n <div className=\"dab-rule-section-title\">{t('rotTitle')}</div>\n <div className=\"dab-chip-row\" style={{ alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${rule.rotate.enabled ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={rule.rotate.enabled} title={t('rotEnable')}\n disabled={!rotatable}\n onClick={() => p.setRuleRotation(rule.id, { enabled: !rule.rotate.enabled })}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotEnable')}</span>\n {!rotatable ? <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotNeedTwo')}</span> : null}\n </div>\n\n {rotatable && rule.rotate.enabled ? (\n <div className=\"dab-rot-panel\">\n <div className=\"dab-rule-section-title\">{t('rotEvery')}</div>\n <div className=\"dab-chip-row\">\n {ROTATE_PRESETS.map(item => (\n <button key={item.ms} type=\"button\"\n className={`dab-chip${item.ms === rule.rotate.intervalMs ? ' is-active' : ''}`}\n onClick={() => p.setRuleRotation(rule.id, { intervalMs: item.ms })}>\n {t(item.key)}\n </button>\n ))}\n <input\n type=\"number\" className=\"dab-num dab-num-sec\" min={5} max={86_400} step={5}\n // The draft is what is being typed; without it the field\n // would fight the user on every keystroke (and \"5\" on the\n // way to \"50\" is a legal value nobody meant).\n value={secDraft ?? (preset === undefined ? Math.round(rule.rotate.intervalMs / 1000) : '')}\n placeholder={t('rotCustom')}\n onChange={e => setSecDraft(e.target.value)}\n onBlur={commitSeconds}\n onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); commitSeconds() } }} />\n <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotSeconds')}</span>\n </div>\n\n <div className=\"dab-rule-section-title\" style={{ marginTop: 12 }}>{t('rotOrder')}</div>\n <div className=\"dab-chip-row\">\n <button type=\"button\" className={`dab-chip${rule.rotate.order === 'order' ? ' is-active' : ''}`}\n onClick={() => p.setRuleRotation(rule.id, { order: 'order' })}>\n {t('rotOrderSeq')}\n </button>\n <button type=\"button\" className={`dab-chip${rule.rotate.order === 'shuffle' ? ' is-active' : ''}`}\n onClick={() => p.setRuleRotation(rule.id, { order: 'shuffle' })}>\n {t('rotOrderShuffle')}\n </button>\n </div>\n\n <div className=\"dab-chip-row\" style={{ marginTop: 12, alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${rule.rotate.advanceOnSwitch ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={rule.rotate.advanceOnSwitch} title={t('rotOnSwitch')}\n onClick={() => p.setRuleRotation(rule.id, { advanceOnSwitch: !rule.rotate.advanceOnSwitch })}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotOnSwitch')}</span>\n </div>\n\n <div className=\"dab-chip-row\" style={{ marginTop: 12, alignItems: 'center' }}>\n <button type=\"button\" className=\"dab-btn\" disabled={!active} onClick={() => p.rotateNow(rule.id)}>\n {t('rotNext')}\n </button>\n <span className=\"dab-hint\" style={{ padding: 0 }}>\n {/* \"On screen\" rather than \"image N\": the row above\n already reads \"image N\" for the image being EDITED,\n and two numbers under the same wording would be the\n one place this panel could mislead. */}\n {active ? `${t('rotShowing')} ${rule.images.length === 0 ? 0 : Math.min(liveIndex + 1, rule.images.length)} / ${rule.images.length}` : t('rotNextInactive')}\n </span>\n </div>\n </div>\n ) : null}\n </div>\n\n <div style={{ marginTop: 14 }}>\n <div className=\"dab-rule-section-title\">{t('ruleLayout')}</div>\n <div className=\"dab-chip-row\">\n {BG_MODES.map(m => (\n <button key={m.mode} type=\"button\"\n className={`dab-chip${rule.bgMode === m.mode ? ' is-active' : ''}`}\n onClick={() => p.setRule(rule.id, { bgMode: m.mode })}>\n {t(m.key)}\n </button>\n ))}\n {/* The framing editor sits at the END of this row, not among the\n modes: it is not a sixth mode, and dropping it between two\n chips would read as one (the modes are mutually exclusive,\n this is an action). It belongs here rather than next to the\n upload buttons because what it edits is how the picture fills\n the area — the row it now shares with 适应/填充/…. It stays\n conditional on `fit`: dragging the framing is what \"适应\"\n means, and the other four modes have nothing to drag. */}\n {url !== null && rule.bgMode === 'fit' ? (\n <button type=\"button\" className=\"dab-btn\" onClick={() => setEditorOpen(true)}>\n <EditIcon size={13} />{t('ruleFramingEdit')}\n </button>\n ) : null}\n </div>\n </div>\n </div>\n\n {/* ── color + wallpaper effects ──────────────────────────────── */}\n <div>\n <div className=\"dab-rule-section-title\">{t('ruleColor')}</div>\n {/* Which of the two things below the controls edit. Since a theme\n color belongs to an image, the same wheel means different things\n depending on the strip, and a section that silently retargets is\n exactly how \"I changed the color and nothing happened\" is born. */}\n <p className=\"dab-hint\" style={{ marginTop: 6 }}>\n {image === undefined\n ? t('ruleColorTargetRule')\n : `${t('ruleColorTargetImage')} ${selIdx + 1} / ${rule.images.length}`}\n </p>\n {ownColor === null ? (\n <>\n <div className=\"dab-chip-row\">\n {/* This button LEAVES the system-theme state, so it says so:\n the \"系统主题\" label belongs to the clearing button below. */}\n <button type=\"button\" className=\"dab-btn\" disabled={extracting} onClick={() => void onPickColor()}>\n <DropletIcon size={14} />{extracting ? t('extracting') : t('ruleColorPick')}\n </button>\n <button type=\"button\" className=\"dab-btn\" disabled={url === null || extracting} onClick={() => void onExtract()}>\n <SparkleIcon size={14} />{extracting ? t('extracting') : t('ruleColorExtract')}\n </button>\n </div>\n <p className=\"dab-hint\" style={{ marginTop: 8 }}>{t('ruleColorNoneHint')}</p>\n {/* The extraction promise belongs to a target that HAS bytes:\n next to a disabled \"extract\" button it read as a broken\n feature, not as a hint — and for a rule with no image at all\n the honest sentence is a different one (it has nothing to\n take a color from, but a color of its own is still enough to\n paint the interface). */}\n {url !== null\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('ruleColorPickHint')}</p>\n : image === undefined\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('ruleColorNoImageHint')}</p>\n : <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('ruleColorPendingImageHint')}</p>}\n </>\n ) : (\n <>\n <div style={{ display: 'flex', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>\n <ColorWheel hue={wheel[0]} sat={wheel[1]} lit={wheel[2]} onChange={onColor} />\n {/* No hex caption above the toggle any more: the preview\n field inside ColorInputs prints that same value on the\n color itself, where it also explains what the field is. */}\n <div className=\"dab-inputs\">\n <ColorInputs hue={wheel[0]} sat={wheel[1]} lit={wheel[2]} onChange={onColor} />\n </div>\n </div>\n <div className=\"dab-chip-row\" style={{ marginTop: 12 }}>\n <button type=\"button\" className=\"dab-btn\" disabled={url === null || extracting} onClick={() => void onExtract()}>\n <SparkleIcon size={13} />{extracting ? t('extracting') : t('ruleColorExtract')}\n </button>\n <button type=\"button\" className=\"dab-btn\" disabled={url === null} onClick={() => setPickerOpen(true)}>\n <PipetteIcon size={13} />{t('eyedropper')}\n </button>\n {/* Clears THIS image's color and hands the interface back to\n the host palette for as long as that image is on screen —\n the rule's own color (if it has one) is untouched, because\n it is not this image's fallback. Carries the sun because\n that is the host's own appearance glyph, and reads as the\n action it performs rather than the state it lands in — as a\n bare \"系统主题\" it looked like the label of whatever control\n sat beside it. */}\n <button type=\"button\" className=\"dab-btn dab-btn-ghost\" onClick={() => setColor(null)}>\n <SunIcon size={13} />{t('ruleColorNone')}\n </button>\n </div>\n <div className=\"dab-swatches\" style={{ marginTop: 12 }}>\n {PALETTE.map(([sh, ss, sl], i) => (\n <button\n key={i} type=\"button\" className=\"dab-swatch\"\n style={{ background: `hsl(${sh} ${Math.round(ss * 100)}% ${Math.round(sl * 100)}%)` }}\n title={toHex(hslToRgb(sh, ss, sl)).toUpperCase()}\n onClick={() => setColor([sh, ss, sl])} />\n ))}\n </div>\n </>\n )}\n\n <div style={{ marginTop: 16 }}>\n <LiveSlider\n label={t('ruleOpacity')} min={0} max={100} step={1}\n def={Math.round(rule.wallpaperOpacity * 100)} fmt={v => `${v}%`}\n onChange={v => p.setRule(rule.id, { wallpaperOpacity: v / 100 })} />\n <LiveSlider\n label={t('ruleBlur')} min={0} max={60} step={1}\n def={rule.blur} fmt={v => `${v}px`}\n onChange={v => p.setRule(rule.id, { blur: v })} />\n <p className=\"dab-hint\" style={{ marginTop: 10 }}>{t('ruleBlurHint')}</p>\n </div>\n </div>\n </div>\n </div>\n ) : null}\n\n {/* `multiple` because a rotation is built by picking a handful of pictures\n at once; the strip's drop zone and the URL box take batches too. A\n replacement only ever takes the first file — see onFiles. */}\n <input ref={fileRef} type=\"file\" accept=\"image/*\" multiple style={{ display: 'none' }} onChange={e => {\n const files = Array.from(e.target.files ?? [])\n if (files.length === 0) return\n onFiles(files)\n e.target.value = ''\n setReplace(false)\n }} />\n\n {editorOpen && url !== null && image !== undefined ? (\n <BgEditor\n url={url} state={image.bgState} t={t} onClose={() => setEditorOpen(false)}\n onCommit={(z, x, y, iw, ih) => {\n // Framing belongs to the IMAGE, so the commit is addressed by slot:\n // editing image 3's crop must not rewrite image 1's.\n p.setImageFraming(rule.id, image.slot, { zoom: z, x, y, iw, ih })\n setEditorOpen(false)\n }} />\n ) : null}\n\n {pickerOpen && url !== null ? (\n <ColorPicker url={url} t={t} onClose={() => setPickerOpen(false)}\n onPick={hsv => { onColor(hsv[0], hsv[1], hsv[2]); setPickerOpen(false) }} />\n ) : null}\n </section>\n )\n}\n","import { useRef } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { ThemeSectionProps, ThemeStoreState } from '../../types'\nimport { cfg } from '../../state'\nimport { DownloadIcon, UploadIcon } from '../icons'\n\nexport function ProfilePage({ p, notify }: { p: ThemeSectionProps; notify: (msg: string, ok?: boolean) => void }) {\n const { t, exportTheme, importTheme } = p\n const importRef = useRef<HTMLInputElement>(null)\n\n // The section shell renders this page as a plain child and does not subscribe\n // to the store, so the subscription has to live HERE — without it the holiday\n // switch would not repaint itself.\n p.useStore((s: ThemeStoreState) => s.rev + s.rulesRev)\n const holidays = cfg.holidays\n\n const onImport = async (file: File) => {\n try {\n const ok = await importTheme(file)\n notify(ok ? t('importDone') : t('importFail'), ok)\n } catch {\n notify(t('importFail'), false)\n }\n }\n\n return (\n <>\n <header className=\"dab-head dab-rise\" style={{ '--d': 0 } as CSSProperties}>\n <div className=\"dab-overline\">Profile</div>\n <h2 className=\"dab-h1\">{t('pageProfile')}</h2>\n <p className=\"dab-desc\">{t('descProfile')}</p>\n </header>\n\n {/* The whole holiday override is one switch. There is deliberately no card\n per holiday, no thumbnail and no image picker: the feature is a small\n easter egg, and the panels that used to live here made it look like\n something the user is expected to configure — art included. The\n wallpapers ship in the package and are not swappable at all.\n\n Nor is there a line under the switch explaining it. The label carries\n the meaning, and the control's tooltip carries the windows; a\n paragraph here only made a one-switch feature read as a settings\n block. Do not add one back. */}\n <section className=\"dab-card dab-rise\" style={{ '--d': 1 } as CSSProperties}>\n <div className=\"dab-chip-row\" style={{ alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${holidays.enabled ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={holidays.enabled} title={t('holidayEnable')}\n onClick={() => p.setHolidaysEnabled(!holidays.enabled)}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-holiday-label\">{t('holidayTitle')}</span>\n </div>\n </section>\n\n <div className=\"dab-profile-grid dab-rise\" style={{ '--d': 2 } as CSSProperties}>\n <section className=\"dab-card dab-card-hover\">\n <div className=\"dab-profile-ico\"><DownloadIcon size={17} /></div>\n <div className=\"dab-profile-title\">{t('exportCardTitle')}</div>\n <div className=\"dab-profile-desc\">{t('exportCardDesc')}</div>\n <button type=\"button\" className=\"dab-btn dab-btn-primary\" onClick={() => { exportTheme(); notify(t('toastExportDone')) }}>\n <DownloadIcon size={14} />{t('exportTheme')}\n </button>\n </section>\n\n <section className=\"dab-card dab-card-hover\">\n <div className=\"dab-profile-ico\"><UploadIcon size={17} /></div>\n <div className=\"dab-profile-title\">{t('importCardTitle')}</div>\n <div className=\"dab-profile-desc\">{t('importCardDesc')}</div>\n <button type=\"button\" className=\"dab-btn\" onClick={() => importRef.current?.click()}>\n <UploadIcon size={14} />{t('importTheme')}\n </button>\n <input ref={importRef} type=\"file\" accept=\"application/json,.json\" style={{ display: 'none' }} onChange={e => {\n const f = e.target.files?.[0]; if (!f) return\n void onImport(f); e.target.value = ''\n }} />\n </section>\n </div>\n\n <footer className=\"dab-footer dab-rise\" style={{ '--d': 3 } as CSSProperties}>\n <span className=\"dab-footer-mono\">dsh-background-by-model</span>\n <span>{t('footerTag')}</span>\n </footer>\n </>\n )\n}\n","/**\n * dsh-background-by-model — settings section shell.\n *\n * The host renders this section only while the settings dialog is open and the\n * section is the active nav entry, so mounting IS being visible. The section is\n * rendered INLINE inside the host settings dialog's content column (the host\n * provides the modal chrome); the shell is a left nav rail + page body. Only\n * the transient toast escapes through a Portal (the shell's container-type\n * containment would otherwise capture its fixed positioning).\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { ThemeSectionProps } from '../types'\nimport { ensureUiCss, NAV_ITEM_H, NAV_GAP } from './ui.css'\nimport { SunIcon, LayersIcon, PhotoIcon, SlidersIcon, AlertIcon, CheckIcon } from './icons'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport { Portal } from './Portal'\nimport { InterfacePage } from './pages/InterfacePage'\nimport { ModelBgPage } from './pages/ModelBgPage'\nimport { ProfilePage } from './pages/ProfilePage'\n\nexport function ThemeSection(props: ThemeSectionProps) {\n ensureUiCss()\n const { t } = props\n const [page, setPage] = useState(0)\n const [toast, setToast] = useState<{ msg: string; ok: boolean } | null>(null)\n const toastTimer = useRef<number | undefined>(undefined)\n\n useEffect(() => () => window.clearTimeout(toastTimer.current), [])\n\n const notify = (msg: string, ok = true): void => {\n setToast({ msg, ok })\n window.clearTimeout(toastTimer.current)\n toastTimer.current = window.setTimeout(() => setToast(null), 2600)\n }\n\n const pages = [\n { label: t('pageInterface'), Icon: LayersIcon, node: <InterfacePage p={props} /> },\n { label: t('pageModelBg'), Icon: PhotoIcon, node: <ModelBgPage p={props} notify={notify} /> },\n { label: t('pageProfile'), Icon: SlidersIcon, node: <ProfilePage p={props} notify={notify} /> },\n ]\n\n return (\n <ErrorBoundary t={t}>\n <div className=\"dab-root\">\n <div className=\"dab-shell\">\n <nav className=\"dab-nav\">\n <div className=\"dab-brand\">\n <div className=\"dab-brand-tile\"><SunIcon size={15} /></div>\n <div>\n <div className=\"dab-brand-name\">{t('nav')}</div>\n <div className=\"dab-brand-tag\">{t('brandTag')}</div>\n </div>\n </div>\n <div className=\"dab-nav-list\">\n <div className=\"dab-nav-ind\" style={{ transform: `translateY(${page * (NAV_ITEM_H + NAV_GAP)}px)` }} />\n {pages.map((pg, i) => (\n <button\n key={pg.label} type=\"button\"\n className={`dab-nav-item${i === page ? ' is-active' : ''}`}\n onClick={() => setPage(i)}>\n <pg.Icon size={16} />\n <span>{pg.label}</span>\n </button>\n ))}\n </div>\n </nav>\n\n <div className=\"dab-page\" key={page}>\n {pages[page].node}\n </div>\n </div>\n </div>\n\n {toast ? (\n <Portal>\n <div className=\"dab-toast\" role=\"status\">\n <span className={toast.ok ? 'dab-toast-ok' : 'dab-toast-err'}>\n {toast.ok ? <CheckIcon size={14} /> : <AlertIcon size={14} />}\n </span>\n <span>{toast.msg}</span>\n </div>\n </Portal>\n ) : null}\n </ErrorBoundary>\n )\n}\n","/**\n * dsh-background-by-model — browser half entry.\n *\n * Wires the plugin lifecycle: rule resolution against the current model,\n * wallpaper layer, theme skin, viewport watch, i18n, settings-section injection,\n * boot restore and watchdogs. The heavy lifting lives in the sibling modules\n * (state / modelbg / rpc / wallpaper / components).\n */\nimport { defineStore } from './runtime'\nimport type {\n Ctx, RpcResultLike, ThemeSectionProps, PartOpacities, PartBlurs, BgImage, BgRule, BgState, HolidayRule,\n FetchResult, ModelFacts,\n} from './types'\nimport { NS, zh, en } from './i18n'\nimport {\n cfg, adoptConfig, imageOf, displayImageOf, setImage, newRule, nextSlot, nextRuleId, ruleById,\n holidayById, normalizeRuleInPlace, patchRotation, ruleSlots, setActive, setModelLabel,\n activeRule, activeColor, activeRuleId, activeMatched, modelLabel, imageIndexOf, setRotIndex, takenSlots,\n rWp, rRightbarOpacity, DEFAULT_BG_STATE,\n} from './state'\nimport { activeHoliday, pickHoliday } from '../holiday'\nimport { nextIndex, isRotating } from './rotation'\nimport { shouldRepaint } from './repaint'\nimport {\n RPC_CHANNEL, initRpc, saveConfig, flushSave, persistConfig, loadPersisted,\n readImage, writeImage, deleteImage, fetchImageUrl, readDefaultModel, hostIsLegacy,\n} from './rpc'\nimport {\n applyWp, teardownWp, applySettingsOverrides, applyRightbarOverrides, SETTINGS_STYLE_RULE, TRAJECTORY_STYLE_RULE,\n RIGHTBAR_STYLE_RULE, INPUT_BLUR_RULE, PLACEHOLDER_RULE, OWN_SCHEME, setHostScheme, refreshSystemTheme,\n watchParts, watchThemeResets,\n} from './wallpaper'\nimport { genTokens, extractWallpaperColor } from './utils/color'\nimport { matchRule, watchModel } from './modelbg'\nimport { ThemeSection } from './components/ThemeSection'\nimport { markOwnSheet } from './components/ui.css'\nimport { SUN_PATHS } from './components/icons'\n\nexport const name = 'dsh-background-by-model'\nexport const inject = ['slots', 'locale', 'theme', 'connection']\n\nconst CUSTOM_ID = 'custom-color'\n\nexport function apply(ctx: Ctx): void {\n // Bind the dedicated `/dsh-background-by-model` RPC caller so the persistence\n // module can reach the node half's file-backed store.\n initRpc((endpoint, payload) =>\n ctx.connection.rpc.call(RPC_CHANNEL, endpoint, payload).then((res: any) => res as RpcResultLike | undefined)\n )\n\n // ── 1. Custom theme skin, driven by the ACTIVE rule's color ────────────────\n let customDispose: (() => void) | null = null\n // Trailing debounce for the theme-skin switch (see applyActive): a color drag\n // would otherwise dispose + re-register + re-activate the host theme on every\n // pointer move.\n let skinTimer: number | null = null\n const registerCustom = (h: number, s: number, l: number): void => {\n customDispose?.()\n try {\n const { colorScheme, tokens } = genTokens(h, s, l)\n customDispose = ctx.theme.register({ id: CUSTOM_ID, colorScheme, tokens })\n } catch {\n // A live registration from an earlier HMR apply pass cannot be torn down\n // here; keep it and activate it below. Without this the duplicate-id\n // throw would abort apply and skip the wallpaper/opacity restore.\n customDispose = null\n }\n // Only activate the custom theme if it is actually registered.\n if (ctx.theme.getTheme().themes.some(t => t.id === CUSTOM_ID)) {\n ctx.theme.setTheme(CUSTOM_ID)\n }\n }\n /** A rule without a saved color means \"follow the system theme\". */\n const dropCustom = (): void => {\n customDispose?.()\n customDispose = null\n try {\n if (ctx.theme.getTheme().preference === CUSTOM_ID) ctx.theme.setTheme('system')\n } catch {\n // A host build without a `system` preference keeps its own choice.\n }\n }\n\n /**\n * Re-emit the interface palette for whatever is painted RIGHT NOW.\n *\n * Called from two places, and the second one is why this is a function: a\n * model switch (`applyActive`) and a ROTATION STEP (`paintImage`). A theme color\n * belongs to an image since 0.7.1, so stepping to the next picture changes the\n * palette as much as switching models does — and a step that only repainted the\n * wallpaper would leave the previous picture's color on the interface until\n * something else happened to re-run an apply (dragging the wheel, switching\n * models), which is precisely the \"it only updates when I touch the color wheel\"\n * report this plugin already had once.\n *\n * The debounce is for the OTHER caller: a color drag runs a full apply dozens of\n * times per second, and the host-visible skin switch (dispose + register +\n * activate) must not happen on every pointer move. A rotation step pays the same\n * 60 ms, which is invisible next to a dwell time of 5 s or more.\n */\n const applyPalette = (): void => {\n const color = activeColor()\n if (skinTimer !== null) window.clearTimeout(skinTimer)\n if (color === null) {\n // Hand the palette back BEFORE the apply that follows. The theme service's\n // snapshot is what tells the wallpaper layer which scheme the host itself\n // resolves to, and while our custom skin is still active that snapshot\n // reports OUR scheme — the readback would then capture the host's light\n // palette on a dark system and keep painting it (the interface only\n // recovered when some later slider drag happened to re-run an apply).\n // Dropping the skin is idempotent, so it needs none of the debouncing a\n // color drag does.\n skinTimer = null\n dropCustom()\n } else {\n // The skin is a host-visible switch (dispose + register + activate) and is\n // batched; the wallpaper and tokens below land immediately either way.\n skinTimer = window.setTimeout(() => {\n skinTimer = null\n registerCustom(color[0], color[1], color[2])\n }, 60)\n }\n syncHostScheme()\n }\n ctx.effect(() => () => {\n if (skinTimer !== null) window.clearTimeout(skinTimer)\n customDispose?.()\n }, 'dsh-background-by-model: skin dispose')\n\n // ── 2. Gradient CSS (for custom dark themes) + static rules ────────────────\n const styleEl = document.createElement('style')\n styleEl.dataset.plugin = 'dsh-background-by-model'\n markOwnSheet(styleEl)\n // The gradient only applies while applyCustomTokens marks the body with the\n // plugin's own dark-mode value, avoiding matches against the host's attribute.\n styleEl.textContent = `body[data-ds-dark-theme=\"${OWN_SCHEME}\"]::before{content:'';position:fixed;inset:0;z-index:-1;pointer-events:none;background:radial-gradient(ellipse 80% 60% at 50% 0%,rgba(255,255,255,0.03) 0%,transparent 60%)}${SETTINGS_STYLE_RULE}${TRAJECTORY_STYLE_RULE}${RIGHTBAR_STYLE_RULE}${INPUT_BLUR_RULE}` + PLACEHOLDER_RULE\n document.head.appendChild(styleEl)\n ctx.effect(() => () => { styleEl?.parentNode?.removeChild(styleEl) }, 'dsh-background-by-model: gradient')\n\n // ── 3. State store ────────────────────────────────────────────────────────\n let rev = 0\n let rulesRev = 0\n let modelText = ''\n let modelSource: 'session' | 'default' = 'default'\n // Why no per-session model is available yet ('waiting' until the sessions\n // service mounts, then the failing hop, then 'fallback'). Shown by the status\n // readout so a dead hop is never mistaken for a real model.\n let modelNote = 'waiting'\n // Text + source last acted on, so the watch's forced re-emits (and the 1.5 s\n // safety poll) cannot re-run the whole apply while nothing changed.\n let modelKey = '\\u0000'\n const store = defineStore({\n init: () => ({\n url: null as string | null,\n rev: -1,\n rulesRev: -1,\n model: '',\n modelSource: 'session' as 'session' | 'default',\n modelNote: 'waiting',\n activeRuleId: null as string | null,\n matched: false,\n rotIndex: 0,\n rotTotal: 0,\n rotating: false,\n hostStale: false,\n }),\n actions: {\n sync: (d: any, url: string | null, r: number, rr: number, model: string, source: 'session' | 'default', note: string, id: string | null, matched: boolean, rotIndex: number, rotTotal: number, rotating: boolean, hostStale: boolean) => {\n if (r > d.rev) { d.url = url; d.rev = r }\n if (rr > d.rulesRev) d.rulesRev = rr\n d.model = model\n d.modelSource = source\n d.modelNote = note\n d.activeRuleId = id\n d.matched = matched\n d.rotIndex = rotIndex\n d.rotTotal = rotTotal\n d.rotating = rotating\n d.hostStale = hostStale\n },\n },\n })\n let bound: { sync: (...a: any[]) => void } | null = null\n /** Rotation facts of whatever is painted now, for the section's readout. */\n const rotationFacts = (): { index: number; total: number; rotating: boolean } => {\n const rule = activeRule()\n if (rule === null) return { index: 0, total: 0, rotating: false }\n return {\n index: imageIndexOf(rule),\n total: rule.images.length,\n // The badge and the timer read the SAME predicate, so \"rotating\" can never\n // be shown while nothing is scheduled (the failure this feature would\n // otherwise produce silently).\n rotating: isRotating(rule.images.length, rule.rotate.enabled, rule.rotate.intervalMs) && !document.hidden,\n }\n }\n const sync = (): void => {\n rev++\n const rot = rotationFacts()\n bound?.sync(rWp(), rev, rulesRev, modelLabel !== '' ? modelLabel : modelText, modelSource, modelNote, activeRuleId, activeMatched, rot.index, rot.total, rot.rotating, hostIsLegacy())\n }\n\n /**\n * Publish the scheme the host's own preference resolves to. The theme service\n * is the only place that knows it (a custom active theme included); the\n * wallpaper layer needs it to hand `data-ds-dark-theme` back in the host's own\n * form while a color-less rule follows that theme, instead of leaving the flag\n * off — which pins the host to its LIGHT palette on a dark system.\n */\n const syncHostScheme = (): void => {\n try {\n setHostScheme(ctx.theme.getTheme().active.colorScheme === 'dark')\n } catch {\n // A host build without a resolvable snapshot: let the wallpaper layer fall\n // back to the preference the boot script published.\n setHostScheme(null)\n }\n }\n\n /**\n * Which rule wins for the current model RIGHT NOW, and whether it was a\n * substring hit (a holiday override is never a \"match\" of the model).\n *\n * Read by the repaint AND by the panel's write path, which has to know whether\n * an edit changed the answer: `color`, `enabled` and `match` all feed the\n * resolution (a rule with no image still paints from its own color — see\n * `ruleCanPaint`). Without this, editing a rule that was not the active one —\n * giving an emptied rule its first color, typing a match string that should\n * promote it — changed nothing on screen until some unrelated event happened to\n * re-run the resolution.\n */\n const resolveRule = (): { rule: BgRule | null; matched: boolean } => {\n // The holiday override sits ABOVE the rule list: while one is in force the\n // model is irrelevant, which is the whole point of the switch.\n const holiday = activeHolidayRule()\n return holiday !== null\n ? { rule: holiday as BgRule, matched: false }\n : matchRule(cfg.rules, modelText)\n }\n\n /** Id of the rule that would paint right now; `null` = the host's own look. */\n const winnerId = (): string | null => resolveRule().rule?.id ?? null\n\n /**\n * Close a rule edit: repaint when it could have moved what is on screen, and\n * merely refresh the panel's readout when it could not.\n *\n * `winnerBefore` is sampled by the caller BEFORE its mutation (`winnerId()`),\n * and the comparison itself lives in ./repaint, where it is checked on plain\n * node. Every write path below ends here — the old per-path test\n * (`id === activeRuleId`) missed the edit that CREATES the winner, which is the\n * \"上传图片 / 提取主题色之后界面不动,动一下调色盘或切模型才出现\" report.\n */\n const repaintIfMoved = (id: string, winnerBefore: string | null): void => {\n if (shouldRepaint(id, winnerBefore, winnerId())) applyActive()\n else sync()\n }\n\n /**\n * Resolve the active rule for the current model and repaint everything.\n *\n * @param advance - true only on a MODEL switch: the rotation of the rule that\n * took over may then step once (`rotate.advanceOnSwitch`), which is how a\n * model gets \"a different picture every time\" without any timer at all.\n */\n const applyActive = (advance = false): void => {\n const { rule, matched } = resolveRule()\n // Set BEFORE the index is read: `setActive` resets the image index whenever\n // the rule itself changes, so a switch onto a fresh rule starts at its first\n // image (and `advanceOnSwitch` then steps off it — see below).\n setActive(rule === null ? null : rule.id, matched)\n if (advance && rule !== null && rule.rotate.advanceOnSwitch) {\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n if (next !== null) setRotIndex(next)\n }\n scheduleRotation()\n // AFTER the index moved: the palette belongs to the image that is on screen,\n // and `advanceOnSwitch` above may have just changed which one that is.\n applyPalette()\n applyWp()\n sync()\n }\n\n // ── 3a. Multi-image rotation ──────────────────────────────────────────────\n // ONE interval for the whole plugin, always aimed at the ACTIVE rule. A timer\n // per rule would burn wakeups on rules that are not painting anything, and\n // since only one rule's images can be on screen at a time, one timer is all\n // that is needed.\n //\n // `loadSlot` below (section 6) is only CALLED from here, never during this\n // synchronous apply, so the order of these two declarations does not matter.\n let rotTimer: number | null = null\n /** Identity of the schedule currently armed; a change means \"re-arm\". */\n let rotSig = ''\n\n /** Warm one image so a later switch fades toward bytes that are already here. */\n const warmImage = (rule: BgRule, idx: number): void => {\n const slot = rule.images[idx]?.slot\n if (slot !== undefined) void loadSlot(slot)\n }\n\n /** Show the image at `idx` at once, loading it first when it is not in memory. */\n const paintImage = (rule: BgRule, idx: number): void => {\n const slot = rule.images[idx]?.slot\n if (slot === undefined) return\n // The palette first, and always: this image may carry a theme color of its\n // own, and it becomes the one in force the moment the index moves (see\n // `applyPalette`). `setRotIndex` has already run in every caller.\n applyPalette()\n if (imageOf(slot) !== null) { applyWp(); sync(); return }\n // A cold image cannot be cross-faded toward — the outgoing layer would fade\n // to an empty one and the interface would show through for a frame — so the\n // paint happens after the bytes land. Reading the slot over this channel costs\n // one local round trip, which is the price of not shipping every image of\n // every rule at boot.\n void loadSlot(slot).then(() => { applyWp(); sync() })\n }\n\n const rotateTick = (): void => {\n const rule = activeRule()\n if (rule === null) return\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n // Nothing to step to (the list shrank to a single image under us): stop\n // rather than leave a timer firing forever at a rule with one picture.\n if (next === null) { scheduleRotation(true); return }\n setRotIndex(next)\n paintImage(rule, next)\n // Warm the image AFTER the one just shown, so the next tick has decoded bytes\n // to fade toward instead of paying a read at the moment of the switch.\n const after = nextIndex(rule.images.length, rule.rotate.order, next)\n if (after !== null) warmImage(rule, after)\n }\n\n /**\n * Arm (or re-arm) the rotation for the active rule.\n *\n * Idempotent by SIGNATURE rather than by \"already armed\": a slider drag on the\n * active rule re-runs the whole apply dozens of times per second, and restarting\n * the interval on each of those would mean the dwell timer never elapses while\n * the user is dragging (and a 10 s rotation would never advance). The signature\n * carries exactly the inputs the schedule depends on, so a real change — another\n * rule, another interval, the tab becoming visible again — re-arms while a\n * repaint does not.\n */\n const scheduleRotation = (force = false): void => {\n const rule = activeRule()\n // `activeRule()` also answers with a holiday entry, whose images are the\n // package's single picture; `isRotating` turns that into \"no schedule\".\n const sig = rule === null\n ? ''\n : [rule.id, rule.rotate.enabled, rule.rotate.intervalMs, rule.rotate.order, rule.images.length, document.hidden].join('|')\n if (!force && sig === rotSig) return\n rotSig = sig\n if (rotTimer !== null) { window.clearInterval(rotTimer); rotTimer = null }\n if (rule === null || document.hidden) return\n if (!isRotating(rule.images.length, rule.rotate.enabled, rule.rotate.intervalMs)) return\n // Warm the first image this schedule will ask for, so the very first tick is\n // not the one that has to pay for the read.\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n if (next !== null) warmImage(rule, next)\n rotTimer = window.setInterval(rotateTick, rule.rotate.intervalMs)\n }\n ctx.effect(() => () => {\n if (rotTimer !== null) { window.clearInterval(rotTimer); rotTimer = null }\n }, 'dsh-background-by-model: rotation timer')\n // A hidden tab has nothing to paint, so the rotation stops with the pixels and\n // resumes on a fresh interval: coming back to a background that changed three\n // times while nobody was looking is not what \"every 30 seconds\" means to anyone\n // watching it. `sync()` is what moves the \"rotating\" readout with it — the\n // section cannot be seen while the tab is hidden, but the badge must be right the\n // moment it is shown again.\n const onVisibility = (): void => { scheduleRotation(); sync() }\n document.addEventListener('visibilitychange', onVisibility)\n ctx.effect(() => () => document.removeEventListener('visibilitychange', onVisibility), 'dsh-background-by-model: rotation visibility')\n\n /**\n * The holiday the background must follow right now, or null.\n *\n * The decision itself is `pickHoliday` (pure, and covered by\n * `scripts/holiday-check.ts`); this only supplies the two things it cannot\n * know — today's holiday from the calendar, and whether the slot has bytes.\n */\n const activeHolidayRule = (): HolidayRule | null =>\n pickHoliday(cfg.holidays.enabled, cfg.holidays.items, activeHoliday(), slot => imageOf(slot) !== null)\n\n // ── 3b. Holiday theme color ───────────────────────────────────────────────\n // There is nothing to compute: a holiday's color is a fixed part of its\n // definition (see `HOLIDAYS`), forced on every read by ./schema. The extractor\n // that used to run here decoded a full-size festival photo to re-derive a hue\n // that was always going to be the same one.\n\n // ── 4. First paint + the AppFrame watch ───────────────────────────────────\n syncHostScheme()\n applyWp()\n sync()\n watchParts()\n\n // ── 5. Model watch ────────────────────────────────────────────────────────\n // The session's own durable model selection is the authority; the host default\n // is only a last resort, and the settings page labels it as such.\n const offModel = watchModel(ctx, (text, label, source, note) => {\n const key = `${text}\\u0001${source}\\u0001${note}`\n if (key === modelKey) return\n const textChanged = text !== modelText\n modelKey = key\n modelText = text\n modelSource = source\n modelNote = note\n setModelLabel(label !== '' ? label : text)\n // A note-only change (e.g. still waiting for the sessions service) must\n // refresh the readout without repainting the whole interface.\n if (textChanged) applyActive(true)\n else sync()\n })\n ctx.effect(() => () => offModel(), 'dsh-background-by-model: model watch')\n // A trimmed client (or one whose session is not materialized yet) leaves the\n // per-session sources empty; the host's default model is a coarse but honest\n // stand-in, tagged so the UI never claims it is this session's selection.\n void (async () => {\n if (modelText !== '') return\n const fallback = await readDefaultModel()\n if (fallback !== null && modelText === '') {\n modelKey = `${fallback}\\u0001default\\u0001fallback`\n modelText = fallback\n modelSource = 'default'\n modelNote = 'fallback'\n setModelLabel(fallback)\n applyActive()\n }\n })()\n\n // ── 5b. Holiday rollover ──────────────────────────────────────────────────\n // The holiday answer only changes at Beijing midnight — a switch flip calls\n // applyActive directly — so this is a slow tick that does nothing at all until\n // the day key actually moves. 30 s is plenty for a boundary that is a whole day\n // wide, and it costs one `Intl` format per tick.\n //\n // `todayHolidaySlot` / `loadSlot` are declared below, in section 6; both are\n // initialized during this same synchronous apply, long before any tick fires.\n let holidayKey = activeHoliday() ?? ''\n const holidayTimer = window.setInterval(() => {\n const next = activeHoliday() ?? ''\n if (next === holidayKey) return\n holidayKey = next\n // Midnight can land ON a holiday, and that holiday's art was deliberately\n // not fetched at boot (it was not that day yet) — fetch it, then repaint.\n const slot = todayHolidaySlot()\n if (slot === null) applyActive()\n else void loadSlot(slot).then(() => applyActive())\n }, 30_000)\n ctx.effect(() => () => { window.clearInterval(holidayTimer) }, 'dsh-background-by-model: holiday rollover')\n\n // ── 6. Boot restore ───────────────────────────────────────────────────────\n /** Read one slot's bytes into the cache unless they are already there. */\n const loadSlot = async (slot: string): Promise<void> => {\n if (imageOf(slot) !== null) return\n const url = await readImage(slot)\n if (url !== null) setImage(slot, url)\n }\n /**\n * The slot of the holiday that could paint TODAY, or null.\n *\n * Gated on the CALENDAR, not merely on the switch. Now that the override is on\n * by default and invisible, a profile that simply is not on a holiday must not\n * pull ~730 KB of bundled art (≈970 KB of base64 over this channel) at every\n * boot just because the feature is armed.\n */\n const todayHolidaySlot = (): string | null => {\n if (!cfg.holidays.enabled) return null\n const id = activeHoliday()\n if (id === null) return null\n const item = holidayById(id)\n if (item === null || !item.enabled) return null\n return ruleSlots(item)[0] ?? null\n }\n /**\n * The slots boot hydrates, in no particular order: the FIRST image of every\n * rule, today's holiday, and the image the current model paints.\n *\n * That first-image set is exactly what this plugin loaded per rule before\n * multi-image existed — a rule card draws its first image as its thumbnail, so\n * the settings page looks the same as it always did. Everything past the first\n * image of a rule is read ON DEMAND: by the rotation (which warms the image it\n * is about to need as soon as its schedule is armed) and by the settings page\n * when a card is expanded. Hydrating every image of every rule here would mean\n * twenty full-size data URLs over this channel before the first frame on a\n * five-rule setup with four pictures each, which is the one cost this feature\n * must not pay.\n *\n * The slot list the store knows about (`readPersisted().slots`) is deliberately\n * NOT hydrated any more: an orphaned slot that no rule references has no card to\n * appear on, so pulling its bytes over the channel at boot is pure waste. It\n * stays on disk — and is still reported by the node half — until a rule\n * references it again or it is deleted with its rule.\n */\n const bootSlots = (): string[] => {\n const holiday = todayHolidaySlot()\n const firsts = cfg.rules\n .map(r => r.images[0]?.slot)\n .filter((slot): slot is string => slot !== undefined)\n const current = prioritySlot()\n return Array.from(new Set([\n ...firsts,\n ...(holiday === null ? [] : [holiday]),\n ...(current === null ? [] : [current]),\n ]))\n }\n /**\n * The slot that paints before anything else: the holiday in force when there\n * is one, otherwise the FIRST image of the current model's rule. A holiday\n * outranks the rule here for the same reason it outranks it when painting.\n *\n * Always the first image (never the one `advanceOnSwitch` would step to): boot\n * paints without an advance, and hydrating an image the first frame is not going\n * to use would leave the frame blank until the real one arrived.\n */\n const prioritySlot = (): string | null =>\n todayHolidaySlot() ?? matchRule(cfg.rules, modelText).rule?.images[0]?.slot ?? null\n void (async () => {\n const persisted = await loadPersisted()\n if (persisted !== null) {\n adoptConfig(persisted.config)\n const first = prioritySlot()\n // The active rule's bytes paint first; the remaining slots stream in after\n // so a large multi-rule setup never delays the first frame.\n const slots = bootSlots()\n const order = first === null ? slots : [first, ...slots.filter(s => s !== first)]\n for (const slot of order) {\n await loadSlot(slot)\n if (slot === first) applyActive()\n }\n }\n applyActive()\n })()\n\n ctx.effect(() => () => { teardownWp() }, 'dsh-background-by-model: wp cleanup')\n\n ctx.effect(() => ctx.on('theme/change', () => {\n // The custom theme's preference lives in memory, so a host adoption can\n // silently reset it; re-assert it while the active rule has a color. Guard\n // on registry presence — registerCustom disposes the old skin first, so\n // during that transient the registry lacks CUSTOM_ID.\n // The resolved scheme is read first: an OS flip while the preference is\n // `system` arrives exactly here, and a color-less rule has to follow it.\n syncHostScheme()\n if (activeColor() !== null) {\n const snapshot = ctx.theme.getTheme()\n if (snapshot.preference !== CUSTOM_ID && snapshot.themes.some(t => t.id === CUSTOM_ID)) {\n ctx.theme.setTheme(CUSTOM_ID)\n }\n }\n applyWp()\n }), 'dsh-background-by-model: theme change')\n\n // Wallpaper placement is computed in absolute viewport pixels, so watch the\n // viewport itself: a fixed inset:0 sentinel's box always equals the viewport,\n // so a ResizeObserver on it catches any viewport change (window resize,\n // monitor moves, panel splitters, zoom); a resolution media query catches\n // DPI-only moves. Re-applies are coalesced to one per animation frame.\n let frame = 0\n const applySoon = (): void => {\n if (frame !== 0) return\n frame = requestAnimationFrame(() => { frame = 0; applyWp() })\n }\n const sentinel = document.createElement('div')\n sentinel.style.cssText = 'position:fixed;inset:0;pointer-events:none;visibility:hidden'\n document.body.append(sentinel)\n const viewportObserver = new ResizeObserver(applySoon)\n viewportObserver.observe(sentinel)\n const dprQuery = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)\n dprQuery.addEventListener('change', applySoon)\n ctx.effect(() => () => {\n viewportObserver.disconnect()\n dprQuery.removeEventListener('change', applySoon)\n sentinel.remove()\n }, 'dsh-background-by-model: viewport watch')\n\n // ── 7. Locale ─────────────────────────────────────────────────────────────\n ctx.effect(() => ctx.locale.register(NS, { zh, en }) as any, 'dsh-background-by-model: i18n')\n\n /**\n * The automatic half of \"extract from image\": fill an IMAGE's theme color from\n * its own bytes when it has none of its own, and only then — a color the user\n * picked (or a previous extraction produced) is never overwritten, so this\n * cannot fight a deliberate choice.\n *\n * `slot` names the image that just arrived, because a rule's images each carry\n * their own palette since 0.7.1 and the one the user just added is the one they\n * are looking at. Omitted (or unknown) falls back to the rule's first image.\n *\n * The question is asked of the IMAGE, not of the rule: a rule whose pictures\n * were all cleared and then re-filled must theme each new picture, and a rule\n * with a color of its own still has no say over the colors of its pictures.\n *\n * The decode is asynchronous, so the \"still empty?\" question is asked AGAIN on\n * arrival: a color chosen while it ran must win over the one being computed.\n */\n const maybeAutoExtract = async (id: string, slot?: string): Promise<void> => {\n if (!cfg.autoExtract) return\n /** The entry this extraction is about, re-resolved on every read. */\n const target = (rule: BgRule | null): BgImage | undefined => {\n if (rule === null) return undefined\n return (slot === undefined ? undefined : rule.images.find(i => i.slot === slot)) ?? rule.images[0]\n }\n const image = target(ruleById(id))\n if (image === undefined || image.color !== null) return\n const url = displayImageOf(image.slot)\n if (url === null) return\n let hsl: [number, number, number] | null = null\n try { hsl = await extractWallpaperColor(url, image.bgState) } catch { hsl = null }\n if (hsl === null) return\n const current = target(ruleById(id))\n if (current === undefined || current.color !== null) return\n // Same as `extractColor`: this color can be the one that makes the rule\n // paintable, and it arrives AFTER the upload's own repaint — so the winner is\n // sampled here, on arrival, and the interface follows at once.\n const winner = winnerId()\n current.color = hsl\n rulesRev++\n saveConfig()\n repaintIfMoved(id, winner)\n }\n\n /**\n * The batch form, for one upload that carried several pictures.\n *\n * EVERY picture that arrived is themed from its own bytes, the first ones\n * included. The single-slot reading of an upload (\"the last image added is the\n * one being looked at\") is true of the CARD's selection and false of the\n * palette: since a theme color belongs to an image, a batch that themed only\n * its last file left the rest of a fresh rotation on the system theme, with\n * nothing in the interface to say why.\n *\n * Sequential on purpose: a batch is a handful of full-size photos, and ten\n * parallel decodes buy nothing the user can see, while landing the colors in\n * list order does (the card fills in from its first picture).\n */\n const maybeAutoExtractEach = async (id: string, slots: readonly string[]): Promise<void> => {\n for (const slot of slots) await maybeAutoExtract(id, slot)\n }\n\n // ── 8. Section injection ──────────────────────────────────────────────────\n // The section's props are built ONCE by the slot host, so anything that changes\n // at runtime rides the store; the two exceptions are the context (needed by the\n // host self-check probe) and the language (read at build time, refreshed when\n // the section is rebuilt).\n const activeLang = (): 'zh' | 'en' => {\n try {\n const snapshot = ctx.locale.getSnapshot()\n return typeof snapshot?.active === 'string' && snapshot.active.toLowerCase().startsWith('zh') ? 'zh' : 'en'\n } catch {\n return 'en'\n }\n }\n /** The model-resolution facts the host self-check reports, read on demand. */\n const readModelFacts = (): ModelFacts => {\n const rule = activeRuleId === null ? null : ruleById(activeRuleId)\n return {\n text: modelText,\n source: modelSource,\n note: modelNote,\n rule: rule === null ? '' : (rule.match !== '' ? rule.match : rule.id),\n matched: activeMatched,\n }\n }\n const sectionInject = (actions: { sync: (...a: any[]) => void }): Omit<ThemeSectionProps, 'useStore'> => {\n bound = actions\n sync()\n return {\n t: ctx.locale.bind(NS),\n ctx,\n lang: activeLang(),\n readModelFacts,\n imageOf: (slot: string) => displayImageOf(slot),\n addRule: (): string => {\n // No slot is allocated here: a new rule holds no image, so the first free\n // slot is taken when the first picture arrives (see newRule).\n const rule = newRule(nextRuleId())\n cfg.rules.push(rule)\n rulesRev++\n persistConfig()\n applyActive()\n return rule.id\n },\n removeRule: (id: string): void => {\n const idx = cfg.rules.findIndex(r => r.id === id)\n if (idx < 0) return\n const [rule] = cfg.rules.splice(idx, 1)\n if (rule !== undefined) {\n // A slot is released only when NOTHING else points at it — another rule\n // (its own images included, hence the re-scan after the splice) or a\n // holiday entry. Multi-image made this a per-slot question instead of a\n // whole-rule one, and a wrong answer here deletes a picture another\n // card is still showing.\n const stillUsed = takenSlots()\n for (const slot of ruleSlots(rule)) {\n if (stillUsed.has(slot)) continue\n setImage(slot, null)\n void deleteImage(slot)\n }\n }\n rulesRev++\n persistConfig()\n applyActive()\n },\n moveRule: (id: string, dir: -1 | 1): void => {\n const idx = cfg.rules.findIndex(r => r.id === id)\n const to = idx + dir\n if (idx < 0 || to < 0 || to >= cfg.rules.length) return\n const [rule] = cfg.rules.splice(idx, 1)\n cfg.rules.splice(to, 0, rule!)\n rulesRev++\n persistConfig()\n applyActive()\n },\n setRule: (id: string, patch: Partial<BgRule>): void => {\n const rule = ruleById(id)\n if (rule === null) return\n // Text/color/match/slider edits all arrive here, and all of them can move\n // the resolution (see `shouldRepaint`), so the winner is sampled first.\n const winner = winnerId()\n Object.assign(rule, patch)\n // The shared sanitizer, so a live edit can never hold a value the next\n // load would clamp differently (see ./schema).\n normalizeRuleInPlace(rule)\n rulesRev++\n // Text/color/slider edits arrive per keystroke and per pointer move, so\n // the write is coalesced; structural edits below stay immediate.\n saveConfig()\n repaintIfMoved(id, winner)\n },\n addRuleImages: (id: string, dataUrls: readonly string[]): void => {\n const rule = ruleById(id)\n if (rule === null || dataUrls.length === 0) return\n // This is the edit that most often CREATES the winner: a rule that just\n // came out of \"+ 新增规则\" has no picture, so it is not the active rule —\n // and the picture it is being given now is exactly what makes it one.\n const winner = winnerId()\n /** Slots of THIS batch, in list order — the extraction below is per slot. */\n const added: string[] = []\n for (const dataUrl of dataUrls) {\n const slot = nextSlot()\n // `color: null` (not absent): this image has no color of its own YET, and\n // the auto-extraction below is what fills it. An absent key would mean\n // \"written before 0.7.1\" instead, and would be lifted from the rule's color\n // on the next read — which is the opposite of what a new picture wants.\n const image = { slot, bgState: { ...DEFAULT_BG_STATE }, color: null }\n rule.images.push(image)\n added.push(slot)\n setImage(slot, dataUrl)\n // One write per image, immediately: adding a picture is a structural\n // edit, and losing the batch to a page close would leave the config\n // referencing slots the disk never received.\n void writeImage(slot, dataUrl)\n }\n rulesRev++\n persistConfig()\n repaintIfMoved(id, winner)\n // A rule that has never been themed should simply come out themed; an\n // explicit color (or a cleared one the user set on purpose) is left be.\n // Addressed by SLOT and over the whole batch: a rotation is built by\n // picking several files at once and every one of them carries a palette of\n // its own, so the batch is what gets themed — not just the last file, and\n // not just the one the card happens to select.\n void maybeAutoExtractEach(id, added)\n },\n removeRuleImage: (id: string, slot: string): void => {\n const rule = ruleById(id)\n if (rule === null) return\n const idx = rule.images.findIndex(i => i.slot === slot)\n if (idx < 0) return\n // Removing can also move the winner — it is the mirror image of the\n // upload above: the rule that was painting may have just lost the last\n // thing it had to paint with.\n const winner = winnerId()\n // The LAST image can be removed too, and the rule is then simply empty: a\n // rule with a color of its own still paints (the interface, no wallpaper)\n // and one with neither is skipped by `ruleCanPaint` until something\n // arrives. Refusing this (the first cut of the feature did) left a cleared\n // entry behind, and that entry sat at position 1 — so the next upload\n // became image 2 of a rule that kept painting nothing, with no way back.\n rule.images.splice(idx, 1)\n // The painted image may be the one that just went away, so the index has\n // to move with it — and `applyActive` below resets it when the rule itself\n // is the active one.\n if (id === activeRuleId) setRotIndex(0)\n rulesRev++\n persistConfig()\n if (!takenSlots().has(slot)) {\n setImage(slot, null)\n void deleteImage(slot)\n }\n repaintIfMoved(id, winner)\n },\n moveRuleImageTo: (id: string, slot: string, to: number): void => {\n const rule = ruleById(id)\n if (rule === null) return\n const idx = rule.images.findIndex(i => i.slot === slot)\n if (idx < 0) return\n // `to` is an index of the list this move PRODUCES, which is what a drop\n // target is expressed in — so it is clamped against the same length the\n // splice below restores the image into.\n const at = Math.max(0, Math.min(rule.images.length - 1, Math.trunc(to)))\n if (at === idx) return\n const winner = winnerId()\n // What is on screen is a PICTURE, not a position in a list. Reordering is\n // the user tidying the rotation, not a request to change the wallpaper, so\n // the painted slot is remembered here and the index is put back on it\n // after the splice — a reorder can never swap the picture out from under\n // them. (The one-step arrows and \"make first\" used to move the index onto\n // the image they moved, which is exactly the surprise this avoids.)\n const painted = id === activeRuleId ? rule.images[imageIndexOf(rule)]?.slot ?? null : null\n const [image] = rule.images.splice(idx, 1)\n rule.images.splice(at, 0, image!)\n rulesRev++\n // The count is unchanged, so the timer's signature cannot see a reorder —\n // re-arm explicitly, both to pick up the new cycle order and to make sure\n // the index below is what the next step starts from.\n if (id === activeRuleId) {\n // Reordering never removes a picture, so the painted one is always still\n // in the list; the fallback is only there to keep the index in range.\n const keep = painted === null ? -1 : rule.images.findIndex(i => i.slot === painted)\n setRotIndex(keep < 0 ? Math.min(at, rule.images.length - 1) : keep)\n scheduleRotation(true)\n }\n persistConfig()\n repaintIfMoved(id, winner)\n },\n setImageFraming: (id: string, slot: string, bgState: BgState): void => {\n const rule = ruleById(id)\n const image = rule?.images.find(i => i.slot === slot)\n if (image === undefined) return\n const winner = winnerId()\n image.bgState = bgState\n normalizeRuleInPlace(rule!)\n rulesRev++\n saveConfig()\n // Framing is per image, so a repaint of the CURRENT image is what makes\n // the editor's commit visible; `applyWp` re-reads the framing of whatever\n // is painted, which is this image only while it is the current one.\n repaintIfMoved(id, winner)\n },\n setRuleRotation: (id: string, patch: Partial<BgRule['rotate']>): void => {\n const rule = ruleById(id)\n if (rule === null) return\n patchRotation(rule, patch)\n rulesRev++\n persistConfig()\n // Turning the rotation on has to be able to paint at once, and turning it\n // off has to be able to stop the timer at once: both go through the\n // signature check in `scheduleRotation`.\n scheduleRotation()\n sync()\n },\n rotateNow: (id: string): void => {\n const rule = ruleById(id)\n // Only the ACTIVE rule can step: the image index describes what is on\n // screen, and a rule that is not painting has nothing on screen to change.\n if (rule === null || id !== activeRuleId) return\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n if (next === null) return\n setRotIndex(next)\n paintImage(rule, next)\n // A manual step restarts the dwell, so the tick that was already on its\n // way does not follow the user's click a second later.\n scheduleRotation(true)\n },\n showRuleImage: (id: string, slot: string): void => {\n const rule = ruleById(id)\n // Same rule as `rotateNow` above, and for the same reason: the image index\n // describes what is ON SCREEN, so a rule that is not painting has nothing\n // on screen to change. Pointing it at one of its pictures would be a\n // promise nothing keeps — the index is reset the moment it takes over.\n if (rule === null || id !== activeRuleId) return\n const idx = rule.images.findIndex(i => i.slot === slot)\n if (idx < 0) return\n setRotIndex(idx)\n // Not `applyActive`: this paints the one image the user asked for, and\n // `paintImage` is also what waits for cold bytes before showing them.\n paintImage(rule, idx)\n // A jump is a manual step, so it restarts the dwell as well — otherwise the\n // tick already on its way would carry the picture off a moment later.\n scheduleRotation(true)\n // NOTE: no `persistConfig` and no config field changes here. Which image is\n // being shown is runtime state, not a setting: it is not saved, and it is\n // not restored on the next boot (which starts at the rule's first image).\n },\n loadRuleImages: async (id: string): Promise<void> => {\n const rule = ruleById(id)\n if (rule === null) return\n // Sequential on purpose: an expanded card wants its thumbnails in list\n // order, and firing ten parallel reads over one RPC channel would only\n // race them into the cache in a random order.\n for (const slot of ruleSlots(rule)) await loadSlot(slot)\n sync()\n },\n setRuleImage: (id: string, slot: string, dataUrl: string | null): void => {\n const rule = ruleById(id)\n if (rule === null || !rule.images.some(i => i.slot === slot)) return\n const winner = winnerId()\n setImage(slot, dataUrl)\n void (dataUrl === null ? deleteImage(slot) : writeImage(slot, dataUrl))\n repaintIfMoved(id, winner)\n // A rule that has never been themed should simply come out themed; an\n // explicit color (or a cleared one the user set on purpose) is left be.\n if (dataUrl !== null) void maybeAutoExtract(id, slot)\n },\n addRuleImageFromUrl: async (id: string, url: string): Promise<FetchResult> => {\n const rule = ruleById(id)\n if (rule === null) return { ok: false, error: 'unknown rule' }\n // The slot is allocated before the download so the node half can write\n // straight into it (its `fetchImageUrl` is slot-addressed); a failed\n // download simply leaves the new entry empty, which is removed again\n // right here rather than showing a broken thumbnail.\n const slot = nextSlot()\n const res = await fetchImageUrl(slot, url)\n if (!res.ok) return res\n // Sampled here, not before the download: the list is only touched now.\n const winner = winnerId()\n rule.images.push({ slot, bgState: { ...DEFAULT_BG_STATE }, color: null })\n setImage(slot, res.dataUrl ?? null)\n rulesRev++\n persistConfig()\n repaintIfMoved(id, winner)\n void maybeAutoExtract(id, slot)\n return res\n },\n /**\n * Store ONE image's theme color (null = that image follows the system\n * theme). Addressed by slot exactly like `setImageFraming`, because the\n * color belongs to the image: editing image 3's color must not rewrite\n * image 1's, and it must not touch the RULE's color either — that one is\n * what the rule paints once its last picture is gone, and it is edited only\n * while there is no image to edit (the panel's own branch).\n */\n setImageColor: (id: string, slot: string, color: [number, number, number] | null): void => {\n const rule = ruleById(id)\n const image = rule?.images.find(i => i.slot === slot)\n if (rule === null || rule === undefined || image === undefined) return\n // A color is what a paint is made of, so the winner is sampled first: this\n // can be the edit that makes an unusable rule usable (see repaintIfMoved).\n const winner = winnerId()\n image.color = color\n normalizeRuleInPlace(rule)\n rulesRev++\n // Pointer-move frequency (the wheel, the RGB inputs), so the write is\n // coalesced — the same rule `setRule` follows for its color.\n saveConfig()\n repaintIfMoved(id, winner)\n },\n extractColor: async (id: string, slot?: string): Promise<boolean> => {\n const rule = ruleById(id)\n if (rule === null) return false\n const image = rule.images.find(i => i.slot === slot) ?? rule.images[0]\n if (image === undefined) return false\n const url = displayImageOf(image.slot)\n if (url === null) return false\n const hsl = await extractWallpaperColor(url, image.bgState)\n if (hsl === null) return false\n // Addressed by SLOT, like the framing editor: the extraction belongs to the\n // picture the user pressed the button on, and a rule with several pictures\n // must be able to keep their palettes apart.\n const current = ruleById(id)?.images.find(i => i.slot === image.slot)\n if (current === undefined) return false\n // The color is what makes a picture-less rule paintable at all, so this\n // edit can hand the interface a rule it was not showing (the \"从本图提取\n // 之后色没上来\" half of the report).\n const winner = winnerId()\n current.color = hsl\n rulesRev++\n saveConfig()\n repaintIfMoved(id, winner)\n return true\n },\n setOps: (ops: PartOpacities): void => { cfg.opacities = ops; applyWp(); sync(); saveConfig() },\n setBlurs: (blurs: PartBlurs): void => { cfg.blurs = blurs; applyWp(); sync(); saveConfig() },\n setSop: (v: number): void => { cfg.settingsOpacity = v; applySettingsOverrides(v); saveConfig() },\n // The file-preview panel owns its surface from the first drag on; a null\n // hands it back to the main-background slider.\n setRightbarOpacity: (v: number | null): void => {\n cfg.rightbarOpacity = v\n applyRightbarOverrides(rRightbarOpacity())\n saveConfig()\n },\n setAutoExtract: (v: boolean): void => { cfg.autoExtract = v; saveConfig(); sync() },\n\n // ── Holiday overrides ─────────────────────────────────────────────────\n setHolidaysEnabled: (v: boolean): void => {\n cfg.holidays.enabled = v\n persistConfig()\n // Switching it back on has to be able to paint immediately, so today's\n // holiday art is fetched if it is not in memory yet. Only TODAY's: the\n // other one cannot paint, and nothing in the UI shows it.\n const slot = todayHolidaySlot()\n if (v && slot !== null) void loadSlot(slot).then(() => applyActive())\n applyActive()\n },\n\n // Download every rule plus its images as one JSON file.\n exportTheme: (): void => {\n const images: Record<string, string> = {}\n // Rule slots only, but ALL of them: a theme file that carried just each\n // rule's first image would silently drop the rest of a rotation on the\n // way out, and the import below would restore a smaller rule set than the\n // one that was exported. A holiday's wallpaper belongs to the package and\n // is served from there, so it is still never written into a theme file —\n // that would ship ~970 KB of base64 every install already has, to a slot\n // nothing could restore it to (it is read-only).\n const slots = cfg.rules.flatMap(ruleSlots)\n for (const slot of slots) {\n const url = imageOf(slot)\n if (url !== null) images[slot] = url\n }\n const payload = {\n // 5 = a theme color belongs to an image (`images[].color`). 4 and older\n // still import: their image entries carry no `color` key at all, which is\n // exactly the shape `normalizeImage` lifts the rule's color onto, so a\n // theme file written before that feature restores its look unchanged.\n version: 5,\n exportedAt: new Date().toISOString(),\n config: cfg,\n images,\n }\n const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'dsh-background-by-model-theme.json'\n a.click()\n URL.revokeObjectURL(url)\n },\n // Import: replaces the whole rule set and every rule image.\n importTheme: async (file: File): Promise<boolean> => {\n try {\n const data: unknown = JSON.parse(await file.text())\n if (!data || typeof data !== 'object') return false\n const d = data as { version?: number; config?: unknown; images?: unknown }\n if (typeof d.config !== 'object' || d.config === null) return false\n adoptConfig(d.config)\n const incoming = (d.images ?? {}) as Record<string, unknown>\n const keep = new Set<string>()\n // Every slot the imported config references — the same set the export\n // writes. A holiday slot that an older theme file still carries falls\n // outside `keep` and is swept below; the node half refuses to write such\n // a slot either way, so it is inert from both directions.\n for (const slot of cfg.rules.flatMap(ruleSlots)) {\n keep.add(slot)\n const raw = incoming[slot]\n if (typeof raw === 'string' && /^data:image\\//.test(raw)) {\n setImage(slot, raw)\n void writeImage(slot, raw)\n } else {\n setImage(slot, null)\n void deleteImage(slot)\n }\n }\n // Slots the imported config no longer references are released.\n for (const slot of Object.keys(incoming)) {\n if (!keep.has(slot) && /^[A-Za-z0-9_-]{1,32}$/.test(slot)) void deleteImage(slot)\n }\n persistConfig()\n applyActive()\n return true\n } catch {\n return false\n }\n },\n }\n }\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section', id: 'dsh-background-by-model', order: 35,\n label: () => ctx.locale.bind(NS)('nav'),\n locale: NS, store, inject: sectionInject,\n }, ThemeSection as any))\n\n // ── 9. Settings-nav icon ──────────────────────────────────────────────────\n // The harness derives the nav glyph from the section id (unknown ids fall back\n // to the settings gear) with no plugin hook, so patch the mounted nav cell in\n // place — find the cell whose label matches this section's nav text and swap\n // its svg for the sun glyph.\n const navLabel = (): string => ctx.locale.bind(NS)('nav')\n const applyNavIcon = (): void => {\n const panel = document.querySelector<HTMLElement>('[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]')\n const nav = panel?.querySelector('nav')\n if (!nav) return\n const target = navLabel()\n for (const cell of Array.from(nav.querySelectorAll('button'))) {\n const label = cell.querySelector('span')\n if (label && label.textContent?.trim() === target) {\n const svg = cell.querySelector('svg')\n if (svg && svg.dataset.dshAnyIcon !== '1') {\n const sun = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n sun.setAttribute('width', '16')\n sun.setAttribute('height', '16')\n sun.setAttribute('viewBox', '0 0 16 16')\n sun.setAttribute('fill', 'none')\n sun.setAttribute('xmlns', 'http://www.w3.org/2000/svg')\n sun.dataset.dshAnyIcon = '1'\n sun.innerHTML = SUN_PATHS\n svg.replaceWith(sun)\n }\n return\n }\n }\n }\n let navIconObserver: MutationObserver | null = null\n const watchNavIcon = (): void => {\n if (navIconObserver !== null || typeof MutationObserver === 'undefined') return\n navIconObserver = new MutationObserver(records => {\n // React only when the settings panel (or its nav) is (re)created, so\n // chat-content mutations don't trigger a scan.\n const relevant = records.some(r => {\n for (const n of r.addedNodes) {\n if (n.nodeType !== 1) continue\n const el = n as Element\n if (el.matches?.('[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]') || el.querySelector?.('[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]')) return true\n }\n return false\n })\n if (relevant) applyNavIcon()\n })\n navIconObserver.observe(document.body, { childList: true, subtree: true })\n applyNavIcon()\n }\n watchNavIcon()\n ctx.effect(() => () => { navIconObserver?.disconnect(); navIconObserver = null }, 'dsh-background-by-model: nav icon watch')\n\n // ── 10. Deferred boot restore ─────────────────────────────────────────────\n // The theme service and the host settings scope settle asynchronously after\n // this apply, so the synchronous restore can be observed mid-flight — a late\n // host adoption resets the preference, or the presenter re-applies over our\n // overrides. Re-running the restore a few ticks later guarantees the saved\n // records land.\n const restoreSaved = (): void => {\n syncHostScheme()\n const color = activeColor()\n if (color !== null) {\n const snapshot = ctx.theme.getTheme()\n if (!snapshot.themes.some(t => t.id === CUSTOM_ID)) {\n // Theme missing (host adoption dropped it): re-register + activate.\n registerCustom(color[0], color[1], color[2])\n } else if (snapshot.preference !== CUSTOM_ID) {\n // Theme present but inactive: just re-assert the preference. Calling\n // registerCustom here would dispose + re-create the skin, flashing the\n // interface back to the system theme for a frame on every boot.\n ctx.theme.setTheme(CUSTOM_ID)\n }\n }\n applyWp()\n }\n const restoreTimers = [300, 1500].map(delay => window.setTimeout(restoreSaved, delay))\n ctx.effect(() => () => { restoreTimers.forEach(id => window.clearTimeout(id)) }, 'dsh-background-by-model: boot restore')\n\n // ── 11. Theme watchdog ────────────────────────────────────────────────────\n // The theme service keeps only built-in preferences in memory, so ANY\n // host-scope adoption can silently drop the custom theme — reverting the label\n // colors and the inner surfaces to the system palette. While the active rule\n // carries a color, re-register and re-assert on a slow interval.\n //\n // A color-less rule needs the same slow re-check for the opposite reason: it\n // paints from the HOST palette, which the host can re-project (or which the\n // scheme flag can fall behind) with no event of ours to hang a repaint on.\n // Without this, such a rule keeps whatever palette it read first — the light\n // one, if the read happened while the plugin's own light palette was still\n // forcing the flag off — until an unrelated apply happens to run.\n const watchdogId = window.setInterval(() => {\n syncHostScheme()\n const color = activeColor()\n if (color === null) {\n refreshSystemTheme()\n return\n }\n const snapshot = ctx.theme.getTheme()\n let changed = false\n if (!snapshot.themes.some(t => t.id === CUSTOM_ID)) {\n registerCustom(color[0], color[1], color[2])\n changed = true\n } else if (snapshot.preference !== CUSTOM_ID) {\n ctx.theme.setTheme(CUSTOM_ID)\n changed = true\n }\n if (changed) applyWp()\n }, 1000)\n ctx.effect(() => () => { window.clearInterval(watchdogId) }, 'dsh-background-by-model: theme watchdog')\n\n // ── 12. Theme-reset watchdog ──────────────────────────────────────────────\n const disposeThemeResets = watchThemeResets()\n ctx.effect(() => () => { disposeThemeResets() }, 'dsh-background-by-model: theme resets watch')\n\n // ── 13. Flush pending writes on page hide ─────────────────────────────────\n const onPageHide = (): void => flushSave()\n window.addEventListener('pagehide', onPageHide)\n ctx.effect(() => () => window.removeEventListener('pagehide', onPageHide), 'dsh-background-by-model: pagehide flush')\n}\n"],"mappings":";;;;;;;;;;EAsBA,SAAS,eAA4B;GACnC,IAAI;IAGF,OAAO,QAAQ,+BAA+B;GAChD,QAAQ,CAER;GAEA,OAAO,QAAQ,wCAAwC;EACzD;EAEA,MAAa,cAAmB,aAAa,CAAC,CAAC;;;EClC/C,MAAa,KAAK;EAElB,MAAa,KAA6B;GACxC,KAAK;GAAQ,UAAU;GACvB,eAAe;GAAM,aAAa;GAAQ,aAAa;GACvD,eAAe;GACf,aAAa;GACb,aAAa;GAEb,SAAS;GACT,WAAW;GAAO,QAAQ;GAC1B,aAAa;GAAO,eAAe;GAAO,eAAe;GAAW,gBAAgB;GACpF,OAAO;GAAW,cAAc;GAAS,cAAc;GACvD,WAAW;GAIX,mBAAmB;GACnB,yBAAyB;GACzB,qBAAqB;GACrB,qBAAqB;GACrB,wBAAwB;GACxB,0BAA0B;GAI1B,eAAe;GACf,aAAa;GACb,mBAAmB;GACnB,kBAAkB;GAClB,WAAW;GACX,gBAAgB;GAChB,YAAY;GACZ,aAAa;GACb,aAAa;GACb,SAAS;GACT,mBAAmB;GACnB,sBAAsB;GACtB,aAAa;GACb,QAAQ;GAAM,UAAU;GAAM,YAAY;GAC1C,aAAa;GACb,aAAa;GAAO,oBAAoB;GACxC,cAAc;GAAM,eAAe;GAAM,iBAAiB;GAC1D,gBAAgB;GAAuB,aAAa;GACpD,iBAAiB;GACjB,eAAe;GAEf,mBAAmB;GAGnB,sBAAsB;GACtB,WAAW;GACX,eAAe;GACf,mBAAmB;GAGnB,eAAe;GACf,mBAAmB;GAGnB,sBAAsB;GAGtB,2BAA2B;GAC3B,kBAAkB;GAKlB,sBAAsB;GACtB,qBAAqB;GACrB,YAAY;GACZ,iBAAiB;GACjB,aAAa;GACb,UAAU;GACV,cAAc;GAId,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,aAAa;GACb,iBAAiB;GACjB,aAAa;GACb,SAAS;GACT,iBAAiB;GACjB,QAAQ;GACR,YAAY;GACZ,aAAa;GAGb,iBAAiB;GACjB,aAAa;GACb,YAAY;GACZ,aAAa;GAAQ,aAAa;GAAQ,YAAY;GACtD,YAAY;GAAQ,aAAa;GAAS,YAAY;GAGtD,WAAW;GAAM,YAAY;GAAM,eAAe;GAAM,YAAY;GAAM,cAAc;GACxF,aAAa;GAAS,YAAY;GAClC,cAAc;GAAM,cAAc;GAAM,aAAa;GAErD,YAAY;GACZ,aAAa;GACb,aAAa;GACb,YAAY;GACZ,aAAa;GACb,YAAY;GACZ,aAAa;GAEb,YAAY;GACZ,WAAW;GACX,YAAY;GAEZ,aAAa;GAAQ,aAAa;GAClC,iBAAiB;GACjB,gBAAgB;GAChB,iBAAiB;GACjB,gBAAgB;GAChB,iBAAiB;GACjB,YAAY;GACZ,YAAY;GACZ,WAAW;GAGX,cAAc;GACd,eAAe;EACjB;EAEA,MAAa,KAA6B;GACxC,KAAK;GAAoB,UAAU;GACnC,eAAe;GAAa,aAAa;GAAoB,aAAa;GAC1E,eAAe;GACf,aAAa;GACb,aAAa;GAEb,SAAS;GACT,WAAW;GAAW,QAAQ;GAC9B,aAAa;GAAmB,eAAe;GAAc,eAAe;GAAiB,gBAAgB;GAC7G,OAAO;GAA8B,cAAc;GAA2B,cAAc;GAC5F,WAAW;GAIX,mBAAmB;GACnB,yBAAyB;GACzB,qBAAqB;GACrB,qBAAqB;GACrB,wBAAwB;GACxB,0BAA0B;GAI1B,eAAe;GACf,aAAa;GACb,mBAAmB;GACnB,kBAAkB;GAClB,WAAW;GACX,gBAAgB;GAChB,YAAY;GACZ,aAAa;GACb,aAAa;GACb,SAAS;GACT,mBAAmB;GACnB,sBAAsB;GACtB,aAAa;GACb,QAAQ;GAAW,UAAU;GAAa,YAAY;GACtD,aAAa;GACb,aAAa;GAAY,oBAAoB;GAC7C,cAAc;GAAS,eAAe;GAAU,iBAAiB;GACjE,gBAAgB;GAA4C,aAAa;GACzE,iBAAiB;GACjB,eAAe;GAEf,mBAAmB;GAGnB,sBAAsB;GACtB,WAAW;GACX,eAAe;GACf,mBAAmB;GAGnB,eAAe;GACf,mBAAmB;GAGnB,sBAAsB;GAGtB,2BAA2B;GAC3B,sBAAsB;GACtB,qBAAqB;GACrB,kBAAkB;GAClB,YAAY;GACZ,iBAAiB;GACjB,aAAa;GACb,UAAU;GACV,cAAc;GAKd,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,WAAW;GACX,YAAY;GACZ,UAAU;GACV,aAAa;GACb,iBAAiB;GACjB,aAAa;GACb,SAAS;GACT,iBAAiB;GACjB,QAAQ;GACR,YAAY;GACZ,aAAa;GAGb,iBAAiB;GACjB,aAAa;GACb,YAAY;GACZ,aAAa;GAAQ,aAAa;GAAQ,YAAY;GACtD,YAAY;GAAS,aAAa;GAAU,YAAY;GAGxD,WAAW;GAAO,YAAY;GAAQ,eAAe;GAAW,YAAY;GAAQ,cAAc;GAClG,aAAa;GAAqB,YAAY;GAC9C,cAAc;GAAW,cAAc;GAAU,aAAa;GAE9D,YAAY;GACZ,aAAa;GACb,aAAa;GACb,YAAY;GACZ,aAAa;GACb,YAAY;GACZ,aAAa;GAEb,YAAY;GACZ,WAAW;GACX,YAAY;GAEZ,aAAa;GAAU,aAAa;GACpC,iBAAiB;GACjB,gBAAgB;GAChB,iBAAiB;GACjB,gBAAgB;GAChB,iBAAiB;GACjB,YAAY;GACZ,YAAY;GACZ,WAAW;GAGX,cAAc;GACd,eAAe;EACjB;;;ECvNA,MAAa,WAAkC,CAC7C;GAAE,IAAI;GAAc,MAAM;GAAe,OAAO;GAAmB,OAAO;GAAW,MAAM;EAAQ,GACnG;GAAE,IAAI;GAAgB,MAAM;GAAiB,OAAO;GAAqB,OAAO;GAAW,MAAM;EAAY,CAC/G;EAwBA,MAAM,KAAK;EAEX,IAAI;EACJ,SAAS,WAAuC;GAC9C,IAAI,mBAAmB,KAAA,GACrB,IAAI;IACF,iBAAiB,IAAI,KAAK,eAAe,SAAS;KAChD,UAAU;KAAI,MAAM;KAAW,OAAO;KAAW,KAAK;IACxD,CAAC;GACH,QAAQ;IACN,iBAAiB;GACnB;GAEF,OAAO;EACT;EAEA,IAAI;EACJ,SAAS,WAAuC;GAC9C,IAAI,mBAAmB,KAAA,GACrB,IAAI;IACF,iBAAiB,IAAI,KAAK,eAAe,mBAAmB;KAC1D,UAAU;KAAI,MAAM;KAAW,OAAO;KAAW,KAAK;IACxD,CAAC;GACH,QAAQ;IACN,iBAAiB;GACnB;GAEF,OAAO;EACT;EAEA,SAAS,QAAQ,KAA0B,MAA2C;GACpF,IAAI;IACF,MAAM,MAA8B,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,cAAc,IAAI,GACpC,IAAI,EAAE,SAAS,WAAW,IAAI,EAAE,QAAQ,EAAE;IAE5C,OAAO;GACT,QAAQ;IACN,OAAO;GACT;EACF;;EAGA,SAAgB,aAAa,MAAwD;GACnF,MAAM,MAAM,SAAS;GACrB,IAAI,QAAQ,MAAM,OAAO;GACzB,MAAM,IAAI,QAAQ,KAAK,IAAI;GAC3B,IAAI,MAAM,MAAM,OAAO;GACvB,MAAM,IAAI,OAAO,EAAE,IAAI;GACvB,MAAM,IAAI,OAAO,EAAE,KAAK;GACxB,MAAM,IAAI,OAAO,EAAE,GAAG;GACtB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,OAAO;GACzD,OAAO;IAAE;IAAG;IAAG;GAAE;EACnB;;;;;;;;;;EAgBA,SAAgB,cAAc,MAAmD;GAC/E,MAAM,MAAM,SAAS;GACrB,IAAI,QAAQ,MAAM,OAAO;GACzB,MAAM,IAAI,QAAQ,KAAK,IAAI;GAC3B,IAAI,MAAM,QAAQ,EAAE,UAAU,KAAA,KAAa,EAAE,QAAQ,KAAA,GAAW,OAAO;GACvE,OAAO;IAAE,OAAO,EAAE;IAAO,KAAK,EAAE;GAAI;EACtC;;EAKA,SAAgB,YAAY,uBAAa,IAAI,KAAK,GAAY;GAC5D,MAAM,QAAQ,cAAc,IAAI;GAChC,OAAO,UAAU,QAAQ,MAAM,UAAU,OAAO,MAAM,QAAQ;EAChE;;EAGA,SAAgB,cAAc,uBAAa,IAAI,KAAK,GAAY;GAC9D,MAAM,QAAQ,aAAa,IAAI;GAC/B,OAAO,UAAU,QAAQ,MAAM,MAAM,MAAM,MAAM,KAAK,KAAK,MAAM,KAAK;EACxE;;;;;;;;EASA,SAAgB,cAAc,uBAAa,IAAI,KAAK,GAAqB;GACvE,IAAI,YAAY,IAAI,GAAG,OAAO;GAC9B,IAAI,cAAc,IAAI,GAAG,OAAO;GAChC,OAAO;EACT;;;;;;;;;;;;;;;;;;;;EAyEA,SAAgB,YACd,QACA,OACA,SACA,UACU;GACV,IAAI,CAAC,UAAU,YAAY,MAAM,OAAO;GACxC,MAAM,OAAO,MAAM,MAAK,MAAK,EAAE,OAAO,OAAO;GAC7C,IAAI,SAAS,KAAA,KAAa,CAAC,KAAK,SAAS,OAAO;GAChD,OAAO,KAAK,OAAO,MAAK,UAAS,SAAS,MAAM,IAAI,CAAC,IAAI,OAAO;EAClE;;;;;;;;;;;;;;;;;;;;;;;;ECtOA,MAAa,mBAA4B;GAAE,MAAM;GAAG,GAAG;GAAG,GAAG;GAAG,IAAI;GAAG,IAAI;EAAE;;EA6C7E,MAAaA,aAA8B;GAAC;GAAO;GAAQ;GAAW;GAAQ;EAAQ;;EAQtF,MAAa,gBAAwC,CAAC,SAAS,SAAS;;EAGxE,MAAa,gBAAgB;;EAE7B,MAAa,gBAAgB;;EAE7B,MAAa,qBAAqB;;EAwBlC,MAAa,mBAA+B;GAC1C,SAAS;GACT,YAAY;GACZ,OAAO;GACP,iBAAiB;GACjB,QAAQ;EACV;;EAGA,SAAgB,kBAA8B;GAAE,OAAO,EAAE,GAAG,iBAAiB;EAAE;;;;;;;;;EAU/E,MAAa,oBAAoB;GAAC;GAAM;GAAW;GAAQ;EAAO;EAKlE,MAAa,yBAAwC;GAAE,IAAI;GAAM,SAAS;GAAM,MAAM;GAAG,OAAO;EAAE;;;;;;;;;;;;EAalG,MAAa,iBAAiB;GAAC;GAAM;GAAW;GAAQ;GAAY;GAAQ;GAAc;GAAY;EAAO;EAK7G,MAAa,qBAAgC;GAC3C,IAAI;GAAG,SAAS;GAAG,MAAM;GAAG,UAAU;GAAG,MAAM;GAAG,YAAY;GAAG,UAAU;GAAG,OAAO;EACvF;;;EAsDA,SAAgB,UAAU,MAAwB;GAChD,OAAO,KAAK,OAAO,KAAI,MAAK,EAAE,IAAI;EACpC;;;;;;;;;;;;;;;;;;;;;;;;EAyBA,SAAgB,aAAa,MAAuB;GAClD,OAAO,KAAK,YAAY,UAAU,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK,UAAU;EACvE;;;;;;;;;;EA8FA,SAAgB,SAAS,KAA8C;GACrE,MAAM,IAAI,qBAAqB,KAAK,IAAI,KAAK,CAAC;GAC9C,IAAI,MAAM,MAAM,OAAO;GACvB,MAAM,IAAI,SAAS,EAAE,IAAK,EAAE;GAC5B,MAAM,KAAM,KAAK,KAAM,OAAQ;GAC/B,MAAM,KAAM,KAAK,IAAK,OAAQ;GAC9B,MAAM,KAAK,IAAI,OAAQ;GACvB,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC;GAC5B,MAAM,MAAM,KAAK,IAAI,GAAG,GAAG,CAAC;GAC5B,MAAM,KAAK,MAAM,OAAO;GACxB,MAAM,IAAI,MAAM;GAEhB,IAAI,MAAM,GAAG,OAAO;IAAC;IAAG;IAAG;GAAC;GAC5B,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC;GACrC,IAAI;GACJ,IAAI,QAAQ,GAAG,IAAI,OAAQ,IAAI,KAAK,IAAK;QACpC,IAAI,QAAQ,GAAG,IAAI,OAAO,IAAI,KAAK,IAAI;QACvC,IAAI,OAAO,IAAI,KAAK,IAAI;GAC7B,IAAI,IAAI,GAAG,KAAK;GAKhB,OAAO;IAACC,QAAM,GAAG,GAAG,KAAK,CAAC;IAAG,QAAQ,GAAG,CAAC;IAAG,QAAQ,GAAG,EAAG;GAAC;EAC7D;;;;;;;;EASA,SAAgB,mBAAmB,KAA8B;GAM/D,MAAM,QAAQ,SAAS,IAAI,KAAK;GAChC,OAAO;IACL,IAAI,IAAI;IAGR,QAAQ,CAAC;KAAE,MAAM,IAAI;KAAM,SAAS,EAAE,GAAG,iBAAiB;KAAG;IAAM,CAAC;IACpE,OAAO;IACP,SAAS;IACT;IACA,QAAQ;IACR,kBAAkB;IAClB,MAAM;IACN,QAAQ,gBAAgB;GAC1B;EACF;;EAGA,SAAgB,sBAAqC;GACnD,OAAO,SAAS,IAAI,kBAAkB;EACxC;;EAGA,SAAgB,mBAAgC;GAC9C,OAAO;IACL,OAAO,CAAC;IACR,WAAW,EAAE,GAAG,uBAAuB;IACvC,OAAO,EAAE,GAAG,mBAAmB;IAC/B,iBAAA;IACA,iBAAA;IACA,mBAAA;IACA,iBAAA;IACA,aAAA;IACA,UAAU;KAAE,SAAA;KAAmC,OAAO,oBAAoB;IAAE;GAC9E;EACF;;EAQA,MAAa,UAAU;EA0BvB,SAAgBA,QAAM,GAAY,IAAY,IAAY,KAAqB;GAC7E,OAAO,OAAO,MAAM,YAAY,SAAS,CAAC,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI;EAChF;EAEA,MAAa,WAAW,GAAY,QAAwBA,QAAM,GAAG,GAAG,GAAG,GAAG;EAE9E,SAAgB,iBAAiB,GAA0C;GACzE,MAAM,IAAI,KAAK,CAAC;GAChB,OAAO;IACL,MAAMA,QAAM,EAAE,MAAM,IAAK,IAAI,CAAC;IAC9B,GAAG,OAAO,EAAE,MAAM,YAAY,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI;IACpD,GAAG,OAAO,EAAE,MAAM,YAAY,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI;IACpD,IAAI,OAAO,EAAE,OAAO,YAAY,EAAE,KAAK,IAAI,EAAE,KAAK;IAClD,IAAI,OAAO,EAAE,OAAO,YAAY,EAAE,KAAK,IAAI,EAAE,KAAK;GACpD;EACF;;EAGA,SAAgB,aAAa,KAA+C;GAC1E,IAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,GAAG,OAAO;GACpD,IAAI,CAAC,IAAI,OAAM,MAAK,OAAO,MAAM,YAAY,SAAS,CAAC,CAAC,GAAG,OAAO;GAClE,OAAO;IAACA,QAAM,IAAI,IAAI,GAAG,KAAK,GAAG;IAAGA,QAAM,IAAI,IAAI,GAAG,GAAG,GAAI;IAAGA,QAAM,IAAI,IAAI,GAAG,GAAG,GAAI;GAAC;EAC1F;;EAGA,SAAgB,kBAAkB,KAA0B;GAC1D,MAAM,IAAK,OAAO,CAAC;GACnB,MAAM,IAAI;GACV,OAAO;IAGL,SAAS,EAAE,YAAY;IACvB,YAAYA,QAAM,EAAE,YAAY,eAAe,eAAe,EAAE,UAAU;IAC1E,OAAO,cAAc,SAAS,EAAE,KAAoB,IAAK,EAAE,QAAwB,EAAE;IACrF,iBAAiB,EAAE,oBAAoB;IAEvC,QAAQA,QAAM,EAAE,QAAQ,GAAG,oBAAoB,EAAE,MAAM;GACzD;EACF;;EAGA,SAAS,OAAO,GAAW,KAAsB;GAC/C,OAAO,OAAO,UAAU,eAAe,KAAK,GAAG,GAAG;EACpD;;;;;;;;;;;;;;;;EAiBA,SAAgB,eAAe,KAAc,UAA2C,MAAsB;GAC5G,MAAM,IAAK,OAAO,CAAC;GACnB,IAAI,OAAO,EAAE,SAAS,YAAY,CAAC,QAAQ,KAAK,EAAE,IAAI,GAAG,OAAO;GAChE,OAAO;IACL,MAAM,EAAE;IACR,SAAS,iBAAiB,EAAE,OAAuC;IACnE,OAAO,OAAO,GAAG,OAAO,IAAI,aAAa,EAAE,KAAK,IAAI;GACtD;EACF;;;;;;;;;;;;;;;;;;;;;;;;;EA0BA,SAAgB,cAAc,KAA6B;GACzD,MAAM,IAAK,OAAO,CAAC;GACnB,MAAM,KAAK,OAAO,EAAE,OAAO,YAAY,EAAE,OAAO,KAAK,EAAE,KAAK;GAC5D,IAAI,OAAO,MAAM,OAAO;GACxB,MAAM,QAAQ,aAAa,EAAE,KAAK;GAClC,MAAM,SAAoB,CAAC;GAC3B,MAAM,uBAAO,IAAI,IAAY;GAC7B,MAAM,UAAU,MAAM,QAAQ,EAAE,MAAM;GACtC,IAAI,SACF,KAAK,MAAM,SAAS,EAAE,QAAqB;IACzC,MAAM,QAAQ,eAAe,OAAO,KAAK;IACzC,IAAI,UAAU,QAAQ,KAAK,IAAI,MAAM,IAAI,GAAG;IAC5C,KAAK,IAAI,MAAM,IAAI;IACnB,OAAO,KAAK,KAAK;GACnB;GAEF,MAAM,aAAa,OAAO,EAAE,SAAS,YAAY,QAAQ,KAAK,EAAE,IAAI,IAAI,EAAE,OAAO;GACjF,IAAI,OAAO,WAAW,KAAK,eAAe,MAIxC,OAAO,KAAK;IAAE,MAAM;IAAY,SAAS,iBAAiB,EAAE,OAAuC;IAAG;GAAM,CAAC;GAG/G,IAAI,OAAO,WAAW,KAAK,CAAC,SAAS,OAAO;GAC5C,MAAM,OAAeD,WAAS,SAAS,EAAE,MAAgB,IAAK,EAAE,SAAoB;GACpF,OAAO;IACL;IACA;IACA,OAAO,OAAO,EAAE,UAAU,WAAW,EAAE,QAAQ;IAC/C,SAAS,EAAE,YAAY;IACvB;IACA,QAAQ;IACR,kBAAkB,QAAQ,EAAE,kBAAkB,CAAC;IAC/C,MAAMC,QAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,kBAAkB,EAAE,MAAM;GACpC;EACF;;;;;;;;;;;;;EAcA,SAAgB,qBAAqB,KAAiB,KAA2B;GAC/E,MAAM,IAAK,OAAO,CAAC;GACnB,MAAM,OAAO,mBAAmB,GAAG;GACnC,OAAO;IACL,GAAG;IAGH,SAAS,EAAE,YAAY;IACvB,QAAQD,WAAS,SAAS,EAAE,MAAgB,IAAK,EAAE,SAAoB,KAAK;IAC5E,kBAAkB,QAAQ,EAAE,kBAAkB,KAAK,gBAAgB;IACnE,MAAMC,QAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI;IAMpC,QAAQ,KAAK,OAAO,KAAI,WAAU;KAChC,MAAM,MAAM;KACZ,SAAS,iBAAkB,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,OAAwC;KAC/F,OAAO,MAAM;IACf,EAAE;GACJ;EACF;;EAGA,SAAgB,kBAAkB,KAA8B;GAC9D,MAAM,IAAK,OAAO,CAAC;GACnB,MAAM,yBAAS,IAAI,IAAqB;GACxC,IAAI,MAAM,QAAQ,EAAE,KAAK,GACvB,KAAK,MAAM,QAAQ,EAAE,OAAO;IAC1B,MAAM,KAAM,MAA8C;IAC1D,IAAI,OAAO,OAAO,UAAU,OAAO,IAAI,IAAI,IAAI;GACjD;GAEF,OAAO;IAIL,SAAS,EAAE,YAAY;IACvB,OAAO,SAAS,KAAI,QAAO,qBAAqB,KAAK,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;GAC1E;EACF;;EAGA,SAAgB,gBAAgB,KAA2B;GACzD,MAAM,IAAK,OAAO,CAAC;GACnB,MAAM,QAAQ,MAAM,QAAQ,EAAE,KAAK,IAC/B,EAAE,MAAM,IAAI,aAAa,CAAC,CAAC,QAAQ,MAAmB,MAAM,IAAI,IAChE,CAAC;GACL,MAAM,MAAO,EAAE,aAAa,CAAC;GAC7B,MAAM,KAAM,EAAE,SAAS,CAAC;GACxB,MAAM,QAAQ,CAAC;GACf,KAAK,MAAM,KAAK,gBACd,MAAM,KAAKA,QAAM,GAAG,IAAI,GAAG,IAAI,mBAAmB,EAAE;GAEtD,MAAM,YAAY,CAAC;GACnB,KAAK,MAAM,KAAK,mBACd,UAAU,KAAK,QAAQ,IAAI,IAAI,uBAAuB,EAAE;GAE1D,OAAO;IACL;IACA;IACA;IACA,iBAAiB,QAAQ,EAAE,iBAAA,CAAyC;IACpE,iBAAiB,QAAQ,EAAE,iBAAA,CAA0C;IACrE,mBAAmB,QAAQ,EAAE,mBAAA,CAA6C;IAG1E,iBAAiB,OAAO,EAAE,oBAAoB,YAAY,SAAS,EAAE,eAAe,IAChF,QAAQ,EAAE,iBAAiB,CAAC,IAAA;IAIhC,aAAa,EAAE,gBAAgB;IAC/B,UAAU,kBAAkB,EAAE,QAAQ;GACxC;EACF;;;ECxoBA,MAAM,UAA2C;GAC/C;IAAC;IAAK;IAAM;GAAI;GAAG;IAAC;IAAI;IAAM;GAAI;GAAG;IAAC;IAAI;IAAK;GAAI;GAAG;IAAC;IAAK;IAAM;GAAG;GACrE;IAAC;IAAK;IAAM;GAAI;GAAG;IAAC;IAAK;IAAM;GAAI;GAAG;IAAC;IAAK;IAAM;GAAG;GAAG;IAAC;IAAK;IAAM;GAAI;EAC1E;EAI2C,iBAAiB;EAI5D,IAAW,MAAmB,iBAAiB;EAY/C,MAAM,yBAAS,IAAI,IAAoB;EACvC,MAAM,8BAAc,IAAI,IAAoB;EAE5C,SAAS,cAAc,MAAoB;GACzC,MAAM,MAAM,YAAY,IAAI,IAAI;GAChC,IAAI,QAAQ,KAAA,GAAW;GACvB,YAAY,OAAO,IAAI;GAIvB,OAAO,iBAAiB;IACtB,IAAI;KAAE,IAAI,gBAAgB,GAAG;IAAE,QAAQ,CAA8C;GACvF,GAAG,GAAI;EACT;EAEA,SAAgB,SAAS,MAAc,KAA0B;GAC/D,cAAc,IAAI;GAClB,IAAI,QAAQ,MAAM,OAAO,OAAO,IAAI;QAC/B,OAAO,IAAI,MAAM,GAAG;EAC3B;;EAEA,SAAgB,QAAQ,MAA6B;GAAE,OAAO,OAAO,IAAI,IAAI,KAAK;EAAK;;;EAIvF,SAAgB,eAAe,MAA6B;GAC1D,MAAM,SAAS,YAAY,IAAI,IAAI;GACnC,IAAI,WAAW,KAAA,GAAW,OAAO;GACjC,MAAM,OAAO,OAAO,IAAI,IAAI;GAC5B,IAAI,SAAS,KAAA,GAAW,OAAO;GAC/B,MAAM,OAAO,YAAY,IAAI;GAC7B,IAAI,SAAS,MAAM,OAAO;GAC1B,YAAY,IAAI,MAAM,IAAI;GAC1B,OAAO;EACT;EAEA,SAAS,YAAY,SAAgC;GACnD,IAAI;IACF,IAAI,OAAO,QAAQ,eAAe,OAAO,IAAI,oBAAoB,YAAY,OAAO;IACpF,MAAM,QAAQ,QAAQ,QAAQ,GAAG;IACjC,IAAI,QAAQ,GAAG,OAAO;IACtB,MAAM,OAAO,QAAQ,MAAM,GAAG,KAAK;IACnC,IAAI,CAAC,YAAY,KAAK,IAAI,GAAG,OAAO;IACpC,MAAM,OAAO,KAAK,MAAM,GAAG,EAAE,KAAK;IAClC,MAAM,MAAM,KAAK,QAAQ,MAAM,QAAQ,CAAC,CAAC;IACzC,MAAM,QAAQ,IAAI,WAAW,IAAI,MAAM;IACvC,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC;IAChE,OAAO,IAAI,gBAAgB,IAAI,KAAK,CAAC,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC,CAAC;GAC9D,QAAQ;IACN,OAAO;GACT;EACF;EAQA,IAAW,eAA8B;EACzC,IAAW,gBAAgB;EAC3B,IAAW,aAAa;;;;;;;;;EAUxB,IAAI,WAAW;EAEf,SAAgB,UAAU,QAAuB,SAAwB;GAGvE,IAAI,WAAW,cAAc,WAAW;GACxC,eAAe;GACf,gBAAgB;EAClB;EACA,SAAgB,cAAc,OAAqB;GAAE,aAAa;EAAM;;EAGxE,SAAgB,aAAa,MAAsB;GACjD,IAAI,KAAK,OAAO,WAAW,GAAG,OAAO;GACrC,MAAM,IAAI,KAAK,MAAM,QAAQ;GAC7B,OAAO,KAAK,KAAK,IAAI,KAAK,OAAO,SAAS,IAAI;EAChD;;EAGA,SAAgB,YAAY,GAAiB;GAAE,WAAW,KAAK,MAAM,CAAC;EAAE;;EAGxE,SAAgB,cAA8B;GAC5C,MAAM,OAAO,WAAW;GACxB,IAAI,SAAS,MAAM,OAAO;GAC1B,OAAO,KAAK,OAAO,aAAa,IAAI,MAAM;EAC5C;;EAGA,SAAgB,aAAqB;GAAE,OAAO,YAAY,CAAC,EAAE,QAAQ;EAAG;;;;;;;;;;;;;;;;;;;;EAqBxE,SAAgB,cAA+C;GAC7D,MAAM,OAAO,WAAW;GACxB,IAAI,SAAS,MAAM,OAAO;GAC1B,IAAI,KAAK,OAAO,WAAW,GAAG,OAAO,KAAK;GAC1C,OAAO,YAAY,CAAC,EAAE,SAAS;EACjC;;;;;;;;;EAUA,SAAgB,SAAS,IAA2B;GAClD,OAAO,IAAI,MAAM,MAAK,MAAK,EAAE,OAAO,EAAE,KACjC,IAAI,SAAS,MAAM,MAAK,MAAK,EAAE,OAAO,EAAE,KACxC;EACP;EACA,SAAgB,aAA4B;GAC1C,OAAO,iBAAiB,OAAO,OAAO,SAAS,YAAY;EAC7D;;EAGA,SAAgB,YAAY,IAAgC;GAC1D,OAAO,IAAI,SAAS,MAAM,MAAK,MAAK,EAAE,OAAO,EAAE,KAAK;EACtD;;;;;;;;;;;EAaA,SAAgB,QAAQ,IAAoB;GAC1C,OAAO;IACL;IACA,QAAQ,CAAC;IACT,OAAO;IAAI,SAAS;IAAM,OAAO;IACjC,QAAQ;IAAO,kBAAkB;IAAG,MAAM;IAC1C,QAAQ,gBAAgB;GAC1B;EACF;;EAGA,SAAgB,aAA0B;GACxC,MAAM,wBAAQ,IAAI,IAAY;GAC9B,KAAK,MAAM,QAAQ,IAAI,OAAO,KAAK,MAAM,QAAQ,UAAU,IAAI,GAAG,MAAM,IAAI,IAAI;GAChF,KAAK,MAAM,QAAQ,IAAI,SAAS,OAAO,KAAK,MAAM,QAAQ,UAAU,IAAI,GAAG,MAAM,IAAI,IAAI;GACzF,OAAO;EACT;;;;;;;;;EAUA,SAAgB,WAAmB;GACjC,MAAM,QAAQ,WAAW;GACzB,KAAK,IAAI,IAAI,GAAG,IAAI,KAAM,KAAK;IAC7B,MAAM,OAAO,IAAI;IACjB,IAAI,CAAC,MAAM,IAAI,IAAI,GAAG,OAAO;GAC/B;GACA,OAAO,IAAI,KAAK,IAAI;EACtB;;EAGA,SAAgB,aAAqB;GACnC,MAAM,QAAQ,IAAI,IAAI,IAAI,MAAM,KAAI,MAAK,EAAE,EAAE,CAAC;GAC9C,KAAK,IAAI,IAAI,GAAG,IAAI,KAAO,KAAK;IAC9B,MAAM,KAAK,IAAI;IACf,IAAI,CAAC,MAAM,IAAI,EAAE,GAAG,OAAO;GAC7B;GACA,OAAO,IAAI,KAAK,IAAI;EACtB;;;EAIA,SAAgB,cAAc,MAAc,OAAwC;GAClF,KAAK,SAAS,kBAAkB;IAAE,GAAG,KAAK;IAAQ,GAAG;GAAM,CAAC;EAC9D;;EAGA,SAAgB,qBAAqB,MAAoB;GACvD,MAAM,aAAa,cAAc,IAAI;GACrC,IAAI,eAAe,MAAM,OAAO,OAAO,MAAM,UAAU;EACzD;EAGA,SAAgB,YAAqB;GAAE,OAAO,YAAY,MAAM;EAAK;EACrE,SAAgB,SAAmC;GAAE,OAAO,YAAY,KAAK;IAAC;IAAK;IAAM;GAAI;EAAE;EAC/F,SAAgB,UAAkB;GAAE,OAAO,WAAW,CAAC,EAAE,UAAU;EAAM;EACzE,SAAgB,OAAe;GAAE,OAAO,QAAQ,WAAW,CAAC,EAAE,kBAAkB,CAAC;EAAE;EACnF,SAAgB,MAAc;GAAE,OAAOC,QAAM,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;EAAE;;EAE3E,SAAgB,WAAoB;GAAE,OAAO,YAAY,CAAC,EAAE,WAAW;EAAiB;;EAExF,SAAgB,YAA8B;GAAE,OAAO,WAAW,CAAC,EAAE,UAAU,gBAAgB;EAAE;;EAEjG,SAAgB,UAAkB;GAAE,OAAO,UAAU,CAAC,CAAC;EAAO;;EAE9D,SAAgB,MAAqB;GACnC,MAAM,OAAO,WAAW;GACxB,OAAO,SAAS,KAAK,OAAO,eAAe,IAAI;EACjD;EACA,SAAgB,OAAsB;GACpC,MAAM,IAAI,IAAI,aAAa,CAAC;GAC5B,MAAM,MAAM,CAAC;GACb,KAAK,MAAM,KAAK,mBACd,IAAI,KAAK,QAAQ,EAAE,IAAI,uBAAuB,EAAE;GAElD,OAAO;EACT;EACA,SAAgB,SAAoB;GAClC,MAAM,IAAI,IAAI,SAAS,CAAC;GACxB,MAAM,MAAM,CAAC;GACb,KAAK,MAAM,KAAK,gBACd,IAAI,KAAKA,QAAM,EAAE,IAAI,GAAG,IAAI,mBAAmB,EAAE;GAEnD,OAAO;EACT;EACA,SAAgB,OAAe;GAAE,OAAO,QAAQ,IAAI,iBAAA,CAAyC;EAAE;EAC/F,SAAgB,mBAA2B;GAAE,OAAO,QAAQ,IAAI,iBAAA,CAA0C;EAAE;EAC5G,SAAgB,qBAA6B;GAAE,OAAO,QAAQ,IAAI,mBAAA,CAA6C;EAAE;;EAEjH,SAAgB,mBAA2B;GACzC,MAAM,MAAM,IAAI;GAChB,OAAO,OAAO,QAAQ,YAAY,SAAS,GAAG,IAAI,QAAQ,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;EAC7E;;EAQA,SAAgB,YAAY,KAAoB;GAC9C,MAAM,gBAAgB,GAAG;GAIzB,IAAI,iBAAiB,QAAQ,SAAS,YAAY,MAAM,MAAM;IAC5D,eAAe;IACf,gBAAgB;GAClB;GAGA,WAAW;EACb;;;;EC7SA,MAAa,iBAA6D;GACxE;IAAE,IAAI;IAAQ,KAAK;GAAc;GACjC;IAAE,IAAI;IAAQ,KAAK;GAAc;GACjC;IAAE,IAAI;IAAQ,KAAK;GAAa;GAChC;IAAE,IAAI;IAAY,KAAK;GAAa;GACpC;IAAE,IAAI;IAAa,KAAK;GAAc;GACtC;IAAE,IAAI;IAAa,KAAK;GAAa;EACvC;;;;;;;;;;;;;;EAeA,SAAgB,UACd,KACA,OACA,SACA,OAAqB,KAAK,QACX;GACf,IAAI,CAAC,OAAO,SAAS,GAAG,KAAK,MAAM,GAAG,OAAO;GAC7C,MAAM,QAAQ,KAAK,MAAM,GAAG;GAC5B,MAAM,MAAM,OAAO,SAAS,OAAO,KAAK,WAAW,KAAK,UAAU,QAAQ,KAAK,MAAM,OAAO,IAAI;GAChG,IAAI,UAAU,WAAW;IAGvB,MAAM,OAAO,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,GAAG,CAAC,KAAK,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAC9E,OAAO,QAAQ,MAAM,OAAO,IAAI;GAClC;GACA,QAAQ,MAAM,KAAK;EACrB;;;;;;;EAQA,SAAgB,WAAW,KAAa,SAAkB,YAA6B;GACrF,OAAO,WAAW,OAAO,KAAK,OAAO,SAAS,UAAU,KAAK,aAAa;EAC5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EC7BA,SAAgB,cACd,UACA,cACA,aACS;GACT,OAAO,gBAAgB,YAAY,gBAAgB;EACrD;;;ECjCA,MAAa,cAAc;EAC3B,MAAM,SAAS;EACf,MAAM,eAAe,WAA2B,GAAG,OAAO,GAAG;EAe7D,IAAI,YAAuB;EAC3B,IAAI,eAAe;;EAGnB,SAAgB,iBAA0B;GAAE,OAAO,cAAc;EAAS;;EAG1E,SAAgB,eAAwB;GAAE,OAAO,cAAc;EAAS;EAExE,SAAS,YAAkB;GACzB,IAAI,cAAc;GAClB,eAAe;GACf,QAAQ,KACN,6NAGF;EACF;EAEA,IAAI,YAAiG;EAErG,SAAgB,QAAQ,MAAwF;GAC9G,YAAY;EACd;EAEA,eAAe,QAAQ,QAAgB,SAAoC;GACzE,IAAI,CAAC,WAAW,OAAO,KAAA;GACvB,IAAI;IACF,MAAM,MAAM,MAAM,UAAU,YAAY,MAAM,GAAG,OAAO;IACxD,IAAI,OAAO,IAAI,OAAO,MAAM,OAAO,IAAI;IACvC,QAAQ,KAAK,iCAAiC,OAAO,WAAW,KAAK,KAAK;IAC1E;GACF,SAAS,GAAG;IACV,QAAQ,KAAK,iCAAiC,OAAO,UAAU,CAAC;IAChE;GACF;EACF;;EAGA,eAAe,OAAO,QAAgB,SAAsD;GAC1F,IAAI,CAAC,WAAW,OAAO,KAAA;GACvB,IAAI;IACF,OAAO,MAAM,UAAU,YAAY,MAAM,GAAG,OAAO;GACrD,QAAQ;IACN;GACF;EACF;EAKA,MAAM,mBAAmB;EACzB,IAAI;EAEJ,SAAgB,aAAmB;GACjC,IAAI,CAAC,eAAe,GAAG;IAAE,UAAU;IAAG;GAAO;GAC7C,IAAI,cAAc,KAAA,GAAW,OAAO,aAAa,SAAS;GAC1D,YAAY,OAAO,iBAAiB;IAClC,YAAY,KAAA;IACZ,QAAa,eAAe,EAAE,QAAQ,IAAI,CAAC;GAC7C,GAAG,gBAAgB;EACrB;EAEA,SAAgB,YAAkB;GAChC,IAAI,cAAc,KAAA,GAAW;GAC7B,OAAO,aAAa,SAAS;GAC7B,YAAY,KAAA;GAGZ,IAAI,CAAC,eAAe,GAAG;IAAE,UAAU;IAAG;GAAO;GAC7C,QAAa,eAAe,EAAE,QAAQ,IAAI,CAAC;EAC7C;;EAGA,SAAgB,gBAAsB;GACpC,IAAI,CAAC,eAAe,GAAG;IAAE,UAAU;IAAG;GAAO;GAC7C,QAAa,eAAe,EAAE,QAAQ,IAAI,CAAC;EAC7C;;EAgBA,eAAsB,gBAA2C;GAC/D,MAAM,OAAO,MAAM,QAAQ,QAAQ,CAAC,CAAC;GACrC,IAAI,SAAS,QAAQ,OAAO,SAAS,UAAU,OAAO;GACtD,MAAM,IAAI;GACV,MAAM,QAAQ,MAAM,QAAQ,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,MAAmB,OAAO,MAAM,QAAQ,IAAI,CAAC;GACpG,MAAM,SAAS,OAAO,EAAE,WAAW,YAAY,SAAS,EAAE,MAAM,IAAI,EAAE,SAAS;GAG/E,YAAY,WAAW,OAAO,WAAY,UAAA,IAA2B,YAAY;GACjF,IAAI,cAAc,UAAU,UAAU;GACtC,OAAO;IAAE,QAAQ,EAAE;IAAQ;IAAO;GAAO;EAC3C;;EAGA,eAAsB,UAAU,MAAsC;GACpE,MAAM,OAAO,MAAM,QAAQ,aAAa,EAAE,KAAK,CAAC;GAChD,IAAI,SAAS,QAAQ,OAAO,SAAS,UAAU,OAAO;GACtD,MAAM,MAAO,KAA+B;GAC5C,OAAO,OAAO,QAAQ,WAAW,MAAM;EACzC;;EAGA,eAAsB,WAAW,MAAc,SAA0C;GAEvF,OAAO,MADW,QAAQ,cAAc;IAAE;IAAM;GAAQ,CAAC,MAC1C;EACjB;;EAGA,eAAsB,YAAY,MAAgC;GAEhE,OAAO,MADW,QAAQ,eAAe,EAAE,KAAK,CAAC,MAClC;EACjB;;EAGA,eAAsB,cAAc,MAAc,KAAmC;GACnF,MAAM,MAAM,MAAM,OAAO,iBAAiB;IAAE;IAAM;GAAI,CAAC;GACvD,IAAI,CAAC,KAAK,OAAO;IAAE,IAAI;IAAO,OAAO;GAAc;GACnD,IAAI,IAAI,OAAO,MAEb,OAAO;IAAE,IAAI;IAAO,OADP,IAAyC,OACtB,WAAW;GAAiB;GAE9D,MAAM,IAAI,IAAI;GACd,OAAO,GAAG,OAAO,OACb;IAAE,IAAI;IAAM,SAAS,EAAE,WAAW;GAAK,IACvC;IAAE,IAAI;IAAO,OAAO,GAAG,SAAS;GAAS;EAC/C;;EAGA,eAAsB,mBAA2C;GAC/D,MAAM,OAAO,MAAM,QAAQ,gBAAgB,CAAC,CAAC;GAC7C,IAAI,SAAS,QAAQ,OAAO,SAAS,UAAU,OAAO;GACtD,MAAM,IAAI;GACV,MAAM,QAAQ,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,QAAQ,MAAmB,OAAO,MAAM,YAAY,MAAM,EAAE;GAChG,OAAO,MAAM,SAAS,IAAI,MAAM,KAAK,GAAG,IAAI;EAC9C;;;ECnKA,SAAgB,SAAS,GAAW,GAAW,GAAqC;GAClF,MAAM,IAAI,KAAK,IAAI,IAAI;GAEvB,OAAO;IAAC;IADG,MAAM,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IAChD;GAAC;EAClB;EAEA,SAAgB,SAAS,GAAW,GAAW,GAAqC;GAClF,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;GAEnC,OAAO;IAAC;IADG,MAAM,IAAI,IAAI,KAAK,IAAI,IAAI;IACvB;GAAC;EAClB;EAEA,IAAI,iBAAiB;EACrB,IAAI,cAAwF;;;;;;;EAQ5F,SAAgB,UAAU,KAAa,KAAa,KAAgF;GAClI,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG;GAC7B,IAAI,mBAAmB,OAAO,aAAa,OAAO;GAClD,iBAAiB;GACjB,cAAc,YAAY,KAAK,KAAK,GAAG;GACvC,OAAO;EACT;EAEA,SAAS,YAAY,KAAa,KAAa,KAAgF;GAC7H,MAAM,OAAO,MAAM;GACnB,MAAM,KAAK,QAAgB,MAAM,KAAK,MAAM,OAAO;GACnD,MAAM,KAAK,MAAc,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC,CAAC;GACzD,MAAM,KAAK,MAAc,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC,CAAC;GACzD,MAAM,OAAO,IAAY,IAAY,OAAe,OAAO,KAAK,MAAM,EAAE,EAAE,GAAG,KAAK,MAAM,KAAK,GAAG,EAAE,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE;GAC3H,MAAM,QAAQ,IAAY,IAAY,IAAY,MAChD,QAAQ,KAAK,MAAM,EAAE,EAAE,GAAG,KAAK,MAAM,KAAK,GAAG,EAAE,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE;GAShF,MAAM,UAAU,EAAE,EAAG,IAAI,KAAM,SAAS;GAExC,IAAI,MAAM;IAOR,MAAM,WAAW,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;IACxC,OAAO;KACL,aAAa;KACb,QAAQ;MACN,uBAAuB,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAK,CAAC;MAC/C,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACjD,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACjD,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;MACrD,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;MACrD,kCAAkC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACzD,+BAA+B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAG,CAAC;MACrD,2BAA2B;MAC3B,yBAAyB,KAAK,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,GAAI,GAAG,GAAI;MAC1D,yBAAyB,KAAK,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,GAAI,GAAG,GAAI;MAC1D,yBAAyB;MACzB,yBAAyB;MACzB,+BAA+B;MAC/B,6BAA6B,IAAI,GAAG,GAAG,CAAC;MACxC,+BAA+B;MAC/B,8BAA8B;MAG9B,6BAA6B;MAC7B,4BAA4B;MAC5B,gCAAgC;MAChC,oCAAoC;MACpC,wCAAwC;MAGxC,sCAAsC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,KAAK,IAAI,EAAE,GAAI,GAAG,GAAI,CAAC;MAChF,oCAAoC,IAAI,GAAG,GAAG,CAAC;MAC/C,6BAA6B,IAAI,EAAE,CAAC,GAAG,EAAE,EAAG,GAAG,KAAK,IAAI,EAAE,EAAG,GAAG,EAAG,CAAC;MACpE,0BAA0B;MAC1B,mCAAmC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAG,GAAG,KAAK,IAAI,EAAE,EAAG,GAAG,EAAG,CAAC;MAC1E,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAG,GAAG,KAAK,IAAI,EAAE,GAAI,GAAG,GAAI,CAAC;MAC7E,qCAAqC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC5D,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC3D,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC3D,qCAAqC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,EAAG,CAAC;MAC3D,oCAAoC;MACpC,qCAAqC;MACrC,wCAAwC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC/D,0CAA0C;MAC1C,yCAAyC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAChE,gCAAgC;MAChC,iCAAiC;MACjC,oCAAoC,IAAI,GAAG,GAAG,CAAC;MAC/C,oCAAoC,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,IAAI,EAAE,GAAI,GAAG,EAAG,GAAG,GAAI;MACjF,0CAA0C,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,IAAI,EAAE,GAAI,GAAG,EAAG,GAAG,GAAI;MACvF,2CAA2C;MAC3C,2CAA2C;MAC3C,qCAAqC,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,IAAI,EAAE,GAAI,GAAG,EAAG,GAAG,EAAG;MACjF,mCAAmC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAK,CAAC;MAC3D,0CAA0C,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAK,CAAC;MAClE,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC3D,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAK,CAAC;MAC5D,4BAA4B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACnD,iCAAiC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACxD,8CAA8C,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACrE,gDAAgD,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAK,CAAC;MACxE,mCAAmC;MACnC,qCAAqC;MACrC,qCAAqC;MACrC,uCAAuC;MAKvC,sCAAsC;MACtC,kCAAkC;MAClC,oCAAoC;MACpC,mCAAmC;MACnC,gCAAgC;MAChC,sCAAsC;MACtC,uCAAuC;MACvC,+BAA+B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAK,CAAC;MACvD,0CAA0C,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACjE,yCAAyC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;MAC7D,8BAA8B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACrD,uBAAuB;MACvB,2BAA2B;MAC3B,yBAAyB,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAChD,mCAAmC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC1D,2BAA2B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAClD,8BAA8B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACrD,sBAAsB,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC7C,wBAAwB,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MAC/C,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,CAAC;MACjD,+BAA+B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;MAC1D,+BAA+B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;MAC1D,kCAAkC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;MAC7D,kCAAkC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;KAC/D;IACF;GACF;GAEA,MAAM,WAAW,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;GAC5C,OAAO;IACL,aAAa;IACb,QAAQ;KACN,uBAAuB,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;KAClD,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;KACrD,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,IAAK,CAAC;KACrD,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,IAAK,CAAC;KACtD,0BAA0B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;KACrD,yBAAyB,KAAK,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,IAAK,GAAG,GAAI;KAC5D,yBAAyB,KAAK,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,IAAK,GAAG,EAAG;KAC3D,6BAA6B,IAAI,GAAG,GAAG,CAAC;KACxC,+BAA+B;KAC/B,8BAA8B;KAG9B,6BAA6B;KAC7B,4BAA4B;KAC5B,gCAAgC;KAKhC,sCAAsC;KACtC,6BAA6B,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,KAAK,IAAI,EAAE,IAAK,GAAG,GAAI,CAAC;KACxE,0BAA0B;KAC1B,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,KAAK,IAAI,EAAE,IAAK,GAAG,EAAG,CAAC;KAC9E,qCAAqC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,IAAK,CAAC;KAChE,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,EAAG,CAAC;KAC7D,qCAAqC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,GAAI,CAAC;KAC/D,oCAAoC,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,GAAI;KAClE,qCAAqC,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,GAAI;KACnE,mCAAmC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,IAAK,CAAC;KAC9D,oCAAoC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;KAC/D,+BAA+B,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,IAAK,CAAC;KAC1D,0CAA0C,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,GAAI,CAAC;KACrE,yCAAyC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,CAAC,CAAC;KACjE,8BAA8B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,EAAG,CAAC;KACxD,uBAAuB;KACvB,2BAA2B;KAC3B,+BAA+B,IAAI,EAAE,CAAC,GAAG,EAAE,GAAI,GAAG,EAAE,IAAK,CAAC;KAC1D,+BAA+B,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,IAAK,CAAC;KAC3D,kCAAkC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,IAAK,CAAC;KAC9D,kCAAkC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAK,GAAG,EAAE,IAAK,CAAC;IAChE;GACF;EACF;EAEA,SAAgB,OAAO,GAAW,GAAmB;GACnD,MAAM,KAAK,gCAAgC,KAAK,EAAE,KAAK,CAAC;GACxD,IAAI,IAAI;IAAE,IAAI,IAAI,GAAG;IAAK,IAAI,EAAE,WAAW,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,KAAI,MAAK,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;IAAG,MAAM,IAAI,SAAS,GAAG,EAAE;IAAG,OAAO,QAAS,KAAK,KAAM,IAAI,GAAI,KAAK,IAAK,IAAI,GAAG,IAAI,IAAI,GAAG,EAAE;GAAG;GACvL,MAAM,MAAM,sEAAsE,KAAK,EAAE,KAAK,CAAC;GAC/F,IAAI,KAAK,OAAO,QAAQ,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,GAAG,EAAE;GACxD,MAAM,MAAM,uDAAuD,KAAK,EAAE,KAAK,CAAC;GAChF,IAAI,KAAK,OAAO,QAAQ,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,EAAE;GAC1D,OAAO,EAAE,KAAK;EAChB;EAEA,SAAgB,SAAS,GAAW,GAAW,GAAqC;GAClF,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,IAAI;GAC3C,MAAM,MAAM,KAAK,IAAI,IAAI,IAAI,EAAE,GAAG,MAAM,KAAK,IAAI,IAAI,IAAI,EAAE;GAC3D,MAAM,KAAK,MAAM,OAAO;GACxB,IAAI,QAAQ,KAAK,OAAO;IAAC;IAAG;IAAG;GAAC;GAChC,MAAM,IAAI,MAAM;GAChB,MAAM,IAAI,IAAI,KAAM,KAAK,IAAI,MAAM,OAAO,KAAK,MAAM;GACrD,IAAI;GACJ,IAAI,QAAQ,IAAI,KAAM,KAAK,MAAM,IAAK;QACjC,IAAI,QAAQ,IAAI,KAAK,KAAK,MAAM,IAAI;QACpC,KAAK,KAAK,MAAM,IAAI;GACzB,KAAK;GACL,IAAI,IAAI,GAAG,KAAK;GAChB,OAAO;IAAC;IAAG;IAAG;GAAC;EACjB;EASA,MAAM,eAAe;EAIrB,SAAS,aAAa,GAAqC;GACzD,OAAO,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK;EAC7D;EAEA,SAAS,wBAAwB,SAAiB,SAAgD;GAChG,OAAO,IAAI,SAAQ,YAAW;IAC5B,MAAM,MAAM,IAAI,MAAM;IACtB,IAAI,gBAAgB,QAAQ,IAAI;IAChC,IAAI,eAAe;KACjB,IAAI;MACF,MAAM,KAAK,IAAI,gBAAgB,IAAI;MACnC,MAAM,KAAK,IAAI,iBAAiB,IAAI;MACpC,MAAM,KAAK;MACX,IAAI,KAAK,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK;MAClC,IAAI,GAAG,OAAO,MAAM,GAAG,OAAO,MAAM,GAAG,KAAK,GAAG;OAC7C,MAAM,MAAM,KAAK,IAAI,OAAO,aAAa,IAAI,OAAO,cAAc,EAAE;OACpE,MAAM,IAAI,KAAK,MAAM,GAAG;OACxB,MAAM,IAAI,KAAK,MAAM,GAAG;OACxB,KAAK,KAAK,IAAI,GAAG,GAAG,IAAI,OAAO,aAAa,IAAI,CAAC;OACjD,KAAK,KAAK,IAAI,GAAG,GAAG,IAAI,OAAO,cAAc,IAAI,CAAC;OAClD,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;OACxB,KAAK,KAAK,IAAI,KAAK,IAAI,CAAC;OACxB,IAAI,MAAM,KAAK,MAAM,GAAG;QAAE,KAAK;QAAG,KAAK;QAAG,KAAK;QAAI,KAAK;OAAG;MAC7D;MACA,MAAM,IAAI,SAAS,cAAc,QAAQ;MACzC,EAAE,QAAQ;MAAc,EAAE,SAAS;MACnC,MAAM,IAAI,EAAE,WAAW,MAAM,EAAE,oBAAoB,KAAK,CAAC;MACzD,EAAE,UAAU,KAAK,IAAI,IAAI,IAAI,IAAI,GAAG,GAAG,cAAc,YAAY;MACjE,MAAM,KAAK,EAAE,aAAa,GAAG,GAAG,cAAc,YAAY,CAAC,CAAC;MAC5D,MAAM,yBAAS,IAAI,YAAY,IAAI;MACnC,MAAM,uBAAO,IAAI,aAAa,KAAQ;MACtC,IAAI,WAAW;MACf,IAAI,UAAU;MACd,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK,GAAG;OACrC,MAAM,IAAI,GAAG,IAAI,KAAK,GAAG,IAAI,IAAI,IAAI,GAAG,IAAI;OAC5C,MAAM,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;OACvD,MAAM,IAAI,MAAM;OAChB,MAAM,IAAI,QAAQ,IAAI,KAAK,MAAM,OAAO;OAQxC,aAAa,QAAS,IAAI,QAAS,KAAK,QAAS,KAAK;OACtD;OACA,IAAI,IAAI,OAAQ,IAAI,OAAQ,IAAI,KAAM;OACtC,MAAM,MAAQ,KAAK,KAAM,IAAO,MAAM,KAAM,IAAM,KAAK;OACvD,OAAO,IAAI;OACX,KAAK,MAAM,MAAM;OAAG,KAAK,MAAM,IAAI,MAAM;OAAI,KAAK,MAAM,IAAI,MAAM;MACpE;MACA,MAAM,UAAoB,CAAC;MAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,KAAK;OAC7B,IAAI,OAAO,OAAO,GAAG;OACrB,QAAQ,KAAK;QACX,OAAO,OAAO;QACd,GAAG,KAAK,IAAI;QACZ,GAAG,KAAK,IAAI,IAAI;QAChB,GAAG,KAAK,IAAI,IAAI;QAChB,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,EAAE,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,EAAE,KAAK,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,EAAE,KAAK;OACtL,CAAC;MACH;MACA,IAAI,QAAQ,WAAW,GAAG;OAAE,QAAQ,IAAI;OAAG;MAAO;MAElD,QAAQ,MAAM,GAAG,MAAM,EAAE,SAAS,KAAM,EAAE,KAAK,EAAE,SAAS,KAAM,EAAE,EAAE;MACpE,MAAM,UAAU,aAAa,QAAQ,EAAG;MACxC,MAAM,aAAa,QAAQ;MAE3B,IAAI,YAAY;MAChB,KAAK,MAAM,KAAK,QAAQ,MAAM,CAAC,GAAG;OAChC,MAAM,CAAC,KAAK,aAAa,CAAC;OAE1B,IADY,KAAK,KAAM,IAAI,aAAa,OAAO,MAAO,GAChD,IAAI,IAAI;QAAE,YAAY,aAAa,CAAC;QAAG;OAAM;MACrD;MAEA,IAAI,WAAqC;QAAG,aAAa,OAAO;OAAM,KAAK,IAAI,IAAK,QAAQ,EAAE;OAAG,KAAK,IAAI,IAAK,QAAQ,EAAE;MAAC;MAC1H,KAAK,MAAM,KAAK,QAAQ,MAAM,CAAC,GAAG;OAChC,MAAM,CAAC,KAAK,aAAa,CAAC;OAC1B,MAAM,MAAM,KAAK,KAAM,IAAI,aAAa,OAAO,MAAO,GAAG;OACzD,IAAI,MAAM,MAAM,MAAM,KAAK;QAAE,WAAW,aAAa,CAAC;QAAG;OAAM;MACjE;MAEA,MAAM,UAAoC;OAAC;OAAY,KAAK,IAAI,KAAM,QAAQ,KAAK,EAAG;OAAG,QAAQ;MAAE;MAGnG,MAAM,YAAY,UAAU,IAAI,WAAW,UAAU,QAAQ;MAI7D,QAAQ,KAFS,YAAY,KACP,KAAK,IAAI,KAAM,KAAK,IAAI,IAAK,QAAQ,EAAE,CAAC,IAAI,KAAK,IAAI,IAAK,KAAK,IAAI,KAAM,QAAQ,EAAE,CAAC;MAE1G,QAAQ;OACN,SAAS;QAAC,QAAQ;QAAI,KAAK,IAAI,IAAK,KAAK,IAAI,KAAM,QAAQ,EAAE,CAAC;QAAG,QAAQ;OAAE;OAC3E,WAAW;QAAC,UAAU;QAAI,KAAK,IAAI,KAAM,KAAK,IAAI,IAAK,UAAU,EAAE,CAAC;QAAG,KAAK,IAAI,KAAM,KAAK,IAAI,KAAM,UAAU,EAAE,CAAC;OAAC;OACnH,UAAU;QAAC,SAAS;QAAI,KAAK,IAAI,IAAK,KAAK,IAAI,IAAK,SAAS,EAAE,CAAC;QAAG,KAAK,IAAI,IAAK,KAAK,IAAI,KAAM,SAAS,EAAE,CAAC;OAAC;OAC7G;OACA;MACF,CAAC;KACH,QAAQ;MACN,QAAQ,IAAI;KACd;IACF;IACA,IAAI,MAAM;GACZ,CAAC;EACH;;EAGA,eAAsB,sBAAsB,SAAiB,SAA4D;GACvH,MAAM,UAAU,MAAM,wBAAwB,SAAS,OAAO;GAC9D,OAAO,UAAU,QAAQ,UAAU;EACrC;;EAsCA,SAAgB,SAAS,GAAW,GAAW,GAAqC;GAClF,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK;GACtC,MAAM,KAAK,IAAI;GACf,MAAM,IAAI,KAAK,IAAI,KAAK,IAAK,KAAK,IAAK,CAAC;GACxC,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI;GACtB,IAAI,KAAK,GAAG;IAAE,IAAI;IAAG,IAAI;GAAE,OACtB,IAAI,KAAK,GAAG;IAAE,IAAI;IAAG,IAAI;GAAE,OAC3B,IAAI,KAAK,GAAG;IAAE,IAAI;IAAG,IAAI;GAAE,OAC3B,IAAI,KAAK,GAAG;IAAE,IAAI;IAAG,IAAI;GAAE,OAC3B,IAAI,KAAK,GAAG;IAAE,IAAI;IAAG,IAAI;GAAE,OAC3B;IAAE,IAAI;IAAG,IAAI;GAAE;GACpB,MAAM,IAAI,IAAI,IAAI;GAClB,OAAO;IAAC,KAAK,OAAO,IAAI,KAAK,GAAG;IAAG,KAAK,OAAO,IAAI,KAAK,GAAG;IAAG,KAAK,OAAO,IAAI,KAAK,GAAG;GAAC;EACzF;ECpYA,MAAa,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2UtB,MAAM,SAAS;;;;;;;;;;;EAYf,MAAa,iBAAiB;;EAG9B,SAAgB,aAAa,IAAwC;GACnE,GAAG,aAAa,gBAAgB,KAAK;GACrC,OAAO;EACT;;EAGA,SAAgB,cAAoB;GAClC,IAAI,OAAO,aAAa,aAAa;GACrC,IAAI,KAAK,SAAS,eAAe,MAAM;GACvC,IAAI,CAAC,IAAI;IACP,KAAK,SAAS,cAAc,OAAO;IACnC,GAAG,KAAK;IACR,aAAa,EAAE;IACf,SAAS,KAAK,YAAY,EAAE;GAC9B;GACA,IAAI,GAAG,gBAAgB,QAAQ,GAAG,cAAc;EAClD;;;;;;;;;;EC5WA,MAAa,aAAa;EAC1B,MAAM,YAAY;;;;;;;;;EAUlB,MAAM,cAAc;EAEpB,IAAI,OAA8B;EAClC,IAAI,oBAA8B,CAAC;EACnC,IAAI,eAAwC;EAE5C,SAAS,mBAAqC;GAC5C,IAAI,cAAc,aAAa,OAAO;GACtC,eAAe,SAAS,cAAc,OAAO;GAC7C,aAAa,QAAQ,SAAS;GAC9B,aAAa,YAAY;GACzB,SAAS,KAAK,YAAY,YAAY;GACtC,OAAO;EACT;EAEA,SAAS,oBAA0B;GACjC,IAAI,cAAc,aAAa,cAAc;GAC7C,KAAK,MAAM,QAAQ,mBAAmB,SAAS,KAAK,MAAM,eAAe,IAAI;GAC7E,oBAAoB,CAAC;GAGrB,eAAe;GACf,YAAY;EACd;;;;;EAMA,SAAS,qBAA2B;GAClC,cAAc;GACd,MAAM,OAAO,SAAS;GACtB,KAAK,MAAM,QAAQ,oBAAoB,KAAK,MAAM,eAAe,IAAI;GACrE,KAAK,MAAM,MAAM;IAAC;IAAS;IAAU;GAAS,GAAG,IAAI,MAAM,eAAe,YAAY;EACxF;EAaA,MAAM,uBAA8E;GAClF;IAAE,MAAM;IAAM,OAAO,CAAC,qBAAqB;GAAE;GAC7C;IAAE,MAAM;IAAW,OAAO,CAAC,6BAA6B;GAAE;GAC1D;IAAE,MAAM;IAAQ,OAAO;KAAC;KAA0B;KAA0B;KAA0B;KAAuB;IAAyB;GAAE;GACxJ;IAAE,MAAM;IAAS,OAAO,CAAC,4BAA4B;GAAE;EACzD;EAMA,MAAM,eAAuC;GAC3C,uBAAuB;GACvB,+BAA+B;GAC/B,0BAA0B;GAC1B,0BAA0B;GAC1B,0BAA0B;GAC1B,8BAA8B;GAI9B,uBAAuB;GACvB,2BAA2B;EAC7B;EAKA,IAAI,eAAe;EAYnB,MAAM,sBAAgC,OAAO,KAAK,YAAY;;EAG9D,MAAM,wBAAwB;GAC5B;GACA;GACA;GACA;EACF;EACA,MAAM,0BAA0B;GAC9B;GACA;GACA;EACF;EACA,MAAM,qBAAqB,CAAC,GAAG,uBAAuB,GAAG,uBAAuB;EAQhF,IAAI,YAAgC;;;;EAKpC,SAAS,gBAAgB,KAA4B;GACnD,MAAM,QAAQ,IAAI,KAAK;GACvB,IAAI,UAAU,IAAI,OAAO;GACzB,IAAI,cAAc,MAAM;IACtB,YAAY,SAAS,cAAc,MAAM;IACzC,UAAU,aAAa,eAAe,MAAM;IAC5C,UAAU,MAAM,UAAU;GAC5B;GACA,IAAI,CAAC,UAAU,aAAa,SAAS,KAAK,YAAY,SAAS;GAE/D,UAAU,MAAM,QAAQ;GACxB,UAAU,MAAM,QAAQ;GACxB,IAAI,UAAU,MAAM,UAAU,IAAI,OAAO;GACzC,OAAO,iBAAiB,SAAS,CAAC,CAAC,SAAS;EAC9C;;EAGA,SAAS,kBAAkC;GACzC,MAAM,QAAQ;GAId,MAAM,QAAQ,UAAU,QAAQ,MAAM,eAAe,CAAC,MAAM;GAC5D,IAAI,OAAO,MAAO,WAAW;GAC7B,IAAI;IACF,MAAM,WAAW,iBAAiB,SAAS,IAAI;IAC/C,MAAM,SAAiC,CAAC;IACxC,KAAK,MAAM,QAAQ,qBAAqB;KACtC,MAAM,OAAO,gBAAgB,SAAS,iBAAiB,IAAI,CAAC;KAC5D,IAAI,SAAS,MAAM,OAAO,QAAQ;IACpC;IAGA,OAAO,OAAO,2BAA2B,KAAA,IAAY,OAAO;KAAE,KAAK;KAAO;IAAO;GACnF,UAAU;IACR,IAAI,OAAO,MAAO,WAAW;GAC/B;EACF;EAKA,IAAI,mBAAmE;EACvE,MAAM,sBAAsB;EAE5B,SAAgB,wBAA8B;GAAE,mBAAmB;EAAK;EAExE,SAAS,cAA8B;GACrC,MAAM,MAAM,KAAK,IAAI;GACrB,IAAI,qBAAqB,QAAQ,MAAM,iBAAiB,KAAK,qBAAqB,OAAO,iBAAiB;GAC1G,MAAM,OAAO,gBAAgB;GAC7B,mBAAmB;IAAE,IAAI;IAAK,SAAS;GAAK;GAC5C,OAAO;EACT;;EAGA,SAAS,UAA0B;GACjC,IAAI,CAAC,UAAU,GAAG,OAAO,YAAY;GACrC,MAAM,CAAC,GAAG,GAAG,KAAK,OAAO;GACzB,OAAO;IAAE,KAAK;IAAM,QAAQ,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC;GAAO;EACxD;;;;;;;EAQA,SAAS,UAAU,OAAe,OAAuB;GACvD,MAAM,YAAY,OAAO,OAAO,KAAK;GACrC,IAAI,kBAAkB,KAAK,SAAS,GAAG,OAAO;GAE9C,OAAO,sBAAsB,MAAM,GADvB,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,IAAI,GACjB,EAAE;EAC5C;;;;;;;EAQA,IAAI,iBAAiC;EAErC,SAAgB,cAAc,MAA4B;GAAE,iBAAiB;EAAK;EAElF,SAAS,kBAA2B;GAClC,IAAI,OAAO,mBAAmB,WAAW,OAAO;GAGhD,MAAM,SAAS,SAAS,gBAAgB,QAAQ;GAChD,IAAI,WAAW,QAAQ,OAAO;GAC9B,IAAI,WAAW,SAAS,OAAO;GAC/B,IAAI;IAAE,OAAO,OAAO,WAAW,8BAA8B,CAAC,CAAC;GAAQ,QAAQ;IAAE,OAAO;GAAM;EAChG;;;;;;;;;;;;;;EAeA,SAAgB,kBAAwB;GACtC,MAAM,OAAO,gBAAgB;GAC7B,MAAM,UAAU,SAAS,KAAK,aAAa,SAAS;GACpD,IAAI,MACE;QAAA,YAAY,IAAI,SAAS,KAAK,aAAa,WAAW,EAAE;GAAA,OACvD,IAAI,YAAY,MACrB,SAAS,KAAK,gBAAgB,SAAS;EAE3C;;;;EAKA,SAAgB,qBAA2B;GACzC,gBAAgB;GAChB,sBAAsB;GACtB,kBAAkB,KAAK,CAAC;EAC1B;EAKA,IAAI,aAAmC;EACvC,IAAI,YAA2B;EAE/B,SAAgB,kBAAkB,KAA0B;GAC1D,aAAa;GACb,IAAI,cAAc,MAAM;GACxB,YAAY,4BAA4B;IACtC,YAAY;IACZ,IAAI,eAAe,MAAM;IACzB,MAAM,IAAI;IACV,aAAa;IACb,qBAAqB,CAAC;GACxB,CAAC;EACH;EAIA,IAAI,YAAY;EAEhB,SAAS,qBAAqB,KAA0B;GACtD,MAAM,MAAM,QAAQ;GACpB,IAAI,QAAQ,MAAM;IAIhB,kBAAkB;IAClB,mBAAmB;IACnB,gBAAgB;IAChB;GACF;GACA,MAAM,EAAE,KAAK,WAAW;GACxB,MAAM,CAAC,GAAG,GAAG,KAAK,OAAO;GACzB,IAAI;IACF,MAAM,YAAY,OAAO,IAAI;IAG7B,MAAM,MAAM,MACR,OAAO,EAAE,GAAG,EAAE,GAAG,MACjB,QAAQ,oBAAoB,KAAI,MAAK,OAAO,MAAM,EAAE,CAAC,CAAC,KAAK,GAAG;IAClE,IAAI,QAAQ,cAAc;KAOxB,IAAI,KAAK;MACP,IAAI,WAAW,SAAS,KAAK,aAAa,WAAW,UAAU;WAC1D,SAAS,KAAK,gBAAgB,SAAS;KAC9C,OACE,gBAAgB;KAElB,MAAM,QAAkB,MAAM,CAAC,gBAAgB,YAAY,SAAS,SAAS,IAAI,CAAC;KAClF,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,MAAM,GAAG;MAClD,MAAM,QAAQ,aAAa;MAC3B,MAAM,KAAK,GAAG,KAAK,GAAG,UAAU,KAAA,IAAY,OAAO,MAAM,KAAK,MAAM,WAAW;KACjF;KACA,iBAAiB,CAAC,CAAC,cAAc,QAAQ,MAAM,KAAK,GAAG,EAAE;KACzD,IAAI,KAAK;MAEP,KAAK,MAAM,QAAQ,mBAAmB,SAAS,KAAK,MAAM,eAAe,IAAI;MAC7E,oBAAoB,OAAO,KAAK,MAAM;KACxC;KAGA,eAAe;IACjB;IAEA,MAAM,OAAO,SAAS;IACtB,KAAK,MAAM,KAAK,sBACd,KAAK,MAAM,QAAQ,EAAE,OACnB,KAAK,MAAM,YAAY,aAAa,OAAO,UAAU,OAAO,SAAS,QAAQ,IAAI,EAAE,KAAK,CAAC;IAI7F,KAAK,MAAM,YAAY,4BAA4B,UAAU,OAAO,0BAA0B,QAAQ,IAAI,KAAK,CAAC;IAChH,MAAM,QAAQ,GAAG,aAAa,GAAG,IAAI;IACrC,IAAI,UAAU,WAAW;KAAE,YAAY;KAAO,mBAAmB,GAAG;IAAE;GACxE,QAAQ,CAER;EACF;EAQA,MAAM,qBAAqB;EAC3B,MAAa,sBACX,GAAG,mBAAmB,qIASd,YAAY,IAAI,mBAAmB,iLAKxC,mBAAmB;EAYxB,MAAa,kBACX;EAKF,SAAS,eAAe,IAAkB;GACxC,IAAI,KAAK,GAAG,SAAS,gBAAgB,MAAM,YAAY,wBAAwB,QAAQ,GAAG,IAAI;QACzF,SAAS,gBAAgB,MAAM,eAAe,sBAAsB;EAC3E;EAgBA,SAAgB,uBAAuB,IAAkB;GAKvD,MAAM,SAAS,QAAQ,CAAC,EAAE,UAAU,CAAC;GACrC,MAAM,OAAO,SAAS;GACtB,MAAM,SAAS,MAAc,UAAwB;IACnD,MAAM,QAAQ,OAAO;IACrB,IAAI,UAAU,KAAA,GAAW,KAAK,MAAM,eAAe,IAAI;SAClD,KAAK,MAAM,YAAY,MAAM,UAAU,OAAO,EAAE,CAAC;GACxD;GAIA,MAAM,iCAAiC,wBAAwB;GAG/D,MAAM,iCAAiC,wBAAwB;GAC/D,MAAM,iCAAiC,wBAAwB;GAC/D,MAAM,iCAAiC,wBAAwB;EACjE;EAMA,MAAa,wBAEX,QAAQ,YAAY;EAMtB,SAAgB,yBAAyB,IAAkB;GAGzD,MAAM,SAAS,QAAQ,CAAC,EAAE,UAAU,CAAC;GACrC,MAAM,OAAO,SAAS;GACtB,MAAM,SAAS,MAAc,UAAwB;IACnD,MAAM,QAAQ,OAAO;IACrB,IAAI,UAAU,KAAA,GAAW,KAAK,MAAM,eAAe,IAAI;SAClD,KAAK,MAAM,YAAY,MAAM,UAAU,OAAO,EAAE,CAAC;GACxD;GACA,MAAM,0BAA0B,wBAAwB;GACxD,MAAM,0BAA0B,wBAAwB;GACxD,MAAM,0BAA0B,wBAAwB;EAC1D;EAmCA,MAAa,sBACX;;EASF,SAAgB,uBAAuB,IAAkB;GACvD,MAAM,OAAO,SAAS;GAItB,MAAM,OAAO,QAAQ,CAAC,EAAE,OAAO;GAC/B,IAAI,SAAS,KAAA,GAAW;IAAE,KAAK,MAAM,eAAe,uBAAuB;IAAG;GAAO;GACrF,KAAK,MAAM,YAAY,yBAAyB,UAAU,MAAM,EAAE,CAAC;EACrE;;EAGA,SAAS,kBAAkB,IAAkB;GAC3C,IAAI,KAAK,GAAG,SAAS,gBAAgB,MAAM,YAAY,2BAA2B,QAAQ,GAAG,IAAI;QAC5F,SAAS,gBAAgB,MAAM,eAAe,yBAAyB;EAC9E;EAWA,IAAI,UAA8B;EAClC,IAAI,YAAgC;EACpC,IAAI,WAA+B;EACnC,IAAI,YAAgC;EAEpC,MAAM,kBAAkB;EACxB,MAAM,sBAAsB;EAC5B,MAAM,iBACJ,GAAG,gBAAgB,sBACf,oBAAoB;EAG1B,IAAI,kBAA2C;EAE/C,SAAS,sBAA4B;GACnC,IAAI,iBAAiB,aAAa;GAClC,kBAAkB,SAAS,cAAc,OAAO;GAChD,gBAAgB,QAAQ,SAAS;GACjC,aAAa,eAAe;GAC5B,gBAAgB,cAAc;GAC9B,SAAS,KAAK,YAAY,eAAe;EAC3C;EAEA,SAAS,gBAAsB;GAC7B,MAAM,UAAU,SAAS,cAA2B,sBAAsB;GAC1E,IAAI,YAAY,MAAM;GACtB,MAAM,QAAQ,QAAQ;GACtB,IAAI,UAAU,MAAM;GACpB,UAAU;GACV,MAAM,MAAM,MAAM,KAAK,MAAM,QAAQ,CAAC,CAAC,QAAQ,OAAO;GACtD,YAAa,MAAM,SAAS,MAAM,MAAkC;GACpE,WAAY,MAAM,SAAS,MAAM,MAAkC;GACnE,YAAa,MAAM,SAAS,MAAM,MAAkC;EACtE;EAEA,SAAS,QAAQ,IAAwB,IAAkB;GACzD,IAAI,OAAO,MAAM;GACjB,MAAM,WAAW,GAAG,cAA8B,aAAa,qBAAqB;GACpF,IAAI,KAAK,GAAG;IACV,oBAAoB;IAIpB,IAAI,CAAC,GAAG,UAAU,SAAS,eAAe,KAAK,iBAAiB,EAAE,CAAC,CAAC,aAAa,UAAU;KACzF,GAAG,MAAM,WAAW;KACpB,GAAG,aAAa,wBAAwB,GAAG;IAC7C;IACA,GAAG,UAAU,IAAI,eAAe;IAChC,IAAI,aAAa,MAAM;KACrB,MAAM,OAAO,SAAS,cAAc,KAAK;KACzC,KAAK,YAAY;KACjB,GAAG,QAAQ,IAAI;IACjB;IACA,GAAG,MAAM,YAAY,uBAAuB,QAAQ,GAAG,IAAI;GAC7D,OAAO;IACL,GAAG,UAAU,OAAO,eAAe;IACnC,GAAG,MAAM,eAAe,qBAAqB;IAC7C,UAAU,OAAO;IACjB,IAAI,GAAG,aAAa,sBAAsB,MAAM,KAAK;KACnD,GAAG,MAAM,eAAe,UAAU;KAClC,GAAG,gBAAgB,sBAAsB;IAC3C;GACF;EACF;EAEA,SAAS,kBAAkB,IAAkB;GAC3C,IAAI,KAAK,GAAG,SAAS,gBAAgB,MAAM,YAAY,2BAA2B,QAAQ,GAAG,IAAI;QAC5F,SAAS,gBAAgB,MAAM,eAAe,yBAAyB;EAC9E;;;;;EAMA,SAAS,mBAAmB,KAA0B;GACpD,cAAc;GACd,IAAI,YAAY,MAAM;GACtB,MAAM,OAAO,QAAQ,CAAC,EAAE,OAAO;GAC/B,IAAI,SAAS,KAAA,GAAW;IAGtB,KAAK,MAAM,MAAM;KAAC;KAAS;KAAU;IAAS,GAAG,IAAI,MAAM,eAAe,YAAY;IACtF;GACF;GACA,QAAQ,MAAM,aAAa;GAC3B,IAAI,aAAa,MAAM,SAAS,MAAM,aAAa,UAAU,MAAM,IAAI,EAAE;GACzE,IAAI,cAAc,MAAM,UAAU,MAAM,aAAa,UAAU,MAAM,IAAI,EAAE;EAC7E;;;;;EAMA,SAAS,oBAAoB,IAAkB;GAC7C,IAAI,KAAK,GAAG,SAAS,gBAAgB,MAAM,YAAY,8BAA8B,QAAQ,GAAG,IAAI;QAC/F,SAAS,gBAAgB,MAAM,eAAe,4BAA4B;EACjF;;EAGA,SAAgB,eAAe,OAAwB;GACrD,cAAc;GAId,QAAQ,SAAS,CAAC;GAClB,QAAQ,WAAW,MAAM,OAAO;GAChC,QAAQ,UAAU,MAAM,EAAE;GAC1B,QAAQ,WAAW,MAAM,EAAE;GAC3B,oBAAoB,MAAM,IAAI;GAC9B,kBAAkB,MAAM,QAAQ;GAChC,eAAe,MAAM,KAAK;GAC1B,kBAAkB,MAAM,QAAQ;GAChC,eAAe;EACjB;;EAGA,SAAgB,YAAY,MAAuB,GAAiB;GAClE,IAAI,SAAS,YAAY;IAAE,kBAAkB,CAAC;IAAG;GAAO;GACxD,IAAI,SAAS,QAAQ;IAAE,oBAAoB,CAAC;IAAG;GAAO;GACtD,IAAI,SAAS,SAAS;IAAE,eAAe,CAAC;IAAG;GAAO;GAClD,IAAI,SAAS,YAAY;IAAE,kBAAkB,CAAC;IAAG;GAAO;GACxD,IAAI,SAAS,UAAU,SAAS,cAAc;IAAE,eAAe;IAAG;GAAO;GACzE,cAAc;GACd,IAAI,SAAS,MAAM;IAAE,QAAQ,UAAU,CAAC;IAAG,QAAQ,WAAW,CAAC;GAAE,OAC5D,QAAQ,WAAW,CAAC;EAC3B;EAiCA,MAAM,aAA6B,CACjC;GAAE,KAAK;GAAoB,MAAM;GAAsB,MAAM;GAAe,SAAS;GAAkB,YAAY,OAAO,CAAC,CAAC;GAAM,UAAU;EAAK,GACjJ;GAAE,KAAK;GAAwC,MAAM;GAAsB,MAAM;GAAe,SAAS;GAAoB,YAAY,OAAO,CAAC,CAAC;GAAY,OAAO;EAAK,CAC5K;EAEA,MAAM,cAAyC,WAAW,UAAU,IAAI;EAExE,SAAS,cAAc,IAA0B;GAC/C,MAAM,KAAK,iBAAiB,EAAE,CAAC,CAAC;GAEhC,OAAO,OAAO,UAAU,OAAO,YAAY,OAAO;EACpD;;;EAIA,SAAS,mBAAmB,IAA0B;GACpD,OAAO,GAAG,cAAc,oHAA4G,MAAM;EAC5I;;EAGA,SAAS,oBAAoB,OAAiC;GAC5D,IAAI,MAAM;GACV,KAAK,IAAI,QAAQ,GAAG,QAAQ,IAAI,SAAS;IACvC,IAAI,cAAc,GAAG,GAAG;IACxB,MAAM,OAAO,MAAM,KAAK,IAAI,QAAQ,CAAC,CAAC,QAAQ,MAAwB,aAAa,WAAW;IAC9F,IAAI,KAAK,WAAW,GAAG;IACvB,MAAM,UAAU,KAAK,QAAQ,GAAG,MAAO,EAAE,eAAe,EAAE,eAAe,IAAI,CAAE;IAC/E,IAAI,mBAAmB,GAAG,GAAG;KAC3B,MAAM,aAAa,KAAK,QAAO,MAAK,CAAC,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,IAAI,eAAe,EAAG;KACtG,IAAI,WAAW,WAAW,GAAG;KAC7B,MAAM,WAAW,QAAQ,GAAG,MAAO,EAAE,eAAe,EAAE,eAAe,IAAI,CAAE;KAC3E;IACF;IACA,IAAI,KAAK,SAAS,KAAK,QAAQ,gBAAgB,IAAI,eAAe,KAAM;KAAE,MAAM;KAAS;IAAS;IAClG;GACF;GACA,OAAO;EACT;EAEA,SAAS,mBAAmB,KAAa,MAAwC;GAC/E,IAAI,aAAa,QAAQ,CAAC,SAAS,KAAK,SAAS,QAAQ,GAAG;IAAE,YAAY,OAAO;IAAM,OAAO;GAAK;GAGnG,MAAM,SAAS,SAAS,cAA2B,KAAK,GAAG;GAC3D,MAAM,SAAS,YAAY;GAC3B,IAAI,WAAW,MAAM;IACnB,IAAI,WAAW,QAAQ,WAAW,QAAQ;KAAE,QAAQ,QAAQ,CAAC;KAAG,gBAAgB,QAAQ,KAAK,MAAM,KAAK,MAAM,KAAK,UAAU,IAAI;IAAE;IACnI,YAAY,OAAO;IACnB,OAAO;GACT;GACA,IAAI,WAAW,QAAQ,SAAS,SAAS,MAAM,GAAG,OAAO;GACzD,YAAY,OAAO;GACnB,IAAI,KAAK,aAAa,MAAM,OAAO;GAInC,IAAI,SAAS,cAAc,4BAA4B,MAAM,MAAM,OAAO;GAE1E,IAAI,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,OAAO;GACpD,IAAI,OAA2B;GAC/B,IAAI,WAAW;GACf,KAAK,MAAM,MAAM,MAAM,KAAK,SAAS,iBAA8B,GAAG,CAAC,GAAG;IACxE,IAAI,CAAC,cAAc,EAAE,GAAG;IACxB,IAAI,GAAG,eAAe,SAAS,eAAe,KAAM;IACpD,MAAM,OAAO,GAAG,cAAc,GAAG;IACjC,IAAI,OAAO,UAAU;KAAE,WAAW;KAAM,OAAO;IAAG;GACpD;GACA,IAAI,SAAS,MACX,KAAK,MAAM,MAAM,MAAM,KAAK,SAAS,QAAQ,GAAG;IAC9C,IAAI,EAAE,cAAc,cAAc;IAClC,IAAI,GAAG,eAAe,SAAS,eAAe,IAAK;IACnD,IAAI,GAAG,gBAAgB,MAAM,gBAAgB,IAAI,OAAO;GAC1D;GAEF,MAAM,UAAU,SAAS,OAAO,oBAAoB,IAAI,IAAI;GAC5D,YAAY,OAAO;GACnB,OAAO;EACT;;EAGA,SAAS,cAAc,IAAiB,MAAc,OAAsB;GAC1E,MAAM,KAAK,GAAG;GACd,GAAG,OAAO,QAAQ,GAAG,MAAM,iBAAiB,YAAY;GACxD,IAAI,OAAO;GACX,GAAG,OAAO,YAAY,GAAG,MAAM,iBAAiB,QAAQ;GACxD,GAAG,OAAO,YAAY,GAAG,MAAM,iBAAiB,eAAe;GAC/D,GAAG,OAAO,aAAa,GAAG,MAAM,iBAAiB,SAAS;EAC5D;;EAGA,SAAS,gBAAgB,IAAiB,MAAc,MAAc,OAAsB;GAC1F,IAAI,CAAC,GAAG,aAAa,IAAI,GAAG;GAC5B,MAAM,KAAK,GAAG;GACd,MAAM,WAAW,MAAc,MAAgC;IAC7D,IAAI,MAAM,KAAA,KAAa,MAAM,IAAI,GAAG,MAAM,YAAY,MAAM,CAAC;SACxD,GAAG,MAAM,eAAe,IAAI;GACnC;GACA,QAAQ,cAAc,GAAG,OAAO,KAAK;GACrC,IAAI,CAAC,OAAO;IACV,QAAQ,UAAU,GAAG,OAAO,SAAS;IACrC,QAAQ,iBAAiB,GAAG,OAAO,SAAS;IAC5C,QAAQ,WAAW,GAAG,OAAO,UAAU;IACvC,OAAO,GAAG,OAAO;IAAW,OAAO,GAAG,OAAO;IAAW,OAAO,GAAG,OAAO;GAC3E;GACA,OAAO,GAAG,OAAO;GACjB,GAAG,gBAAgB,IAAI;EACzB;;EAGA,SAAS,kBAAwB;GAC/B,WAAW,SAAS,MAAM,MAAM;IAC9B,MAAM,KAAK,YAAY;IACvB,IAAI,OAAO,MAAM;KAAE,QAAQ,IAAI,CAAC;KAAG,gBAAgB,IAAI,KAAK,MAAM,KAAK,MAAM,KAAK,UAAU,IAAI;IAAE;IAClG,YAAY,KAAK;GACnB,CAAC;EACH;EAOA,MAAM,iBAAiB;GACrB;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACF,CAAC,CAAC,KAAK,IAAI;EACX,IAAI,kBAA2C;;EAG/C,SAAS,eAAqB;GAE5B,IAAI,EADW,iBAAiB,IAAI,KAAK,OAAO,CAAC,CAAC,OAAO,IAC5C;IACX,IAAI,oBAAoB,MAAM;KAAE,gBAAgB,OAAO;KAAG,kBAAkB;IAAK;IACjF;GACF;GACA,IAAI,oBAAoB,MAAM;IAC5B,kBAAkB,SAAS,cAAc,OAAO;IAChD,gBAAgB,QAAQ,SAAS;IACjC,aAAa,eAAe;IAC5B,gBAAgB,cAAc;GAChC;GACA,IAAI,CAAC,gBAAgB,aAAa,SAAS,KAAK,YAAY,eAAe;EAC7E;;EAGA,SAAgB,iBAAuB;GACrC,cAAc;GACd,IAAI,aAAa,MAAM;GAGvB,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO;GAClC,WAAW,SAAS,MAAM,MAAM;IAC9B,MAAM,SAAS,mBAAmB,GAAG,IAAI;IACzC,IAAI,WAAW,MAAM;IACrB,MAAM,QAAQ,KAAK,UAAU;IAC7B,MAAM,UAAU,KAAK,QAAQ;IAC7B,MAAM,SAAS,KAAK,KAAK;IACzB,IAAI,CAAC,OAAO;KACV,IAAI,CAAC,OAAO,aAAa,KAAK,IAAI,GAAG,cAAc,QAAQ,KAAK,MAAM,KAAK;KAI3E,MAAM,cAAc,UAAU,IAAI,KAAK,IAAI,GAAG,UAAU,GAAG,IAAK,SAAS,IAAI,MAAO;KACpF,OAAO,MAAM,aAAa,YAAY,KAAA,IAAY,UAAU,SAAS,OAAO,IAAI;KAChF,OAAO,MAAM,SAAS,YAAY,KAAA,IAAY,aAAa,UAAU,SAAS,WAAW,MAAM;KAC/F,OAAO,MAAM,eAAe;KAC5B,OAAO,MAAM,UAAU;IACzB;IAEA,OAAO,aAAa,KAAK,MAAM,GAAG;IAClC,QAAQ,QAAQ,MAAM;GACxB,CAAC;GACD,aAAa;EACf;EAEA,IAAI,gBAAyC;;;EAI7C,SAAgB,aAAmB;GACjC,IAAI,kBAAkB,QAAQ,OAAO,qBAAqB,aAAa;GACvE,gBAAgB,IAAI,uBAAuB;IACzC,IAAI,YAAY,QAAQ,cAAc,QAAQ,aAAa,QAAQ,cAAc,QAAQ,SAAS,KAAK,SAAS,OAAO,KAElH,YAAY,OAAM,OAAM,OAAO,QAAQ,SAAS,KAAK,SAAS,EAAE,CAAC,GAAG;IACzE,eAAe,OAAO,CAAC;IACvB,mBAAmB,KAAK,CAAC;GAC3B,CAAC;GACD,cAAc,QAAQ,SAAS,MAAM;IAAE,WAAW;IAAM,SAAS;GAAK,CAAC;EACzE;EAEA,SAAgB,oBAA0B;GACxC,eAAe,WAAW;GAC1B,gBAAgB;EAClB;EASA,IAAI,gBAAyC;EAC7C,IAAI,WAAW;EAEf,SAAS,iBAAuB;GAC9B,MAAM,KAAK,KAAK,OAAO;GACvB,IAAI,IAAI,KAAM,SAAS,KAAK,aAAa,WAAW,UAAU;QACzD,SAAS,KAAK,gBAAgB,SAAS;GAC5C,kBAAkB,KAAK,CAAC;EAC1B;;;;;;EAOA,SAAgB,mBAA+B;GAC7C,IAAI,kBAAkB,QAAQ,OAAO,qBAAqB,aAAa,aAAa,KAAA;GACpF,gBAAgB,IAAI,uBAAuB;IACzC,sBAAsB;IACtB,IAAI,SAAS,KAAK,aAAa,SAAS,MAAA,2BAAkB;IAC1D,IAAI,CAAC,UAAU,GAAG;KAEhB,kBAAkB,KAAK,CAAC;KACxB;IACF;IACA,IAAI,aAAa,GAAG;IACpB,WAAW,4BAA4B;KACrC,WAAW;KACX,IAAI,SAAS,KAAK,aAAa,SAAS,MAAA,2BAAkB;KAC1D,eAAe;IACjB,CAAC;GACH,CAAC;GACD,cAAc,QAAQ,SAAS,MAAM;IAAE,YAAY;IAAM,iBAAiB,CAAC,SAAS;GAAE,CAAC;GACvF,cAAc,QAAQ,SAAS,iBAAiB;IAAE,YAAY;IAAM,iBAAiB,CAAC,SAAS;GAAE,CAAC;GAClG,aAAa;IACX,eAAe,WAAW;IAC1B,gBAAgB;GAClB;EACF;EAsBA,IAAI,SAAoC;;EAExC,IAAI,QAAQ;;EAEZ,IAAI,UAAwB;EAC5B,IAAI,YAA2B;EAE/B,SAAS,cAAuB;GAC9B,MAAM,KAAK,SAAS,cAAc,KAAK;GACvC,GAAG,QAAQ,aAAa;GACxB,GAAG,MAAM,UAAU;GACnB,OAAO;IAAE;IAAI,KAAK;GAAK;EACzB;EAEA,SAAS,oBAA0B;GACjC,IAAI,SAAS,QAAQ,WAAW,QAAQ,SAAS,KAAK,SAAS,IAAI,GAAG;GACtE,IAAI,cAAc,MAAM;IAAE,OAAO,aAAa,SAAS;IAAG,YAAY;GAAK;GAC3E,MAAM,IAAI,YAAY;GACtB,MAAM,IAAI,YAAY;GACtB,OAAO,SAAS,cAAc,KAAK;GACnC,KAAK,QAAQ,QAAQ;GACrB,KAAK,MAAM,UAAU;GACrB,KAAK,OAAO,EAAE,IAAI,EAAE,EAAE;GACtB,SAAS,CAAC,GAAG,CAAC;GACd,QAAQ;GACR,UAAU;GACV,SAAS,KAAK,QAAQ,IAAI;EAC5B;;EAGA,SAAS,kBAAwB;GAC/B,IAAI,cAAc,MAAM;IAAE,OAAO,aAAa,SAAS;IAAG,YAAY;GAAK;GAC3E,UAAU;GACV,QAAQ;GACR,SAAS;GACT,MAAM,OAAO;GACb,OAAO;EACT;;EAGA,SAAS,WAAW,GAAkB;GACpC,IAAI,EAAE,QAAQ,MAAM;GACpB,EAAE,MAAM;GACR,EAAE,GAAG,MAAM,kBAAkB;GAC7B,EAAE,GAAG,MAAM,iBAAiB;GAC5B,EAAE,GAAG,MAAM,qBAAqB;EAClC;;EAGA,IAAI,SAAuD;EAC3D,SAAS,aAAa,KAAa,IAA0C;GAC3E,IAAI,WAAW,QAAQ,OAAO,QAAQ,KAAK;IAAE,GAAG,OAAO,GAAG,OAAO,CAAC;IAAG;GAAO;GAC5E,MAAM,MAAM,IAAI,MAAM;GACtB,IAAI,eAAe;IACjB,SAAS;KAAE;KAAK,GAAG,IAAI;KAAc,GAAG,IAAI;IAAc;IAC1D,GAAG,IAAI,cAAc,IAAI,aAAa;GACxC;GACA,IAAI,gBAAgB,GAAG,GAAG,CAAC;GAC3B,IAAI,MAAM;EACZ;;;;;EAMA,SAAS,WAAW,GAAY,KAAmB;GACjD,MAAM,KAAK,EAAE;GACb,EAAE,MAAM;GACR,MAAM,KAAK,SAAS;GACpB,MAAM,OAAO,QAAQ;GACrB,MAAM,OAAO,QAAQ,IAAI;GAGzB,IAAI,GAAG,MAAM,oBAAoB,MAC/B,GAAG,MAAM,kBAAkB;GAE7B,IAAI,SAAS,OAAO;IAClB,GAAG,MAAM,mBAAmB;IAC5B,IAAI,GAAG,KAAK,GAAG;KAGb,MAAM,MAAM,KAAK,IAAI,OAAO,aAAa,GAAG,IAAI,OAAO,cAAc,GAAG,EAAE;KAC1E,MAAM,IAAI,GAAG,KAAK,MAAM,GAAG;KAC3B,MAAM,IAAI,GAAG,KAAK,MAAM,GAAG;KAC3B,GAAG,MAAM,iBAAiB,GAAG,EAAE,KAAK,EAAE;KACtC,GAAG,MAAM,qBAAqB,GAAG,GAAG,IAAI,OAAO,aAAa,IAAI,EAAE,KAAK,GAAG,IAAI,OAAO,cAAc,IAAI,EAAE;IAC3G,OAAO;KAEL,GAAG,MAAM,iBAAiB;KAC1B,GAAG,MAAM,qBAAqB;IAChC;GACF,OAAO,IAAI,SAAS,QAAQ;IAC1B,GAAG,MAAM,mBAAmB;IAC5B,GAAG,MAAM,iBAAiB;IAC1B,GAAG,MAAM,qBAAqB;GAChC,OAAO,IAAI,SAAS,WAAW;IAC7B,GAAG,MAAM,mBAAmB;IAC5B,GAAG,MAAM,iBAAiB;IAC1B,GAAG,MAAM,qBAAqB;GAChC,OAAO,IAAI,SAAS,QAAQ;IAC1B,GAAG,MAAM,mBAAmB;IAE5B,GAAG,MAAM,iBAAiB;IAC1B,GAAG,MAAM,qBAAqB;GAChC,OAAO;IAGL,GAAG,MAAM,mBAAmB;IAC5B,GAAG,MAAM,iBAAiB;IAC1B,GAAG,MAAM,qBAAqB;IAC9B,aAAa,MAAM,GAAG,MAAM;KAC1B,IAAI,EAAE,QAAQ,OAAO,GAAG,MAAM,oBAAoB,QAAQ,QAAQ,MAAM,UAAU;KAClF,IAAI,IAAI,KAAK,IAAI,GAAG;MAClB,GAAG,MAAM,iBAAiB,GAAG,EAAE,KAAK,EAAE;MACtC,GAAG,MAAM,qBAAqB;KAChC;IACF,CAAC;GACH;EACF;;;EAIA,SAAS,QAAQ,MAAwB;GACvC,IAAI,KAAK,QAAQ,MAAM,OAAO;GAC9B,IAAI,KAAK,KAAK,KAAM,OAAO;GAC3B,MAAM,KAAK,OAAO,OAAO,eAAe,aAAa,OAAO,WAAW,kCAAkC,IAAI;GAC7G,OAAO,OAAO,QAAQ,CAAC,GAAG;EAC5B;;EAGA,SAAS,WAAW,KAAkB;GACpC,IAAI,WAAW,QAAQ,YAAY,KAAK;GACxC,IAAI,cAAc,MAAM;IAAE,OAAO,aAAa,SAAS;IAAG,YAAY;GAAK;GAC3E,UAAU;GACV,QAAQ;GACR,MAAM,KAAK,OAAO,IAAI,CAAC;GAGvB,GAAG,MAAM,UAAU;GACnB,GAAG,MAAM,aAAa;GAGtB,WAAW,OAAO,QAAQ,IAAI,IAAI,EAAE;EACtC;;EAGA,SAAS,aAAmB;GAC1B,IAAI,WAAW,QAAQ,YAAY,MAAM;GACzC,MAAM,MAAM;GACZ,IAAI,cAAc,MAAM;IAAE,OAAO,aAAa,SAAS;IAAG,YAAY;GAAK;GAC3E,UAAU;GACV,QAAQ;GACR,MAAM,KAAK,OAAO,IAAI,CAAC;GACvB,GAAG,MAAM,aAAa;GACtB,GAAG,MAAM,UAAU;GACnB,GAAG,MAAM,aAAa;GACtB,WAAW,OAAO,QAAQ,IAAI,IAAI,EAAE;EACtC;;EAGA,SAAS,aAAmB;GAC1B,IAAI,WAAW,QAAQ,YAAY,MAAM;GACzC,MAAM,MAAM;GACZ,IAAI,cAAc,MAAM;IAAE,OAAO,aAAa,SAAS;IAAG,YAAY;GAAK;GAC3E,UAAU;GACV,MAAM,KAAK,OAAO,IAAI,CAAC;GACvB,GAAG,MAAM,aAAa;GACtB,GAAG,MAAM,UAAU;GACnB,GAAG,MAAM,aAAa;GACtB,WAAW,OAAO,IAAI;EACxB;;EAGA,SAAS,aAAa,KAAmB;GACvC,kBAAkB;GAClB,MAAM,KAAK;GACX,IAAI,YAAY,MAAM;IAGpB,IAAI,GAAG,QAAQ,CAAC,QAAQ,KAAK;KAAE,WAAW,GAAG,UAAU,GAAG;KAAG,eAAe;KAAG;IAAO;IACtF,IAAI,GAAG,MAAM,CAAC,QAAQ,KAAK;KAAE,WAAW;KAAG,WAAW,GAAG,QAAQ,GAAG;KAAG,eAAe;KAAG;IAAO;IAChG,WAAW;GACb;GACA,IAAI,GAAG,MAAM,CAAC,QAAQ,KAAK;IAAE,WAAW,GAAG,QAAQ,GAAG;IAAG,eAAe;IAAG;GAAO;GAClF,MAAM,OAAO,GAAG;GAChB,MAAM,MAAa,UAAU,IAAI,IAAI;GACrC,MAAM,SAAS,GAAG;GAClB,MAAM,KAAK,OAAO;GAGlB,GAAG,MAAM,aAAa;GACtB,GAAG,MAAM,UAAU;GACnB,GAAG,MAAM,SAAS;GAClB,KAAK,GAAG,MAAM,SAAS;GACvB,WAAW,QAAQ,GAAG;GACtB,eAAe;GACf,MAAM,SAAS,QAAQ;GACvB,IAAI,CAAC,QAAQ,IAAI,KAAK,UAAU,GAAG;IACjC,GAAG,MAAM,UAAU;IACnB,QAAQ;IACR,WAAW,IAAI;IACf;GACF;GAIA,GAAG,MAAM,aAAa;GACtB,UAAU;GACV,4BAA4B;IAC1B,IAAI,YAAY,OAAO,WAAW,MAAM;IACxC,GAAG,MAAM,aAAa,WAAW,OAAO;IACxC,GAAG,MAAM,UAAU;GACrB,CAAC;GACD,YAAY,OAAO,iBAAiB,WAAW,GAAG,GAAG,SAAS,GAAG;EACnE;EAEA,SAAS,iBAAuB;GAC9B,IAAI,SAAS,QAAQ,WAAW,MAAM;GACtC,KAAK,MAAM,UAAU,OAAO,KAAK,CAAC;GAIlC,MAAM,OAAO,IAAI;GACjB,MAAM,SAAS,OAAO,IAAI,QAAQ,KAAK,OAAO;GAC9C,OAAO,EAAE,CAAC,GAAG,MAAM,SAAS;GAC5B,OAAO,EAAE,CAAC,GAAG,MAAM,SAAS;EAC9B;;;EAIA,SAAgB,UAAgB;GAC9B,MAAM,MAAM,IAAI;GAChB,IAAI,KACF,aAAa,GAAG;QACX,IAAI,SAAS,MAElB,gBAAgB;GAYlB,IAAI,CAAC,UAAU,KAAK,CAAC,aAAa,WAAW,OAAO,GAAG;IACrD,kBAAkB;IAClB,sBAAsB;GACxB;GACA,IAAI,CAAC,UAAU,GAAG,gBAAgB;GAClC,MAAM,MAAM,QAAQ;GAGpB,SAAS,gBAAgB,gBAAgB,aAAa,QAAQ,IAAI;GAClE,IAAI,QAAQ,MAAM;IAGhB,kBAAkB;IAClB,mBAAmB;GACrB;GACA,kBAAkB,KAAK,CAAC;GACxB,uBAAuB,KAAK,CAAC;GAC7B,yBAAyB,mBAAmB,CAAC;GAC7C,uBAAuB,iBAAiB,CAAC;GACzC,eAAe,OAAO,CAAC;EACzB;EAEA,SAAgB,aAAmB;GACjC,gBAAgB;GAChB,kBAAkB;GAClB,cAAc,OAAO;GAAG,eAAe;GACvC,gBAAgB;GAChB,SAAS,gBAAgB,gBAAgB,WAAW;GACpD,SAAS,KAAK,MAAM,eAAe,cAAc;GAIjD,mBAAmB;GACnB,gBAAgB;GAChB,sBAAsB;GACtB,SAAS,gBAAgB,MAAM,eAAe,yBAAyB;GACvE,SAAS,gBAAgB,MAAM,eAAe,4BAA4B;GAC1E,SAAS,gBAAgB,MAAM,eAAe,sBAAsB;GACpE,SAAS,gBAAgB,MAAM,eAAe,uBAAuB;GACrE,SAAS,gBAAgB,MAAM,eAAe,yBAAyB;GACvE,KAAK,MAAM,KAAK,OAAO,OAAO,YAAY,GAAG,SAAS,gBAAgB,MAAM,eAAe,CAAC;GAC5F,IAAI,cAAc,MAAM;IAAE,qBAAqB,SAAS;IAAG,YAAY;GAAK;GAC5E,aAAa;GACb,iBAAiB,OAAO;GAAG,kBAAkB;GAC7C,QAAQ,SAAS,CAAC;GAAG,QAAQ,WAAW,CAAC;GAAG,QAAQ,UAAU,CAAC;GAAG,QAAQ,WAAW,CAAC;GACtF,kBAAkB;EACpB;;;;ECnrCA,SAAS,OAAO,OAAoC;GAClD,OAAO,MAAM,OAAO,YAAY;EAClC;;;;;;;;;;;;EAaA,SAAgB,UACd,OACA,WAC2C;GAC3C,MAAM,OAAO,OAAO,KAAK;GACzB,IAAI,KAAK,WAAW,GAAG,OAAO;IAAE,MAAM;IAAM,SAAS;GAAM;GAC3D,MAAM,MAAM,UAAU,YAAY;GAClC,IAAI,IAAI,KAAK,MAAM,IACjB,KAAK,MAAM,QAAQ,MAAM;IACvB,MAAM,SAAS,KAAK,MAAM,KAAK,CAAC,CAAC,YAAY;IAC7C,IAAI,WAAW,IAAI;IACnB,IAAI,IAAI,SAAS,MAAM,GAAG,OAAO;KAAE;KAAM,SAAS;IAAK;GACzD;GAEF,OAAO;IAAE,MAAM,KAAK;IAAK,SAAS;GAAM;EAC1C;;EAUA,SAAS,cAAc,OAER,UAAkB,OAAuB;GACtD,IAAI,UAAU,MAAM,CAAC,MAAM,QAAQ,OAAO,MAAM,GAAG,OAAO;GAC1D,KAAK,MAAM,SAAS,MAAO,QAAS;IAClC,IAAI,MAAM,OAAO,UAAU;IAC3B,KAAK,MAAM,SAAS,MAAM,UAAU,CAAC,GACnC,IAAI,MAAM,OAAO,OAAO,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;GAEjF;GACA,OAAO;EACT;;EAaA,MAAM,kBAAkB;;EAExB,MAAM,qBAAqB;;EAE3B,MAAM,UAAU;;EAGhB,SAAS,YAAY,OAA6F;GAChH,MAAM,OAAO,OAAO,QAAQ,OAAO,YAAY;GAC/C,IAAI,SAAS,QAAQ,OAAO,SAAS,UAAU,OAAO;GACtD,MAAM,WAAW,OAAO,KAAK,aAAa,WAAW,KAAK,WAAW;GACrE,MAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;GAC5D,IAAI,aAAa,MAAM,UAAU,IAAI,OAAO;GAC5C,OAAO;IAAE;IAAU;GAAM;EAC3B;;EAGA,SAAS,KAAK,OAA+B;GAC3C,OAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;EAC7D;;;;;;;;;;;;;;;EAgBA,SAAgB,qBACd,WACA,UACe;GAEf,MAAM,gBAAgB,KAAK,WAAW,GAAG;GACzC,IAAI,kBAAkB,MAAM,OAAO;GAEnC,MAAM,SAAS,KAAK,UAAU,OAAO;GACrC,IAAI,WAAW,MAAM,OAAO;GAE5B,MAAM,OAAO,UAAU;GACvB,IAAI,SAAS,KAAA,KAAa,SAAS,MAC5B;SAAA,MAAM,OAAO,OAAO,OAAO,IAAI,GAClC,KAAK,KAAK,YAAY,YAAY,KAAK,GAAG;KACxC,MAAM,KAAK,KAAK,KAAK,EAAE;KACvB,IAAI,OAAO,MAAM,OAAO;IAC1B;;GAGJ,OAAO;EACT;;EAGA,SAAS,cAAc,KAAU,MAAyE;GACxG,IAAI;GACJ,IAAI;IAEF,YADW,IAAI,IAAI,WACN,CAAC,EAAE,SAAS,cAAc;GACzC,QAAQ,CAER;GACA,OAAO,qBAAqB,WAAW,MAAM,YAAY,CAAC;EAC5D;;;;;;;;;;EAWA,SAAgB,WACd,KACA,UACY;GACZ,IAAI,UAAsC;GAC1C,IAAI,OAA2D;GAC/D,IAAI,UAA+B;GACnC,IAAI,YAA2B;GAC/B,IAAI,YAAuC;GAC3C,IAAI,eAAoC;;GAExC,IAAI,YAAqE;GACzE,IAAI,eAAoC;GACxC,IAAI,UAAU;GACd,IAAI,OAAsB;GAC1B,IAAI,QAAuB;GAC3B,IAAI,UAAU;GAEd,MAAM,gBAAsB;IAC1B,IAAI,iBAAiB,MAAM;KAAE,aAAa;KAAG,eAAe;IAAK;IACjE,IAAI,iBAAiB,MAAM;KAAE,aAAa;KAAG,eAAe;IAAK;IACjE,YAAY;IACZ,YAAY;GACd;;GAGA,MAAM,kBAAkB,OAAqB;IAC3C,MAAM,MAAM;IACZ,IAAI,QAAQ,MAAM;IAClB,IAAI;KACF,IAAI,UAAU,OAAO,IAAI,YAAY,aAAa,IAAI,QAAQ,EAAE,IAAI,KAAA;KACpE,IAAI,YAAY,KAAA,KAAa,OAAO,IAAI,UAAU,YAAY;MAG5D,IAAI,MAAM,EAAE;MACZ,UAAU,OAAO,IAAI,YAAY,aAAa,IAAI,QAAQ,EAAE,IAAI,KAAA;KAClE;KACA,MAAM,OAAO,SAAS,SAAS,aAAa,SAAS,gBAAgB;KACrE,IAAI,SAAS,KAAA,KAAa,OAAO,KAAK,cAAc,cAAc,OAAO,KAAK,gBAAgB,YAAY;KAC1G,YAAY;KACZ,eAAe,KAAK,gBAAgB;MAAE,KAAK,KAAK;KAAE,CAAC;IACrD,QAAQ;KACN,YAAY;KACZ,eAAe;IACjB;GACF;GAEA,MAAM,aAAwB;IAC5B,IAAI,YAAY,MAAM,OAAO;IAC7B,IAAI,cAAc,MAAM,OAAO;IAC/B,IAAI,cAAc,QAAQ,cAAc,MAAM,OAAO;IACrD,OAAO;GACT;GAEA,MAAM,QAAQ,UAAyB;IACrC,MAAM,QAAQ,WAAW,MAAM,YAAY;IAC3C,MAAM,gBAAgB,OAAO,WAAW;IACxC,MAAM,MAAM,kBAAkB,OAC1B;KAAE,UAAU,cAAc,YAAY;KAAI,OAAO,cAAc,SAAS;IAAG,WACpE;KACP,IAAI;MAAE,OAAO,YAAY,WAAW,YAAY,CAAC;KAAE,QAAQ;MAAE,OAAO;KAAK;IAC3E,EAAA,CAAG;IACL,MAAM,WAAW,KAAK,YAAY;IAClC,MAAM,QAAQ,KAAK,SAAS;IAC5B,MAAM,OAAO,cAAc,OAAO,UAAU,KAAK;IACjD,MAAM,OAAO;KAAC;KAAU;KAAO;IAAI,CAAC,CAAC,QAAO,MAAK,MAAM,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;IAC1E,MAAM,YAAuB,SAAS,KAAK,KAAK,IAAI;IACpD,MAAM,MAAM,GAAG,KAAK,QAAQ,KAAK,QAAQ;IACzC,IAAI,CAAC,SAAS,QAAQ,SAAS;IAC/B,UAAU;IACV,SAAS,MAAM,SAAS,KAAK,OAAQ,UAAU,KAAK,QAAQ,UAAW,WAAW,SAAS;GAC7F;GAEA,MAAM,aAAmB;IACvB,MAAM,KAAK,cAAc,KAAK,IAAI;IAGlC,IAAI,OAAO,cAAc,cAAc,QAAQ,cAAc,OAAO;KAAE,KAAK,KAAK;KAAG;IAAO;IAC1F,QAAQ;IACR,YAAY;IACZ,IAAI,OAAO,MAAM;KACf,eAAe,EAAE;KACjB,IAAI,cAAc,MAAM;MACtB,MAAM,cAAc,IAAI,IAAI,kBAAkB;MAC9C,IAAI,gBAAgB,KAAA,KAAa,OAAO,YAAY,iBAAiB,YACnE,IAAI;OACF,YAAY,YAAY,aAAa,EAAE;OACvC,eAAe,UAAU,MAAM,gBAAgB;QAAE,KAAK,KAAK;OAAE,CAAC;OAG9D,MAAM,UAAU,UAAU,OAAO;OACjC,IAAI,YAAY,KAAA,KAAa,YAAY,QAAQ,OAAQ,QAA6B,UAAU,YAC9F,QAAmC,YAAY,KAAA,CAAS;MAE5D,QAAQ;OACN,YAAY;OACZ,eAAe;MACjB;KAEJ;IACF;IAIA,KAAK,IAAI;GACX;GAEA,MAAM,kBAAwB;IAC5B,IAAI,UAAU,MAAM;IACpB,OAAO,cAAc,KAAK;IAC1B,QAAQ;GACV;GAEA,MAAM,aAAmB;IACvB,IAAI,SAAS,MAAM;IACnB,IAAI,cAAc,KAAK,IAAI,MAAM,aAAc,cAAc,QAAQ,cAAc,MAAO,KAAK;SAC1F,KAAK,KAAK;GACjB;;;;;;GAOA,MAAM,eAAwB;IAC5B,MAAM,MAAM,IAAI,IAAI,UAAU;IAC9B,IAAI,QAAQ,KAAA,KAAa,QAAQ,MAAM,OAAO;IAC9C,MAAM,OAAO,IAAI;IACjB,IAAI,SAAS,KAAA,KAAa,OAAO,KAAK,cAAc,cAAc,OAAO,KAAK,gBAAgB,YAAY,OAAO;IACjH,UAAU;IACV,OAAO;IACP,UAAU,KAAK,UAAU,IAAI;IAC7B,IAAI,SAAS,MAAM,OAAO,OAAO,YAAY,MAAM,OAAO;IAC1D,KAAK;IACL,OAAO;GACT;GAEA,IAAI,CAAC,OAAO,GACV,QAAQ,OAAO,kBAAkB;IAC/B;IACA,IAAI,OAAO,KAAK,WAAW,oBAAoB,UAAU;GAC3D,GAAG,eAAe;GAGpB,aAAa;IACX,UAAU;IACV,IAAI,SAAS,MAAM;KAAE,OAAO,cAAc,IAAI;KAAG,OAAO;IAAK;IAC7D,IAAI,YAAY,MAAM;KAAE,QAAQ;KAAG,UAAU;IAAK;IAClD,UAAU;IACV,OAAO;IACP,QAAQ;GACV;EACF;;;;ECpVA,MAAa,YAAY;EAEzB,SAAgB,QAAQ,EAAE,OAAO,IAAI,aAAoD;GACvF,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,OAAO;IAAM,QAAQ;IAAiB;IAAW,SAAQ;IAAY,MAAK;IAAO,OAAM;IAA6B,yBAAyB,EAAE,QAAQ,UAAU;GAAI,CAAA;EAE9K;EAEA,SAAS,MAAM,EAAE,UAAU,OAAO,IAAI,aAAyE;GAC7G,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,OAAO;IAAM,QAAQ;IAAiB;IAAW,SAAQ;IAAY,MAAK;IAAO,QAAO;IAAe,aAAa;IAAK,eAAc;IAAQ,gBAAe;IAAQ,eAAY;IACpL;GACE,CAAA;EAET;EAEA,MAAa,eAAe,EAAE,MAAM,gBAClC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAa;GAAiB;GAAW,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,0EAA2E,CAAA;EAAQ,CAAA;EAGtI,MAAa,cAAc,EAAE,MAAM,gBACjC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,mCAAoC,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,wBAAyB,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,yBAA0B,CAAA;GAAQ;;EAGpK,MAAa,aAAa,EAAE,MAAM,gBAChC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,GAAE;KAAI,GAAE;KAAM,OAAM;KAAK,QAAO;KAAM,IAAG;IAAK,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,IAAG;KAAM,IAAG;KAAM,GAAE;IAAO,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,4BAA6B,CAAA;GAAQ;;EAOjL,MAAa,YAAY,EAAE,MAAM,gBAC/B,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAa;GAAiB;GAAW,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,8BAA+B,CAAA;EAAQ,CAAA;EAG1F,MAAa,kBAAkB,EAAE,MAAM,gBACrC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,mCAAoC,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,IAAG;KAAM,IAAG;KAAM,GAAE;IAAO,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,IAAG;KAAI,IAAG;KAAM,GAAE;IAAO,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,IAAG;KAAO,IAAG;KAAK,GAAE;IAAO,CAAA;GAAQ;;EAGzM,MAAa,eAAe,EAAE,MAAM,gBAClC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,sDAAuD,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,IAAG;KAAM,IAAG;KAAM,GAAE;IAAO,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;KAAQ,IAAG;KAAM,IAAG;KAAO,GAAE;IAAO,CAAA;GAAQ;;EAG3L,MAAa,eAAe,EAAE,MAAM,gBAClC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA,CAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,0EAA2E,CAAA,GAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,iEAAkE,CAAA,CAAQ;;EAOjN,MAAa,gBAAgB,EAAE,MAAM,gBACnC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,WAAY,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,wBAAyB,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,iBAAkB,CAAA;GAAQ;;EAGpI,MAAa,cAAc,EAAE,MAAM,gBACjC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,cAAe,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,yBAA0B,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,iBAAkB,CAAA;GAAQ;;EAGxI,MAAa,YAAY,EAAE,MAAM,gBAC/B,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,mBAAoB,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,mDAAoD,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,mDAAoD,CAAA;GAAQ;;EAOzM,MAAa,aAAa,EAAE,MAAM,gBAChC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,gBAAiB,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,uBAAwB,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,6BAA8B,CAAA;GAAQ;;EAGpJ,MAAa,YAAY,EAAE,MAAM,gBAC/B,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA,CAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,iBAAkB,CAAA,GAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,wCAAyC,CAAA,CAAQ;;EAG/H,MAAa,eAAe,EAAE,MAAM,gBAClC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA,CAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAAQ,IAAG;IAAI,IAAG;IAAI,GAAE;GAAO,CAAA,GAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,6CAA8C,CAAA,CAAQ;;EAGzI,MAAa,aAAa,EAAE,MAAM,gBAChC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAa;GAAiB;GAAW,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,sBAAuB,CAAA;EAAQ,CAAA;EAGlF,MAAa,aAAa,EAAE,MAAM,gBAChC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA,CAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,4BAA6B,CAAA,GAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,wBAAyB,CAAA,CAAQ;;EAO1H,MAAa,cAAc,EAAE,MAAM,gBACjC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAa;GAAiB;GAAW,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;IAAM,GAAE;IAAM,GAAE;IAAM,OAAM;IAAO,QAAO;IAAO,IAAG;GAAK,CAAA;EAAQ,CAAA;EAG5G,MAAa,eAAe,EAAE,MAAM,gBAClC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA,CAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;IAAM,GAAE;IAAM,GAAE;IAAM,OAAM;IAAO,QAAO;IAAO,IAAG;GAAK,CAAA,GAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,gBAAiB,CAAA,CAAQ;;;EAItI,MAAa,eAAe,EAAE,MAAM,gBAClC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA;IAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,GAAE;KAAM,GAAE;KAAM,OAAM;KAAO,QAAO;KAAO,IAAG;IAAK,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,gBAAiB,CAAA;IAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,uBAAwB,CAAA;GAAQ;;EAGvK,MAAa,YAAY,EAAE,MAAM,gBAC/B,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;GAAa;GAAiB;GAAW,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,8EAA+E,CAAA;EAAQ,CAAA;EAG1I,MAAa,YAAY,EAAE,MAAM,gBAC/B,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA,CAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAAQ,IAAG;IAAI,IAAG;IAAI,GAAE;GAAO,CAAA,GAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,mHAAoH,CAAA,CAAQ;;EAG/M,MAAa,aAAa,EAAE,MAAM,gBAChC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;GAAa;GAAiB;GAA9B,UAAA,CAAyC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;IAAM,GAAE;IAAM,GAAE;IAAI,OAAM;IAAO,QAAO;IAAI,IAAG;GAAK,CAAA,GAAC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,GAAE,iBAAkB,CAAA,CAAQ;;;;;;;;;;;EClGlI,IAAa,gBAAb,cAAmCC,MAAAA,UAAwB;GACzD,QAAwB,EAAE,OAAO,KAAK;GAEtC,OAAO,yBAAyB,OAAqB;IACnD,OAAO,EAAE,MAAM;GACjB;GAEA,kBAA2B,OAAc,MAAgD;IACvF,QAAQ,MAAM,mDAAmD,OAAO,KAAK,cAAc;GAC7F;GAEA,cAA4B;IAC1B,KAAK,SAAS,EAAE,OAAO,KAAK,CAAC;IAC7B,KAAK,MAAM,UAAU;GACvB;GAEA,SAAkB;IAChB,IAAI,KAAK,MAAM,OACb,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAmB,UAAA,KAAK,MAAM,EAAE,YAAY;MAAO,CAAA;MAClE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAkB,UAAA,KAAK,MAAM,EAAE,WAAW;MAAO,CAAA;MAChE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;OAAQ,MAAK;OAAS,WAAU;OAAU,SAAS,KAAK;OAAQ,UAAA,KAAK,MAAM,EAAE,YAAY;MAAU,CAAA;KAChG;;IAGT,OAAO,KAAK,MAAM;GACpB;EACF;;;;;;;;;;;;EClCA,SAAgB,OAAO,EAAE,YAAqC;GAC5D,MAAM,CAAC,QAAQ,cAAA,GAAaC,MAAAA,SAAAA,CAA6B,IAAI;GAC7D,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,MAAM,KAAK,SAAS,cAAc,KAAK;IACvC,GAAG,QAAQ,YAAY;IACvB,GAAG,MAAM,UAAU;IACnB,SAAS,gBAAgB,YAAY,EAAE;IACvC,UAAU,EAAE;IACZ,aAAa;KAAE,GAAG,OAAO;IAAE;GAC7B,GAAG,CAAC,CAAC;GACL,OAAO,UAAA,GAASC,UAAAA,aAAAA,CAAa,UAAU,MAAM,IAAI;EACnD;;;;;;;;;;ECdA,SAAgB,WAAW,EAAE,KAAK,KAAK,MAAM,KAAK,KAAK,OAAO,SAAS,YAGpE;GACD,MAAM,YAAA,GAAWC,MAAAA,OAAAA,CAAyB,IAAI;GAC9C,MAAM,UAAA,GAASA,MAAAA,OAAAA,CAAwB,IAAI;GAE3C,MAAM,SAAS,IAAsB,MAAoB;IACvD,GAAG,MAAM,YAAY,SAAS,QAAS,IAAI,QAAQ,MAAM,OAAQ,GAAG,CAAC;GACvE;GAIA,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,SAAS,SAAS;KACpB,SAAS,QAAQ,QAAQ,OAAO,GAAG;KACnC,MAAM,SAAS,SAAS,GAAG;IAC7B;IACA,IAAI,OAAO,SAAS,OAAO,QAAQ,cAAc,IAAI,GAAG;GAC1D,GAAG;IAAC;IAAK;IAAK;IAAK;GAAG,CAAC;GAEvB,MAAM,SAAS,MAAoB;IACjC,IAAI,SAAS,SAAS;KACpB,SAAS,QAAQ,QAAQ,OAAO,CAAC;KACjC,MAAM,SAAS,SAAS,CAAC;IAC3B;IACA,IAAI,OAAO,SAAS,OAAO,QAAQ,cAAc,IAAI,CAAC;IACtD,UAAU,CAAC;IACX,SAAS,CAAC;GACZ;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAAoB,UAAA;IAAY,CAAA,IAAI,MAC7D,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,OAAO;MAAE,SAAS;MAAQ,YAAY;MAAU,KAAK;KAAG;KAA7D,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;MACE,KAAK;MAAU,MAAK;MAAQ,WAAU;MACtC,OAAO,EAAE,UAAW,MAAM,QAAQ,MAAM,OAAQ,IAAI;MAC/C;MAAU;MAAW;MAAM,cAAc;MAC9C,OAAO,QAAQ,GAAG,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,GAAG;MACjD,qBAAqB,MAAM,GAAG;MAC9B,UAAS,MAAK;OACZ,MAAM,KAAK,EAAE;OACb,MAAM,IAAI,OAAO,GAAG,KAAK;OACzB,MAAM,IAAI,CAAC;OACX,UAAU,CAAC;OACX,IAAI,OAAO,SAAS,OAAO,QAAQ,cAAc,IAAI,CAAC;MACxD;MACA,WAAU,MAAK,SAAS,OAAQ,EAAE,OAA4B,KAAK,CAAC;KAAI,CAAA,GAC1E,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,KAAK;MAAQ,WAAU;MAAkB,UAAA,IAAI,GAAG;KAAQ,CAAA,CAC3D;IACF,CAAA,CAAA;;EAET;;;ECzCA,MAAM,QAAmB;GACvB;IAAE,OAAO;IAAM,UAAU;IAAe,MAAM;GAAW;GACzD;IAAE,OAAO;IAAW,UAAU;IAAiB,MAAM;GAAY;GACjE;IAAE,YAAY;IAAM,UAAU;IAAa,MAAM;GAAY;GAC7D;IAAE,OAAO;IAAQ,UAAU;IAAiB,MAAM;GAAS;GAC3D;IAAE,OAAO;IAAS,UAAU;IAAkB,MAAM;GAAU;GAC9D;IAAE,YAAY;IAAM,UAAU;IAAS,MAAM;GAAS;GACtD;IAAE,QAAQ;IAAM,UAAU;IAAgB,MAAM;GAAS;GACzD;IAAE,cAAc;IAAM,UAAU;IAAgB,MAAM;GAAe;EACvE;EAEA,SAAgB,cAAc,EAAE,KAA+B;GAC7D,MAAM,EAAE,GAAG,QAAQ,UAAU,QAAQ,uBAAuB;GAE5D,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;IAAQ,WAAU;IAAoB,OAAO,EAAE,OAAO,EAAE;IAAxD,UAAA;KACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAAe,UAAA;KAAa,CAAA;KAC3C,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;MAAI,WAAU;MAAU,UAAA,EAAE,SAAS;KAAM,CAAA;KACzC,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;MAAG,WAAU;MAAY,UAAA,EAAE,eAAe;KAAK,CAAA;IACzC;GAER,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;IAAK,WAAU;IACZ,UAAA,MAAM,KAAK,MAAM,MAAM;KACtB,MAAM,EAAE,UAAU,MAAM,YAAY,QAAQ,cAAc,eAAe;KACzE,MAAM,QAAQ,KAAK;KAYnB,MAAM,UAA2B,SAC7B,SACA,eACE,eACA,aACE,aACA,aAAa,aAAa;KAClC,MAAM,UAAU,SACZ,iBAAiB,IACjB,eACE,mBAAmB,IACnB,aAAa,iBAAiB,IAAI,aAAa,KAAK,IAAI,KAAK,CAAC,CAAC;KACrE,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;MAAuB,WAAU;MAAmC,OAAO,EAAE,OAAO,IAAI,EAAE;MAA1F,UAAA;OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAAK,WAAU;QAAf,UAAA;SACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,WAAU;UAAe,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD,EAAM,MAAM,GAAK,CAAA;SAAM,CAAA;SACrD,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,WAAU;UAAiB,UAAA,EAAE,QAAQ;SAAO,CAAA;SACjD,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;UAAM,WAAU;UAAhB,UAAA,CAAkC,KAAK,MAAM,UAAU,GAAG,GAAE,GAAO;;QAChE;;OAEL,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;QAAY,OAAO,EAAE,WAAW;QAAG,KAAK;QAAG,KAAK;QAAK,MAAM;QAAG,KAAK,KAAK,MAAM,UAAU,GAAG;QACzF,MAAK,MAAK,GAAG,EAAE;QACf,UAAS,MAAK;SACZ,MAAM,KAAK,IAAI;SACf,IAAI,QAAQ;UACV,IAAI,kBAAkB;UACtB,eAAe;SACjB,OAAO,IAAI,cAAc;UACvB,IAAI,oBAAoB;UACxB,yBAAyB,EAAE;SAC7B,OAAO,IAAI,YAAY;UAGrB,IAAI,kBAAkB;UACtB,uBAAuB,EAAE;SAC3B,OAAO,IAAI,YAAY;UACrB,IAAI,kBAAkB;UACtB,uBAAuB,EAAE;SAC3B,OAAO;UACL,MAAM,MAAM,EAAE,GAAG,KAAK,EAAE;UACxB,IAAI,SAAU;UACd,IAAI,YAAY;UAChB,kBAAkB,GAAG;SACvB;SACA,WAAW;QACb;QACA,WAAU,MAAK;SACb,MAAM,KAAK,IAAI;SACf,IAAI,QAAQ;UACV,IAAI,kBAAkB;UACtB,eAAe;UACf,WAAW;SACb,OAAO,IAAI,cAAc;UACvB,IAAI,oBAAoB;UACxB,yBAAyB,EAAE;UAC3B,WAAW;SACb,OAAO,IAAI,YACT,mBAAmB,EAAE;cAChB,IAAI,YACT,OAAO,EAAE;cACJ;UACL,MAAM,MAAM,EAAE,GAAG,KAAK,EAAE;UACxB,IAAI,SAAU;UACd,OAAO,GAAG;SACZ;QACF;OAAI,CAAA;OAEN,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;QAAY,OAAO,EAAE,QAAQ;QAAG,KAAK;QAAG,KAAK;QAAI,MAAM;QAAG,KAAK,OAAO,CAAC,CAAC;QACtE,MAAK,MAAK,GAAG,EAAE;QACf,UAAS,MAAK;SACZ,MAAM,QAAQ,EAAE,GAAG,OAAO,EAAE;SAC5B,MAAM,WAAW;SACjB,IAAI,QAAQ;SACZ,YAAY,SAAS,CAAC;SACtB,WAAW;QACb;QACA,WAAU,MAAK;SACb,MAAM,QAAQ,EAAE,GAAG,OAAO,EAAE;SAC5B,MAAM,WAAW;SACjB,SAAS,KAAK;QAChB;OAAI,CAAA;MACC;KApEK,GAAA,OAoEL;IAEb,CAAC;GACE,CAAA,CACL,EAAA,CAAA;EAEN;;;;;;;;;EC5IA,SAAgB,QAAQ,MAAY,IAAwC;GAC1E,MAAM,IAAI,IAAI,WAAW;GACzB,EAAE,gBAAgB,GAAG,IAAI;GACzB,EAAE,eAAe,GAAG,EAAE,MAAgB;GACtC,EAAE,cAAc,IAAI;EACtB;;;ECTA,MAAM,aAAa;EACnB,MAAM,KAAK,aAAa;EACxB,MAAM,aAAa;EACnB,MAAM,aAAa;EAKnB,MAAM,UAAU,aAAa,KAAK;;EAGlC,IAAI,YAAsC;EAC1C,SAAS,eAAkC;GACzC,IAAI,WAAW,OAAO;GACtB,MAAM,MAAM,SAAS,cAAc,QAAQ;GAC3C,IAAI,QAAQ;GAAY,IAAI,SAAS;GACrC,MAAM,IAAI,IAAI,WAAW,IAAI;GAG7B,MAAM,IAAI,EAAE,oBAAoB,GAAG,IAAI,EAAE;GACzC,KAAK,IAAI,IAAI,GAAG,KAAK,KAAK,KAAK,EAAE,aAAa,IAAI,KAAK,OAAO,EAAE,WAAW;GAC3E,EAAE,UAAU;GACZ,EAAE,IAAI,IAAI,IAAI,YAAY,GAAG,KAAK,KAAK,CAAC;GACxC,EAAE,IAAI,IAAI,IAAI,YAAY,GAAG,KAAK,KAAK,GAAG,IAAI;GAC9C,EAAE,YAAY;GACd,EAAE,KAAK;GACP,YAAY;GACZ,OAAO;EACT;EAEA,SAAS,YAAY,KAA+B,KAAa,KAAa,KAAmB;GAO/F,MAAM,OAAO,MAAM,KAAK,KAAK;GAC7B,MAAM,KAAK;GACX,MAAM,MAAM,KAAK,KAAK,IAAI,IAAI,IAAI;GAClC,MAAM,MAAM,KAAK,KAAK,IAAI,IAAI,IAAI;GAClC,IAAI,UAAU;GAAG,IAAI,IAAI,KAAK,KAAK,GAAG,GAAG,KAAK,KAAK,CAAC;GACpD,IAAI,YAAY;GAAoB,IAAI,KAAK;GAC7C,IAAI,UAAU;GAAG,IAAI,IAAI,KAAK,KAAK,KAAK,GAAG,KAAK,KAAK,CAAC;GACtD,IAAI,cAAc;GAAQ,IAAI,YAAY;GAAG,IAAI,OAAO;GAGxD,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK,UAAU;GAC3D,MAAM,MAAM,KAAK,MAAM;GACvB,MAAM,MAAM,MAAM,IAAI,OAAO;GAC7B,IAAI,UAAU;GAAG,IAAI,IAAI,KAAK,KAAK,GAAG,GAAG,KAAK,KAAK,CAAC;GACpD,IAAI,YAAY;GAAoB,IAAI,KAAK;GAC7C,IAAI,UAAU;GAAG,IAAI,IAAI,KAAK,KAAK,KAAK,GAAG,KAAK,KAAK,CAAC;GACtD,IAAI,cAAc;GAAQ,IAAI,YAAY;GAAG,IAAI,OAAO;GACxD,IAAI,UAAU;GAAG,IAAI,IAAI,KAAK,KAAK,KAAK,GAAG,KAAK,KAAK,CAAC;GACtD,IAAI,cAAc;GAAQ,IAAI,YAAY;GAAG,IAAI,OAAO;EAC1D;EAEA,SAAS,WAAW,GAA6B,KAAmB;GAClE,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK,UAAU;GAC3D,EAAE,UAAU,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;GAC1C,EAAE,YAAY;GAAQ,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE;GAC/C,MAAM,KAAK,EAAE,qBAAqB,IAAI,GAAG,KAAK,IAAI,CAAC;GACnD,GAAG,aAAa,GAAG,qBAAqB;GAAG,GAAG,aAAa,GAAG,OAAO,IAAI,WAAW;GACpF,EAAE,YAAY;GAAI,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE;GAC3C,MAAM,KAAK,EAAE,qBAAqB,GAAG,IAAI,GAAG,KAAK,EAAE;GACnD,GAAG,aAAa,GAAG,eAAe;GAAG,GAAG,aAAa,GAAG,eAAe;GACvE,EAAE,YAAY;GAAI,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE;EAC7C;EAEA,SAAS,QAAQ,GAAW,GAAqC;GAC/D,IAAI,KAAK,IAAI,IAAI,EAAE,KAAK,WAAW,KAAK,IAAI,IAAI,EAAE,KAAK,SAAS,OAAO;GACvE,MAAM,KAAK,IAAI,IAAI,KAAK,IAAI;GAC5B,MAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;GACxC,IAAI,QAAQ,MAAkB,QAAQ,KAAgB,OAAO;GAC7D,OAAO;EACT;EAEA,SAAS,QAAQ,GAAW,GAAmB;GAE7C,IAAI,QAAQ,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,IAAI,MAAM,KAAK;GACpD,IAAI,QAAQ,GAAG,SAAS;GACxB,OAAO;EACT;EAEA,SAAS,OAAO,GAAW,GAA6B;GACtD,MAAM,KAAK,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK,UAAU;GAC3D,OAAO,CACL,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC,GACtC,KAAK,IAAI,KAAM,KAAK,IAAI,KAAM,KAAK,IAAI,MAAM,EAAE,CAAC,CAClD;EACF;EAEA,MAAa,cAAA,GAAaC,MAAAA,KAAAA,CAAK,SAAS,WAAW,EAAE,KAAK,KAAK,KAAK,YAGjE;GACD,MAAM,UAAA,GAASC,MAAAA,OAAAA,CAA0B,IAAI;GAC7C,MAAM,CAAC,KAAK,WAAA,GAAUC,MAAAA,SAAAA,CAAS;IAAE;IAAK;IAAK;GAAI,CAAC;GAChD,MAAM,UAAA,GAASD,MAAAA,OAAAA,CAAO,GAAG;GACzB,OAAO,UAAU;GAGjB,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,QAAO,MAAM,EAAE,QAAQ,OAAO,EAAE,QAAQ,OAAO,EAAE,QAAQ,MAAM,IAAI;KAAE;KAAK;KAAK;IAAI,CAAE;GACvF,GAAG;IAAC;IAAK;IAAK;GAAG,CAAC;GAIlB,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,MAAM,MAAM,OAAO;IACnB,IAAI,CAAC,KAAK;IACV,MAAM,MAAM,IAAI,WAAW,IAAI;IAC/B,IAAI,UAAU,GAAG,GAAG,YAAY,UAAU;IAI1C,WAAW,KAAK,IAAI,GAAG;IACvB,IAAI,UAAU,aAAa,GAAG,GAAG,CAAC;IAClC,YAAY,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG;GAC5C,GAAG,CAAC,GAAG,CAAC;GAIR,MAAM,cAAA,GAAaA,MAAAA,OAAAA,CAAmD,IAAI;GAC1E,MAAM,UAAA,GAASA,MAAAA,OAAAA,CAAsB,IAAI;GACzC,MAAM,gBAAA,GAAeE,MAAAA,YAAAA,OAAkB;IACrC,OAAO,UAAU;IACjB,MAAM,IAAI,WAAW;IACrB,IAAI,CAAC,GAAG;IACR,WAAW,UAAU;IACrB,OAAO;KAAE,KAAK,EAAE;KAAG,KAAK,EAAE;KAAG,KAAK,EAAE;IAAE,CAAC;IACvC,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;GACxB,GAAG,CAAC,QAAQ,CAAC;GAEb,MAAM,YAAA,GAAWA,MAAAA,YAAAA,EAAa,GAAW,GAAW,MAAc;IAChE,WAAW,UAAU;KAAE;KAAG;KAAG;IAAE;IAC/B,IAAI,OAAO,YAAY,MAAM,OAAO,UAAU,sBAAsB,YAAY;GAClF,GAAG,CAAC,YAAY,CAAC;GAEjB,MAAM,UAAA,GAASA,MAAAA,YAAAA,EAAa,MAA2C;IACrE,MAAM,IAAI,OAAO,QAAS,sBAAsB;IAChD,MAAM,IAAI,EAAE,UAAU,EAAE,MAAM,IAAI,EAAE,UAAU,EAAE;IAChD,MAAM,SAAS,QAAQ,GAAG,CAAC;IAC3B,IAAI,CAAC,QAAQ;IACb,IAAI,WAAW,QACb,SAAS,QAAQ,GAAG,CAAC,GAAG,OAAO,QAAQ,KAAK,OAAO,QAAQ,GAAG;SACzD;KACL,MAAM,CAAC,GAAG,KAAK,OAAO,GAAG,CAAC;KAC1B,SAAS,OAAO,QAAQ,KAAK,GAAG,CAAC;IACnC;IACA,MAAM,UAAU,OAAmB;KACjC,MAAM,KAAK,OAAO,QAAS,sBAAsB;KACjD,MAAM,KAAK,GAAG,UAAU,GAAG,MAAM,KAAK,GAAG,UAAU,GAAG;KACtD,IAAI,WAAW,QAAQ;MACrB,MAAM,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,KAAK,OAAO,CAAC;MACnD,IAAI,KAAK,MAAmB,KAAK,KAAiB,SAAS,QAAQ,IAAI,EAAE,GAAG,OAAO,QAAQ,KAAK,OAAO,QAAQ,GAAG;KACpH,OAAO;MACL,MAAM,CAAC,GAAG,KAAK,OAAO,IAAI,EAAE;MAC5B,SAAS,OAAO,QAAQ,KAAK,GAAG,CAAC;KACnC;IACF;IACA,MAAM,aAAa;KAAE,SAAS,oBAAoB,aAAa,MAAM;KAAG,SAAS,oBAAoB,WAAW,IAAI;IAAE;IACtH,SAAS,iBAAiB,aAAa,MAAM;IAAG,SAAS,iBAAiB,WAAW,IAAI;GAC3F,GAAG,CAAC,QAAQ,CAAC;GAEb,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;IAAQ,KAAK;IAAQ,OAAO;IAAY,QAAQ;IAAY,WAAU;IAAY,aAAa;GAAS,CAAA;EACjH,CAAC;;;ECnKD,MAAM,QAAQ;EAEd,SAAS,MAAM,GAAW,KAAa,KAAqB;GAC1D,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,CAAC;EACvC;;EAGA,SAASC,QAAM,KAAuC;GACpD,OAAO,MAAM,IAAI,KAAI,MAAK,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;EAChF;;;;;;;;EASA,SAAS,SAAS,EAAE,OAAO,OAAO,KAAK,KAAK,MAAM,YAG/C;GACD,MAAM,CAAC,MAAM,YAAA,GAAWC,MAAAA,SAAAA,CAAS,OAAO,KAAK,CAAC;GAC9C,MAAM,WAAA,GAAUC,MAAAA,OAAAA,CAAO,KAAK;GAE5B,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,CAAC,QAAQ,SAAS,QAAQ,OAAO,KAAK,CAAC;GAC7C,GAAG,CAAC,KAAK,CAAC;GAEV,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,SAAD;IAAO,WAAU;IAAjB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;KAAM,WAAU;KAAmB,UAAA;IAAY,CAAA,GAC/C,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;KACE,MAAK;KACA;KAAU;KAAW;KAC1B,OAAO;KACP,WAAU;KACV,eAAe;MAAE,QAAQ,UAAU;KAAK;KACxC,cAAc;MAAE,QAAQ,UAAU;MAAO,QAAQ,OAAO,KAAK,CAAC;KAAE;KAChE,WAAU,MAAK;MACb,QAAQ,EAAE,OAAO,KAAK;MACtB,MAAM,IAAI,OAAO,EAAE,OAAO,KAAK;MAC/B,IAAI,OAAO,SAAS,CAAC,GAAG,SAAS,MAAM,GAAG,KAAK,GAAG,CAAC;KACrD;IACD,CAAA,CACI;;EAEX;;;;;;;;;EAUA,SAAgB,YAAY,EAAE,KAAK,KAAK,KAAK,YAG1C;GACD,MAAM,CAAC,MAAM,YAAA,GAAWD,MAAAA,SAAAA,CAAe,KAAK;GAC5C,MAAM,CAAC,GAAG,GAAG,KAAK,SAAS,KAAK,KAAK,GAAG;GACxC,MAAM,CAAC,GAAG,GAAG,KAAK,SAAS,GAAG,GAAG,CAAC;GAClC,MAAM,MAAMD,QAAM;IAAC;IAAG;IAAG;GAAC,CAAC,CAAC,CAAC,YAAY;GAKzC,MAAM,OAAO,QAAS,IAAI,QAAS,IAAI,QAAS,KAAK,MAAM,MAAO,oBAAoB;GAEtF,MAAM,UAAU,IAAY,IAAY,OAAe,SAAS,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC;GACvF,MAAM,UAAU,IAAY,IAAY,OAAe;IACrD,MAAM,CAAC,IAAI,IAAI,MAAM,SAAS,IAAI,IAAI,EAAE;IACxC,SAAS,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC;GAClC;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAU,OAAO,EAAE,OAAO,GAAG,MAAM,IAAI;MAAtD,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAgB,OAAO,EAAE,WAAW,cAAc,SAAS,QAAQ,IAAI,MAAM,KAAK;OAAI,CAAA;OACrG,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAW,eAAe,SAAS,QAAQ,eAAe;QAAM,eAAe,QAAQ,KAAK;QAAG,UAAA;OAAW,CAAA;OAChI,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAW,eAAe,SAAS,QAAQ,eAAe;QAAM,eAAe,QAAQ,KAAK;QAAG,UAAA;OAAW,CAAA;MAC7H;;KACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,eAAe;OAAU,KAAK;MAAE;MAC5D,UAAA,SAAS,QACR,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAU,OAAM;QAAI,OAAO,KAAK,MAAM,CAAC;QAAG,KAAK;QAAG,KAAK;QAAK,MAAM;QAAG,WAAU,MAAK,OAAO,GAAG,GAAG,CAAC;OAAI,CAAA;OACtG,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAU,OAAM;QAAI,OAAO,KAAK,MAAM,IAAI,GAAG;QAAG,KAAK;QAAG,KAAK;QAAK,MAAM;QAAG,WAAU,MAAK,OAAO,GAAG,IAAI,KAAK,CAAC;OAAI,CAAA;OAClH,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAU,OAAM;QAAI,OAAO,KAAK,MAAM,IAAI,GAAG;QAAG,KAAK;QAAG,KAAK;QAAK,MAAM;QAAG,WAAU,MAAK,OAAO,GAAG,GAAG,IAAI,GAAG;OAAI,CAAA;MAClH,EAAA,CAAA,IAEF,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAU,OAAM;QAAI,OAAO;QAAG,KAAK;QAAG,KAAK;QAAK,MAAM;QAAG,WAAU,MAAK,OAAO,GAAG,GAAG,CAAC;OAAI,CAAA;OAC1F,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAU,OAAM;QAAI,OAAO;QAAG,KAAK;QAAG,KAAK;QAAK,MAAM;QAAG,WAAU,MAAK,OAAO,GAAG,GAAG,CAAC;OAAI,CAAA;OAC1F,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAU,OAAM;QAAI,OAAO;QAAG,KAAK;QAAG,KAAK;QAAK,MAAM;QAAG,WAAU,MAAK,OAAO,GAAG,GAAG,CAAC;OAAI,CAAA;MAC1F,EAAA,CAAA;KAED,CAAA;KAML,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MACE,WAAU;MACV,OAAO;OAAE,YAAY,OAAO,KAAK,MAAM,CAAC,EAAE,GAAG,KAAK,MAAM,IAAI,GAAG,EAAE,IAAI,KAAK,MAAM,IAAI,GAAG,EAAE;OAAK,OAAO;MAAI;MACxG,UAAA;KACE,CAAA;IACF;;EAET;;;ECjHA,MAAM,WAAW;EACjB,MAAM,WAAW;EAEjB,SAASG,QAAM,KAAuC;GACpD,OAAO,MAAM,IAAI,KAAI,MAAK,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;EACpE;;;;;;;;EASA,SAAgB,YAAY,EAAE,KAAK,GAAG,QAAQ,WAK3C;GACD,MAAM,aAAA,GAAYC,MAAAA,OAAAA,CAA0B,IAAI;GAChD,MAAM,UAAA,GAASA,MAAAA,OAAAA,CAA0B,IAAI;GAC7C,MAAM,UAAA,GAASA,MAAAA,OAAAA,CAAgC,IAAI;GACnD,MAAM,CAAC,OAAO,aAAA,GAAYC,MAAAA,SAAAA,CAAS,KAAK;GACxC,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAAmD,IAAI;GACjF,MAAM,CAAC,KAAK,WAAA,GAAUA,MAAAA,SAAAA,CAA0C,IAAI;GAEpE,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,MAAM,MAAM,IAAI,MAAM;IACtB,IAAI,eAAe;KAAE,OAAO,UAAU;KAAK,SAAS,IAAI;IAAE;IAC1D,IAAI,MAAM;GACZ,GAAG,CAAC,GAAG,CAAC;GAER,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,CAAC,SAAS,CAAC,UAAU,WAAW,CAAC,OAAO,SAAS;IACrD,MAAM,SAAS,UAAU;IACzB,OAAO,QAAQ,OAAO,QAAQ;IAC9B,OAAO,SAAS,OAAO,QAAQ;IAC/B,MAAM,MAAM,OAAO,WAAW,IAAI;IAClC,IAAI,KAAK,IAAI,UAAU,OAAO,SAAS,GAAG,CAAC;GAC7C,GAAG,CAAC,KAAK,CAAC;GAEV,MAAM,YAAA,GAAWC,MAAAA,YAAAA,EAAa,SAAiB,YAAoB;IACjE,MAAM,SAAS,UAAU;IACzB,IAAI,CAAC,QAAQ,OAAO;IACpB,MAAM,OAAO,OAAO,sBAAsB;IAC1C,IAAI,KAAK,UAAU,KAAK,KAAK,WAAW,GAAG,OAAO;IAClD,MAAM,MAAM,OAAO,WAAW,IAAI;IAClC,IAAI,CAAC,KAAK,OAAO;IACjB,MAAM,KAAK,KAAK,OAAO,UAAU,KAAK,SAAS,OAAO,QAAQ,KAAK,MAAM;IACzE,MAAM,KAAK,KAAK,OAAO,UAAU,KAAK,QAAQ,OAAO,SAAS,KAAK,OAAO;IAC1E,IAAI,KAAK,KAAK,KAAK,KAAK,MAAM,OAAO,SAAS,MAAM,OAAO,QAAQ,OAAO;IAC1E,MAAM,IAAI,IAAI,aAAa,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IACzC,OAAO;KAAE;KAAI;KAAI,KAAK;MAAC,EAAE;MAAI,EAAE;MAAI,EAAE;KAAE;IAA8B;GACvE,GAAG,CAAC,CAAC;GAEL,MAAM,iBAAA,GAAgBA,MAAAA,YAAAA,EAAa,IAAY,OAAe;IAC5D,MAAM,MAAM,OAAO;IACnB,MAAM,MAAM,UAAU;IACtB,IAAI,CAAC,OAAO,CAAC,KAAK;IAClB,MAAM,MAAM,IAAI,WAAW,IAAI;IAC/B,IAAI,CAAC,KAAK;IACV,MAAM,OAAO,WAAW,WAAW;IACnC,IAAI,UAAU,GAAG,GAAG,UAAU,QAAQ;IACtC,IAAI,UAAU,KAAK,KAAK,MAAM,KAAK,MAAM,IAAU,IAAU,GAAG,GAAG,UAAU,QAAQ;IACrF,IAAI,cAAc;IAClB,IAAI,YAAY;IAChB,IAAI,UAAU;IACd,IAAI,OAAO,WAAW,GAAG,CAAC;IAAG,IAAI,OAAO,WAAW,GAAG,QAAQ;IAC9D,IAAI,OAAO,GAAG,WAAW,CAAC;IAAG,IAAI,OAAO,UAAU,WAAW,CAAC;IAC9D,IAAI,OAAO;GACb,GAAG,CAAC,CAAC;GAEL,MAAM,UAAU,MAAwB;IACtC,MAAM,IAAI,SAAS,EAAE,SAAS,EAAE,OAAO;IACvC,IAAI,CAAC,GAAG;KAAE,SAAS,IAAI;KAAG,OAAO,IAAI;KAAG;IAAO;IAC/C,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC;IACvB,cAAc,EAAE,IAAI,EAAE,EAAE;IACxB,MAAM,MAAM;IACZ,IAAI,IAAI,EAAE,UAAU;IACpB,IAAI,IAAI,EAAE,UAAU;IACpB,IAAI,IAAI,WAAW,OAAO,YAAY,IAAI,EAAE,UAAU,MAAM;IAC5D,IAAI,IAAI,WAAW,OAAO,aAAa,IAAI,EAAE,UAAU,MAAM;IAC7D,OAAO;KAAE;KAAG;IAAE,CAAC;GACjB;GAEA,MAAM,WAAW,MAAwB;IACvC,MAAM,IAAI,SAAS,EAAE,SAAS,EAAE,OAAO;IACvC,IAAI,CAAC,GAAG;IACR,MAAM,CAAC,GAAG,IAAI,KAAK,SAAS,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE;IACxD,OAAO,SAAS,GAAG,IAAI,CAAC,CAAC;GAC3B;GAEA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAAqB,UAAA,EAAE,aAAa;KAAO,CAAA;KAC1D,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAAoB,UAAA,EAAE,YAAY;KAAO,CAAA;KACxD,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAAiB,OAAO;OACrC,UAAU;OAAoB,WAAW;OAAQ,UAAU;OAC3D,cAAc;OAAI,QAAQ;OAAmC,YAAY;OAAQ,QAAQ;MAC3F;MACE,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;OAAQ,KAAK;OAAW,OAAO;QAAE,SAAS;QAAS,UAAU;QAAQ,WAAW;QAAQ,WAAW;OAAU;OAC3G,aAAa;OACb,oBAAoB;QAAE,SAAS,IAAI;QAAG,OAAO,IAAI;OAAE;OAC1C;MAAU,CAAA;KAClB,CAAA;KACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,YAAY;OAAU,KAAK;OAAI,UAAU;MAAI;MAA5E,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD,EAAK,OAAO;OAAE,OAAO;OAAI,QAAQ;OAAI,cAAc;OAAG,QAAQ;OAAmC,YAAY,QAAQH,QAAM,MAAM,GAAG,IAAI;MAAc,EAAI,CAAA,GAC1J,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,OAAO;QAAE,OAAO;QAAQ,UAAU;QAAI,YAAY;OAA6B;OAAI,UAAA,QAAQ,GAAGA,QAAM,MAAM,GAAG,EAAE,SAAS,MAAM,IAAI,KAAK,IAAI,EAAE,KAAK;MAAS,CAAA,CAC7J;;KACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,KAAK;MAAG;MACrC,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;OAAQ,MAAK;OAAS,WAAU;OAAU,SAAS;OAAU,UAAA,EAAE,aAAa;MAAU,CAAA;KACnF,CAAA;KACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MAAQ,KAAK;MAAQ,OAAO;MAAU,QAAQ;MAC5C,OAAO;OACL,UAAU;OAAS,OAAO;OAAU,QAAQ;OAAU,cAAc;OACpE,QAAQ;OAAmC,WAAW;OACtD,QAAQ;OAAO,YAAY;OAAQ,eAAe;OAAQ,YAAY;OACtE,MAAM,KAAK,KAAK;OAAG,KAAK,KAAK,KAAK;OAAG,SAAS,MAAM,IAAI;MAC1D;KAAI,CAAA;IACH;GACC,CAAA,EAAA,CAAA;EAEZ;;;;;;;;;ECtHA,SAAgB,SAAS,EAAE,KAAK,OAAO,GAAG,SAAS,YAMhD;GACD,MAAM,KAAK,KAAK,IAAI,OAAO,aAAa,KAAM,GAAG;GACjD,MAAM,KAAK,KAAK,MAAM,KAAK,OAAO,cAAc,OAAO,UAAU;GACjE,MAAM,QAAQ;GACd,MAAM,CAAC,MAAM,YAAA,GAAWI,MAAAA,SAAAA,CAAS,MAAM,KAAK,IAAI,MAAM,OAAO,CAAC;GAC9D,MAAM,CAAC,KAAK,WAAA,GAAUA,MAAAA,SAAAA,CAAS,MAAM,KAAK,IAAI;IAAE,GAAG,MAAM,IAAI;IAAI,GAAG,MAAM,IAAI;GAAG,IAAI;IAAE,GAAG;IAAG,GAAG;GAAE,CAAC;GACnG,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAS;IAAE,GAAG;IAAG,GAAG;GAAE,CAAC;GACrD,MAAM,gBAAA,GAAeC,MAAAA,OAAAA,CAAuB,IAAI;GAChD,MAAM,UAAA,GAASA,MAAAA,OAAAA,CAAyB,IAAI;GAC5C,MAAM,WAAA,GAAUA,MAAAA,OAAAA,CAAO;IAAE,QAAQ;IAAO,IAAI;IAAG,IAAI;IAAG,KAAK;IAAG,KAAK;GAAE,CAAC;GAEtE,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,MAAM,MAAM,IAAI,MAAM;IACtB,IAAI,eAAe;KACjB,MAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,OAAO,KAAK,IAAI,MAAM;KACtD,MAAM,IAAI,IAAI,QAAQ,OAAO,IAAI,IAAI,SAAS;KAC9C,WAAW;MAAE;MAAG;KAAE,CAAC;KACnB,MAAM,IAAI;KACV,IAAI,EAAE,KAAK,KAAK,EAAE,OAAO,IAAI,SAAS,EAAE,OAAO,IAAI,QAAQ;MACzD,QAAQ,EAAE,IAAI;MAId,OAAO;OAAE,GAAG,EAAE,IAAI,KAAK,IAAI,EAAE,OAAO;OAAG,GAAG,EAAE,IAAI,KAAK,IAAI,EAAE,OAAO;MAAE,CAAC;KACvE,OAAO;MACL,QAAQ,CAAC;MACT,OAAO;OAAE,IAAI,KAAK,KAAK;OAAG,IAAI,KAAK,KAAK;MAAE,CAAC;KAC7C;IACF;IACA,IAAI,MAAM;GACZ,GAAG;IAAC;IAAK;IAAO;IAAI;GAAE,CAAC;GAEvB,MAAM,UAAA,GAASC,MAAAA,YAAAA,EAAa,MAAwB;IAClD,EAAE,eAAe;IACjB,QAAQ,UAAU;KAAE,QAAQ;KAAM,IAAI,EAAE;KAAS,IAAI,EAAE;KAAS,KAAK,IAAI;KAAG,KAAK,IAAI;IAAE;IACvF,MAAM,UAAU,OAAmB;KACjC,IAAI,CAAC,QAAQ,QAAQ,QAAQ;KAC7B,OAAO;MAAE,GAAG,QAAQ,QAAQ,MAAM,GAAG,UAAU,QAAQ,QAAQ;MAAI,GAAG,QAAQ,QAAQ,MAAM,GAAG,UAAU,QAAQ,QAAQ;KAAG,CAAC;IAC/H;IACA,MAAM,aAAa;KAAE,QAAQ,QAAQ,SAAS;KAAO,SAAS,oBAAoB,aAAa,MAAM;KAAG,SAAS,oBAAoB,WAAW,IAAI;IAAE;IACtJ,SAAS,iBAAiB,aAAa,MAAM;IAAG,SAAS,iBAAiB,WAAW,IAAI;GAC3F,GAAG,CAAC,GAAG,CAAC;GAER,MAAM,aAAA,GAAYA,MAAAA,YAAAA,EAAa,MAAkB;IAC/C,EAAE,eAAe;IACjB,MAAM,KAAK,aAAa;IACxB,IAAI,CAAC,IAAI;IACT,MAAM,OAAO,GAAG,sBAAsB;IAGtC,MAAM,KAAK,KAAK,QAAQ,GAAG,KAAK,KAAK,SAAS;IAE9C,MAAM,SAAS,EAAE,SAAS,IAAI,MAAO;IACrC,MAAM,KAAK,KAAK,IAAI,IAAK,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC;IACpD,MAAM,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK;IACrC,MAAM,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK;IACrC,QAAQ,EAAE;IAAG,OAAO;KAAE,GAAG;KAAI,GAAG;IAAG,CAAC;GACtC,GAAG,CAAC,MAAM,GAAG,CAAC;GAEd,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,MAAM,KAAK,aAAa;IACxB,IAAI,CAAC,IAAI;IACT,GAAG,iBAAiB,SAAS,WAAW,EAAE,SAAS,MAAM,CAAC;IAC1D,aAAa,GAAG,oBAAoB,SAAS,SAAS;GACxD,GAAG,CAAC,SAAS,CAAC;GAEd,MAAM,aAAA,GAAYA,MAAAA,YAAAA,OAAkB;IAClC,IAAI,QAAQ,MAAM,GAAG;IACrB,QAAQ,CAAC;IAAG,OAAO;KAAE,IAAI,KAAK,QAAQ,KAAK;KAAG,IAAI,KAAK,QAAQ,KAAK;IAAE,CAAC;GACzE,GAAG;IAAC;IAAI;IAAI;GAAO,CAAC;GAEpB,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;IAAK,WAAU;IAAc,UAAS,MAAK;KAAE,IAAI,EAAE,WAAW,EAAE,eAAe,QAAQ;IAAE;IAAzF,UAAA;KACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAAqB,UAAA,EAAE,aAAa;KAAO,CAAA;KAC1D,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,KAAK;MAAc,WAAU;MAAiB,OAAO;OACxD,UAAU;OAAY,UAAU;OAAU,QAAQ;OAClD,cAAc;OAAI,YAAY;OAAQ,QAAQ;OAAQ,OAAO;OAAI,QAAQ;MAC3E;MAAG,aAAa;MACd,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,KAAK;OAAQ,KAAK;OAAK,KAAI;OAAG,WAAW;OAAO,OAAO;QAC1D,UAAU;QAAY,iBAAiB;QAAO,eAAe;QAC7D,OAAO,QAAQ;QAAG,QAAQ,QAAQ;QAClC,WAAW,aAAa,IAAI,EAAE,KAAK,IAAI,EAAE,YAAY,KAAK;OAC5D;MAAI,CAAA;KACD,CAAA;KACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MAAoB,UAAA,EAAE,YAAY;KAAO,CAAA;KACxD,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,OAAO;OAAE,SAAS;OAAQ,KAAK;MAAG;MAAvC,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAU,SAAS;QAAY,UAAA,EAAE,aAAa;OAAU,CAAA;OACxF,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAU,SAAS;QAAU,UAAA,EAAE,cAAc;OAAU,CAAA;OACvF,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAU,eAAe,SAAS,OAAO,IAAI,IAAI,QAAQ,IAAI,OAAO,KAAK,KAAK,IAAI,IAAI,QAAQ,IAAI,OAAO,KAAK,IAAI,OAAO,SAAS,gBAAgB,GAAG,OAAO,SAAS,iBAAiB,CAAC;QAAI,UAAA,EAAE,cAAc;OAAU,CAAA;MAClP;;IACF;GACC,CAAA,EAAA,CAAA;EAEZ;;;EC/FA,MAAM,WAAiD;GACrD;IAAE,MAAM;IAAO,KAAK;GAAY;GAChC;IAAE,MAAM;IAAQ,KAAK;GAAa;GAClC;IAAE,MAAM;IAAW,KAAK;GAAgB;GACxC;IAAE,MAAM;IAAQ,KAAK;GAAa;GAClC;IAAE,MAAM;IAAU,KAAK;GAAe;EACxC;;EAGA,MAAM,aAAuC;GAAC;GAAK;GAAM;EAAI;;;;;EAM7D,MAAM,kBAAsD;GAC1D,cAAc;GACd,cAAc;GACd,iBAAiB;GACjB,mBAAmB;EACrB;EAEA,SAAS,MAAM,KAAuC;GACpD,OAAO,MAAM,IAAI,KAAI,MAAK,KAAK,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;EAChF;EAEA,SAAgB,YAAY,EAAE,GAAG,UAAiF;GAChH,MAAM,EAAE,GAAG,aAAa;GACxB,MAAM,QAAQ,UAAU,MAAuB,CAAC;GAChD,MAAM,QAAQ,IAAI;GAOlB,MAAM,CAAC,MAAM,YAAA,GAAWC,MAAAA,SAAAA,CAAS,EAAE;GACnC,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAS,KAAK;GAC5C,CAAA,GAAA,MAAA,UAAA,OAAgB;IAAE,IAAI,CAAC,SAAS,QAAQ,MAAM,KAAK;GAAE,GAAG,CAAC,MAAM,OAAO,OAAO,CAAC;GAC9E,MAAM,QAAQ,KAAK,KAAK;GACxB,MAAM,gBAA+B;IACnC,IAAI,UAAU,IAAI,OAAO;IACzB,MAAM,MAAM,UAAU,OAAO,KAAK;IAClC,MAAM,OAAO,IAAI;IACjB,IAAI,SAAS,MAAM,OAAO;IAC1B,MAAM,IAAI,MAAM,WAAU,MAAK,EAAE,OAAO,KAAK,EAAE,IAAI;IACnD,OAAO,GAAG,IAAI,UAAU,EAAE,WAAW,IAAI,EAAE,gBAAgB,EAAE,GAAG;GAClE,EAAA,CAAG;GAEH,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;IACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;KAAQ,WAAU;KAAoB,OAAO,EAAE,OAAO,EAAE;KAAxD,UAAA;MACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAe,UAAA;MAAU,CAAA;MACxC,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;OAAI,WAAU;OAAU,UAAA,EAAE,aAAa;MAAM,CAAA;MAC7C,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAAY,UAAA,EAAE,aAAa;MAAK,CAAA;KACvC;;IAER,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;KAAS,WAAU;KAAoB,OAAO,EAAE,OAAO,EAAE;KAAzD,UAAA;MAKG,MAAM,YACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAAqB,OAAO,EAAE,cAAc,GAAG;OAAI,UAAA,EAAE,eAAe;MAAK,CAAA,IACpF;MACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAoB,UAAA,EAAE,aAAa;MAAO,CAAA;MACzD,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,OAAO;QAAE,WAAW;QAAI,SAAS;QAAQ,UAAU;QAAQ,KAAK;QAAG,YAAY;OAAS;OAA7F,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QACE,MAAK;QAAO,WAAU;QAAe,OAAO;QAC5C,aAAa,EAAE,mBAAmB;QAClC,WAAU,MAAK;SAAE,WAAW,IAAI;SAAG,QAAQ,EAAE,OAAO,KAAK;QAAE;OAAI,CAAA,GAChE,MAAM,UAAU,KACf,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAU,eAAe;SAAE,WAAW,IAAI;SAAG,QAAQ,MAAM,KAAK;QAAE;QAC/F,UAAA,EAAE,kBAAkB;OACf,CAAA,IACN,IACD;;MACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAAW,OAAO,EAAE,WAAW,EAAE;OAC3C,UAAA,UAAU,KAAK,EAAE,aAAa,IAAI,WAAW,OAAO,EAAE,YAAY,IAAI;MACtE,CAAA;MAIF,MAAM,UAAU,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAAW,OAAO,EAAE,WAAW,EAAE;OAAI,UAAA,EAAE,mBAAmB;MAAK,CAAA,IAAI;MACrG,MAAM,UAAU,MAAM,MAAM,gBAAgB,YACzC,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAAW,OAAO,EAAE,WAAW,EAAE;OAAI,UAAA,EAAE,yBAAyB;MAAK,CAAA,IAClF;MACH,gBAAgB,MAAM,eAAe,KAAA,IAClC,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAAW,OAAO,EAAE,WAAW,EAAE;OAAI,UAAA,EAAE,gBAAgB,MAAM,UAAW;MAAK,CAAA,IAC1F;KACG;;IAET,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;KAAS,WAAU;KAAW,OAAO,EAAE,OAAO,EAAE;KAAhD,UAAA;MAME,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAU;OAAe,OAAO;QAAE,cAAc;QAAI,YAAY;OAAS;OAA9E,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAW,aAAa,IAAI,cAAc,WAAW;QACzE,MAAK;QAAS,gBAAc,IAAI;QAAa,OAAO,EAAE,aAAa;QACnE,eAAe,EAAE,eAAe,CAAC,IAAI,WAAW;QAChD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,kBAAmB,CAAA;OAC7B,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAY,UAAA,EAAE,aAAa;OAAQ,CAAA,CAChD;;MAEL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OACZ,UAAA,MAAM,KAAK,MAAM,MAChB,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QACmB;QAAS;QAAM,OAAO;QAAG,OAAO,MAAM;QAIvD,WAAW,KAAK,OAAO,MAAM,eAAe,MAAM,WAAW;QAC7D,QAAQ,KAAK,OAAO,MAAM;QAAsB;OAAS,GALpD,KAAK,EAK+C,CAC5D;MACE,CAAA;MAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;OAAQ,MAAK;OAAS,WAAU;OAA0B,OAAO,EAAE,WAAW,GAAG;OAAG,eAAe;QAAE,EAAE,QAAQ;OAAE;OAAjH,UAAA,CAAoH,MAC/G,EAAE,SAAS,CACR;;KACD;;GACT,EAAA,CAAA;EAEN;EAEA,SAAS,SAAS,EAAE,GAAG,MAAM,OAAO,OAAO,QAAQ,WAAW,UAS3D;GACD,MAAM,EAAE,MAAM;GAEd,MAAM,CAAC,MAAM,YAAA,GAAWA,MAAAA,SAAAA,CAAS,MAAM;GACvC,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAS,KAAK;GAO9C,MAAM,eAAA,GAAcC,MAAAA,OAAAA,CAAgF,IAAI;;GAExG,MAAM,UAAA,GAASA,MAAAA,OAAAA,CAA4C,IAAI;GAC/D,MAAM,CAAC,MAAM,YAAA,GAAWD,MAAAA,SAAAA,CAA8C,IAAI;;GAE1E,MAAM,cAAA,GAAaC,MAAAA,OAAAA,CAAO,KAAK;GAC/B,MAAM,CAAC,SAAS,eAAA,GAAcD,MAAAA,SAAAA,CAAS,KAAK;GAC5C,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAS,EAAE;GACvC,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAS,KAAK;GAC5C,MAAM,CAAC,QAAQ,cAAA,GAAaA,MAAAA,SAAAA,CAAwB,IAAI;GACxD,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAS,KAAK;GAClD,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAS,KAAK;GAClD,MAAM,CAAC,YAAY,kBAAA,GAAiBA,MAAAA,SAAAA,CAAS,KAAK;GAClD,MAAM,CAAC,UAAU,gBAAA,GAAeA,MAAAA,SAAAA,CAAwB,IAAI;;GAE5D,MAAM,CAAC,SAAS,eAAA,GAAcA,MAAAA,SAAAA,CAAS,KAAK;GAC5C,MAAM,WAAA,GAAUC,MAAAA,OAAAA,CAAyB,IAAI;GAM7C,MAAM,CAAC,KAAK,WAAA,GAAUD,MAAAA,SAAAA,CAAS,CAAC;GAChC,MAAM,SAAS,KAAK,OAAO,WAAW,IAAI,IAAI,KAAK,IAAI,KAAK,KAAK,OAAO,SAAS,CAAC;GAClF,MAAM,QAAQ,KAAK,OAAO;GAC1B,MAAM,MAAM,UAAU,KAAA,IAAY,OAAO,EAAE,QAAQ,MAAM,IAAI;GAY7D,MAAM,WAAW,UAAU,KAAA,IAAY,KAAK,QAAQ,MAAM;GAC1D,MAAM,YAAY,UAAiD;IACjE,IAAI,UAAU,KAAA,GAAW,EAAE,QAAQ,KAAK,IAAI,EAAE,MAAM,CAAC;SAChD,EAAE,cAAc,KAAK,IAAI,MAAM,MAAM,KAAK;GACjD;GACA,MAAM,CAAC,GAAG,GAAG,KAAK,YAAY;GAC9B,MAAM,QAAQ,SAAS,GAAG,GAAG,CAAC;GAG9B,CAAA,GAAA,MAAA,UAAA,OAAgB;IACd,IAAI,MAAM,EAAO,eAAe,KAAK,EAAE;GAGzC,GAAG;IAAC;IAAM,KAAK;IAAI,KAAK,OAAO;IAAQ;GAAC,CAAC;GAEzC,MAAM,WAAW,IAAY,IAAY,OAAqB;IAC5D,MAAM,CAAC,IAAI,IAAI,MAAM,SAAS,IAAI,IAAI,EAAE;IACxC,SAAS;KAAC;KAAI;KAAI;IAAE,CAAC;GACvB;GAEA,MAAM,WAAW,UAAiC;IAChD,MAAM,OAAO,MAAM,QAAO,MAAK,EAAE,KAAK,WAAW,QAAQ,CAAC;IAC1D,IAAI,KAAK,WAAW,GAAG;IAIvB,IAAI,SAAS;KACX,MAAM,OAAO,KAAK,OAAO,OAAO,EAAE;KAClC,IAAI,SAAS,KAAA,GAAW,QAAQ,KAAK,KAAK,MAAK;MAAE,IAAI,MAAM,MAAM,EAAE,aAAa,KAAK,IAAI,MAAM,CAAC;KAAE,CAAC;KACnG;IACF;IAIA,MAAM,MAAgB,CAAC;IAKvB,MAAM,QAAQ,KAAK,OAAO;IAC1B,IAAI,UAAU,KAAK;IACnB,KAAK,SAAS,GAAG,MAAM;KACrB,QAAQ,IAAG,MAAK;MACd,IAAI,MAAM,MAAM,IAAI,KAAK;MACzB;MACA,IAAI,YAAY,GAAG;OACjB,EAAE,cAAc,KAAK,IAAI,IAAI,QAAQ,MAAmB,OAAO,MAAM,QAAQ,CAAC;OAC9E,OAAO,KAAK;MACd;KACF,CAAC;IACH,CAAC;GACH;GAEA,MAAM,UAAU,MAA6B;IAC3C,EAAE,eAAe;IACjB,YAAY,KAAK;IACjB,MAAM,QAAQ,MAAM,KAAK,EAAE,aAAa,SAAS,CAAC,CAAC;IACnD,IAAI,MAAM,SAAS,GAAG,QAAQ,KAAK;GACrC;GAEA,MAAM,WAAW,YAA2B;IAI1C,MAAM,OAAO,OAAO,MAAM,KAAK,CAAC,CAAC,KAAI,MAAK,EAAE,KAAK,CAAC,CAAC,CAAC,QAAO,MAAK,MAAM,EAAE;IACxE,IAAI,KAAK,WAAW,GAAG;KAAE,UAAU,EAAE,gBAAgB,CAAC;KAAG;IAAO;IAChE,IAAI,KAAK,MAAK,MAAK,CAAC,gBAAgB,KAAK,CAAC,CAAC,GAAG;KAAE,UAAU,EAAE,gBAAgB,CAAC;KAAG;IAAO;IACvF,WAAW,IAAI;IACf,UAAU,IAAI;IAGd,MAAM,QAAQ,KAAK,OAAO;IAC1B,KAAK,MAAM,KAAK,MAAM;KACpB,MAAM,MAAM,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;KAClD,IAAI,CAAC,IAAI,IAAI;MACX,WAAW,KAAK;MAChB,UAAU,IAAI,UAAU,iBAAiB,IAAI,UAAU,uBACnD,EAAE,gBAAgB,IACjB,IAAI,SAAS,EAAE,aAAa,CAAE;MACnC;KACF;IACF;IACA,WAAW,KAAK;IAChB,WAAW,KAAK;IAChB,UAAU,EAAE;IAEZ,OAAO,KAAK;GACd;GAEA,MAAM,YAAY,YAA2B;IAC3C,IAAI,QAAQ,QAAQ,cAAc,UAAU,KAAA,GAAW;IACvD,cAAc,IAAI;IAClB,IAAI;KACF,MAAM,KAAK,MAAM,EAAE,aAAa,KAAK,IAAI,MAAM,IAAI;KACnD,OAAO,KAAK,EAAE,aAAa,IAAI,EAAE,aAAa,GAAG,EAAE;IACrD,QAAQ;KACN,OAAO,EAAE,aAAa,GAAG,KAAK;IAChC,UAAU;KACR,cAAc,KAAK;IACrB;GACF;;;;;;;GAQA,MAAM,cAAc,YAA2B;IAC7C,IAAI,QAAQ,QAAQ,UAAU,KAAA,GAAW;KACvC,cAAc,IAAI;KAClB,IAAI;MACF,IAAI,MAAM,EAAE,aAAa,KAAK,IAAI,MAAM,IAAI,GAAG;KACjD,QAAQ,CAER,UAAU;MACR,cAAc,KAAK;KACrB;IACF;IACA,SAAS,UAAU;GACrB;GAEA,MAAM,MAAM,WAAW,SAAS,eAAe,KAAK,KAAK,UAAU,KAAK;GACxE,MAAM,YAAY,KAAK,OAAO,UAAU;GACxC,MAAM,SAAS,eAAe,MAAK,MAAK,EAAE,OAAO,KAAK,OAAO,UAAU;GACvE,MAAM,UAAU,OAAO,QAAQ;;GAI/B,MAAM,YAAY;GAElB,MAAM,YAAY,GAAW,UAAkB,MAAkD;IAG/F,IAAI,EAAE,WAAW,KAAK,EAAE,gBAAgB,SAAS;IACjD,EAAE,cAAc,kBAAkB,EAAE,SAAS;IAC7C,YAAY,UAAU;KAAE,GAAG,EAAE;KAAS,GAAG,EAAE;KAAS,MAAM;KAAG;KAAM,IAAI,EAAE;IAAU;IACnF,WAAW,UAAU;GACvB;GAEA,MAAM,YAAY,MAAkD;IAClE,MAAM,MAAM,YAAY;IACxB,IAAI,QAAQ,QAAQ,IAAI,OAAO,EAAE,WAAW;IAC5C,MAAM,MAAM,OAAO;IACnB,IAAI,QAAQ,MAAM;KAChB,IAAI,KAAK,IAAI,EAAE,UAAU,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,UAAU,IAAI,CAAC,IAAI,WAAW;KAC3E,WAAW,UAAU;IACvB;IAIA,MAAM,QAAQ,EAAE,cAAc;IAC9B,MAAM,OAAO,UAAU,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,iBAAiB,iBAAiB,CAAC;IAChF,IAAI,KAAK,KAAK;IACd,KAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;KACpC,MAAM,MAAM,KAAK,EAAE,CAAE,sBAAsB;KAC3C,IAAI,EAAE,UAAU,IAAI,OAAO,IAAI,QAAQ,GAAG;MAAE,KAAK;MAAG;KAAM;IAC5D;IACA,IAAI,QAAQ,QAAQ,IAAI,OAAO,IAAI;IACnC,OAAO,UAAU;KAAE,MAAM,IAAI;KAAM;IAAG;IACtC,QAAQ;KAAE,MAAM,IAAI;KAAM;IAAG,CAAC;GAChC;;GAGA,MAAM,UAAU,YAAqB,MAAkD;IACrF,MAAM,MAAM,YAAY;IACxB,YAAY,UAAU;IACtB,IAAI,QAAQ,QAAQ,EAAE,cAAc,kBAAkB,IAAI,EAAE,GAAG,EAAE,cAAc,sBAAsB,IAAI,EAAE;IAC3G,MAAM,MAAM,OAAO;IACnB,OAAO,UAAU;IACjB,QAAQ,IAAI;IACZ,IAAI,CAAC,UAAU,QAAQ,QAAQ,QAAQ,MAAM;IAK7C,MAAM,KAAK,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,IAAI;IAChD,IAAI,OAAO,IAAI,MAAM;IACrB,EAAE,gBAAgB,KAAK,IAAI,IAAI,MAAM,EAAE;IAGvC,OAAO,EAAE;GACX;GACA,MAAM,kBAAwB;IAC5B,IAAI,YAAY,MAAM;IAKtB,MAAM,KAAK;IACX,EAAE,gBAAgB,KAAK,IAAI,OAAO;IAClC,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,OAAO,SAAS,CAAC,CAAC,CAAC;GAC1D;;GAEA,MAAM,sBAA4B;IAChC,IAAI,aAAa,MAAM;IACvB,MAAM,OAAO,OAAO,SAAS,KAAK,CAAC;IACnC,YAAY,IAAI;IAChB,IAAI,CAAC,OAAO,SAAS,IAAI,KAAK,QAAQ,GAAG;IAGzC,EAAE,gBAAgB,KAAK,IAAI,EAAE,YAAY,KAAK,MAAM,OAAO,GAAI,EAAE,CAAC;GACpE;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;IAAS,WAAW;IAApB,UAAA;KACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAf,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAe,eAAe,SAAQ,MAAK,CAAC,CAAC;QAC3E,OAAO,OAAO,aAAa;QAAU,iBAAe;QACnD,UAAA,OAAO,MAAM;OACR,CAAA;OACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAgB,UAAA,QAAQ;OAAQ,CAAA;OAC/C,UAAU,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;QAAM,WAAU;QAAkB,UAAA,EAAE,mBAAmB;OAAQ,CAAA,IAAI;OAClF,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QACE,WAAU;QAAiB,OAAO,KAAK;QACvC,aAAa,EAAE,sBAAsB;QACrC,WAAU,MAAK,EAAE,QAAQ,KAAK,IAAI,EAAE,OAAO,EAAE,OAAO,MAAM,CAAC;OAAI,CAAA;OACjE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAW,aAAa,KAAK,UAAU,WAAW;QACtE,MAAK;QAAS,gBAAc,KAAK;QAAS,OAAO,EAAE,aAAa;QAChE,eAAe,EAAE,QAAQ,KAAK,IAAI,EAAE,SAAS,CAAC,KAAK,QAAQ,CAAC;QAC5D,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,kBAAmB,CAAA;OAC7B,CAAA;OACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAe,UAAU,UAAU;QACjE,OAAO,EAAE,QAAQ;QAAG,eAAe,EAAE,SAAS,KAAK,IAAI,EAAE;QAAG,UAAA;OAAS,CAAA;OACvE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAe,UAAU,UAAU,QAAQ;QACzE,OAAO,EAAE,UAAU;QAAG,eAAe,EAAE,SAAS,KAAK,IAAI,CAAC;QAAG,UAAA;OAAS,CAAA;OACxE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAC9B,OAAO,EAAE,YAAY;QAAG,eAAe,EAAE,WAAW,KAAK,EAAE;QAC3D,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD,EAAW,MAAM,GAAK,CAAA;OAChB,CAAA;MACL;;KAEJ,OACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;MAAK,WAAU;MACb,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CAEE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA;QAsBG,QAAQ,OACP,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SACb,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,KAAK;UAAK,KAAI;UAAG,WAAW;SAAQ,CAAA;QACtC,CAAA,IACH,KAAK,OAAO,WAAW,IACzB,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;SACE,MAAK;SACL,WAAW,oCAAoC,WAAW,aAAa;SACvE,OAAO,EAAE,aAAa;SACtB,aAAY,MAAK;UAAE,EAAE,eAAe;UAAG,YAAY,IAAI;SAAE;SACzD,mBAAmB,YAAY,KAAK;SAC5B;SACR,eAAe;UAAE,WAAW,KAAK;UAAG,QAAQ,SAAS,MAAM;SAAE;SAC7D,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;UAAM,WAAU;UAAhB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD,EAAY,MAAM,GAAK,CAAA,GACvB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,aAAa,EAAQ,CAAA,CAC1B;;QACA,CAAA,IAER,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SACb,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD,EAAY,MAAM,GAAK,CAAA,GACvB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,aAAa,EAAQ,CAAA,CAC3B;;QACF,CAAA;QAcN,KAAK,OAAO,SAAS,IACpB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SACE,WAAW,YAAY,WAAW,aAAa;SAC/C,aAAY,MAAK;UAAE,EAAE,eAAe;UAAG,YAAY,IAAI;SAAE;SACzD,mBAAmB,YAAY,KAAK;SAC5B;SAJV,UAAA,CAKG,KAAK,OAAO,KAAK,KAAK,MAAM;UAC3B,MAAM,QAAQ,EAAE,QAAQ,IAAI,IAAI;UAChC,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WACiB,MAAK;WAKpB,WAAW,iBAAiB,MAAM,SAAS,YAAY,KAAK,SAAS,QAAQ,KAAK,SAAS,IAAI,iBAAiB;WAChH,OAAO,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY;WACjF,eAAe,SAAS,GAAG,IAAI,IAAI;WACnC,eAAe;WACf,aAAa,OAAO,IAAI;WACxB,iBAAiB,OAAO,KAAK;WAC7B,eAAe;YAGb,IAAI,WAAW,SAAS;aAAE,WAAW,UAAU;aAAO;YAAO;YAC7D,OAAO,CAAC;WACV;WAKA,qBAAqB;YAInB,IAAI,CAAC,QAAQ;aAAE,OAAO,EAAE,iBAAiB,CAAC;aAAG;YAAO;YACpD,EAAE,cAAc,KAAK,IAAI,IAAI,IAAI;WACnC;WA5BF,UAAA;YA6BG,UAAU,OACP,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;aAAK,KAAK;aAAO,KAAI;aAAG,WAAW;YAAQ,CAAA,IAC3C,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,iBAAkB,CAAA;YACtC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aAAM,WAAU;aAAiB,UAAA,IAAI;YAAQ,CAAA;YAI5C,SAAS,QAAQ,KAAK,OAAO,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,gBAAiB,CAAA,IAAI;YACtE,SAAS,QAAQ,KAAK,OAAO,KAAK,OAAO,UAAU,MAAM,KAAK,OAAO,SAAS,IAC3E,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,uBAAwB,CAAA,IAAI;YAM/C,IAAI,UAAU,OACb,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aACE,WAAU;aACV,OAAO,MAAM,SAAS,IAAI,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,YAAY;aAC7E,OAAO,EAAE,YAAY,OAAO,IAAI,MAAM,GAAG,GAAG,KAAK,MAAM,IAAI,MAAM,KAAK,GAAG,EAAE,IAAI,KAAK,MAAM,IAAI,MAAM,KAAK,GAAG,EAAE,IAAI;YAAI,CAAA,IACtH;YACH,cAAc,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aAAM,WAAU;aAAiB,OAAO,EAAE,YAAY;YAAI,CAAA,IAAI;WAC3E;UAlDD,GAAA,IAAI,IAkDH;SAEZ,CAAC,GACD,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;UAAQ,MAAK;UAAS,WAAU;UAAgB,OAAO,EAAE,aAAa;UACpE,eAAe;WAAE,WAAW,KAAK;WAAG,QAAQ,SAAS,MAAM;UAAE;UAD/D,UAAA,CAEE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD,EAAY,MAAM,GAAK,CAAA,GACvB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,aAAa,EAAQ,CAAA,CACxB;SACL,CAAA,CAAA;QACH,CAAA,IAAA;QAEJ,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAK,WAAU;SAAe,OAAO,EAAE,WAAW,GAAG;SAArD,UAAA;UAIG,KAAK,OAAO,SAAS,IACpB,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;WAAM,WAAU;WAAhB,UAAA;YAAiC,EAAE,QAAQ;YAAE;YAAE,SAAS;YAAE;YAAI,KAAK,OAAO;WAAa;UACrF,CAAA,IAAA;UACJ,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAAU,eAAe;YAAE,WAAW,KAAK;YAAG,QAAQ,SAAS,MAAM;WAAE;WAAvG,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD,EAAY,MAAM,GAAK,CAAA,GAAE,EAAE,aAAa,CAClC;;UACR,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAAwB,eAAe,YAAW,MAAK,CAAC,CAAC;WAAzF,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAU,MAAM,GAAK,CAAA,GAAE,EAAE,aAAa,CAChC;;UAKP,YAAY,OACX,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAC9B,eAAe;YAAE,WAAW,IAAI;YAAG,QAAQ,SAAS,MAAM;WAAE;WAD9D,UAAA,CAEE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD,EAAY,MAAM,GAAK,CAAA,GAAE,EAAE,iBAAiB,CACtC;UACN,CAAA,IAAA;UAYH,YAAY,OACX,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAC9B,SAAS;WADX,UAAA,CAEE,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD,EAAW,MAAM,GAAK,CAAA,GAAE,EAAE,iBAAiB,CACrC;UACN,CAAA,IAAA;SACD;;QAEJ,UACC,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAK,OAAO;UAAE,WAAW;UAAI,SAAS;UAAQ,UAAU;UAAQ,KAAK;UAAG,YAAY;SAAS;SAA7F,UAAA;UACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;WACE,MAAK;WAAO,WAAU;WAAe,OAAO;WAC5C,aAAa,EAAE,oBAAoB;WAAG,WAAA;WACtC,WAAU,MAAK,UAAU,EAAE,OAAO,KAAK;WACvC,YAAW,MAAK;YAAE,IAAI,EAAE,QAAQ,SAAS;aAAE,EAAE,eAAe;aAAG,SAAc;YAAE;WAAE;UAAI,CAAA;UACvF,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAA0B,UAAU;WAAS,eAAe,KAAK,SAAS;WACvG,UAAA,UAAU,EAAE,iBAAiB,IAAI,EAAE,cAAc;UAC5C,CAAA;UACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAC9B,eAAe;YAAE,WAAW,KAAK;YAAG,UAAU,EAAE;YAAG,UAAU,IAAI;WAAE;WAClE,UAAA,EAAE,eAAe;UACZ,CAAA;SACL;QACH,CAAA,IAAA;QACH,WAAW,OACV,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;SAAG,OAAO;UAAE,WAAW;UAAG,OAAO;UAAwC,UAAU;SAAG;SAAI,UAAA;QAAU,CAAA,IAClG;QAQH,KAAK,OAAO,WAAW,IACtB,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;SAAG,WAAU;SAAW,OAAO,EAAE,WAAW,EAAE;SAC3C,UAAA,KAAK,UAAU,OAAO,EAAE,eAAe,IAAI,EAAE,mBAAmB;QAChE,CAAA,IACD;QACH,KAAK,OAAO,SAAS,KAAK,QAAQ,OACjC,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;SAAG,WAAU;SAAW,OAAO,EAAE,WAAW,EAAE;SAAI,UAAA,EAAE,sBAAsB;QAAK,CAAA,IAC7E;QAGJ,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAK,OAAO,EAAE,WAAW,GAAG;SAA5B,UAAA;UACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAU;WAA0B,UAAA,EAAE,UAAU;UAAO,CAAA;UAC5D,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;WAAK,WAAU;WAAe,OAAO,EAAE,YAAY,SAAS;WAA5D,UAAA;YACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;aAAQ,MAAK;aAAS,WAAW,aAAa,KAAK,OAAO,UAAU,WAAW;aAC7E,MAAK;aAAS,gBAAc,KAAK,OAAO;aAAS,OAAO,EAAE,WAAW;aACrE,UAAU,CAAC;aACX,eAAe,EAAE,gBAAgB,KAAK,IAAI,EAAE,SAAS,CAAC,KAAK,OAAO,QAAQ,CAAC;aAC3E,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,kBAAmB,CAAA;YAC7B,CAAA;YACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aAAM,WAAU;aAAW,OAAO,EAAE,SAAS,EAAE;aAAI,UAAA,EAAE,WAAW;YAAQ,CAAA;YACvE,CAAC,YAAY,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;aAAM,WAAU;aAAW,OAAO,EAAE,SAAS,EAAE;aAAI,UAAA,EAAE,YAAY;YAAQ,CAAA,IAAI;WACxF;;UAEJ,aAAa,KAAK,OAAO,UACxB,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;WAAK,WAAU;WAAf,UAAA;YACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;aAAK,WAAU;aAA0B,UAAA,EAAE,UAAU;YAAO,CAAA;YAC5D,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;aAAK,WAAU;aAAf,UAAA;cACG,eAAe,KAAI,SAClB,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;eAAsB,MAAK;eACzB,WAAW,WAAW,KAAK,OAAO,KAAK,OAAO,aAAa,eAAe;eAC1E,eAAe,EAAE,gBAAgB,KAAK,IAAI,EAAE,YAAY,KAAK,GAAG,CAAC;eAChE,UAAA,EAAE,KAAK,GAAG;cACL,GAJK,KAAK,EAIV,CACT;cACD,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;eACE,MAAK;eAAS,WAAU;eAAsB,KAAK;eAAG,KAAK;eAAQ,MAAM;eAIzE,OAAO,aAAa,WAAW,KAAA,IAAY,KAAK,MAAM,KAAK,OAAO,aAAa,GAAI,IAAI;eACvF,aAAa,EAAE,WAAW;eAC1B,WAAU,MAAK,YAAY,EAAE,OAAO,KAAK;eACzC,QAAQ;eACR,YAAW,MAAK;gBAAE,IAAI,EAAE,QAAQ,SAAS;iBAAE,EAAE,eAAe;iBAAG,cAAc;gBAAE;eAAE;cAAI,CAAA;cACvF,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;eAAM,WAAU;eAAW,OAAO,EAAE,SAAS,EAAE;eAAI,UAAA,EAAE,YAAY;cAAQ,CAAA;aACtE;;YAEL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;aAAK,WAAU;aAAyB,OAAO,EAAE,WAAW,GAAG;aAAI,UAAA,EAAE,UAAU;YAAO,CAAA;YACtF,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;aAAK,WAAU;aAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;cAAQ,MAAK;cAAS,WAAW,WAAW,KAAK,OAAO,UAAU,UAAU,eAAe;cACzF,eAAe,EAAE,gBAAgB,KAAK,IAAI,EAAE,OAAO,QAAQ,CAAC;cAC3D,UAAA,EAAE,aAAa;aACV,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;cAAQ,MAAK;cAAS,WAAW,WAAW,KAAK,OAAO,UAAU,YAAY,eAAe;cAC3F,eAAe,EAAE,gBAAgB,KAAK,IAAI,EAAE,OAAO,UAAU,CAAC;cAC7D,UAAA,EAAE,iBAAiB;aACd,CAAA,CACL;;YAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;aAAK,WAAU;aAAe,OAAO;cAAE,WAAW;cAAI,YAAY;aAAS;aAA3E,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;cAAQ,MAAK;cAAS,WAAW,aAAa,KAAK,OAAO,kBAAkB,WAAW;cACrF,MAAK;cAAS,gBAAc,KAAK,OAAO;cAAiB,OAAO,EAAE,aAAa;cAC/E,eAAe,EAAE,gBAAgB,KAAK,IAAI,EAAE,iBAAiB,CAAC,KAAK,OAAO,gBAAgB,CAAC;cAC3F,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,kBAAmB,CAAA;aAC7B,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;cAAM,WAAU;cAAW,OAAO,EAAE,SAAS,EAAE;cAAI,UAAA,EAAE,aAAa;aAAQ,CAAA,CACvE;;YAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;aAAK,WAAU;aAAe,OAAO;cAAE,WAAW;cAAI,YAAY;aAAS;aAA3E,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;cAAQ,MAAK;cAAS,WAAU;cAAU,UAAU,CAAC;cAAQ,eAAe,EAAE,UAAU,KAAK,EAAE;cAC5F,UAAA,EAAE,SAAS;aACN,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;cAAM,WAAU;cAAW,OAAO,EAAE,SAAS,EAAE;cAK5C,UAAA,SAAS,GAAG,EAAE,YAAY,EAAE,GAAG,KAAK,OAAO,WAAW,IAAI,IAAI,KAAK,IAAI,YAAY,GAAG,KAAK,OAAO,MAAM,EAAE,KAAK,KAAK,OAAO,WAAW,EAAE,iBAAiB;aACtJ,CAAA,CACH;;WACF;UACH,CAAA,IAAA;SACD;;QAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAK,OAAO,EAAE,WAAW,GAAG;SAA5B,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,WAAU;UAA0B,UAAA,EAAE,YAAY;SAAO,CAAA,GAC9D,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACG,SAAS,KAAI,MACZ,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;WAAqB,MAAK;WACxB,WAAW,WAAW,KAAK,WAAW,EAAE,OAAO,eAAe;WAC9D,eAAe,EAAE,QAAQ,KAAK,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC;WACnD,UAAA,EAAE,EAAE,GAAG;UACF,GAJK,EAAE,IAIP,CACT,GASA,QAAQ,QAAQ,KAAK,WAAW,QAC/B,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAAU,eAAe,cAAc,IAAI;WAA3E,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD,EAAU,MAAM,GAAK,CAAA,GAAE,EAAE,iBAAiB,CACpC;UACN,CAAA,IAAA,IACD;SACF,CAAA,CAAA;;OACF,EAAA,CAAA,GAGL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA;QACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAA0B,UAAA,EAAE,WAAW;QAAO,CAAA;QAK7D,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;SAAG,WAAU;SAAW,OAAO,EAAE,WAAW,EAAE;SAC3C,UAAA,UAAU,KAAA,IACP,EAAE,qBAAqB,IACvB,GAAG,EAAE,sBAAsB,EAAE,GAAG,SAAS,EAAE,KAAK,KAAK,OAAO;QAC/D,CAAA;QACF,aAAa,OACZ,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;SACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CAGE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAAU,UAAU;WAAY,eAAe,KAAK,YAAY;WAAhG,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD,EAAa,MAAM,GAAK,CAAA,GAAE,aAAa,EAAE,YAAY,IAAI,EAAE,eAAe,CACpE;UACR,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;WAAQ,MAAK;WAAS,WAAU;WAAU,UAAU,QAAQ,QAAQ;WAAY,eAAe,KAAK,UAAU;WAA9G,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD,EAAa,MAAM,GAAK,CAAA,GAAE,aAAa,EAAE,YAAY,IAAI,EAAE,kBAAkB,CACvE;UACL,CAAA,CAAA;;SACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;UAAG,WAAU;UAAW,OAAO,EAAE,WAAW,EAAE;UAAI,UAAA,EAAE,mBAAmB;SAAK,CAAA;SAO3E,QAAQ,OACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;UAAG,WAAU;UAAW,OAAO,EAAE,WAAW,EAAE;UAAI,UAAA,EAAE,mBAAmB;SAAK,CAAA,IAC5E,UAAU,KAAA,IACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;UAAG,WAAU;UAAW,OAAO,EAAE,WAAW,EAAE;UAAI,UAAA,EAAE,sBAAsB;SAAK,CAAA,IAC/E,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;UAAG,WAAU;UAAW,OAAO,EAAE,WAAW,EAAE;UAAI,UAAA,EAAE,2BAA2B;SAAK,CAAA;QAC1F,EAAA,CAAA,IAEF,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;SACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,OAAO;WAAE,SAAS;WAAQ,KAAK;WAAI,YAAY;WAAU,UAAU;UAAO;UAA/E,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;WAAY,KAAK,MAAM;WAAI,KAAK,MAAM;WAAI,KAAK,MAAM;WAAI,UAAU;UAAU,CAAA,GAI7E,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;WAAK,WAAU;WACb,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD;YAAa,KAAK,MAAM;YAAI,KAAK,MAAM;YAAI,KAAK,MAAM;YAAI,UAAU;WAAU,CAAA;UAC3E,CAAA,CACF;;SACL,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;UAAK,WAAU;UAAe,OAAO,EAAE,WAAW,GAAG;UAArD,UAAA;WACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;YAAQ,MAAK;YAAS,WAAU;YAAU,UAAU,QAAQ,QAAQ;YAAY,eAAe,KAAK,UAAU;YAA9G,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD,EAAa,MAAM,GAAK,CAAA,GAAE,aAAa,EAAE,YAAY,IAAI,EAAE,kBAAkB,CACvE;;WACR,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;YAAQ,MAAK;YAAS,WAAU;YAAU,UAAU,QAAQ;YAAM,eAAe,cAAc,IAAI;YAAnG,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD,EAAa,MAAM,GAAK,CAAA,GAAE,EAAE,YAAY,CAClC;;WASR,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;YAAQ,MAAK;YAAS,WAAU;YAAwB,eAAe,SAAS,IAAI;YAApF,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD,EAAS,MAAM,GAAK,CAAA,GAAE,EAAE,eAAe,CACjC;;UACL;;SACL,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;UAAK,WAAU;UAAe,OAAO,EAAE,WAAW,GAAG;UAClD,UAAA,QAAQ,KAAK,CAAC,IAAI,IAAI,KAAK,MAC1B,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;WACU,MAAK;WAAS,WAAU;WAChC,OAAO,EAAE,YAAY,OAAO,GAAG,GAAG,KAAK,MAAM,KAAK,GAAG,EAAE,IAAI,KAAK,MAAM,KAAK,GAAG,EAAE,IAAI;WACpF,OAAO,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,YAAY;WAC/C,eAAe,SAAS;YAAC;YAAI;YAAI;WAAE,CAAC;UAAI,GAHnC,CAGmC,CAC3C;SACE,CAAA;QACL,EAAA,CAAA;QAGJ,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;SAAK,OAAO,EAAE,WAAW,GAAG;SAA5B,UAAA;UACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;WACE,OAAO,EAAE,aAAa;WAAG,KAAK;WAAG,KAAK;WAAK,MAAM;WACjD,KAAK,KAAK,MAAM,KAAK,mBAAmB,GAAG;WAAG,MAAK,MAAK,GAAG,EAAE;WAC7D,WAAU,MAAK,EAAE,QAAQ,KAAK,IAAI,EAAE,kBAAkB,IAAI,IAAI,CAAC;UAAI,CAAA;UACrE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;WACE,OAAO,EAAE,UAAU;WAAG,KAAK;WAAG,KAAK;WAAI,MAAM;WAC7C,KAAK,KAAK;WAAM,MAAK,MAAK,GAAG,EAAE;WAC/B,WAAU,MAAK,EAAE,QAAQ,KAAK,IAAI,EAAE,MAAM,EAAE,CAAC;UAAI,CAAA;UACnD,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;WAAG,WAAU;WAAW,OAAO,EAAE,WAAW,GAAG;WAAI,UAAA,EAAE,cAAc;UAAK,CAAA;SACrE;;OACF,EAAA,CAAA,CACF;;KACF,CAAA,IACH;KAKJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;MAAO,KAAK;MAAS,MAAK;MAAO,QAAO;MAAU,UAAA;MAAS,OAAO,EAAE,SAAS,OAAO;MAAG,WAAU,MAAK;OACpG,MAAM,QAAQ,MAAM,KAAK,EAAE,OAAO,SAAS,CAAC,CAAC;OAC7C,IAAI,MAAM,WAAW,GAAG;OACxB,QAAQ,KAAK;OACb,EAAE,OAAO,QAAQ;OACjB,WAAW,KAAK;MAClB;KAAI,CAAA;KAEH,cAAc,QAAQ,QAAQ,UAAU,KAAA,IACvC,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;MACO;MAAK,OAAO,MAAM;MAAY;MAAG,eAAe,cAAc,KAAK;MACxE,WAAW,GAAG,GAAG,GAAG,IAAI,OAAO;OAG7B,EAAE,gBAAgB,KAAK,IAAI,MAAM,MAAM;QAAE,MAAM;QAAG;QAAG;QAAG;QAAI;OAAG,CAAC;OAChE,cAAc,KAAK;MACrB;KAAI,CAAA,IACJ;KAEH,cAAc,QAAQ,OACrB,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD;MAAkB;MAAQ;MAAG,eAAe,cAAc,KAAK;MAC7D,SAAQ,QAAO;OAAE,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;OAAG,cAAc,KAAK;MAAE;KAAI,CAAA,IAC3E;IACG;;EAEb;;;EC91BA,SAAgB,YAAY,EAAE,GAAG,UAAiF;GAChH,MAAM,EAAE,GAAG,aAAa,gBAAgB;GACxC,MAAM,aAAA,GAAYE,MAAAA,OAAAA,CAAyB,IAAI;GAK/C,EAAE,UAAU,MAAuB,EAAE,MAAM,EAAE,QAAQ;GACrD,MAAM,WAAW,IAAI;GAErB,MAAM,WAAW,OAAO,SAAe;IACrC,IAAI;KACF,MAAM,KAAK,MAAM,YAAY,IAAI;KACjC,OAAO,KAAK,EAAE,YAAY,IAAI,EAAE,YAAY,GAAG,EAAE;IACnD,QAAQ;KACN,OAAO,EAAE,YAAY,GAAG,KAAK;IAC/B;GACF;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAA,kBAAA,UAAA,EAAA,UAAA;IACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;KAAQ,WAAU;KAAoB,OAAO,EAAE,OAAO,EAAE;KAAxD,UAAA;MACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OAAe,UAAA;MAAY,CAAA;MAC1C,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;OAAI,WAAU;OAAU,UAAA,EAAE,aAAa;MAAM,CAAA;MAC7C,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAAY,UAAA,EAAE,aAAa;MAAK,CAAA;KACvC;;IAYR,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD;KAAS,WAAU;KAAoB,OAAO,EAAE,OAAO,EAAE;KACvD,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAe,OAAO,EAAE,YAAY,SAAS;MAA5D,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,UAAD;OAAQ,MAAK;OAAS,WAAW,aAAa,SAAS,UAAU,WAAW;OAC1E,MAAK;OAAS,gBAAc,SAAS;OAAS,OAAO,EAAE,eAAe;OACtE,eAAe,EAAE,mBAAmB,CAAC,SAAS,OAAO;OACrD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAM,WAAU,kBAAmB,CAAA;MAC7B,CAAA,GACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;OAAM,WAAU;OAAqB,UAAA,EAAE,cAAc;MAAQ,CAAA,CAC1D;;IACE,CAAA;IAET,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAU;KAA4B,OAAO,EAAE,OAAO,EAAE;KAA7D,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;MAAS,WAAU;MAAnB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAkB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAD,EAAc,MAAM,GAAK,CAAA;OAAM,CAAA;OAChE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAqB,UAAA,EAAE,iBAAiB;OAAO,CAAA;OAC9D,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAoB,UAAA,EAAE,gBAAgB;OAAO,CAAA;OAC5D,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAA0B,eAAe;SAAE,YAAY;SAAG,OAAO,EAAE,iBAAiB,CAAC;QAAE;QAAvH,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAD,EAAc,MAAM,GAAK,CAAA,GAAE,EAAE,aAAa,CACpC;;MACD;KAET,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,WAAD;MAAS,WAAU;MAAnB,UAAA;OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAkB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD,EAAY,MAAM,GAAK,CAAA;OAAM,CAAA;OAC9D,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAqB,UAAA,EAAE,iBAAiB;OAAO,CAAA;OAC9D,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;QAAK,WAAU;QAAoB,UAAA,EAAE,gBAAgB;OAAO,CAAA;OAC5D,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;QAAQ,MAAK;QAAS,WAAU;QAAU,eAAe,UAAU,SAAS,MAAM;QAAlF,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD,EAAY,MAAM,GAAK,CAAA,GAAE,EAAE,aAAa,CAClC;;OACR,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD;QAAO,KAAK;QAAW,MAAK;QAAO,QAAO;QAAyB,OAAO,EAAE,SAAS,OAAO;QAAG,WAAU,MAAK;SAC5G,MAAM,IAAI,EAAE,OAAO,QAAQ;SAAI,IAAI,CAAC,GAAG;SACvC,SAAc,CAAC;SAAG,EAAE,OAAO,QAAQ;QACrC;OAAI,CAAA;MACG;KACN,CAAA,CAAA;;IAEL,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;KAAQ,WAAU;KAAsB,OAAO,EAAE,OAAO,EAAE;KAA1D,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAU;MAAkB,UAAA;KAA6B,CAAA,GAC/D,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,EAAE,WAAW,EAAQ,CAAA,CACtB;;GACR,EAAA,CAAA;EAEN;;;;;;;;;;;;;EChEA,SAAgB,aAAa,OAA0B;GACrD,YAAY;GACZ,MAAM,EAAE,MAAM;GACd,MAAM,CAAC,MAAM,YAAA,GAAWC,MAAAA,SAAAA,CAAS,CAAC;GAClC,MAAM,CAAC,OAAO,aAAA,GAAYA,MAAAA,SAAAA,CAA8C,IAAI;GAC5E,MAAM,cAAA,GAAaC,MAAAA,OAAAA,CAA2B,KAAA,CAAS;GAEvD,CAAA,GAAA,MAAA,UAAA,aAAsB,OAAO,aAAa,WAAW,OAAO,GAAG,CAAC,CAAC;GAEjE,MAAM,UAAU,KAAa,KAAK,SAAe;IAC/C,SAAS;KAAE;KAAK;IAAG,CAAC;IACpB,OAAO,aAAa,WAAW,OAAO;IACtC,WAAW,UAAU,OAAO,iBAAiB,SAAS,IAAI,GAAG,IAAI;GACnE;GAEA,MAAM,QAAQ;IACZ;KAAE,OAAO,EAAE,eAAe;KAAG,MAAM;KAAY,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAAC,eAAD,EAAe,GAAG,MAAQ,CAAA;IAAE;IACjF;KAAE,OAAO,EAAE,aAAa;KAAG,MAAM;KAAW,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD;MAAa,GAAG;MAAe;KAAS,CAAA;IAAE;IAC5F;KAAE,OAAO,EAAE,aAAa;KAAG,MAAM;KAAa,MAAM,iBAAA,GAAA,kBAAA,IAAA,CAAC,aAAD;MAAa,GAAG;MAAe;KAAS,CAAA;IAAE;GAChG;GAEA,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,eAAD;IAAkB;IAAlB,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;KAAK,WAAU;KACb,UAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAAiB,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,SAAD,EAAS,MAAM,GAAK,CAAA;QAAM,CAAA,GAC1D,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD,EAAA,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAAkB,UAAA,EAAE,KAAK;QAAO,CAAA,GAC/C,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAAiB,UAAA,EAAE,UAAU;QAAO,CAAA,CAChD,EAAA,CAAA,CACF;OACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;SAAK,WAAU;SAAc,OAAO,EAAE,WAAW,cAAc,OAAA,GAA8B,KAAK;QAAI,CAAA,GACrG,MAAM,KAAK,IAAI,MACd,iBAAA,GAAA,kBAAA,KAAA,CAAC,UAAD;SACiB,MAAK;SACpB,WAAW,eAAe,MAAM,OAAO,eAAe;SACtD,eAAe,QAAQ,CAAC;SAH1B,UAAA,CAIE,iBAAA,GAAA,kBAAA,IAAA,CAAC,GAAG,MAAJ,EAAS,MAAM,GAAK,CAAA,GACpB,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,GAAG,MAAY,CAAA,CAChB;QALD,GAAA,GAAG,KAKF,CACT,CACE;OACF,CAAA,CAAA;MAEL,CAAA,GAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OACZ,UAAA,MAAM,KAAK,CAAC;MACV,GAF0B,IAE1B,CACF;;IACF,CAAA,GAEJ,QACC,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;KAAK,WAAU;KAAY,MAAK;KAAhC,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;MAAM,WAAW,MAAM,KAAK,iBAAiB;MAC1C,UAAA,MAAM,KAAK,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD,EAAW,MAAM,GAAK,CAAA,IAAI,iBAAA,GAAA,kBAAA,IAAA,CAAC,WAAD,EAAW,MAAM,GAAK,CAAA;KACxD,CAAA,GACN,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,MAAM,IAAU,CAAA,CACpB;IACC,CAAA,EAAA,CAAA,IACN,IACS;;EAEnB;;;;;;;;;;;EC/CA,MAAa,OAAO;EACpB,MAAa,SAAS;GAAC;GAAS;GAAU;GAAS;EAAY;EAE/D,MAAM,YAAY;EAElB,SAAgB,MAAM,KAAgB;GAGpC,SAAS,UAAU,YACjB,IAAI,WAAW,IAAI,KAAK,aAAa,UAAU,OAAO,CAAC,CAAC,MAAM,QAAa,GAAgC,CAC7G;GAGA,IAAI,gBAAqC;GAIzC,IAAI,YAA2B;GAC/B,MAAM,kBAAkB,GAAW,GAAW,MAAoB;IAChE,gBAAgB;IAChB,IAAI;KACF,MAAM,EAAE,aAAa,WAAW,UAAU,GAAG,GAAG,CAAC;KACjD,gBAAgB,IAAI,MAAM,SAAS;MAAE,IAAI;MAAW;MAAa;KAAO,CAAC;IAC3E,QAAQ;KAIN,gBAAgB;IAClB;IAEA,IAAI,IAAI,MAAM,SAAS,CAAC,CAAC,OAAO,MAAK,MAAK,EAAE,OAAO,SAAS,GAC1D,IAAI,MAAM,SAAS,SAAS;GAEhC;;GAEA,MAAM,mBAAyB;IAC7B,gBAAgB;IAChB,gBAAgB;IAChB,IAAI;KACF,IAAI,IAAI,MAAM,SAAS,CAAC,CAAC,eAAe,WAAW,IAAI,MAAM,SAAS,QAAQ;IAChF,QAAQ,CAER;GACF;;;;;;;;;;;;;;;;;;GAmBA,MAAM,qBAA2B;IAC/B,MAAM,QAAQ,YAAY;IAC1B,IAAI,cAAc,MAAM,OAAO,aAAa,SAAS;IACrD,IAAI,UAAU,MAAM;KASlB,YAAY;KACZ,WAAW;IACb,OAGE,YAAY,OAAO,iBAAiB;KAClC,YAAY;KACZ,eAAe,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE;IAC7C,GAAG,EAAE;IAEP,eAAe;GACjB;GACA,IAAI,mBAAmB;IACrB,IAAI,cAAc,MAAM,OAAO,aAAa,SAAS;IACrD,gBAAgB;GAClB,GAAG,uCAAuC;GAG1C,MAAM,UAAU,SAAS,cAAc,OAAO;GAC9C,QAAQ,QAAQ,SAAS;GACzB,aAAa,OAAO;GAGpB,QAAQ,cAAc,4BAA4B,WAAW,8KAA8K,sBAAsB,wBAAwB,sBAAsB;GAC/S,SAAS,KAAK,YAAY,OAAO;GACjC,IAAI,mBAAmB;IAAE,SAAS,YAAY,YAAY,OAAO;GAAE,GAAG,mCAAmC;GAGzG,IAAI,MAAM;GACV,IAAI,WAAW;GACf,IAAI,YAAY;GAChB,IAAI,cAAqC;GAIzC,IAAI,YAAY;GAGhB,IAAI,WAAW;GACf,MAAM,QAAQ,YAAY;IACxB,aAAa;KACX,KAAK;KACL,KAAK;KACL,UAAU;KACV,OAAO;KACP,aAAa;KACb,WAAW;KACX,cAAc;KACd,SAAS;KACT,UAAU;KACV,UAAU;KACV,UAAU;KACV,WAAW;IACb;IACA,SAAS,EACP,OAAO,GAAQ,KAAoB,GAAW,IAAY,OAAe,QAA+B,MAAc,IAAmB,SAAkB,UAAkB,UAAkB,UAAmB,cAAuB;KACvO,IAAI,IAAI,EAAE,KAAK;MAAE,EAAE,MAAM;MAAK,EAAE,MAAM;KAAE;KACxC,IAAI,KAAK,EAAE,UAAU,EAAE,WAAW;KAClC,EAAE,QAAQ;KACV,EAAE,cAAc;KAChB,EAAE,YAAY;KACd,EAAE,eAAe;KACjB,EAAE,UAAU;KACZ,EAAE,WAAW;KACb,EAAE,WAAW;KACb,EAAE,WAAW;KACb,EAAE,YAAY;IAChB,EACF;GACF,CAAC;GACD,IAAI,QAAgD;;GAEpD,MAAM,sBAA2E;IAC/E,MAAM,OAAO,WAAW;IACxB,IAAI,SAAS,MAAM,OAAO;KAAE,OAAO;KAAG,OAAO;KAAG,UAAU;IAAM;IAChE,OAAO;KACL,OAAO,aAAa,IAAI;KACxB,OAAO,KAAK,OAAO;KAInB,UAAU,WAAW,KAAK,OAAO,QAAQ,KAAK,OAAO,SAAS,KAAK,OAAO,UAAU,KAAK,CAAC,SAAS;IACrG;GACF;GACA,MAAM,aAAmB;IACvB;IACA,MAAM,MAAM,cAAc;IAC1B,OAAO,KAAK,IAAI,GAAG,KAAK,UAAU,eAAe,KAAK,aAAa,WAAW,aAAa,WAAW,cAAc,eAAe,IAAI,OAAO,IAAI,OAAO,IAAI,UAAU,aAAa,CAAC;GACvL;;;;;;;;GASA,MAAM,uBAA6B;IACjC,IAAI;KACF,cAAc,IAAI,MAAM,SAAS,CAAC,CAAC,OAAO,gBAAgB,MAAM;IAClE,QAAQ;KAGN,cAAc,IAAI;IACpB;GACF;;;;;;;;;;;;;GAcA,MAAM,oBAA+D;IAGnE,MAAM,UAAU,kBAAkB;IAClC,OAAO,YAAY,OACf;KAAE,MAAM;KAAmB,SAAS;IAAM,IAC1C,UAAU,IAAI,OAAO,SAAS;GACpC;;GAGA,MAAM,iBAAgC,YAAY,CAAC,CAAC,MAAM,MAAM;;;;;;;;;;;GAYhE,MAAM,kBAAkB,IAAY,iBAAsC;IACxE,IAAI,cAAc,IAAI,cAAc,SAAS,CAAC,GAAG,YAAY;SACxD,KAAK;GACZ;;;;;;;;GASA,MAAM,eAAe,UAAU,UAAgB;IAC7C,MAAM,EAAE,MAAM,YAAY,YAAY;IAItC,UAAU,SAAS,OAAO,OAAO,KAAK,IAAI,OAAO;IACjD,IAAI,WAAW,SAAS,QAAQ,KAAK,OAAO,iBAAiB;KAC3D,MAAM,OAAO,UAAU,KAAK,OAAO,QAAQ,KAAK,OAAO,OAAO,aAAa,IAAI,CAAC;KAChF,IAAI,SAAS,MAAM,YAAY,IAAI;IACrC;IACA,iBAAiB;IAGjB,aAAa;IACb,QAAQ;IACR,KAAK;GACP;GAUA,IAAI,WAA0B;;GAE9B,IAAI,SAAS;;GAGb,MAAM,aAAa,MAAc,QAAsB;IACrD,MAAM,OAAO,KAAK,OAAO,IAAI,EAAE;IAC/B,IAAI,SAAS,KAAA,GAAW,SAAc,IAAI;GAC5C;;GAGA,MAAM,cAAc,MAAc,QAAsB;IACtD,MAAM,OAAO,KAAK,OAAO,IAAI,EAAE;IAC/B,IAAI,SAAS,KAAA,GAAW;IAIxB,aAAa;IACb,IAAI,QAAQ,IAAI,MAAM,MAAM;KAAE,QAAQ;KAAG,KAAK;KAAG;IAAO;IAMxD,SAAc,IAAI,CAAC,CAAC,WAAW;KAAE,QAAQ;KAAG,KAAK;IAAE,CAAC;GACtD;GAEA,MAAM,mBAAyB;IAC7B,MAAM,OAAO,WAAW;IACxB,IAAI,SAAS,MAAM;IACnB,MAAM,OAAO,UAAU,KAAK,OAAO,QAAQ,KAAK,OAAO,OAAO,aAAa,IAAI,CAAC;IAGhF,IAAI,SAAS,MAAM;KAAE,iBAAiB,IAAI;KAAG;IAAO;IACpD,YAAY,IAAI;IAChB,WAAW,MAAM,IAAI;IAGrB,MAAM,QAAQ,UAAU,KAAK,OAAO,QAAQ,KAAK,OAAO,OAAO,IAAI;IACnE,IAAI,UAAU,MAAM,UAAU,MAAM,KAAK;GAC3C;;;;;;;;;;;;GAaA,MAAM,oBAAoB,QAAQ,UAAgB;IAChD,MAAM,OAAO,WAAW;IAGxB,MAAM,MAAM,SAAS,OACjB,KACA;KAAC,KAAK;KAAI,KAAK,OAAO;KAAS,KAAK,OAAO;KAAY,KAAK,OAAO;KAAO,KAAK,OAAO;KAAQ,SAAS;IAAM,CAAC,CAAC,KAAK,GAAG;IAC3H,IAAI,CAAC,SAAS,QAAQ,QAAQ;IAC9B,SAAS;IACT,IAAI,aAAa,MAAM;KAAE,OAAO,cAAc,QAAQ;KAAG,WAAW;IAAK;IACzE,IAAI,SAAS,QAAQ,SAAS,QAAQ;IACtC,IAAI,CAAC,WAAW,KAAK,OAAO,QAAQ,KAAK,OAAO,SAAS,KAAK,OAAO,UAAU,GAAG;IAGlF,MAAM,OAAO,UAAU,KAAK,OAAO,QAAQ,KAAK,OAAO,OAAO,aAAa,IAAI,CAAC;IAChF,IAAI,SAAS,MAAM,UAAU,MAAM,IAAI;IACvC,WAAW,OAAO,YAAY,YAAY,KAAK,OAAO,UAAU;GAClE;GACA,IAAI,mBAAmB;IACrB,IAAI,aAAa,MAAM;KAAE,OAAO,cAAc,QAAQ;KAAG,WAAW;IAAK;GAC3E,GAAG,yCAAyC;GAO5C,MAAM,qBAA2B;IAAE,iBAAiB;IAAG,KAAK;GAAE;GAC9D,SAAS,iBAAiB,oBAAoB,YAAY;GAC1D,IAAI,mBAAmB,SAAS,oBAAoB,oBAAoB,YAAY,GAAG,8CAA8C;;;;;;;;GASrI,MAAM,0BACJ,YAAY,IAAI,SAAS,SAAS,IAAI,SAAS,OAAO,cAAc,IAAG,SAAQ,QAAQ,IAAI,MAAM,IAAI;GASvG,eAAe;GACf,QAAQ;GACR,KAAK;GACL,WAAW;GAKX,MAAM,WAAW,WAAW,MAAM,MAAM,OAAO,QAAQ,SAAS;IAC9D,MAAM,MAAM,GAAG,KAAK,QAAQ,OAAO,QAAQ;IAC3C,IAAI,QAAQ,UAAU;IACtB,MAAM,cAAc,SAAS;IAC7B,WAAW;IACX,YAAY;IACZ,cAAc;IACd,YAAY;IACZ,cAAc,UAAU,KAAK,QAAQ,IAAI;IAGzC,IAAI,aAAa,YAAY,IAAI;SAC5B,KAAK;GACZ,CAAC;GACD,IAAI,mBAAmB,SAAS,GAAG,sCAAsC;GAIzE,CAAM,YAAY;IAChB,IAAI,cAAc,IAAI;IACtB,MAAM,WAAW,MAAM,iBAAiB;IACxC,IAAI,aAAa,QAAQ,cAAc,IAAI;KACzC,WAAW,GAAG,SAAS;KACvB,YAAY;KACZ,cAAc;KACd,YAAY;KACZ,cAAc,QAAQ;KACtB,YAAY;IACd;GACF,EAAA,CAAG;GAUH,IAAI,aAAa,cAAc,KAAK;GACpC,MAAM,eAAe,OAAO,kBAAkB;IAC5C,MAAM,OAAO,cAAc,KAAK;IAChC,IAAI,SAAS,YAAY;IACzB,aAAa;IAGb,MAAM,OAAO,iBAAiB;IAC9B,IAAI,SAAS,MAAM,YAAY;SAC1B,SAAc,IAAI,CAAC,CAAC,WAAW,YAAY,CAAC;GACnD,GAAG,GAAM;GACT,IAAI,mBAAmB;IAAE,OAAO,cAAc,YAAY;GAAE,GAAG,2CAA2C;;GAI1G,MAAM,WAAW,OAAO,SAAgC;IACtD,IAAI,QAAQ,IAAI,MAAM,MAAM;IAC5B,MAAM,MAAM,MAAM,UAAU,IAAI;IAChC,IAAI,QAAQ,MAAM,SAAS,MAAM,GAAG;GACtC;;;;;;;;;GASA,MAAM,yBAAwC;IAC5C,IAAI,CAAC,IAAI,SAAS,SAAS,OAAO;IAClC,MAAM,KAAK,cAAc;IACzB,IAAI,OAAO,MAAM,OAAO;IACxB,MAAM,OAAO,YAAY,EAAE;IAC3B,IAAI,SAAS,QAAQ,CAAC,KAAK,SAAS,OAAO;IAC3C,OAAO,UAAU,IAAI,CAAC,CAAC,MAAM;GAC/B;;;;;;;;;;;;;;;;;;;;;GAqBA,MAAM,kBAA4B;IAChC,MAAM,UAAU,iBAAiB;IACjC,MAAM,SAAS,IAAI,MAChB,KAAI,MAAK,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,CAC3B,QAAQ,SAAyB,SAAS,KAAA,CAAS;IACtD,MAAM,UAAU,aAAa;IAC7B,OAAO,MAAM,qBAAK,IAAI,IAAI;KACxB,GAAG;KACH,GAAI,YAAY,OAAO,CAAC,IAAI,CAAC,OAAO;KACpC,GAAI,YAAY,OAAO,CAAC,IAAI,CAAC,OAAO;IACtC,CAAC,CAAC;GACJ;;;;;;;;;;GAUA,MAAM,qBACJ,iBAAiB,KAAK,UAAU,IAAI,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,EAAE,EAAE,QAAQ;GACjF,CAAM,YAAY;IAChB,MAAM,YAAY,MAAM,cAAc;IACtC,IAAI,cAAc,MAAM;KACtB,YAAY,UAAU,MAAM;KAC5B,MAAM,QAAQ,aAAa;KAG3B,MAAM,QAAQ,UAAU;KACxB,MAAM,QAAQ,UAAU,OAAO,QAAQ,CAAC,OAAO,GAAG,MAAM,QAAO,MAAK,MAAM,KAAK,CAAC;KAChF,KAAK,MAAM,QAAQ,OAAO;MACxB,MAAM,SAAS,IAAI;MACnB,IAAI,SAAS,OAAO,YAAY;KAClC;IACF;IACA,YAAY;GACd,EAAA,CAAG;GAEH,IAAI,mBAAmB;IAAE,WAAW;GAAE,GAAG,qCAAqC;GAE9E,IAAI,aAAa,IAAI,GAAG,sBAAsB;IAO5C,eAAe;IACf,IAAI,YAAY,MAAM,MAAM;KAC1B,MAAM,WAAW,IAAI,MAAM,SAAS;KACpC,IAAI,SAAS,eAAe,aAAa,SAAS,OAAO,MAAK,MAAK,EAAE,OAAO,SAAS,GACnF,IAAI,MAAM,SAAS,SAAS;IAEhC;IACA,QAAQ;GACV,CAAC,GAAG,uCAAuC;GAO3C,IAAI,QAAQ;GACZ,MAAM,kBAAwB;IAC5B,IAAI,UAAU,GAAG;IACjB,QAAQ,4BAA4B;KAAE,QAAQ;KAAG,QAAQ;IAAE,CAAC;GAC9D;GACA,MAAM,WAAW,SAAS,cAAc,KAAK;GAC7C,SAAS,MAAM,UAAU;GACzB,SAAS,KAAK,OAAO,QAAQ;GAC7B,MAAM,mBAAmB,IAAI,eAAe,SAAS;GACrD,iBAAiB,QAAQ,QAAQ;GACjC,MAAM,WAAW,OAAO,WAAW,gBAAgB,OAAO,iBAAiB,MAAM;GACjF,SAAS,iBAAiB,UAAU,SAAS;GAC7C,IAAI,mBAAmB;IACrB,iBAAiB,WAAW;IAC5B,SAAS,oBAAoB,UAAU,SAAS;IAChD,SAAS,OAAO;GAClB,GAAG,yCAAyC;GAG5C,IAAI,aAAa,IAAI,OAAO,SAAS,IAAI;IAAE;IAAI;GAAG,CAAC,GAAU,+BAA+B;;;;;;;;;;;;;;;;;;GAmB5F,MAAM,mBAAmB,OAAO,IAAY,SAAiC;IAC3E,IAAI,CAAC,IAAI,aAAa;;IAEtB,MAAM,UAAU,SAA6C;KAC3D,IAAI,SAAS,MAAM,OAAO,KAAA;KAC1B,QAAQ,SAAS,KAAA,IAAY,KAAA,IAAY,KAAK,OAAO,MAAK,MAAK,EAAE,SAAS,IAAI,MAAM,KAAK,OAAO;IAClG;IACA,MAAM,QAAQ,OAAO,SAAS,EAAE,CAAC;IACjC,IAAI,UAAU,KAAA,KAAa,MAAM,UAAU,MAAM;IACjD,MAAM,MAAM,eAAe,MAAM,IAAI;IACrC,IAAI,QAAQ,MAAM;IAClB,IAAI,MAAuC;IAC3C,IAAI;KAAE,MAAM,MAAM,sBAAsB,KAAK,MAAM,OAAO;IAAE,QAAQ;KAAE,MAAM;IAAK;IACjF,IAAI,QAAQ,MAAM;IAClB,MAAM,UAAU,OAAO,SAAS,EAAE,CAAC;IACnC,IAAI,YAAY,KAAA,KAAa,QAAQ,UAAU,MAAM;IAIrD,MAAM,SAAS,SAAS;IACxB,QAAQ,QAAQ;IAChB;IACA,WAAW;IACX,eAAe,IAAI,MAAM;GAC3B;;;;;;;;;;;;;;;GAgBA,MAAM,uBAAuB,OAAO,IAAY,UAA4C;IAC1F,KAAK,MAAM,QAAQ,OAAO,MAAM,iBAAiB,IAAI,IAAI;GAC3D;GAOA,MAAM,mBAAgC;IACpC,IAAI;KACF,MAAM,WAAW,IAAI,OAAO,YAAY;KACxC,OAAO,OAAO,UAAU,WAAW,YAAY,SAAS,OAAO,YAAY,CAAC,CAAC,WAAW,IAAI,IAAI,OAAO;IACzG,QAAQ;KACN,OAAO;IACT;GACF;;GAEA,MAAM,uBAAmC;IACvC,MAAM,OAAO,iBAAiB,OAAO,OAAO,SAAS,YAAY;IACjE,OAAO;KACL,MAAM;KACN,QAAQ;KACR,MAAM;KACN,MAAM,SAAS,OAAO,KAAM,KAAK,UAAU,KAAK,KAAK,QAAQ,KAAK;KAClE,SAAS;IACX;GACF;GACA,MAAM,iBAAiB,YAAkF;IACvG,QAAQ;IACR,KAAK;IACL,OAAO;KACL,GAAG,IAAI,OAAO,KAAK,EAAE;KACrB;KACA,MAAM,WAAW;KACjB;KACA,UAAU,SAAiB,eAAe,IAAI;KAC9C,eAAuB;MAGrB,MAAM,OAAO,QAAQ,WAAW,CAAC;MACjC,IAAI,MAAM,KAAK,IAAI;MACnB;MACA,cAAc;MACd,YAAY;MACZ,OAAO,KAAK;KACd;KACA,aAAa,OAAqB;MAChC,MAAM,MAAM,IAAI,MAAM,WAAU,MAAK,EAAE,OAAO,EAAE;MAChD,IAAI,MAAM,GAAG;MACb,MAAM,CAAC,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;MACtC,IAAI,SAAS,KAAA,GAAW;OAMtB,MAAM,YAAY,WAAW;OAC7B,KAAK,MAAM,QAAQ,UAAU,IAAI,GAAG;QAClC,IAAI,UAAU,IAAI,IAAI,GAAG;QACzB,SAAS,MAAM,IAAI;QACnB,YAAiB,IAAI;OACvB;MACF;MACA;MACA,cAAc;MACd,YAAY;KACd;KACA,WAAW,IAAY,QAAsB;MAC3C,MAAM,MAAM,IAAI,MAAM,WAAU,MAAK,EAAE,OAAO,EAAE;MAChD,MAAM,KAAK,MAAM;MACjB,IAAI,MAAM,KAAK,KAAK,KAAK,MAAM,IAAI,MAAM,QAAQ;MACjD,MAAM,CAAC,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;MACtC,IAAI,MAAM,OAAO,IAAI,GAAG,IAAK;MAC7B;MACA,cAAc;MACd,YAAY;KACd;KACA,UAAU,IAAY,UAAiC;MACrD,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,MAAM;MAGnB,MAAM,SAAS,SAAS;MACxB,OAAO,OAAO,MAAM,KAAK;MAGzB,qBAAqB,IAAI;MACzB;MAGA,WAAW;MACX,eAAe,IAAI,MAAM;KAC3B;KACA,gBAAgB,IAAY,aAAsC;MAChE,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,QAAQ,SAAS,WAAW,GAAG;MAI5C,MAAM,SAAS,SAAS;;MAExB,MAAM,QAAkB,CAAC;MACzB,KAAK,MAAM,WAAW,UAAU;OAC9B,MAAM,OAAO,SAAS;OAKtB,MAAM,QAAQ;QAAE;QAAM,SAAS,EAAE,GAAG,iBAAiB;QAAG,OAAO;OAAK;OACpE,KAAK,OAAO,KAAK,KAAK;OACtB,MAAM,KAAK,IAAI;OACf,SAAS,MAAM,OAAO;OAItB,WAAgB,MAAM,OAAO;MAC/B;MACA;MACA,cAAc;MACd,eAAe,IAAI,MAAM;MAOzB,qBAA0B,IAAI,KAAK;KACrC;KACA,kBAAkB,IAAY,SAAuB;MACnD,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,MAAM;MACnB,MAAM,MAAM,KAAK,OAAO,WAAU,MAAK,EAAE,SAAS,IAAI;MACtD,IAAI,MAAM,GAAG;MAIb,MAAM,SAAS,SAAS;MAOxB,KAAK,OAAO,OAAO,KAAK,CAAC;MAIzB,IAAI,OAAO,cAAc,YAAY,CAAC;MACtC;MACA,cAAc;MACd,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,IAAI,GAAG;OAC3B,SAAS,MAAM,IAAI;OACnB,YAAiB,IAAI;MACvB;MACA,eAAe,IAAI,MAAM;KAC3B;KACA,kBAAkB,IAAY,MAAc,OAAqB;MAC/D,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,MAAM;MACnB,MAAM,MAAM,KAAK,OAAO,WAAU,MAAK,EAAE,SAAS,IAAI;MACtD,IAAI,MAAM,GAAG;MAIb,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO,SAAS,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC;MACvE,IAAI,OAAO,KAAK;MAChB,MAAM,SAAS,SAAS;MAOxB,MAAM,UAAU,OAAO,eAAe,KAAK,OAAO,aAAa,IAAI,EAAE,EAAE,QAAQ,OAAO;MACtF,MAAM,CAAC,SAAS,KAAK,OAAO,OAAO,KAAK,CAAC;MACzC,KAAK,OAAO,OAAO,IAAI,GAAG,KAAM;MAChC;MAIA,IAAI,OAAO,cAAc;OAGvB,MAAM,OAAO,YAAY,OAAO,KAAK,KAAK,OAAO,WAAU,MAAK,EAAE,SAAS,OAAO;OAClF,YAAY,OAAO,IAAI,KAAK,IAAI,IAAI,KAAK,OAAO,SAAS,CAAC,IAAI,IAAI;OAClE,iBAAiB,IAAI;MACvB;MACA,cAAc;MACd,eAAe,IAAI,MAAM;KAC3B;KACA,kBAAkB,IAAY,MAAc,YAA2B;MACrE,MAAM,OAAO,SAAS,EAAE;MACxB,MAAM,QAAQ,MAAM,OAAO,MAAK,MAAK,EAAE,SAAS,IAAI;MACpD,IAAI,UAAU,KAAA,GAAW;MACzB,MAAM,SAAS,SAAS;MACxB,MAAM,UAAU;MAChB,qBAAqB,IAAK;MAC1B;MACA,WAAW;MAIX,eAAe,IAAI,MAAM;KAC3B;KACA,kBAAkB,IAAY,UAA2C;MACvE,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,MAAM;MACnB,cAAc,MAAM,KAAK;MACzB;MACA,cAAc;MAId,iBAAiB;MACjB,KAAK;KACP;KACA,YAAY,OAAqB;MAC/B,MAAM,OAAO,SAAS,EAAE;MAGxB,IAAI,SAAS,QAAQ,OAAO,cAAc;MAC1C,MAAM,OAAO,UAAU,KAAK,OAAO,QAAQ,KAAK,OAAO,OAAO,aAAa,IAAI,CAAC;MAChF,IAAI,SAAS,MAAM;MACnB,YAAY,IAAI;MAChB,WAAW,MAAM,IAAI;MAGrB,iBAAiB,IAAI;KACvB;KACA,gBAAgB,IAAY,SAAuB;MACjD,MAAM,OAAO,SAAS,EAAE;MAKxB,IAAI,SAAS,QAAQ,OAAO,cAAc;MAC1C,MAAM,MAAM,KAAK,OAAO,WAAU,MAAK,EAAE,SAAS,IAAI;MACtD,IAAI,MAAM,GAAG;MACb,YAAY,GAAG;MAGf,WAAW,MAAM,GAAG;MAGpB,iBAAiB,IAAI;KAIvB;KACA,gBAAgB,OAAO,OAA8B;MACnD,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,MAAM;MAInB,KAAK,MAAM,QAAQ,UAAU,IAAI,GAAG,MAAM,SAAS,IAAI;MACvD,KAAK;KACP;KACA,eAAe,IAAY,MAAc,YAAiC;MACxE,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,QAAQ,CAAC,KAAK,OAAO,MAAK,MAAK,EAAE,SAAS,IAAI,GAAG;MAC9D,MAAM,SAAS,SAAS;MACxB,SAAS,MAAM,OAAO;MACtB,YAAkB,OAAO,YAAY,IAAI,IAAI,WAAW,MAAM,OAAO;MACrE,eAAe,IAAI,MAAM;MAGzB,IAAI,YAAY,MAAM,iBAAsB,IAAI,IAAI;KACtD;KACA,qBAAqB,OAAO,IAAY,QAAsC;MAC5E,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,MAAM,OAAO;OAAE,IAAI;OAAO,OAAO;MAAe;MAK7D,MAAM,OAAO,SAAS;MACtB,MAAM,MAAM,MAAM,cAAc,MAAM,GAAG;MACzC,IAAI,CAAC,IAAI,IAAI,OAAO;MAEpB,MAAM,SAAS,SAAS;MACxB,KAAK,OAAO,KAAK;OAAE;OAAM,SAAS,EAAE,GAAG,iBAAiB;OAAG,OAAO;MAAK,CAAC;MACxE,SAAS,MAAM,IAAI,WAAW,IAAI;MAClC;MACA,cAAc;MACd,eAAe,IAAI,MAAM;MACzB,iBAAsB,IAAI,IAAI;MAC9B,OAAO;KACT;;;;;;;;;KASA,gBAAgB,IAAY,MAAc,UAAiD;MACzF,MAAM,OAAO,SAAS,EAAE;MACxB,MAAM,QAAQ,MAAM,OAAO,MAAK,MAAK,EAAE,SAAS,IAAI;MACpD,IAAI,SAAS,QAAQ,SAAS,KAAA,KAAa,UAAU,KAAA,GAAW;MAGhE,MAAM,SAAS,SAAS;MACxB,MAAM,QAAQ;MACd,qBAAqB,IAAI;MACzB;MAGA,WAAW;MACX,eAAe,IAAI,MAAM;KAC3B;KACA,cAAc,OAAO,IAAY,SAAoC;MACnE,MAAM,OAAO,SAAS,EAAE;MACxB,IAAI,SAAS,MAAM,OAAO;MAC1B,MAAM,QAAQ,KAAK,OAAO,MAAK,MAAK,EAAE,SAAS,IAAI,KAAK,KAAK,OAAO;MACpE,IAAI,UAAU,KAAA,GAAW,OAAO;MAChC,MAAM,MAAM,eAAe,MAAM,IAAI;MACrC,IAAI,QAAQ,MAAM,OAAO;MACzB,MAAM,MAAM,MAAM,sBAAsB,KAAK,MAAM,OAAO;MAC1D,IAAI,QAAQ,MAAM,OAAO;MAIzB,MAAM,UAAU,SAAS,EAAE,CAAC,EAAE,OAAO,MAAK,MAAK,EAAE,SAAS,MAAM,IAAI;MACpE,IAAI,YAAY,KAAA,GAAW,OAAO;MAIlC,MAAM,SAAS,SAAS;MACxB,QAAQ,QAAQ;MAChB;MACA,WAAW;MACX,eAAe,IAAI,MAAM;MACzB,OAAO;KACT;KACA,SAAS,QAA6B;MAAE,IAAI,YAAY;MAAK,QAAQ;MAAG,KAAK;MAAG,WAAW;KAAE;KAC7F,WAAW,UAA2B;MAAE,IAAI,QAAQ;MAAO,QAAQ;MAAG,KAAK;MAAG,WAAW;KAAE;KAC3F,SAAS,MAAoB;MAAE,IAAI,kBAAkB;MAAG,uBAAuB,CAAC;MAAG,WAAW;KAAE;KAGhG,qBAAqB,MAA2B;MAC9C,IAAI,kBAAkB;MACtB,uBAAuB,iBAAiB,CAAC;MACzC,WAAW;KACb;KACA,iBAAiB,MAAqB;MAAE,IAAI,cAAc;MAAG,WAAW;MAAG,KAAK;KAAE;KAGlF,qBAAqB,MAAqB;MACxC,IAAI,SAAS,UAAU;MACvB,cAAc;MAId,MAAM,OAAO,iBAAiB;MAC9B,IAAI,KAAK,SAAS,MAAM,SAAc,IAAI,CAAC,CAAC,WAAW,YAAY,CAAC;MACpE,YAAY;KACd;KAGA,mBAAyB;MACvB,MAAM,SAAiC,CAAC;MAQxC,MAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS;MACzC,KAAK,MAAM,QAAQ,OAAO;OACxB,MAAM,MAAM,QAAQ,IAAI;OACxB,IAAI,QAAQ,MAAM,OAAO,QAAQ;MACnC;MACA,MAAM,UAAU;OAKd,SAAS;OACT,6BAAY,IAAI,KAAK,EAAA,CAAE,YAAY;OACnC,QAAQ;OACR;MACF;MACA,MAAM,OAAO,IAAI,KAAK,CAAC,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,mBAAmB,CAAC;MACtF,MAAM,MAAM,IAAI,gBAAgB,IAAI;MACpC,MAAM,IAAI,SAAS,cAAc,GAAG;MACpC,EAAE,OAAO;MACT,EAAE,WAAW;MACb,EAAE,MAAM;MACR,IAAI,gBAAgB,GAAG;KACzB;KAEA,aAAa,OAAO,SAAiC;MACnD,IAAI;OACF,MAAM,OAAgB,KAAK,MAAM,MAAM,KAAK,KAAK,CAAC;OAClD,IAAI,CAAC,QAAQ,OAAO,SAAS,UAAU,OAAO;OAC9C,MAAM,IAAI;OACV,IAAI,OAAO,EAAE,WAAW,YAAY,EAAE,WAAW,MAAM,OAAO;OAC9D,YAAY,EAAE,MAAM;OACpB,MAAM,WAAY,EAAE,UAAU,CAAC;OAC/B,MAAM,uBAAO,IAAI,IAAY;OAK7B,KAAK,MAAM,QAAQ,IAAI,MAAM,QAAQ,SAAS,GAAG;QAC/C,KAAK,IAAI,IAAI;QACb,MAAM,MAAM,SAAS;QACrB,IAAI,OAAO,QAAQ,YAAY,gBAAgB,KAAK,GAAG,GAAG;SACxD,SAAS,MAAM,GAAG;SAClB,WAAgB,MAAM,GAAG;QAC3B,OAAO;SACL,SAAS,MAAM,IAAI;SACnB,YAAiB,IAAI;QACvB;OACF;OAEA,KAAK,MAAM,QAAQ,OAAO,KAAK,QAAQ,GACrC,IAAI,CAAC,KAAK,IAAI,IAAI,KAAK,wBAAwB,KAAK,IAAI,GAAG,YAAiB,IAAI;OAElF,cAAc;OACd,YAAY;OACZ,OAAO;MACT,QAAQ;OACN,OAAO;MACT;KACF;IACF;GACF;GACA,IAAI,MAAM,OAAO,0BAA0B,IAAI,MAAM,SAAS;IAC5D,MAAM;IAAoB,IAAI;IAA2B,OAAO;IAChE,aAAa,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,KAAK;IACtC,QAAQ;IAAI;IAAO,QAAQ;GAC7B,GAAG,YAAmB,CAAC;GAOvB,MAAM,iBAAyB,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,KAAK;GACxD,MAAM,qBAA2B;IAE/B,MAAM,MADQ,SAAS,cAA2B,yDAClC,CAAC,EAAE,cAAc,KAAK;IACtC,IAAI,CAAC,KAAK;IACV,MAAM,SAAS,SAAS;IACxB,KAAK,MAAM,QAAQ,MAAM,KAAK,IAAI,iBAAiB,QAAQ,CAAC,GAAG;KAC7D,MAAM,QAAQ,KAAK,cAAc,MAAM;KACvC,IAAI,SAAS,MAAM,aAAa,KAAK,MAAM,QAAQ;MACjD,MAAM,MAAM,KAAK,cAAc,KAAK;MACpC,IAAI,OAAO,IAAI,QAAQ,eAAe,KAAK;OACzC,MAAM,MAAM,SAAS,gBAAgB,8BAA8B,KAAK;OACxE,IAAI,aAAa,SAAS,IAAI;OAC9B,IAAI,aAAa,UAAU,IAAI;OAC/B,IAAI,aAAa,WAAW,WAAW;OACvC,IAAI,aAAa,QAAQ,MAAM;OAC/B,IAAI,aAAa,SAAS,4BAA4B;OACtD,IAAI,QAAQ,aAAa;OACzB,IAAI,YAAY;OAChB,IAAI,YAAY,GAAG;MACrB;MACA;KACF;IACF;GACF;GACA,IAAI,kBAA2C;GAC/C,MAAM,qBAA2B;IAC/B,IAAI,oBAAoB,QAAQ,OAAO,qBAAqB,aAAa;IACzE,kBAAkB,IAAI,kBAAiB,YAAW;KAWhD,IARiB,QAAQ,MAAK,MAAK;MACjC,KAAK,MAAM,KAAK,EAAE,YAAY;OAC5B,IAAI,EAAE,aAAa,GAAG;OACtB,MAAM,KAAK;OACX,IAAI,GAAG,UAAU,yDAAqD,KAAK,GAAG,gBAAgB,yDAAqD,GAAG,OAAO;MAC/J;MACA,OAAO;KACT,CACW,GAAG,aAAa;IAC7B,CAAC;IACD,gBAAgB,QAAQ,SAAS,MAAM;KAAE,WAAW;KAAM,SAAS;IAAK,CAAC;IACzE,aAAa;GACf;GACA,aAAa;GACb,IAAI,mBAAmB;IAAE,iBAAiB,WAAW;IAAG,kBAAkB;GAAK,GAAG,yCAAyC;GAQ3H,MAAM,qBAA2B;IAC/B,eAAe;IACf,MAAM,QAAQ,YAAY;IAC1B,IAAI,UAAU,MAAM;KAClB,MAAM,WAAW,IAAI,MAAM,SAAS;KACpC,IAAI,CAAC,SAAS,OAAO,MAAK,MAAK,EAAE,OAAO,SAAS,GAE/C,eAAe,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE;UACtC,IAAI,SAAS,eAAe,WAIjC,IAAI,MAAM,SAAS,SAAS;IAEhC;IACA,QAAQ;GACV;GACA,MAAM,gBAAgB,CAAC,KAAK,IAAI,CAAC,CAAC,KAAI,UAAS,OAAO,WAAW,cAAc,KAAK,CAAC;GACrF,IAAI,mBAAmB;IAAE,cAAc,SAAQ,OAAM,OAAO,aAAa,EAAE,CAAC;GAAE,GAAG,uCAAuC;GAcxH,MAAM,aAAa,OAAO,kBAAkB;IAC1C,eAAe;IACf,MAAM,QAAQ,YAAY;IAC1B,IAAI,UAAU,MAAM;KAClB,mBAAmB;KACnB;IACF;IACA,MAAM,WAAW,IAAI,MAAM,SAAS;IACpC,IAAI,UAAU;IACd,IAAI,CAAC,SAAS,OAAO,MAAK,MAAK,EAAE,OAAO,SAAS,GAAG;KAClD,eAAe,MAAM,IAAI,MAAM,IAAI,MAAM,EAAE;KAC3C,UAAU;IACZ,OAAO,IAAI,SAAS,eAAe,WAAW;KAC5C,IAAI,MAAM,SAAS,SAAS;KAC5B,UAAU;IACZ;IACA,IAAI,SAAS,QAAQ;GACvB,GAAG,GAAI;GACP,IAAI,mBAAmB;IAAE,OAAO,cAAc,UAAU;GAAE,GAAG,yCAAyC;GAGtG,MAAM,qBAAqB,iBAAiB;GAC5C,IAAI,mBAAmB;IAAE,mBAAmB;GAAE,GAAG,6CAA6C;GAG9F,MAAM,mBAAyB,UAAU;GACzC,OAAO,iBAAiB,YAAY,UAAU;GAC9C,IAAI,mBAAmB,OAAO,oBAAoB,YAAY,UAAU,GAAG,yCAAyC;EACtH"}
|
|
1
|
+
{"version":3,"file":"client.js","names":["BG_MODES","clamp","clamp","Component","useState","createPortal","useRef","memo","useRef","useState","useCallback","toHex","useState","useRef","toHex","useRef","useState","useCallback","useState","useRef","useCallback","useState","useRef","useRef","useState","useRef"],"sources":["../src/client/runtime.ts","../src/client/i18n.ts","../src/client/transition.ts","../src/holiday.ts","../src/schema.ts","../src/client/state.ts","../src/client/rotation.ts","../src/client/repaint.ts","../src/client/rpc.ts","../src/client/palette-fade.ts","../src/client/utils/color.ts","../src/client/components/ui.css.ts","../src/client/wallpaper.ts","../src/client/modelbg.ts","../src/client/components/icons.tsx","../src/client/components/ErrorBoundary.tsx","../src/client/components/Portal.tsx","../src/client/components/LiveSlider.tsx","../src/client/components/pages/InterfacePage.tsx","../src/client/utils/image.ts","../src/client/components/ColorWheel.tsx","../src/client/components/ColorInputs.tsx","../src/client/components/ColorPicker.tsx","../src/client/components/BgEditor.tsx","../src/client/components/pages/ModelBgPage.tsx","../src/client/components/pages/ProfilePage.tsx","../src/client/components/ThemeSection.tsx","../src/client/index.tsx"],"sourcesContent":["/**\r\n * Harness-version-agnostic access to the client runtime.\r\n *\r\n * Before dsh 0.1.2 the store primitive lived on the composite package\r\n * `@deepseek-ai/dsh-client-runtime` (the `/client` subpath). The new harness\r\n * split it into `@deepseek-ai/dsh-client-store`. Both specifiers are kept\r\n * external so they resolve against the host client-module table; a missing\r\n * table entry on one side throws (the \"missed the module table\" error) and is\r\n * caught, falling through to the other package. This lets one bundle load on\r\n * both the old npm release and the new source.\r\n *\r\n * The host's synchronous `require` is injected by the loader into the bundle\r\n * factory; tsdown keeps these two bare specifiers as external CJS requires so\r\n * they bind to that factory `require`.\r\n */\r\n\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\n\r\ninterface StoreModule {\r\n defineStore: any\r\n}\r\n\r\nfunction resolveStore(): StoreModule {\r\n try {\r\n // New harness (dsh >= 0.1.2): dedicated store package after the runtime\r\n // was split. Missing here means the loader table has no such row → throw.\r\n return require('@deepseek-ai/dsh-client-store') as StoreModule\r\n } catch {\r\n /* fall through to the legacy composite runtime below */\r\n }\r\n // Legacy harness (npm release): composite runtime, /client subpath.\r\n return require('@deepseek-ai/dsh-client-runtime/client') as StoreModule\r\n}\r\n\r\nexport const defineStore: any = resolveStore().defineStore","export const NS = 'settings.anyBg'\r\n\r\nexport const zh: Record<string, string> = {\r\n nav: '模型背景', brandTag: '按模型换背景',\r\n pageInterface: '界面', pageModelBg: '模型背景', pageProfile: '配置',\r\n descInterface: '为主界面的各个区域单独调节透明度与模糊,营造空间层次感。这里的设置对所有模型生效',\r\n descModelBg: '每条规则 = 一个匹配串 + 一组背景图与外观。切换模型时,从上往下找第一条匹配串出现在模型名里的规则;都没中就使用第 1 条。一条规则可以放多张图,按你设的节奏轮换',\r\n descProfile: '调整壁纸切换效果,并把当前全部规则连同图片导出备份,或从文件一键恢复',\r\n\r\n uiTitle: '主界面',\r\n uiOpacity: '透明度', uiBlur: '模糊度',\r\n uiOpacityBg: '主背景', uiOpacitySide: '左侧栏', uiOpacityCard: '卡片与菜单面板', uiOpacityInput: '输入框与控件',\r\n uiSop: '设置界面透明度', uiChatRegion: '对话文本框', uiTrajectory: '轨迹页',\r\n uiPreview: '右侧栏',\r\n\r\n // Only the diagnostics survive: the model/rule readout they used to sit under\r\n // is gone (the match tester at the top of the page answers the same question).\r\n statusUnknownHint: '检测不到时一律使用第 1 条可用规则;切换一次模型或稍等片刻会自动重试',\r\n statusSourceDefaultHint: '只读到宿主默认模型,它不是本会话当前选择的模型;本会话的模型选择可用后会自动纠正',\r\n statusNoteNoService: '仍未拿到会话服务(会话控制器晚于本插件加载),正在自动重试',\r\n statusNoteNoSession: '会话服务已就绪,但还没有当前会话 id',\r\n statusNoteNoProjection: '拿不到本会话的模型选择投影(binding / projections 不可用)',\r\n statusNoteEmptySelection: '本会话的模型选择投影还没有值(切一次模型即可写入)',\r\n\r\n // Shown only when the running host process predates multi-image: the panel works\r\n // but holds its writes, and the user has to restart DSH to make them land.\r\n hostStaleHint: '检测到 DSH 主进程仍在运行旧版插件:新版配置格式它还读不懂,为避免丢规则,本次只改界面不写入配置。重启 DSH 后多图与轮换即可正常保存',\r\n tryoutTitle: '匹配试跑',\r\n tryoutPlaceholder: '输入模型名,如 deepseek-flash',\r\n tryoutUseCurrent: '填入当前模型',\r\n tryoutHit: '命中规则',\r\n tryoutFallback: '无匹配 · 走兜底规则',\r\n tryoutNone: '没有可用规则(规则需要启用,并且有图片或主题色)',\r\n tryoutEmpty: '输入模型名即可试跑',\r\n autoExtract: '选图后自动取主题色',\r\n ruleAdd: '新增规则',\r\n ruleFallbackBadge: '兜底',\r\n ruleMatchPlaceholder: '如 flash / glm(忽略大小写,留空则不参与匹配)',\r\n ruleEnabled: '启用',\r\n ruleUp: '上移', ruleDown: '下移', ruleRemove: '删除规则',\r\n ruleNoImage: '尚未选择图片',\r\n ruleFromUrl: '从网址', ruleUrlPlaceholder: '粘贴图片网址 https://…',\r\n ruleUrlApply: '应用', ruleUrlCancel: '取消', ruleUrlApplying: '加载中…',\r\n ruleUrlBadHttp: '仅支持 http/https 图片网址', ruleUrlFail: '获取图片失败',\r\n ruleImageRemove: '移除',\r\n ruleEmptyHint: '这条规则还没有图片,也没有自己的主题色:没有可显示的内容,匹配和兜底都会跳过它',\r\n // The other no-image state — the rule kept its own color, so it DOES paint.\r\n ruleColorOnlyHint: '这条规则还没有图片:不会铺壁纸,界面只用这个主题色',\r\n // Images exist but the selected one has no bytes (deleted outside DSH, or still\r\n // being read): saying \"this rule has no image\" there was simply wrong.\r\n ruleImagePendingHint: '这张图片还没有取到内容,稍后会自己出现(也可以直接替换它)',\r\n ruleColor: '主题色',\r\n ruleColorNone: '跟随系统主题',\r\n ruleColorNoneHint: '未设颜色时跟随系统主题:界面用宿主的配色,壁纸与各部位的透明度、模糊照旧生效',\r\n // Shown where a rule has NO color yet: pressing it picks a color, which is the\r\n // opposite of what the button above does, so it must not borrow that label.\r\n ruleColorPick: '自定义颜色',\r\n ruleColorPickHint: '优先从本图取色,取不到就用默认色',\r\n // Same button, but there is no image to extract from: promising an extraction\r\n // next to a disabled \"extract\" button is the one thing this hint cannot say.\r\n ruleColorNoImageHint: '这条规则还没有图片,取不到色:选一个颜色可以只铺主题色,或先添加图片',\r\n // …and its sibling: there IS an image, it just has no bytes yet. Saying \"this\r\n // rule has no image\" here would contradict the strip right above it.\r\n ruleColorPendingImageHint: '这张图片还没有取到内容,暂时取不了色:可以直接选一个颜色,或等它加载完',\r\n ruleColorExtract: '从本图提取',\r\n // Which of the two things the color controls below edit. A theme color belongs\r\n // to an image, so the same wheel means different things depending on the strip,\r\n // and a section that silently retargets is how \"I changed it and nothing\r\n // happened\" starts.\r\n ruleColorTargetImage: '作用于选中的图片:',\r\n ruleColorTargetRule: '作用于本规则(它还没有图片)',\r\n ruleLayout: '布局模式',\r\n ruleFramingEdit: '编辑位置',\r\n ruleOpacity: '背景透明度',\r\n ruleBlur: '背景模糊',\r\n ruleBlurHint: '背景模糊作用于壁纸层;界面页里的模糊作用于界面各区域,两者互不影响',\r\n\r\n // ── 多图轮换 ──────────────────────────────────────────────────────────────\r\n // 默认关闭:轮换会真的花流量、内存和电,不能靠\"默认\"偷偷替用户做主。\r\n rotTitle: '多图轮换',\r\n rotEnable: '轮换这组图',\r\n rotNeedTwo: '至少两张图才能轮换',\r\n rotEvery: '每张停留',\r\n rotCustom: '自定义秒数',\r\n rotSeconds: '秒',\r\n rotOrder: '换图顺序',\r\n rotOrderSeq: '按顺序',\r\n rotOrderShuffle: '随机',\r\n rotOnSwitch: '切换模型时也换一张',\r\n rotNext: '下一张',\r\n rotNextInactive: '只有正在生效的规则能换画面上的图',\r\n rotPos: '第',\r\n rotShowing: '正在显示',\r\n rotAddImage: '添加',\r\n // Replacing keeps the image's position in the rotation, so it is a different\r\n // action from adding and must not borrow that label.\r\n rotReplaceImage: '替换',\r\n rotDragHint: '拖动排序',\r\n rotDblHint: '双击切换',\r\n rotEvery10s: '10 秒', rotEvery30s: '30 秒', rotEvery1m: '1 分钟',\r\n rotEvery5m: '5 分钟', rotEvery30m: '30 分钟', rotEvery1h: '1 小时',\r\n\r\n\r\n bgModeFit: '适应', bgModeFill: '填充', bgModeStretch: '拉伸', bgModeTile: '平铺', bgModeCenter: '居中',\r\n editorTitle: '背景编辑器', editorHint: '拖动移动画面,滚轮缩放大小',\r\n editorCommit: '确认', editorCancel: '取消', editorReset: '重置',\r\n\r\n extracting: '取色中…',\r\n extractDone: '已应用图片配色',\r\n extractFail: '未在这张图里找到鲜明的颜色,请换一张',\r\n eyedropper: '从图片取色',\r\n pickerTitle: '从图片取色',\r\n pickerHint: '移动鼠标预览颜色,点击图片选取为主题色',\r\n pickerClose: '关闭',\r\n\r\n crashTitle: '界面渲染出错',\r\n crashDesc: '设置面板遇到问题,点击下方按钮重置后重试',\r\n crashReset: '重置面板',\r\n\r\n exportTheme: '导出配置', importTheme: '导入配置',\r\n exportCardTitle: '导出配置',\r\n exportCardDesc: '把全部规则、每条规则的颜色/布局/透明度/模糊与图片打包为 dsh-background-by-model-theme.json',\r\n importCardTitle: '导入配置',\r\n importCardDesc: '从之前导出的 JSON 文件一键恢复全部规则(会覆盖当前规则与图片)',\r\n toastExportDone: '配置文件已开始下载',\r\n importDone: '已导入配置',\r\n importFail: '导入失败,文件格式不正确',\r\n footerTag: '按模型换背景插件',\r\n\r\n // ── 节日特殊背景(默认开启;界面上只有一行开关)───────────────────────────\r\n holidayTitle: '节日特殊背景',\r\n holidayEnable: '启用节日特殊背景(中秋当天、国庆 10 月 1–7 日)',\r\n\r\n // ── 切换效果(全局;配置页)───────────────────────────────────────────────\r\n // 效果与缓动是全局的(规则没有\"效果\"这个概念),时长默认仍由每条规则决定。\r\n trTitle: '切换效果',\r\n trEffect: '切换方式',\r\n trEffectFade: '淡入淡出',\r\n trEffectNone: '直接切换',\r\n trEffectZoom: '缩放淡入',\r\n trEffectSlide: '平移推入',\r\n trEasing: '缓动',\r\n trEasingEase: '标准',\r\n trEasingLinear: '匀速',\r\n trEasingOut: '先快后慢',\r\n trEasingInOut: '两端慢',\r\n trDuration: '切换时长',\r\n trPreview: '试放',\r\n trHint: '效果对所有换图生效:切模型、轮换、手动下一张、节日。「直接切换」和 0 秒一样是硬切',\r\n trReducedHint: '系统开启了「减少动态效果」,实际切换不会播放动画',\r\n}\r\n\r\nexport const en: Record<string, string> = {\r\n nav: 'Model background', brandTag: 'Per-model wallpaper',\r\n pageInterface: 'Interface', pageModelBg: 'Model background', pageProfile: 'Profile',\r\n descInterface: 'Tune opacity and blur per surface to build depth. These settings are global and apply to every model',\r\n descModelBg: 'Each rule is a match string plus a set of wallpapers and one look. On a model switch the list is scanned top-down for the first match string contained in the model name; if nothing hits, rule 1 is used. A rule can hold several images and rotate through them on a rhythm you set',\r\n descProfile: 'Tune how the wallpaper switches, and back up every rule together with its image — or restore one from a file',\r\n\r\n uiTitle: 'Interface',\r\n uiOpacity: 'Opacity', uiBlur: 'Blur',\r\n uiOpacityBg: 'Main background', uiOpacitySide: 'Left panel', uiOpacityCard: 'Cards & menus', uiOpacityInput: 'Input & controls',\r\n uiSop: 'Settings interface opacity', uiChatRegion: 'Conversation text frame', uiTrajectory: 'Trajectory view',\r\n uiPreview: 'Right panel',\r\n\r\n // Only the diagnostics survive: the model/rule readout they used to sit under\r\n // is gone (the match tester at the top of the page answers the same question).\r\n statusUnknownHint: 'Without a detected model rule 1 is always used; switching the model once or waiting a moment retries automatically',\r\n statusSourceDefaultHint: 'Only the host-wide default model could be read — that is not necessarily this session\\'s selection. It self-corrects once this session\\'s model selection is available.',\r\n statusNoteNoService: 'The sessions service is not available yet (the session controller loads after this plugin); retrying automatically',\r\n statusNoteNoSession: 'The sessions service is up but reports no current session yet',\r\n statusNoteNoProjection: 'This session\\'s model-selection projection is unreachable (no binding / projections)',\r\n statusNoteEmptySelection: 'The model-selection projection exists but carries no value yet (selecting a model once writes it)',\r\n\r\n // Shown only when the running host process predates multi-image: the panel works\r\n // but holds its writes, and the user has to restart DSH to make them land.\r\n hostStaleHint: 'The DSH host process is still running the older plugin, which cannot read the new config shape. To avoid dropping rules, this session changes the interface but holds every config write — restart DSH and multi-image plus rotation will save normally',\r\n tryoutTitle: 'Match test',\r\n tryoutPlaceholder: 'Type a model name, e.g. deepseek-flash',\r\n tryoutUseCurrent: 'Use current model',\r\n tryoutHit: 'matches rule',\r\n tryoutFallback: 'no match · fallback rule',\r\n tryoutNone: 'No usable rule (a rule needs to be enabled and carry an image or a theme color)',\r\n tryoutEmpty: 'Type a model name to test the list',\r\n autoExtract: 'Extract the theme color when an image is chosen',\r\n ruleAdd: 'Add rule',\r\n ruleFallbackBadge: 'fallback',\r\n ruleMatchPlaceholder: 'e.g. flash / glm (case-insensitive, empty never matches)',\r\n ruleEnabled: 'Enabled',\r\n ruleUp: 'Move up', ruleDown: 'Move down', ruleRemove: 'Remove rule',\r\n ruleNoImage: 'No image yet',\r\n ruleFromUrl: 'From URL', ruleUrlPlaceholder: 'Paste an image URL https://…',\r\n ruleUrlApply: 'Apply', ruleUrlCancel: 'Cancel', ruleUrlApplying: 'Loading…',\r\n ruleUrlBadHttp: 'Only http/https image URLs are supported', ruleUrlFail: 'Could not fetch the image',\r\n ruleImageRemove: 'Remove',\r\n ruleEmptyHint: 'This rule has no image and no theme color of its own: it has nothing to show, so matching and the fallback both skip it',\r\n // The other no-image state — the rule kept its own color, so it DOES paint.\r\n ruleColorOnlyHint: 'No image in this rule yet: no wallpaper is shown, and the interface is painted from this theme color alone',\r\n // Images exist but the selected one has no bytes (deleted outside DSH, or still\r\n // being read): saying \"this rule has no image\" there was simply wrong.\r\n ruleImagePendingHint: 'This image has no content yet — it appears once it loads; you can also replace it',\r\n ruleColor: 'Theme color',\r\n ruleColorNone: 'Follow system theme',\r\n ruleColorNoneHint: 'Without a color this rule follows the system theme: the host palette paints the interface while the wallpaper and every opacity/blur slider keep working',\r\n // Shown where a rule has NO color yet: pressing it picks a color, which is the\r\n // opposite of what the button above does, so it must not borrow that label.\r\n ruleColorPick: 'Custom color',\r\n ruleColorPickHint: 'Extracts from this image when it can, otherwise uses a default color',\r\n // Same button, but there is no image to extract from: promising an extraction\r\n // next to a disabled \"extract\" button is the one thing this hint cannot say.\r\n ruleColorNoImageHint: 'This rule has no image to take a color from: pick a color to tint the interface alone, or add an image first',\r\n // …and its sibling: there IS an image, it just has no bytes yet. Saying \"this\r\n // rule has no image\" here would contradict the strip right above it.\r\n ruleColorPendingImageHint: 'This image has no content yet, so there is nothing to extract from: pick a color directly, or wait for it to load',\r\n ruleColorTargetImage: 'Applies to the selected image:',\r\n ruleColorTargetRule: 'Applies to this rule (it has no image yet)',\r\n ruleColorExtract: 'Extract from image',\r\n ruleLayout: 'Layout mode',\r\n ruleFramingEdit: 'Edit position',\r\n ruleOpacity: 'Background opacity',\r\n ruleBlur: 'Background blur',\r\n ruleBlurHint: 'Background blur affects the wallpaper layer; the blur on the Interface page affects interface surfaces — they are independent',\r\n\r\n // ── Multi-image rotation ──────────────────────────────────────────────────\r\n // Off by default: rotating really does spend bandwidth, memory and battery,\r\n // and no default should quietly decide that for the user.\r\n rotTitle: 'Image rotation',\r\n rotEnable: 'Rotate these images',\r\n rotNeedTwo: 'At least two images are needed to rotate',\r\n rotEvery: 'Dwell time per image',\r\n rotCustom: 'Custom seconds',\r\n rotSeconds: 's',\r\n rotOrder: 'Order',\r\n rotOrderSeq: 'In order',\r\n rotOrderShuffle: 'Shuffle',\r\n rotOnSwitch: 'Also step on a model switch',\r\n rotNext: 'Next image',\r\n rotNextInactive: 'Only the active rule can step the background',\r\n rotPos: 'Image',\r\n rotShowing: 'On screen',\r\n rotAddImage: 'Add',\r\n // Replacing keeps the image's position in the rotation, so it is a different\r\n // action from adding and must not borrow that label.\r\n rotReplaceImage: 'Replace',\r\n rotDragHint: 'drag to reorder',\r\n rotDblHint: 'double-click to show',\r\n rotEvery10s: '10 s', rotEvery30s: '30 s', rotEvery1m: '1 min',\r\n rotEvery5m: '5 min', rotEvery30m: '30 min', rotEvery1h: '1 h',\r\n\r\n\r\n bgModeFit: 'Fit', bgModeFill: 'Fill', bgModeStretch: 'Stretch', bgModeTile: 'Tile', bgModeCenter: 'Center',\r\n editorTitle: 'Background editor', editorHint: 'Drag to move, scroll to zoom',\r\n editorCommit: 'Confirm', editorCancel: 'Cancel', editorReset: 'Reset',\r\n\r\n extracting: 'Extracting…',\r\n extractDone: 'Image colors applied',\r\n extractFail: 'No vivid color found in this image, try another',\r\n eyedropper: 'Eyedropper',\r\n pickerTitle: 'Pick from image',\r\n pickerHint: 'Hover to preview, click to pick as the theme color',\r\n pickerClose: 'Close',\r\n\r\n crashTitle: 'Section crashed',\r\n crashDesc: 'The panel hit an error. Reset below to recover.',\r\n crashReset: 'Reset panel',\r\n\r\n exportTheme: 'Export', importTheme: 'Import',\r\n exportCardTitle: 'Export profile',\r\n exportCardDesc: 'Bundle every rule — color, layout, opacity, blur — and its image into dsh-background-by-model-theme.json',\r\n importCardTitle: 'Import profile',\r\n importCardDesc: 'Restore every rule and image from a previously exported JSON file (replaces the current set)',\r\n toastExportDone: 'Export started',\r\n importDone: 'Profile imported',\r\n importFail: 'Import failed — invalid file',\r\n footerTag: 'Per-model wallpaper plugin',\r\n\r\n // ── Holiday overrides (on by default; one switch, no cards) ───────────────\r\n holidayTitle: 'Holiday backgrounds',\r\n holidayEnable: 'Enable holiday backgrounds (Mid-Autumn day, Oct 1–7)',\r\n\r\n // ── Switch effect (global; the Config page) ───────────────────────────────\r\n // The effect and the easing are global — a rule has no notion of one — while\r\n // the duration stays each rule's own unless it is unified here.\r\n trTitle: 'Switch effect',\r\n trEffect: 'Transition',\r\n trEffectFade: 'Cross-fade',\r\n trEffectNone: 'Instant',\r\n trEffectZoom: 'Zoom in',\r\n trEffectSlide: 'Slide in',\r\n trEasing: 'Easing',\r\n trEasingEase: 'Standard',\r\n trEasingLinear: 'Linear',\r\n trEasingOut: 'Ease out',\r\n trEasingInOut: 'Ease in-out',\r\n trDuration: 'Duration',\r\n trPreview: 'Preview',\r\n trHint: 'The effect applies to every change: model switch, rotation, manual next, holidays. “Instant” and 0 s are the same hard cut',\r\n trReducedHint: 'Your system asks for reduced motion, so a real switch will not animate',\r\n}\r\n","/**\n * The wallpaper-switch transition: what a change LOOKS like, and how long it\n * takes.\n *\n * Pure and import-free at runtime on purpose — the layers, the timers and the\n * rAF that actually paint live in the apply closure (./wallpaper), but the\n * DECISION lives here so `scripts/transition-check.ts` can pin it down. Every\n * failure this feature can produce is silent:\n *\n * 1. a start state equal to the end state (an effect that visibly does\n * nothing, indistinguishable from \"the setting was not saved\");\n * 2. a duration of `0` read as \"absent\" and defaulted instead of honoured;\n * 3. an effect selected while `reduced-motion` is on, animating anyway;\n * 4. a garbage duration animating for an unknown length.\n *\n * This module deliberately imports NOTHING from `src/schema.ts`, exactly like\n * `./rotation` and for the same reason: that module has a real (extensionless)\n * runtime import of `./holiday`, which the bundler resolves and plain `node`\n * does not. The persisted shape's own clamps are checked where they run —\n * through the node half's RPC, in `scripts/node-half-check.mjs`.\n */\nimport type { TransitionConfig, TransitionEffect, TransitionEasing } from './types'\n\n/** One wallpaper layer's inline style, in the two properties a switch touches. */\nexport interface LayerStyle {\n opacity: string\n transform: string\n}\n\n/** Everything the render layer needs to run (or skip) one switch. */\nexport interface TransitionPlan {\n /** Whether any animation runs at all. */\n animate: boolean\n /** Duration to use, in ms — `0` whenever nothing animates. */\n durationMs: number\n /** Start state of the INCOMING layer. */\n from: LayerStyle\n /** End state of the incoming layer. */\n to: LayerStyle\n /** The `transition` shorthand, written before `to` is applied. */\n transition: string\n /** `will-change` while the animation runs (`''` = none). */\n willChange: string\n}\n\n/**\n * Resolve the duration one switch uses, in ms (`0` = a hard cut).\n *\n * 1. `effect: 'none'` is a hard cut whatever the duration says — asking for no\n * animation and asking for 0 ms are the same request, and the effect is the\n * more explicit of the two;\n * 2. otherwise the global `durationMs` decides, because a rule has no notion of\n * a transition and there is exactly one duration for every switch.\n *\n * A non-finite or negative value answers `0` (a hard cut) rather than a default:\n * animating for an unknown length is the one answer that cannot be right. The\n * input is already clamped by the shared sanitizer (`./schema`), so this is a\n * guard against a hand-edited config, not a second clamp.\n */\nexport function resolveFadeMs(transition: TransitionConfig): number {\n if (transition.effect === 'none') return 0\n return Number.isFinite(transition.durationMs) && transition.durationMs > 0 ? transition.durationMs : 0\n}\n\n/**\n * The transform the incoming layer starts from, per effect.\n *\n * `zoom` starts ABOVE 1 and settles back to exactly `none`, never below or past\n * it: the wallpaper would otherwise be left larger than the viewport, cropping a\n * `fit` framing the user committed by hand. `slide` is a small push because a\n * full-width travel of a full-bleed wallpaper reads as two wallpapers, not one\n * transition.\n */\nconst START_TRANSFORM: Record<TransitionEffect, string> = {\n fade: 'none',\n // Never animates (see `resolveFadeMs`), so its start state is its end state.\n none: 'none',\n zoom: 'scale(1.06)',\n slide: 'translateX(6%)',\n}\n\n/** The properties one effect actually animates — an unchanged property must not\n * be put on the transition list, or `fade` would stop being byte-for-byte the\n * cross-fade every release so far performed. */\nfunction animatedProps(effect: TransitionEffect): string[] {\n return effect === 'fade' ? ['opacity'] : ['opacity', 'transform']\n}\n\n/**\n * Decide one switch: whether to animate, from what, to what, and on what curve.\n *\n * `canAnimate` is the caller's answer to \"is there anything to animate from\" —\n * a first paint has no previous layer, and a wallpaper at 0% opacity is not on\n * screen — plus the window-visibility question the caller already owns. It is\n * passed in rather than computed here so this stays a pure function of its\n * inputs.\n *\n * `reducedMotion` is honoured as a hard veto rather than a shortened duration:\n * the point of the preference is that the interface stops moving, and a fast\n * animation is still an animation.\n */\nexport function transitionPlan(input: {\n effect: TransitionEffect\n easing: TransitionEasing\n /** Already-resolved duration (see `resolveFadeMs`). */\n durationMs: number\n canAnimate: boolean\n reducedMotion: boolean\n}): TransitionPlan {\n const still: LayerStyle = { opacity: '1', transform: 'none' }\n const moves = input.durationMs > 0\n if (!input.canAnimate || input.reducedMotion || input.effect === 'none' || !moves) {\n // Nothing animates: the layer is put straight on its end state, and the\n // `transition: none` is part of the answer because the previous switch may\n // have left a transition on this very element.\n return { animate: false, durationMs: 0, from: still, to: still, transition: 'none', willChange: '' }\n }\n const props = animatedProps(input.effect)\n const timing = `${input.durationMs}ms ${input.easing}`\n return {\n animate: true,\n durationMs: input.durationMs,\n from: { opacity: '0', transform: START_TRANSFORM[input.effect] },\n to: still,\n transition: props.map(p => `${p} ${timing}`).join(', '),\n willChange: props.join(', '),\n }\n}\n","/**\n * The built-in holiday calendar behind the \"holiday background\" override.\n *\n * Imported by BOTH halves — the node half only reads `HOLIDAYS` (the fixed slot\n * ids and the bundled asset names), the browser half does the date maths — so\n * nothing here may touch the DOM, Node or the Cordis context, and every\n * `Intl` formatter is built lazily so the node half never constructs one.\n *\n * Both holidays are evaluated in **Asia/Shanghai**, not in the machine's own\n * zone: 中秋 is a lunar date, and the lunar day rolls over at Beijing midnight,\n * so reading \"today\" from a UTC or UTC-8 clock puts the festival on the wrong\n * day for most of the planet.\n *\n * mid-autumn 农历八月十五 — moves across the Gregorian calendar\n * (2024-09-17, 2025-10-06, 2026-09-25, 2027-09-15 …)\n * national-day 公历 10 月 1–7 日 — the fixed National Day holiday window\n */\n\nexport type HolidayId = 'mid-autumn' | 'national-day'\n\nexport interface HolidayDef {\n id: HolidayId\n /**\n * Image slot holding this holiday's wallpaper. Fixed, and namespaced with an\n * `h-` prefix so it can never collide with a rule slot (`nextSlot` only ever\n * hands out `m<n>`, and slots are what reach the filesystem).\n */\n slot: string\n /** Wallpaper bundled inside the package under `holiday/`. */\n asset: string\n /**\n * The theme color this holiday paints with, as `#RRGGBB`.\n *\n * Fixed, and fixed HERE — beside the slot and the art — rather than derived\n * from the wallpaper: the palette of a festival is a design decision, and\n * decoding a 3456×1920 photo to re-derive the same hue was both slower and\n * less predictable than naming it. ./schema turns this into the `[h, s, l]`\n * triple the rule shape stores, and takes it from the definition rather than\n * from disk, so a config can never paint a festival in a color it does not\n * have.\n */\n color: string\n /** How the window is computed — also drives the \"next occurrence\" scan. */\n kind: 'lunar' | 'gregorian'\n}\n\nexport const HOLIDAYS: readonly HolidayDef[] = [\n { id: 'mid-autumn', slot: 'h-midautumn', asset: 'mid-autumn.webp', color: '#384A77', kind: 'lunar' },\n { id: 'national-day', slot: 'h-nationalday', asset: 'national-day.webp', color: '#FFF6EB', kind: 'gregorian' },\n]\n\n/** 中秋 always falls between these two Gregorian days, so a scan can skip the rest. */\nconst MID_AUTUMN_FROM = { m: 9, d: 7 }\nconst MID_AUTUMN_TO = { m: 10, d: 8 }\n\nexport function holidayDef(id: string): HolidayDef | null {\n return HOLIDAYS.find(h => h.id === id) ?? null\n}\n\nexport function isHolidayId(id: string): id is HolidayId {\n return HOLIDAYS.some(h => h.id === id)\n}\n\n/** The slot a holiday's wallpaper lives in; '' for an unknown id. */\nexport function holidaySlot(id: string): string {\n return holidayDef(id)?.slot ?? ''\n}\n\n// ── Calendar primitives ────────────────────────────────────────────────────\n// Both formatters are optional: a build without full ICU (a small-icu Node, an\n// exotic browser) simply cannot answer, and every caller degrades to \"no\n// holiday\" instead of throwing inside a render.\n\nconst TZ = 'Asia/Shanghai'\n\nlet civilFormatter: Intl.DateTimeFormat | null | undefined\nfunction civilFmt(): Intl.DateTimeFormat | null {\n if (civilFormatter === undefined) {\n try {\n civilFormatter = new Intl.DateTimeFormat('en-US', {\n timeZone: TZ, year: 'numeric', month: 'numeric', day: 'numeric',\n })\n } catch {\n civilFormatter = null\n }\n }\n return civilFormatter\n}\n\nlet lunarFormatter: Intl.DateTimeFormat | null | undefined\nfunction lunarFmt(): Intl.DateTimeFormat | null {\n if (lunarFormatter === undefined) {\n try {\n lunarFormatter = new Intl.DateTimeFormat('en-u-ca-chinese', {\n timeZone: TZ, year: 'numeric', month: 'numeric', day: 'numeric',\n })\n } catch {\n lunarFormatter = null\n }\n }\n return lunarFormatter\n}\n\nfunction partsOf(fmt: Intl.DateTimeFormat, date: Date): Record<string, string> | null {\n try {\n const out: Record<string, string> = {}\n for (const p of fmt.formatToParts(date)) {\n if (p.type !== 'literal') out[p.type] = p.value\n }\n return out\n } catch {\n return null\n }\n}\n\n/** The civil (Gregorian) date in Asia/Shanghai, or null when ICU cannot answer. */\nexport function shanghaiDate(date: Date): { y: number; m: number; d: number } | null {\n const fmt = civilFmt()\n if (fmt === null) return null\n const p = partsOf(fmt, date)\n if (p === null) return null\n const y = Number(p.year)\n const m = Number(p.month)\n const d = Number(p.day)\n if (!isFinite(y) || !isFinite(m) || !isFinite(d)) return null\n return { y, m, d }\n}\n\n/** `YYYY-MM-DD` of one Asia/Shanghai civil date. */\nexport function civilKey(date: { y: number; m: number; d: number }): string {\n return `${date.y}-${String(date.m).padStart(2, '0')}-${String(date.d).padStart(2, '0')}`\n}\n\n/**\n * The Chinese-calendar month and day in Asia/Shanghai.\n *\n * ICU marks a **leap** month by suffixing `bis` — a leap fourth month reads\n * `4bis`, a leap eighth month would read `8bis`. 中秋 is the FIFTEENTH DAY OF THE\n * REGULAR EIGHTH MONTH, so the exact `month === '8'` test below is what keeps a\n * leap eighth month (which does occur, roughly once every few decades) from\n * dragging the festival a month late.\n */\nexport function lunarMonthDay(date: Date): { month: string; day: string } | null {\n const fmt = lunarFmt()\n if (fmt === null) return null\n const p = partsOf(fmt, date)\n if (p === null || p.month === undefined || p.day === undefined) return null\n return { month: p.month, day: p.day }\n}\n\n// ── The two windows ────────────────────────────────────────────────────────\n\n/** 农历八月十五, in the regular eighth month — i.e. 中秋 itself. */\nexport function isMidAutumn(date: Date = new Date()): boolean {\n const lunar = lunarMonthDay(date)\n return lunar !== null && lunar.month === '8' && lunar.day === '15'\n}\n\n/** 公历 10 月 1–7 日 — the National Day holiday period. */\nexport function isNationalDay(date: Date = new Date()): boolean {\n const civil = shanghaiDate(date)\n return civil !== null && civil.m === 10 && civil.d >= 1 && civil.d <= 7\n}\n\n/**\n * The holiday whose window contains `date`, or null.\n *\n * 中秋 wins the overlap: it is a single precise day, while National Day is a\n * seven-day window, and the two do collide (2025-10-06 was both). On a tie the\n * rarer, more specific answer is the better one.\n */\nexport function activeHoliday(date: Date = new Date()): HolidayId | null {\n if (isMidAutumn(date)) return 'mid-autumn'\n if (isNationalDay(date)) return 'national-day'\n return null\n}\n\n/**\n * The next Asia/Shanghai civil date on which `id` starts, as `YYYY-MM-DD`, or\n * null when the calendar is unavailable.\n *\n * The scan is anchored at 04:00 UTC — noon in Beijing, and Shanghai has no DST —\n * so stepping a whole day at a time can never skip or repeat a civil date. Days\n * outside the possible window of a lunar holiday are skipped before the\n * (expensive) lunar lookup, which is what keeps this cheap enough to run while\n * the settings page renders.\n */\nexport function nextHolidayStart(id: HolidayId, from: Date = new Date()): string | null {\n const start = shanghaiDate(from)\n if (start === null) return null\n const anchor = Date.UTC(start.y, start.m - 1, start.d, 4)\n for (let i = 0; i < 400; i++) {\n const probe = new Date(anchor + i * 86_400_000)\n const civil = shanghaiDate(probe)\n if (civil === null) return null\n // A day that cannot hold this holiday is skipped BEFORE the lunar lookup,\n // which is what makes a year-long scan cheap enough to run while the\n // settings page renders.\n if (holidayDef(id)?.kind === 'lunar' && !inMidAutumnRange(civil)) continue\n if (activeHoliday(probe) === id) return civilKey(civil)\n }\n return null\n}\n\nfunction inMidAutumnRange(civil: { m: number; d: number }): boolean {\n if (civil.m === MID_AUTUMN_FROM.m) return civil.d >= MID_AUTUMN_FROM.d\n if (civil.m === MID_AUTUMN_TO.m) return civil.d <= MID_AUTUMN_TO.d\n return false\n}\n\n// ── Which holiday overrides the rules right now ────────────────────────────\n\n/**\n * The bits of a holiday entry the picker needs. Structural on purpose: the\n * persisted shape lives in ./schema, and this module importing THAT would close a\n * cycle, since ./schema imports `HOLIDAYS` from here.\n *\n * The image LIST (rather than one slot) is what a rule owns since 0.7, and this\n * mirrors just enough of it to ask the picker's only question: \"is there anything\n * to paint?\". A holiday's own list is always the single packaged image (see\n * `defaultHolidayRule`), so the shape stays a formality for it — and a rule that\n * happens to be passed in answers through the same field.\n */\nexport interface HolidayCandidate {\n id: string\n enabled: boolean\n images: readonly { slot: string }[]\n}\n\n/**\n * The holiday the background must follow right now, or null.\n *\n * Four gates, every one of them deliberate:\n *\n * 1. the master switch — an override that discards the user's rule list must\n * never happen without being asked for;\n * 2. a built-in holiday whose window contains today;\n * 3. that holiday's own switch;\n * 4. actual bytes in its slot.\n *\n * The last one matters most, and it is the reason this is not a one-liner at the\n * call site: a switched-on holiday with no image at all has to fall through to\n * the model rules, not blank the wallpaper.\n *\n * It lives here, as a pure function, so the decision is covered by\n * `scripts/holiday-check.ts` instead of hiding inside the plugin's apply closure\n * where nothing can reach it.\n */\nexport function pickHoliday<T extends HolidayCandidate>(\n master: boolean,\n items: readonly T[],\n todayId: HolidayId | null,\n hasImage: (slot: string) => boolean,\n): T | null {\n if (!master || todayId === null) return null\n const item = items.find(i => i.id === todayId)\n if (item === undefined || !item.enabled) return null\n return item.images.some(image => hasImage(image.slot)) ? item : null\n}\n","/**\n * The persisted configuration shape — declared exactly ONCE, for both halves.\n *\n * This shape used to be written out twice: the node half owns persistence and\n * sanitizes every write, the browser half owns the UI and its own reading of the\n * same file. A field added to only one side was silently dropped by the other\n * side's sanitizer — the matching slider stayed live in memory, `writeConfig`\n * wrote a config without it, and the next load fell back to the default.\n * `blurs.rightbar` / `rightbarOpacity` in 0.3.2 was exactly that bug, and the key\n * lists were duplicated 6 times across the two halves, so it was due to happen.\n *\n * The types, the key lists, the defaults and the pure normalizers therefore live\n * here and both halves import them: adding a field means editing this file, and\n * the two halves cannot disagree about the shape. The host additionally logs one\n * warning per unknown key while sanitizing a write (see `warnUnknownConfigKeys`\n * in `src/index.ts`), so a field that reaches the node half without being\n * declared here shows up in the host log instead of quietly disappearing.\n *\n * Nothing in this module may touch the DOM, Node or the Cordis context: it is\n * imported by the browser bundle and by the node half alike.\n */\n\nimport { HOLIDAYS } from './holiday'\nimport type { HolidayDef } from './holiday'\n\n/** Placement state of one background image (zoom + fractional center + intrinsic size). */\nexport interface BgState { zoom: number; x: number; y: number; iw: number; ih: number }\n\nexport const DEFAULT_BG_STATE: BgState = { zoom: 1, x: 0, y: 0, iw: 0, ih: 0 }\n\n/**\n * One image of a rule: its slot, plus everything that belongs to THAT image —\n * its framing and its theme color.\n *\n * The framing is per image rather than per rule because a crop is a property of\n * a picture: two wallpapers with different aspect ratios share the rule's\n * `bgMode`, opacity and blur, but a single `fit` framing computed for one of\n * them is simply wrong for the other.\n *\n * The theme color is per image for the same reason one step further out: a rule\n * is a rotation through several pictures, and pictures that were collected for\n * different moods do not share one accent. A rule's own `color` therefore means\n * something narrower than it used to (see `BgRule.color`) — it is what a rule\n * with no image left paints.\n */\nexport interface BgImage {\n /** Image slot; the bytes live in `modelbg-<slot>` under the data dir. */\n slot: string\n /** This image's framing (zoom + fractional center + intrinsic size). */\n bgState: BgState\n /**\n * This image's own theme color as `[h, s, l]`, or null for \"follow the system\n * theme while THIS image is on screen\".\n *\n * Null is an opinion, not an absence: it is the state the clear button puts an\n * image in, and it is deliberately NOT the rule's color — an image's color is\n * the image's, which is what makes a rotation through a green, a red and a\n * system-themed picture expressible at all. The rule's own color only applies\n * when the rule has no image to speak for it.\n *\n * Written by every release from 0.7.1 on. An entry that predates the field has\n * no `color` KEY at all, which is exactly how `normalizeImage` tells \"this\n * image never had a color of its own\" from \"this image was explicitly cleared\"\n * — and why the rule's color is lifted onto such an entry on read rather than\n * being quietly dropped.\n */\n color: [number, number, number] | null\n}\n\n/** Adaptive placement of a background image. */\nexport type BgMode = 'fit' | 'fill' | 'stretch' | 'tile' | 'center'\n\n/** Every accepted `bgMode`, in UI order. */\nexport const BG_MODES: readonly BgMode[] = ['fit', 'fill', 'stretch', 'tile', 'center']\n\n// ── Multi-image rotation ───────────────────────────────────────────────────\n\n/** How a rule walks its own image list. */\nexport type RotateOrder = 'order' | 'shuffle'\n\n/** Every accepted `rotate.order`, in UI order. */\nexport const ROTATE_ORDERS: readonly RotateOrder[] = ['order', 'shuffle']\n\n/** Fastest allowed dwell time — below this the cross-fade never settles. */\nexport const ROTATE_MIN_MS = 5_000\n/** Slowest allowed dwell time (24 h): one image per day is still \"rotation\". */\nexport const ROTATE_MAX_MS = 24 * 60 * 60 * 1000\n\n/**\n * Multi-image rotation, per rule.\n *\n * OFF by default, and that is a deliberate product decision: switching images by\n * itself costs memory, bandwidth and CPU on a wallpaper that nobody asked to\n * animate. `intervalMs` is the dwell time, `order` picks the next image, and\n * `advanceOnSwitch` also steps once when the model switch lands on this rule —\n * so a model can have \"a different picture every time\" without any timer at all.\n *\n * There is deliberately no fade here: how long a switch takes is the GLOBAL\n * switch effect's business (`TransitionConfig`), because a rule has no notion of\n * a transition. The per-rule `fadeMs` this block used to carry was a field no\n * control ever reached — a setting nobody could set — so the first build that\n * has a duration control at all folded it into the global one (see\n * `normalizeTransition`).\n */\nexport interface BgRotation {\n enabled: boolean\n /** Dwell time per image, ms (`ROTATE_MIN_MS`..`ROTATE_MAX_MS`). */\n intervalMs: number\n /** `order` walks the list top-down; `shuffle` never repeats the current image. */\n order: RotateOrder\n /** Step once when this rule becomes the active one. */\n advanceOnSwitch: boolean\n}\n\n/** Everything off: the shipped default, and what a config predating this feature gets. */\nexport const DEFAULT_ROTATION: BgRotation = {\n enabled: false,\n intervalMs: 60_000,\n order: 'order',\n advanceOnSwitch: false,\n}\n\n/** A fresh rotation block (never hand out the shared default object). */\nexport function defaultRotation(): BgRotation { return { ...DEFAULT_ROTATION } }\n\n/**\n * Main interface opacities (0..1), global (Interface page):\n * `bg` main background (`--dsw-alias-bg-base`)\n * `sidebar` sidebar (`--dsw-specific-sidebar-fill`)\n * `card` cards/panels (`--dsw-alias-bg-layer-1/2/3`, `--dsw-specific-menu`\n * and its 0.1.7 alias `--dsw-menu-surface-fill`)\n * `input` input/control surfaces (`--dsw-specific-input-major`)\n */\nexport const PART_OPACITY_KEYS = ['bg', 'sidebar', 'card', 'input'] as const\n\n/** Per-part main interface opacities (0..1), keyed BY the list above. */\nexport type PartOpacities = Record<(typeof PART_OPACITY_KEYS)[number], number>\n\nexport const DEFAULT_PART_OPACITIES: PartOpacities = { bg: 0.85, sidebar: 0.93, card: 1, input: 1 }\n\n/**\n * Interface blur (px, 0..60), global (Interface page):\n * `bg` main background (AppFrame grid)\n * `sidebar` sidebar column\n * `card` cards/panels (center + details columns, dialog option panels)\n * `settings` settings panel\n * `chat` conversation text region (message column of the chat view)\n * `trajectory` trajectory view surface\n * `rightbar` file-preview panel — the right sidebar a file click opens\n * `input` input/control surfaces ([data-composer-card], [data-cordis-panel])\n */\nexport const PART_BLUR_KEYS = ['bg', 'sidebar', 'card', 'settings', 'chat', 'trajectory', 'rightbar', 'input'] as const\n\n/** Per-part interface blur (px, 0..60), keyed BY the list above. */\nexport type PartBlurs = Record<(typeof PART_BLUR_KEYS)[number], number>\n\nexport const DEFAULT_PART_BLURS: PartBlurs = {\n bg: 0, sidebar: 0, card: 0, settings: 0, chat: 0, trajectory: 0, rightbar: 0, input: 0,\n}\n\n// ── Wallpaper switch transition (global) ───────────────────────────────────\n\n/** Longest allowed switch duration; 0 is a hard cut. */\nexport const TRANSITION_MAX_MS = 3_000\n\n/**\n * What a wallpaper CHANGE looks like.\n *\n * Global by design, all three parts of it: a rule has no notion of a transition,\n * and there is exactly ONE duration for every switch. The per-rule `fadeMs` that\n * used to carry the duration was a field no control ever reached, so offering a\n * choice between \"each rule's own\" and \"one global value\" would have been\n * offering a choice between a real setting and a phantom one.\n *\n * `fade` is the cross-fade every release so far performed, so the shipped\n * default is exactly the behaviour of the build before this setting existed:\n * adding a global switch must not change what anybody already sees.\n */\nexport type TransitionEffect = 'fade' | 'none' | 'zoom' | 'slide'\n\n/** Every accepted `effect`, in UI order. */\nexport const TRANSITION_EFFECTS: readonly TransitionEffect[] = ['fade', 'none', 'zoom', 'slide']\n\n/**\n * The transition's timing function, global along with the effect.\n *\n * `ease` is the curve the cross-fade already ran on, so the default does not\n * move either.\n */\nexport type TransitionEasing = 'ease' | 'linear' | 'ease-out' | 'ease-in-out'\n\n/** Every accepted `easing`, in UI order. */\nexport const TRANSITION_EASINGS: readonly TransitionEasing[] = ['ease', 'linear', 'ease-out', 'ease-in-out']\n\n/**\n * The global wallpaper-switch transition.\n *\n * There is deliberately no `enabled`: switching it off and picking `none` are\n * the same state, and two controls that mean one thing is how a panel starts\n * contradicting itself.\n */\nexport interface TransitionConfig {\n /** What a change looks like. `none` is a hard cut whatever the duration says. */\n effect: TransitionEffect\n /** Timing function of the animation. */\n easing: TransitionEasing\n /** How long a change takes, in ms (`0` = a hard cut, max `TRANSITION_MAX_MS`). */\n durationMs: number\n}\n\n/** The shipped default: the cross-fade this plugin already performed, at 320 ms. */\nexport const DEFAULT_TRANSITION: TransitionConfig = {\n effect: 'fade',\n easing: 'ease',\n durationMs: 320,\n}\n\n/** A fresh transition block (never hand out the shared default object). */\nexport function defaultTransition(): TransitionConfig { return { ...DEFAULT_TRANSITION } }\n\n/**\n * One model rule: a match string plus everything the background needs while it\n * is the active rule. Every appearance field lives HERE rather than globally —\n * the settings UI edits a rule, and the render layer follows whichever rule the\n * current model selected.\n */\nexport interface BgRule {\n /** Stable id; also the render key. */\n id: string\n /**\n * Case-insensitive substring tested against the current model text (provider,\n * model id and display name joined with spaces). An EMPTY string never matches\n * on its own — that rule then only ever serves as the fallback.\n */\n match: string\n /**\n * The rule's images, in order. `images[0]` is the one painted when no rotation\n * is running. The list may legitimately be EMPTY (every picture removed): the\n * rule then paints its own theme color alone, or nothing at all when it has no\n * color either — see `ruleCanPaint`, which is what matching asks.\n *\n * This replaced the single `slot`/`bgState` pair in 0.7.0. A config written by\n * an earlier version is lifted to `[{ slot, bgState }]` on read (see\n * `normalizeRule`), so both shapes live on ONE in-memory shape and only the new\n * one is ever written back — the same \"declare it once\" rule as this file's\n * header.\n */\n images: BgImage[]\n /** Disabled rules are skipped by matching AND by the fallback pick. */\n enabled: boolean\n /**\n * The theme color of the rule ITSELF: what an image-less rule paints the\n * interface from. Null = that rule falls back to the system theme.\n *\n * It is not a default for the rule's images — each of those carries its own\n * (`BgImage.color`) and never inherits this one at paint time. The only\n * inheritance that exists is a one-shot LIFT at read time for configs written\n * before per-image colors, so a rule that was themed before 0.7.1 comes back\n * looking exactly the same (see `normalizeImage`).\n */\n color: [number, number, number] | null\n bgMode: BgMode\n /** Wallpaper layer opacity (0..1). */\n wallpaperOpacity: number\n /** Wallpaper layer blur (px, 0..60) — NOT the interface part blur. */\n blur: number\n /** How the rule cycles `images`; off by default. */\n rotate: BgRotation\n}\n\n/** Every slot a rule owns, in order. The one thing the render and store layers\n * ask of the image list, so a rule's slots are never enumerated ad hoc. */\nexport function ruleSlots(rule: BgRule): string[] {\n return rule.images.map(i => i.slot)\n}\n\n/**\n * Whether a rule has anything to show at all: an image, or a theme color of its\n * own. Used by matching (`usable` in ./client/modelbg) and by the panel's copy.\n *\n * An image is the obvious way a rule paints, and until 0.7 it was the ONLY one —\n * which stopped being true the moment the last image became removable. A\n * rule-level theme color is the second: it recolors the interface through the\n * token palette with no wallpaper involved, so a rule whose pictures were all\n * removed still paints, and treating it as unusable made every control left on\n * its card (the wheel, the swatches, the clear-to-system-theme button) dead — the\n * one state where the panel was confidently showing a lie. It also silently\n * handed the model to the NEXT rule, so clearing the default rule's images put\n * another model's wallpaper on the screen.\n *\n * Note that a per-image color (0.7.1) does not enter this question at all: an\n * image is already enough, so the answer here is about the IMAGE LIST being\n * non-empty, never about what those images are painted in.\n *\n * A rule with no image and no color of its own paints nothing: the system theme\n * is not a paint of this rule's own, so such a rule is skipped by matching, which\n * is what makes a freshly added rule (empty, colorless) invisible until the user\n * gives it something.\n */\nexport function ruleCanPaint(rule: BgRule): boolean {\n return rule.enabled && (ruleSlots(rule).length > 0 || rule.color !== null)\n}\n\n/**\n * One built-in holiday override.\n *\n * Deliberately the SAME shape as a rule — an alias rather than an extension: the\n * render layer resolves whatever `ruleById` returns, so making a holiday a rule\n * is what lets the wallpaper, the theme color, the layout mode and the framing\n * all work without a second code path. `id` and `slot` are fixed by `HOLIDAYS` —\n * the sanitizer overwrites them from the definition, so a hand-edited config can\n * never point a holiday at another rule's slot.\n *\n * There is deliberately nothing here about the IMAGE. A holiday's wallpaper is\n * the one bundled in the package (under `holiday/`), the node half serves it\n * straight out of there, and a holiday slot is read-only — no entry point takes\n * bytes for it. The feature is an easter egg, not a thing to configure.\n *\n * Its theme colors are forced from the definition for the same reason, one level\n * deeper: a holiday's color belongs to it, so `normalizeHolidayRule` rewrites both\n * the rule's color and every image's. That is also what makes a future holiday\n * with SEVERAL pictures (a rotation through festival art, each piece with its own\n * palette) a change to `HOLIDAYS` and its assets alone, rather than a second code\n * path in the render layer.\n */\nexport type HolidayRule = BgRule\n\n/** The holiday override: one master switch plus one entry per built-in holiday. */\nexport interface HolidaysConfig {\n /**\n * While on, a holiday whose window contains today replaces the rule the model\n * resolved to. On unless it is explicitly turned off — the switch on the Config\n * page is an off-ramp, not an opt-in.\n */\n enabled: boolean\n /** One entry per `HOLIDAYS` definition, in that order. */\n items: HolidayRule[]\n}\n\n/** The persisted plugin configuration. */\nexport interface ThemeConfig { /** Ordered rules: matching runs top→bottom, rule 1 doubles as the fallback. */\n rules: BgRule[]\n /** Global per-part opacities (Interface page). */\n opacities: PartOpacities\n /** Global per-part blur (Interface page). */\n blurs: PartBlurs\n /**\n * Global wallpaper-switch transition (Config page): the effect and easing\n * every change uses, plus where its duration comes from.\n */\n transition: TransitionConfig\n /** Settings-panel opacity (0..1). */\n settingsOpacity: number\n /** Translucent tint over the conversation text region (0 = none, 1 = solid). */\n chatTextOpacity: number\n /** Translucent tint over the trajectory view surface (0 = none, 1 = solid). */\n trajectoryOpacity: number\n /**\n * Surface opacity of the file-preview panel (0..1). `null` = never touched, so\n * the panel keeps following `opacities.bg`: the panel's only surface IS\n * `--dsw-alias-bg-base`, which the main-background slider already re-emits, so\n * an untouched card must stay indistinguishable from the interface behind it.\n */\n rightbarOpacity: number | null\n /**\n * Extract a rule's theme color from its own image when the rule has none yet.\n * Only ever FILLS an empty color — a color the user picked or that an earlier\n * extraction produced is never overwritten, so this cannot fight the user.\n */\n autoExtract: boolean\n /** Built-in holiday overrides (中秋 / 国庆), switched off as a whole. */\n holidays: HolidaysConfig\n}\n\n/** 100% = untouched host surface; zero would blank the page by default. */\nexport const DEFAULT_SETTINGS_OPACITY = 1\nexport const DEFAULT_CHAT_TEXT_OPACITY = 0\n/** 100% = untouched host surface; zero would blank the page by default. */\nexport const DEFAULT_TRAJECTORY_OPACITY = 1\n/** `null` = the file-preview panel still follows the main background. */\nexport const DEFAULT_RIGHTBAR_OPACITY: number | null = null\n/** Picking an image should just work; the toggle is there for people who don't want it. */\nexport const DEFAULT_AUTO_EXTRACT = true\n/**\n * Holiday overrides are ON out of the box: the point is that the background\n * changes by itself on the day and changes back the next morning. The single\n * switch on the Config page is the off-ramp, so only an explicit `false` turns\n * the feature off.\n */\nexport const DEFAULT_HOLIDAYS_ENABLED = true\n\n/**\n * `#RRGGBB` → the `[h, s, l]` triple every rule stores (`s` and `l` in 0..1), or\n * null when the string is not a hex color.\n *\n * A holiday names its color as hex because that is how a color is quoted, and a\n * hand-converted triple is a magic number nothing downstream can check. The\n * conversion lives here rather than in ./holiday because `[h, s, l]` is this\n * module's own rule shape.\n */\nexport function hexToHsl(hex: string): [number, number, number] | null {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim())\n if (m === null) return null\n const n = parseInt(m[1]!, 16)\n const r = ((n >> 16) & 0xff) / 255\n const g = ((n >> 8) & 0xff) / 255\n const b = (n & 0xff) / 255\n const max = Math.max(r, g, b)\n const min = Math.min(r, g, b)\n const l = (max + min) / 2\n const d = max - min\n // Grey: no hue to name, and the saturation formula below would divide by zero.\n if (d === 0) return [0, 0, l]\n const s = d / (1 - Math.abs(2 * l - 1))\n let h: number\n if (max === r) h = 60 * (((g - b) / d) % 6)\n else if (max === g) h = 60 * ((b - r) / d + 2)\n else h = 60 * ((r - g) / d + 4)\n if (h < 0) h += 360\n // Clamped like every other color this module stores: the float arithmetic\n // above lands a hair outside the range on a saturated input (a pure #FFF6EB\n // gives s = 1.0000000000000008), and that would travel into the token\n // generator as an out-of-range channel.\n return [clamp(h, 0, 360, 0), clamp01(s, 0), clamp01(l, 0.5)]\n}\n\n/**\n * One holiday's appearance, untouched.\n *\n * Holidays default to `fill` rather than a rule's `fit`: these are full-bleed\n * festival wallpapers, and `fit` would letterbox them on every aspect ratio the\n * art was not cut for.\n */\nexport function defaultHolidayRule(def: HolidayDef): HolidayRule {\n // The definition's own color, never an extracted one — see hexToHsl. It is\n // written BOTH on the rule (what an image-less festival would paint) and on the\n // image (what actually paints today), because those are two different slots in\n // the shape now and a holiday that only filled one of them would look themed or\n // unthemed depending on which branch the render layer happened to read.\n const color = hexToHsl(def.color)\n return {\n id: def.id,\n // Exactly one image: a holiday's art is the package's, so there is nothing\n // for a second entry to point at and nothing for a rotation to walk.\n images: [{ slot: def.slot, bgState: { ...DEFAULT_BG_STATE }, color }],\n match: '',\n enabled: true,\n color,\n bgMode: 'fill',\n wallpaperOpacity: 1,\n blur: 0,\n rotate: defaultRotation(),\n }\n}\n\n/** Every built-in holiday at its default, in `HOLIDAYS` order. */\nexport function defaultHolidayRules(): HolidayRule[] {\n return HOLIDAYS.map(defaultHolidayRule)\n}\n\n/** A default config with independent nested objects (never hand out the shared ones). */\nexport function freshThemeConfig(): ThemeConfig {\n return {\n rules: [],\n opacities: { ...DEFAULT_PART_OPACITIES },\n blurs: { ...DEFAULT_PART_BLURS },\n transition: defaultTransition(),\n settingsOpacity: DEFAULT_SETTINGS_OPACITY,\n chatTextOpacity: DEFAULT_CHAT_TEXT_OPACITY,\n trajectoryOpacity: DEFAULT_TRAJECTORY_OPACITY,\n rightbarOpacity: DEFAULT_RIGHTBAR_OPACITY,\n autoExtract: DEFAULT_AUTO_EXTRACT,\n holidays: { enabled: DEFAULT_HOLIDAYS_ENABLED, items: defaultHolidayRules() },\n }\n}\n\n// ── Sanitizers ─────────────────────────────────────────────────────────────\n// Pure coercions from a possibly-old / possibly-hand-edited JSON value into the\n// shape above. Both halves run THESE, so a clamp can never differ between what\n// the UI shows and what lands on disk.\n\n/** Slot names reach the filesystem, so they are strictly whitelisted. */\nexport const SLOT_RE = /^[A-Za-z0-9_-]{1,32}$/\n\n/**\n * The persisted SHAPE this build writes: 5 = the global wallpaper-switch\n * transition (`transition`) is part of the config; 4 = a theme color belongs to\n * an IMAGE (`images[].color`), and a rule's own color is what an image-less rule\n * paints.\n *\n * Declared here, with the shape itself, and published by the node half on every\n * `read`. The browser half compares it before it writes anything: a client bundle\n * from a newer release can be served to a page whose host process is still\n * running an OLDER node half (update the package, then just refresh the page),\n * and that older sanitizer would silently drop every rule it does not understand.\n * Knowing the shape up front is what lets the client hold its writes and say so\n * instead.\n *\n * Both bumps so far were of that kind, not cosmetic. 2 → 3 was \"an empty image\n * list is legal\": a schema-2 host refuses one, so once this bundle could PRODUCE\n * an empty rule, every write was at risk of erasing the user's rule list — the\n * failure mode is data loss, and it arrived on the first slider drag after\n * emptying a rule. 3 → 4 is `images[].color`: the field is unknown to a schema-3\n * sanitizer, which REBUILDS each image entry from the keys it knows, so a color\n * the user set would survive in memory until the next reload and then be gone —\n * a silent, per-image loss that no warning would accompany. 4 → 5 is\n * `transition`, the same mechanism one level up: a schema-4 sanitizer rebuilds\n * the whole config from the keys it knows, so the effect, the easing and the\n * duration would all be dropped on the first write after a refresh paired a new\n * client bundle with an older host process — and 5 also carries the removal of\n * the per-rule `rotate.fadeMs`, whose value is lifted into that global duration\n * on read (see `legacyFadeMs`). The check is a plain `>=`, so an older host\n * lands in the hold-writes path automatically.\n */\nexport const SCHEMA_VERSION = 5\n\nexport function clamp(n: unknown, lo: number, hi: number, def: number): number {\n return typeof n === 'number' && isFinite(n) ? Math.min(hi, Math.max(lo, n)) : def\n}\n\nexport const clamp01 = (n: unknown, def: number): number => clamp(n, 0, 1, def)\n\nexport function normalizeBgState(s: Partial<BgState> | undefined): BgState {\n const v = s ?? {}\n return {\n zoom: clamp(v.zoom, 0.1, 10, 1),\n x: typeof v.x === 'number' && isFinite(v.x) ? v.x : 0,\n y: typeof v.y === 'number' && isFinite(v.y) ? v.y : 0,\n iw: typeof v.iw === 'number' && v.iw > 0 ? v.iw : 0,\n ih: typeof v.ih === 'number' && v.ih > 0 ? v.ih : 0,\n }\n}\n\n/** One `[h, s, l]` triple, or null when the value is not a complete finite triple. */\nexport function normalizeHsl(raw: unknown): [number, number, number] | null {\n if (!Array.isArray(raw) || raw.length !== 3) return null\n if (!raw.every(n => typeof n === 'number' && isFinite(n))) return null\n return [clamp(raw[0], 0, 360, 220), clamp(raw[1], 0, 1, 0.55), clamp(raw[2], 0, 1, 0.25)]\n}\n\n/** Coerce one persisted rotation block; a config without one gets the shipped default. */\nexport function normalizeRotation(raw: unknown): BgRotation {\n const r = (raw ?? {}) as Partial<BgRotation>\n const d = DEFAULT_ROTATION\n return {\n // Only an explicit `true` turns rotation on: it is the one setting here that\n // spends the user's bandwidth and CPU, so it never becomes on by accident.\n enabled: r.enabled === true,\n intervalMs: clamp(r.intervalMs, ROTATE_MIN_MS, ROTATE_MAX_MS, d.intervalMs),\n order: ROTATE_ORDERS.includes(r.order as RotateOrder) ? (r.order as RotateOrder) : d.order,\n advanceOnSwitch: r.advanceOnSwitch === true,\n }\n}\n\n/** Own-property test for values that may be anything at all (a raw JSON entry). */\nfunction hasOwn(o: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(o, key)\n}\n\n/**\n * The duration a config written before the switch effect carries on any of its\n * rules, or `undefined` when it carries none worth adopting.\n *\n * `rotate.fadeMs` was the per-rule duration from 0.7.0 on, and it had NO control\n * anywhere — it could only be hand-edited, which is why the global setting\n * replaced it. This is the one-shot lift that keeps such a hand-tuned value from\n * being silently dropped on upgrade: the first rule whose value differs from the\n * 320 ms every build shipped is adopted as the global duration. Values that are\n * all the default are ignored, so an ordinary config keeps the ordinary default,\n * and rules that DISAGREE cannot be represented by one global number — the first\n * deliberate value wins, and the others are gone with the field they lived on.\n */\nexport function legacyFadeMs(rawRules: unknown): number | undefined {\n if (!Array.isArray(rawRules)) return undefined\n for (const entry of rawRules) {\n const rotate = (entry as { rotate?: unknown } | null | undefined)?.rotate\n if (rotate === null || typeof rotate !== 'object') continue\n const value = (rotate as { fadeMs?: unknown }).fadeMs\n if (typeof value !== 'number' || !isFinite(value)) continue\n if (value === DEFAULT_TRANSITION.durationMs) continue\n return clamp(value, 0, TRANSITION_MAX_MS, DEFAULT_TRANSITION.durationMs)\n }\n return undefined\n}\n\n/**\n * Coerce one persisted transition block; a config written before this setting\n * existed has no `transition` key at all and gets the shipped default, which is\n * the behaviour it already had.\n *\n * `legacyMs` is the per-rule `fadeMs` this shape replaced (see `legacyFadeMs`),\n * adopted only when the incoming config has no `durationMs` of its own — so a\n * deliberate hand-tuned blend survives the upgrade instead of being dropped with\n * the field it used to live on.\n *\n * `durationMs` is clamped with `0` kept as a real value (a hard cut) rather than\n * read as \"absent\": 0 is exactly how a hard cut is asked for without changing\n * the effect.\n */\nexport function normalizeTransition(raw: unknown, legacyMs?: number): TransitionConfig {\n const t = (raw ?? {}) as Partial<TransitionConfig>\n const d = DEFAULT_TRANSITION\n const fallback = typeof legacyMs === 'number' && isFinite(legacyMs) ? legacyMs : d.durationMs\n return {\n effect: TRANSITION_EFFECTS.includes(t.effect as TransitionEffect) ? (t.effect as TransitionEffect) : d.effect,\n easing: TRANSITION_EASINGS.includes(t.easing as TransitionEasing) ? (t.easing as TransitionEasing) : d.easing,\n durationMs: clamp(t.durationMs, 0, TRANSITION_MAX_MS, fallback),\n }\n}\n\n/**\n * Coerce one persisted image entry, or null when it lacks a usable slot.\n *\n * `inherit` is the RULE's own color, and it is applied only to an entry that has\n * no `color` key at all — the shape every release before 0.7.1 wrote, where a\n * rule's color was the only color there was. Lifting it here, once, is what makes\n * an upgrade a no-op on screen: a themed wallpaper keeps its theme instead of\n * silently dropping to the system palette, and it happens in the shared sanitizer\n * so both halves lift identically.\n *\n * The KEY's presence is the whole distinction, which is why `null` is not the\n * same as absent: an entry with `color: null` is an image the user explicitly set\n * to \"follow the system theme\", and re-inheriting the rule's color over that\n * would undo a deliberate choice on every load.\n */\nexport function normalizeImage(raw: unknown, inherit: [number, number, number] | null = null): BgImage | null {\n const i = (raw ?? {}) as Partial<BgImage>\n if (typeof i.slot !== 'string' || !SLOT_RE.test(i.slot)) return null\n return {\n slot: i.slot,\n bgState: normalizeBgState(i.bgState as Partial<BgState> | undefined),\n color: hasOwn(i, 'color') ? normalizeHsl(i.color) : inherit,\n }\n}\n\n/**\n * Coerce one persisted rule, or null when it names no image AT ALL.\n *\n * Accepts BOTH image shapes: the 0.7 list (`images`), and the single\n * `slot`/`bgState` pair every earlier version wrote — the latter is lifted to a\n * one-entry list here rather than at a dozen call sites, which is what keeps the\n * rest of the codebase free of \"old config\" branches. Duplicate slots inside one\n * rule are dropped: two entries pointing at the same bytes would only make the\n * rotation look stuck.\n *\n * The rule's color is resolved FIRST and handed to every image entry, because it\n * is what an entry written before 0.7.1 inherits (`normalizeImage`). The rule keeps\n * it as well: it is not a default for its images at paint time any more, but it\n * is still what the rule paints once its last picture is gone.\n *\n * An EMPTY list is a legitimate rule, not a broken one: removing a rule's last\n * picture has to be expressible, and forcing an entry back in is what produced a\n * phantom blank image that took slot 1 and could never be deleted again (the next\n * upload landed at position 2 and the rule kept painting nothing). What such a\n * rule then does is `ruleCanPaint`'s business: with a color of its own it paints\n * the interface, with neither it is skipped by matching — which the card's own\n * hint says in so many words. Only a rule that names no image anywhere — no list,\n * no legacy slot, or a slot that could never be a filename — is dropped.\n */\nexport function normalizeRule(raw: unknown): BgRule | null {\n const r = (raw ?? {}) as Partial<BgRule> & { slot?: unknown; bgState?: unknown }\n const id = typeof r.id === 'string' && r.id !== '' ? r.id : null\n if (id === null) return null\n const color = normalizeHsl(r.color)\n const images: BgImage[] = []\n const seen = new Set<string>()\n const hadList = Array.isArray(r.images)\n if (hadList) {\n for (const entry of r.images as unknown[]) {\n const image = normalizeImage(entry, color)\n if (image === null || seen.has(image.slot)) continue\n seen.add(image.slot)\n images.push(image)\n }\n }\n const legacySlot = typeof r.slot === 'string' && SLOT_RE.test(r.slot) ? r.slot : null\n if (images.length === 0 && legacySlot !== null) {\n // Synthesized, not read: the pre-0.7 pair has no image entry of its own, so\n // the rule's color is what this image starts out with (the same lift as\n // above, for the shape that has no `color` key to be absent from).\n images.push({ slot: legacySlot, bgState: normalizeBgState(r.bgState as Partial<BgState> | undefined), color })\n }\n // Nothing usable anywhere: a pre-0.7 rule whose slot was empty or malformed.\n if (images.length === 0 && !hadList) return null\n const mode: BgMode = BG_MODES.includes(r.bgMode as BgMode) ? (r.bgMode as BgMode) : 'fit'\n return {\n id,\n images,\n match: typeof r.match === 'string' ? r.match : '',\n enabled: r.enabled !== false,\n color,\n bgMode: mode,\n wallpaperOpacity: clamp01(r.wallpaperOpacity, 1),\n blur: clamp(r.blur, 0, 60, 0),\n rotate: normalizeRotation(r.rotate),\n }\n}\n\n/**\n * Coerce one persisted holiday entry.\n *\n * `id`, `images` and every theme color (the rule's and each image's) come from\n * the DEFINITION, never from disk: a holiday's slot is the only thing tying it to\n * its bytes, and its theme color is a fixed part of what that holiday looks like —\n * so a stale or hand-edited value would either orphan the wallpaper, point the\n * holiday at a rule's image, or paint a festival in a color it does not have.\n * Everything else is sanitized exactly like a rule's field — except the image\n * list and the rotation, which stay the definition's own single image and stay\n * off, so a festival can never be swapped or cycled.\n */\nexport function normalizeHolidayRule(def: HolidayDef, raw: unknown): HolidayRule {\n const r = (raw ?? {}) as Partial<HolidayRule> & { bgState?: unknown }\n const base = defaultHolidayRule(def)\n return {\n ...base,\n // Only an explicit `false` disables the entry, so a config written before\n // this feature existed starts with every holiday usable.\n enabled: r.enabled !== false,\n bgMode: BG_MODES.includes(r.bgMode as BgMode) ? (r.bgMode as BgMode) : base.bgMode,\n wallpaperOpacity: clamp01(r.wallpaperOpacity, base.wallpaperOpacity),\n blur: clamp(r.blur, 0, 60, base.blur),\n // A holiday's own framing is still the user's: which part of the festival art\n // fills the screen is a taste question, and the editor allows it. Its COLOR is\n // not — it comes from `base` (the definition), like the slot beside it, so the\n // `hasOwn` lift in normalizeImage can never reach a holiday and a hand-edited\n // per-image color cannot repaint a festival.\n images: base.images.map(image => ({\n slot: image.slot,\n bgState: normalizeBgState((r.images?.[0]?.bgState ?? r.bgState) as Partial<BgState> | undefined),\n color: image.color,\n })),\n }\n}\n\n/** Coerce the whole holiday block; unknown ids are dropped, missing ones defaulted. */\nexport function normalizeHolidays(raw: unknown): HolidaysConfig {\n const r = (raw ?? {}) as Partial<HolidaysConfig>\n const stored = new Map<string, unknown>()\n if (Array.isArray(r.items)) {\n for (const item of r.items) {\n const id = (item as { id?: unknown } | null | undefined)?.id\n if (typeof id === 'string') stored.set(id, item)\n }\n }\n return {\n // Only an explicit `false` turns the feature off — the same \"absent means\n // on\" rule the per-item switch uses, so a config predating the feature (or\n // one whose hidden panel was never opened) keeps working.\n enabled: r.enabled !== false,\n items: HOLIDAYS.map(def => normalizeHolidayRule(def, stored.get(def.id))),\n }\n}\n\n/** Coerce an unknown persisted value into a valid ThemeConfig, falling back per-field. */\nexport function normalizeConfig(raw: unknown): ThemeConfig {\n const r = (raw ?? {}) as Partial<ThemeConfig>\n const rules = Array.isArray(r.rules)\n ? r.rules.map(normalizeRule).filter((x): x is BgRule => x !== null)\n : []\n const ops = (r.opacities ?? {}) as Partial<PartOpacities>\n const bl = (r.blurs ?? {}) as Partial<PartBlurs>\n const blurs = {} as PartBlurs\n for (const k of PART_BLUR_KEYS) {\n blurs[k] = clamp(bl[k], 0, 60, DEFAULT_PART_BLURS[k])\n }\n const opacities = {} as PartOpacities\n for (const k of PART_OPACITY_KEYS) {\n opacities[k] = clamp01(ops[k], DEFAULT_PART_OPACITIES[k])\n }\n return {\n rules,\n opacities,\n blurs,\n transition: normalizeTransition(r.transition, legacyFadeMs(r.rules)),\n settingsOpacity: clamp01(r.settingsOpacity, DEFAULT_SETTINGS_OPACITY),\n chatTextOpacity: clamp01(r.chatTextOpacity, DEFAULT_CHAT_TEXT_OPACITY),\n trajectoryOpacity: clamp01(r.trajectoryOpacity, DEFAULT_TRAJECTORY_OPACITY),\n // Anything but a real number means \"not owned yet\" — including the absent\n // field of a config written before this option existed.\n rightbarOpacity: typeof r.rightbarOpacity === 'number' && isFinite(r.rightbarOpacity)\n ? clamp01(r.rightbarOpacity, 1)\n : DEFAULT_RIGHTBAR_OPACITY,\n // Only an explicit `false` turns it off, so a config written before this\n // option existed starts with the helpful default.\n autoExtract: r.autoExtract !== false,\n holidays: normalizeHolidays(r.holidays),\n }\n}\n","import type { BgImage, BgRule, BgState, BgMode, HolidayRule, ThemeConfig, PartOpacities, PartBlurs, TransitionConfig } from './types'\n// The switch's decision (which effect, how long, whether it runs at all) is pure\n// and lives in ./transition — it is checked without a browser by\n// `scripts/transition-check.ts`, so the render layer only has to apply it.\nimport { resolveFadeMs } from './transition'\n// The persisted shape, its key lists, its defaults and its sanitizers all live in\n// ../schema, shared verbatim with the node half — a field declared on one side\n// only used to be silently dropped by the other side's sanitizer.\nimport {\n DEFAULT_BG_STATE, DEFAULT_CHAT_TEXT_OPACITY, DEFAULT_PART_BLURS, DEFAULT_PART_OPACITIES,\n DEFAULT_SETTINGS_OPACITY, DEFAULT_TRAJECTORY_OPACITY, DEFAULT_TRANSITION, PART_BLUR_KEYS, PART_OPACITY_KEYS,\n clamp, clamp01, defaultRotation, freshThemeConfig, normalizeConfig, normalizeRotation, normalizeRule,\n ruleSlots,\n} from '../schema'\n\nexport { DEFAULT_BG_STATE, normalizeRule, ruleSlots }\n\nconst PALETTE: Array<[number, number, number]> = [\n [356, 0.72, 0.55], [24, 0.78, 0.55], [44, 0.8, 0.55], [152, 0.62, 0.5],\n [174, 0.68, 0.48], [208, 0.72, 0.55], [252, 0.68, 0.6], [300, 0.64, 0.58],\n]\nexport { PALETTE }\n\n/** The defaults every accessor falls back to; the shape itself lives in ../schema. */\nexport const DEFAULT_CONFIG: ThemeConfig = freshThemeConfig()\n\n// In-memory mirror of the file-backed store; the UI reads and mutates this and\n// it is synced to disk via the RPC layer.\nexport let cfg: ThemeConfig = freshThemeConfig()\n\n// ── Image cache (slot → data URL) ──────────────────────────────────────────\n// Rule images are fetched lazily per slot; only the active rule's bytes are\n// needed to paint, the rest are loaded when their card is expanded.\n//\n// Two URLs are kept per slot: the DATA URL is what gets persisted and embedded\n// in an export, while the DISPLAY URL is an object URL derived from it. Painting\n// goes through the display URL because `background-image: url(data:…)` is\n// re-decoded on every assignment — a visible stall on every model switch for a\n// multi-megabyte wallpaper — whereas a blob URL is served from the browser's\n// memory cache after the first load.\nconst images = new Map<string, string>()\nconst displayUrls = new Map<string, string>()\n\nfunction revokeDisplay(slot: string): void {\n const url = displayUrls.get(slot)\n if (url === undefined) return\n displayUrls.delete(slot)\n // Deferred on purpose: the wallpaper layer may still be painting this URL\n // while the replacement fades in over it, and revoking it mid-fade would blank\n // the wallpaper behind the incoming image for a frame.\n window.setTimeout(() => {\n try { URL.revokeObjectURL(url) } catch { /* not a live object URL (e.g. fallback) */ }\n }, 2000)\n}\n\nexport function setImage(slot: string, url: string | null): void {\n revokeDisplay(slot)\n if (url === null) images.delete(slot)\n else images.set(slot, url)\n}\n/** Persisted data URL (RPC / export). Use `displayImageOf` to paint it. */\nexport function imageOf(slot: string): string | null { return images.get(slot) ?? null }\n\n/** Paintable URL for one slot, created on first use and cached; falls back to\n * the data URL when no object URL can be built. */\nexport function displayImageOf(slot: string): string | null {\n const cached = displayUrls.get(slot)\n if (cached !== undefined) return cached\n const data = images.get(slot)\n if (data === undefined) return null\n const made = toObjectUrl(data)\n if (made === null) return data\n displayUrls.set(slot, made)\n return made\n}\n\nfunction toObjectUrl(dataUrl: string): string | null {\n try {\n if (typeof URL === 'undefined' || typeof URL.createObjectURL !== 'function') return null\n const comma = dataUrl.indexOf(',')\n if (comma < 0) return null\n const meta = dataUrl.slice(0, comma)\n if (!/;base64$/i.test(meta)) return null\n const mime = meta.slice(5, -7) || 'image/jpeg'\n const bin = atob(dataUrl.slice(comma + 1))\n const bytes = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i)\n return URL.createObjectURL(new Blob([bytes], { type: mime }))\n } catch {\n return null\n }\n}\n\nexport function clearImages(): void {\n for (const slot of Array.from(displayUrls.keys())) revokeDisplay(slot)\n images.clear()\n}\n\n// ── Active rule (what the render layer follows) ────────────────────────────\nexport let activeRuleId: string | null = null\nexport let activeMatched = false\nexport let modelLabel = ''\n\n/**\n * Which image of the ACTIVE rule is painted right now.\n *\n * Deliberately NOT persisted: a background that comes back on image 3 of 7 after\n * a reload, with no way to say why, is worse than one that starts at the first\n * image every time. Clamped to the rule's own length on every read, so an index\n * left over from a longer list can never point at nothing.\n */\nlet rotIndex = 0\n\nexport function setActive(ruleId: string | null, matched: boolean): void {\n // Every switch starts at the rule's FIRST image. Without this, a model switch\n // from a 7-image rule to a 2-image one would land on whatever index survived.\n if (ruleId !== activeRuleId) rotIndex = 0\n activeRuleId = ruleId\n activeMatched = matched\n}\nexport function setModelLabel(label: string): void { modelLabel = label }\n\n/** The image index the render layer is on, clamped into `rule`'s own range. */\nexport function imageIndexOf(rule: BgRule): number {\n if (rule.images.length === 0) return 0\n const i = Math.floor(rotIndex)\n return i >= 0 && i < rule.images.length ? i : 0\n}\n\n/** Point the active rule at another of its images (the rotation's one mutator). */\nexport function setRotIndex(i: number): void { rotIndex = Math.floor(i) }\n\n/** The image the active rule is painting now, or null when it has none. */\nexport function activeImage(): BgImage | null {\n const rule = activeRule()\n if (rule === null) return null\n return rule.images[imageIndexOf(rule)] ?? null\n}\n\n/** Slot of the active rule's current image; '' when there is nothing to paint. */\nexport function activeSlot(): string { return activeImage()?.slot ?? '' }\n\n/**\n * The theme color in force right now, or null for \"follow the system theme\".\n *\n * Two rungs, in this order and no others:\n * 1. the color of the IMAGE that is on screen, when the rule has one;\n * 2. the rule's own color, which is all an image-less rule has to paint with.\n *\n * There is deliberately no third rung where an image INHERITS its rule's color:\n * a rule's color is not a default for its pictures (see `BgRule.color`). If it\n * were, a rotation through a green picture, a red one and a system-themed one\n * could not be expressed at all — clearing a picture's color would only hand it\n * back to the rule's, and the clear button would look broken. Images that predate\n * per-image colors get the rule's color LIFTED onto them at read time instead\n * (`normalizeImage`), so nothing loses its theme on upgrade.\n *\n * The image is the one being PAINTED (`imageIndexOf`), not the one the panel has\n * selected — the panel's selection is an editing cursor and must not repaint the\n * interface while the user is fixing another picture's framing.\n */\nexport function activeColor(): [number, number, number] | null {\n const rule = activeRule()\n if (rule === null) return null\n if (rule.images.length === 0) return rule.color\n return activeImage()?.color ?? null\n}\n\n/**\n * One rule by id — from the USER's list first, then from the holiday overrides.\n *\n * Every render accessor (`rWp` / `rColor` / `rBgMode` / `rBgState` …) resolves\n * through here, so teaching this one function about holidays is what makes an\n * active holiday paint through the entire existing pipeline instead of needing a\n * parallel one.\n */\nexport function ruleById(id: string): BgRule | null {\n return cfg.rules.find(r => r.id === id)\n ?? cfg.holidays.items.find(r => r.id === id)\n ?? null\n}\nexport function activeRule(): BgRule | null {\n return activeRuleId === null ? null : ruleById(activeRuleId)\n}\n\n/** One holiday override entry, or null for an unknown id. */\nexport function holidayById(id: string): HolidayRule | null {\n return cfg.holidays.items.find(r => r.id === id) ?? null\n}\n\n// ── Rule factories / allocation ────────────────────────────────────────────\n/**\n * A fresh rule, holding NO image yet.\n *\n * It used to be born with an allocated slot and an empty entry, which is what put\n * a blank tile at position 1 of a new rule's strip — and, worse, stopped the\n * picture the user added next from being the first one (a rule paints its first\n * image). A rule with no pictures is a valid state: `ruleCanPaint` (./schema) skips\n * it — it has no image and no color yet — until either arrives, and the slot is\n * allocated when the first picture does.\n */\nexport function newRule(id: string): BgRule {\n return {\n id,\n images: [],\n match: '', enabled: true, color: null,\n bgMode: 'fit', wallpaperOpacity: 1, blur: 0,\n rotate: defaultRotation(),\n }\n}\n\n/** Every slot any rule owns — the user's rules and the holiday entries alike. */\nexport function takenSlots(): Set<string> {\n const taken = new Set<string>()\n for (const rule of cfg.rules) for (const slot of ruleSlots(rule)) taken.add(slot)\n for (const rule of cfg.holidays.items) for (const slot of ruleSlots(rule)) taken.add(slot)\n return taken\n}\n\n/**\n * First free image slot (`m1`, `m2`, …).\n *\n * Scans EVERY slot in the config, not just the primary one of each rule: with\n * several images per rule, \"the slots this file already uses\" is the only set\n * that can be safely handed out, and a collision here would silently point two\n * cards at the same bytes (and let one card's delete orphan the other).\n */\nexport function nextSlot(): string {\n const taken = takenSlots()\n for (let i = 1; i < 1000; i++) {\n const slot = `m${i}`\n if (!taken.has(slot)) return slot\n }\n return `m${Date.now()}`\n}\n\n/** Unique rule id (independent from the slot so removals never renumber). */\nexport function nextRuleId(): string {\n const taken = new Set(cfg.rules.map(r => r.id))\n for (let i = 1; i < 10000; i++) {\n const id = `r${i}`\n if (!taken.has(id)) return id\n }\n return `r${Date.now()}`\n}\n\n/** Patch one rule's rotation block, through the shared sanitizer so a live edit\n * can never hold a value the next load would clamp differently. */\nexport function patchRotation(rule: BgRule, patch: Partial<BgRule['rotate']>): void {\n rule.rotate = normalizeRotation({ ...rule.rotate, ...patch })\n}\n\n/** Re-sanitize one rule in place, so what the UI holds equals what would persist. */\nexport function normalizeRuleInPlace(rule: BgRule): void {\n const normalized = normalizeRule(rule)\n if (normalized !== null) Object.assign(rule, normalized)\n}\n\n// ── Accessors used by the render layer (they follow the ACTIVE rule) ───────\nexport function rHasColor(): boolean { return activeColor() !== null }\nexport function rColor(): [number, number, number] { return activeColor() ?? [220, 0.55, 0.25] }\nexport function rBgMode(): BgMode { return activeRule()?.bgMode ?? 'fit' }\nexport function rWop(): number { return clamp01(activeRule()?.wallpaperOpacity, 1) }\nexport function rBl(): number { return clamp(activeRule()?.blur, 0, 60, 0) }\n/** Framing of the CURRENT image (per image, see BgImage). */\nexport function rBgState(): BgState { return activeImage()?.bgState ?? DEFAULT_BG_STATE }\n/** Rotation of the active rule; the shipped default when nothing is active. */\nexport function rRotation(): BgRule['rotate'] { return activeRule()?.rotate ?? defaultRotation() }\n/**\n * The GLOBAL wallpaper-switch transition (effect, easing, duration).\n *\n * Read from the config on every apply rather than cached: the Config page edits\n * it while a wallpaper is on screen, and the next switch has to use what the\n * user just chose.\n */\nexport function rTransition(): TransitionConfig { return cfg.transition ?? DEFAULT_TRANSITION }\n/**\n * Duration the next switch runs for, in ms (`0` = a hard cut).\n *\n * The two rungs are `resolveFadeMs`'s business (./transition): the effect can\n * veto the animation outright, and otherwise the global duration decides. It is\n * deliberately NOT a per-rule value — a rule has no notion of a transition, and\n * the per-rule field this replaced had no control anywhere to set it with.\n */\nexport function rFadeMs(): number { return resolveFadeMs(rTransition()) }\n/** Paintable URL of the active rule's CURRENT image, or null when it has none. */\nexport function rWp(): string | null {\n const slot = activeSlot()\n return slot === '' ? null : displayImageOf(slot)\n}\nexport function rOps(): PartOpacities {\n const o = cfg.opacities ?? {}\n const out = {} as PartOpacities\n for (const k of PART_OPACITY_KEYS) {\n out[k] = clamp01(o[k], DEFAULT_PART_OPACITIES[k])\n }\n return out\n}\nexport function rBlurs(): PartBlurs {\n const b = cfg.blurs ?? {}\n const out = {} as PartBlurs\n for (const k of PART_BLUR_KEYS) {\n out[k] = clamp(b[k], 0, 60, DEFAULT_PART_BLURS[k])\n }\n return out\n}\nexport function rSop(): number { return clamp01(cfg.settingsOpacity, DEFAULT_SETTINGS_OPACITY) }\nexport function rChatTextOpacity(): number { return clamp01(cfg.chatTextOpacity, DEFAULT_CHAT_TEXT_OPACITY) }\nexport function rTrajectoryOpacity(): number { return clamp01(cfg.trajectoryOpacity, DEFAULT_TRAJECTORY_OPACITY) }\n/** Own opacity of the file-preview panel; while unowned it IS the main background's. */\nexport function rRightbarOpacity(): number {\n const own = cfg.rightbarOpacity\n return typeof own === 'number' && isFinite(own) ? clamp01(own, 1) : rOps().bg\n}\n\n// ── Normalization ──────────────────────────────────────────────────────────\n// The sanitizers are the shared ones from ../schema (the same code the node half\n// runs before writing to disk), so what the UI shows and what is persisted can\n// never be clamped differently.\n\n/** Move a possibly-absent partial config into the shape the UI reads. */\nexport function adoptConfig(raw: unknown): void {\n cfg = normalizeConfig(raw)\n // A rule that vanished (import/removal) must not stay active — and a holiday\n // that is still in `cfg.holidays.items` legitimately stays active, which is\n // why this asks `ruleById` instead of scanning `cfg.rules` directly.\n if (activeRuleId !== null && ruleById(activeRuleId) === null) {\n activeRuleId = null\n activeMatched = false\n }\n // The list this index belonged to is gone (an import can replace it wholesale),\n // so the first image is the only index that is certainly valid.\n rotIndex = 0\n}\n\nexport function resetConfig(): void {\n cfg = freshThemeConfig()\n clearImages()\n activeRuleId = null\n activeMatched = false\n modelLabel = ''\n rotIndex = 0\n}\n","/**\n * Multi-image rotation: which image comes next, and how often.\n *\n * Pure and dependency-free on purpose — the timer that calls this lives in the\n * plugin's apply closure (where nothing can reach it), but the DECISION lives\n * here so `scripts/rotation-check.ts` can pin it down: a picker that walks off\n * the end of the list, or that \"shuffles\" onto the image it is already showing,\n * looks exactly like a rotation that has stopped, and neither shows up as an\n * error anywhere.\n */\nimport type { RotateOrder } from './types'\n\n/** Dwell-time presets the settings UI offers, in ms. */\nexport const ROTATE_PRESETS: ReadonlyArray<{ ms: number; key: string }> = [\n { ms: 10_000, key: 'rotEvery10s' },\n { ms: 30_000, key: 'rotEvery30s' },\n { ms: 60_000, key: 'rotEvery1m' },\n { ms: 5 * 60_000, key: 'rotEvery5m' },\n { ms: 30 * 60_000, key: 'rotEvery30m' },\n { ms: 60 * 60_000, key: 'rotEvery1h' },\n]\n\n/**\n * The index to paint after the current one, or null when there is nowhere to go\n * (fewer than two images — the caller must not start a timer at all then).\n *\n * `order` walks the list and wraps; `shuffle` picks uniformly among every index\n * EXCEPT the current one, because landing on the same image reads as a missed\n * tick. `current` outside the list is treated as 0 rather than trusted: it comes\n * from the UI as often as from the timer, and a stale index must not be able to\n * index past the end.\n *\n * `rand` is injectable so the shuffle branch is testable without stubbing a\n * global.\n */\nexport function nextIndex(\n len: number,\n order: RotateOrder,\n current: number,\n rand: () => number = Math.random,\n): number | null {\n if (!Number.isFinite(len) || len < 2) return null\n const count = Math.floor(len)\n const cur = Number.isFinite(current) && current >= 0 && current < count ? Math.floor(current) : 0\n if (order === 'shuffle') {\n // Uniform over the count-1 candidates, skipping `cur`. `rand() === 1` (which\n // a caller-supplied generator may return) would otherwise land on `count`.\n const roll = Math.min(Math.floor(Math.max(rand(), 0) * (count - 1)), count - 2)\n return roll >= cur ? roll + 1 : roll\n }\n return (cur + 1) % count\n}\n\n/**\n * Whether a rotation is worth running: two images, the switch on, and a positive\n * dwell time. Kept here (rather than at the call site) so the UI's \"rotating\"\n * badge and the timer agree by construction — a badge that says \"rotating\" while\n * no timer exists is the one failure this feature can produce silently.\n */\nexport function isRotating(len: number, enabled: boolean, intervalMs: number): boolean {\n return enabled && len >= 2 && Number.isFinite(intervalMs) && intervalMs > 0\n}\n","/**\n * The repaint decision, as a pure function.\n *\n * Every edit to a rule ends with the same question: does the interface have to be\n * repainted, or is refreshing the panel's readout enough? Repainting is the\n * expensive half (the theme skin is re-registered, the wallpaper layer is\n * rewritten, the host's theme is switched), so it must not be done for a rule\n * that is not the one on screen — but it MUST be done the moment the edit\n * changes what should be on screen.\n *\n * The naive test — \"is the edited rule the active one?\" — is wrong in exactly the\n * case that kept being reported as \"更新的不太及时,只有我动调色盘或者切模型的时候\n * 才出现\": an edit that CREATES the winner. Uploading a rule's first picture, or\n * an auto-extracted color landing on a rule that had none, makes that rule\n * paintable *through that very edit* (see `ruleCanPaint`), so the rule is not the\n * active one at the moment of the check; the wallpaper and the skin then only\n * showed up later, when an unrelated drag or model switch happened to re-run the\n * resolution.\n *\n * Sampling the winner on BOTH sides of the edit is what makes such a change land\n * at once, and `editedId === winnerAfter` additionally covers the edit that does\n * not move the resolution but changes the look of the rule that IS painting (a\n * color, a slider, a framing).\n *\n * `null` is \"nothing of ours is painting\" (the interface falls back to the host's\n * own look), which is a winner like any other id.\n *\n * Kept free of imports on purpose: `scripts/repaint-check.ts` exercises it on\n * plain node, the same way `rotation.ts` is exercised. A rule's `color`/`match`\n * are the inputs that make the resolution move, which is why they are the fields\n * whose write paths all end here.\n */\nexport function shouldRepaint(\n editedId: string,\n winnerBefore: string | null,\n winnerAfter: string | null\n): boolean {\n return winnerAfter === editedId || winnerAfter !== winnerBefore\n}\n","import type { FetchResult, RpcResultLike } from './types'\nimport { cfg } from './state'\n// The shape this bundle writes, and the one the host announces on `read`.\nimport { SCHEMA_VERSION } from '../schema'\n\nexport const RPC_CHANNEL = '/dsh-background-by-model'\nconst RPC_NS = 'dshBackgroundByModel'\nconst rpcEndpoint = (method: string): string => `${RPC_NS}/${method}`\n\n/**\n * What the host process said about the config shape it writes.\n *\n * `unknown` — the RPC never answered (offline/broken): writes are allowed, and\n * the ordinary failure paths deal with it.\n * `legacy` — it answered WITHOUT a schema, i.e. it is running a node half from\n * before multi-image. Its sanitizer drops any rule whose image list\n * it does not understand, so writing our config would erase the\n * user's rule list; every config write is held instead.\n * `current` — same shape as this bundle.\n */\nexport type HostShape = 'unknown' | 'legacy' | 'current'\n\nlet hostShape: HostShape = 'unknown'\nlet warnedLegacy = false\n\n/** Whether this bundle may write its config to the host it is talking to. */\nexport function canWriteConfig(): boolean { return hostShape !== 'legacy' }\n\n/** Whether the running host process is older than this client bundle. */\nexport function hostIsLegacy(): boolean { return hostShape === 'legacy' }\n\nfunction holdWrite(): void {\n if (warnedLegacy) return\n warnedLegacy = true\n console.warn(\n 'dsh-background-by-model: the running host is an older build that cannot read the multi-image ' +\n 'config shape — holding config writes so its sanitizer cannot drop this profile\\'s rules. ' +\n 'Restart DSH to load the new node half.',\n )\n}\n\nlet rpcCallFn: ((endpoint: string, payload: unknown) => Promise<RpcResultLike | undefined>) | null = null\n\nexport function initRpc(call: (endpoint: string, payload: unknown) => Promise<RpcResultLike | undefined>): void {\n rpcCallFn = call\n}\n\nasync function rpcCall(method: string, payload: unknown): Promise<unknown> {\n if (!rpcCallFn) return undefined\n try {\n const res = await rpcCallFn(rpcEndpoint(method), payload)\n if (res && res.ok === true) return res.value\n console.warn(`dsh-background-by-model: rpc \"${method}\" failed`, res?.error)\n return undefined\n } catch (e) {\n console.warn(`dsh-background-by-model: rpc \"${method}\" threw`, e)\n return undefined\n }\n}\n\n/** Raw call for the few places that need the host's error message. */\nasync function rpcRaw(method: string, payload: unknown): Promise<RpcResultLike | undefined> {\n if (!rpcCallFn) return undefined\n try {\n return await rpcCallFn(rpcEndpoint(method), payload)\n } catch {\n return undefined\n }\n}\n\n// Slider drags fire dozens of events per second; coalesce writes to a trailing\n// debounce and flush the last pending write on pagehide so a quick close never\n// loses it.\nconst SAVE_DEBOUNCE_MS = 250\nlet saveTimer: number | undefined\n\nexport function saveConfig(): void {\n if (!canWriteConfig()) { holdWrite(); return }\n if (saveTimer !== undefined) window.clearTimeout(saveTimer)\n saveTimer = window.setTimeout(() => {\n saveTimer = undefined\n void rpcCall('writeConfig', { config: cfg })\n }, SAVE_DEBOUNCE_MS)\n}\n\nexport function flushSave(): void {\n if (saveTimer === undefined) return\n window.clearTimeout(saveTimer)\n saveTimer = undefined\n // Deliberately checked AFTER the timer is dropped: a held write must not stay\n // queued and fire on the next flush either.\n if (!canWriteConfig()) { holdWrite(); return }\n void rpcCall('writeConfig', { config: cfg })\n}\n\n/** Persist the current config immediately (no debounce). */\nexport function persistConfig(): void {\n if (!canWriteConfig()) { holdWrite(); return }\n void rpcCall('writeConfig', { config: cfg })\n}\n\nexport interface Persisted {\n config: unknown\n /**\n * Every image slot the store holds. Reported for diagnostics and asserted by\n * `scripts/node-half-check.mjs`; the plugin no longer HYDRATES from it — boot\n * reads the slots the config actually references, because a slot nothing points\n * at has no card to appear on and pulling its bytes costs a full-size transfer.\n */\n slots: string[]\n /** The config shape the host writes; null when it predates this field. */\n schema: number | null\n}\n\n/** Load the persisted config plus the list of stored image slots. */\nexport async function loadPersisted(): Promise<Persisted | null> {\n const data = await rpcCall('read', {})\n if (data === null || typeof data !== 'object') return null\n const d = data as { config?: unknown; slots?: unknown; schema?: unknown }\n const slots = Array.isArray(d.slots) ? d.slots.filter((s): s is string => typeof s === 'string') : []\n const schema = typeof d.schema === 'number' && isFinite(d.schema) ? d.schema : null\n // The one place the answer arrives, so the one place it is recorded: a host that\n // answered without a schema is a pre-0.7 node half (see HostShape).\n hostShape = schema === null ? 'legacy' : (schema >= SCHEMA_VERSION ? 'current' : 'legacy')\n if (hostShape === 'legacy') holdWrite()\n return { config: d.config, slots, schema }\n}\n\n/** Read one rule image as a data URL (null when the slot is empty). */\nexport async function readImage(slot: string): Promise<string | null> {\n const data = await rpcCall('readImage', { slot })\n if (data === null || typeof data !== 'object') return null\n const url = (data as { dataUrl?: unknown }).dataUrl\n return typeof url === 'string' ? url : null\n}\n\n/** Persist (or clear) one rule image; one-shot, no debounce. */\nexport async function writeImage(slot: string, dataUrl: string | null): Promise<boolean> {\n const res = await rpcCall('writeImage', { slot, dataUrl })\n return res === true\n}\n\n/** Remove one rule image from disk. */\nexport async function deleteImage(slot: string): Promise<boolean> {\n const res = await rpcCall('deleteImage', { slot })\n return res === true\n}\n\n/** Download an image from a network URL into one slot, replacing its bytes. */\nexport async function fetchImageUrl(slot: string, url: string): Promise<FetchResult> {\n const res = await rpcRaw('fetchImageUrl', { slot, url })\n if (!res) return { ok: false, error: 'no response' }\n if (res.ok !== true) {\n const err = (res as { error?: { message?: string } }).error\n return { ok: false, error: err?.message ?? 'request failed' }\n }\n const v = res.value as FetchResult | undefined\n return v?.ok === true\n ? { ok: true, dataUrl: v.dataUrl ?? null }\n : { ok: false, error: v?.error ?? 'failed' }\n}\n\n/** Host default model — used only when the per-session services are absent. */\nexport async function readDefaultModel(): Promise<string | null> {\n const data = await rpcCall('defaultModel', {})\n if (data === null || typeof data !== 'object') return null\n const d = data as { provider?: unknown; model?: unknown }\n const parts = [d.provider, d.model].filter((s): s is string => typeof s === 'string' && s !== '')\n return parts.length > 0 ? parts.join(' ') : null\n}\n","/**\n * The palette fade: a theme-COLOUR change that interpolates instead of snapping.\n *\n * A custom property is not animatable until it is REGISTERED, so a palette switch\n * — which is one rewrite of `body{--dsw-alias-…}` — changes every surface in a\n * single frame. The wallpaper cross-fades and the interface jumps, which is what\n * this module exists to fix: it emits the `@property` registrations that turn the\n * alias tokens into interpolable `<color>`s, plus the `transition` declarations\n * for the elements whose own token declarations are what changed.\n *\n * Two rules shape it, and both are about not inventing behaviour:\n *\n * 1. **A token the host does not publish is left alone.** Registration requires\n * an `initial-value`, and a registered property that nothing else sets\n * resolves to THAT value rather than to the `var(…, fallback)` chain the\n * plugin's own stylesheet relies on — so a name the host answers with a\n * colour is registered, and one it does not is skipped instead of being\n * given an invented colour. `initial` is that answer (the host's resolved\n * value) and doubles as the declaration.\n * 2. **The duration and the vetoes are the SWITCH's, not a second opinion.** The\n * caller passes the same decision the wallpaper layer uses, so \"instant\", a\n * 0 ms duration and `prefers-reduced-motion` mean the same thing on both\n * halves of a switch, and there is only one place to change them.\n *\n * Pure: it takes resolved values and returns CSS, so `scripts/transition-check.ts`\n * can pin the shape down without a browser.\n */\nexport interface PaletteFadeInput {\n /** Elements whose OWN token declarations change when the palette does. */\n selectors: readonly string[]\n /** Registered colour token -> the value it must never be without. */\n initial: Readonly<Record<string, string>>\n /** Transition length in ms; `0` emits the registrations alone (no animation). */\n durationMs: number\n easing: string\n}\n\n/**\n * Whether a palette change may interpolate at all.\n *\n * Only while the SCHEME stays put. A light↔dark flip is not a tint of the same\n * palette, it is a different palette: interpolating between them walks the whole\n * interface through mid-tones whose ink is wrong in both directions (dark text\n * half-way into a dark palette), which looks worse than the switch it replaces.\n * The wallpaper has no such problem — one image fades into another either way —\n * so its own animation is deliberately untouched by this.\n *\n * `previous === null` means nothing has been painted yet (the first apply after a\n * load): there is no colour to come from, so there is nothing to fade.\n */\nexport function paletteFadeAllowed(previous: 'light' | 'dark' | null, next: 'light' | 'dark'): boolean {\n return previous === next\n}\n\n/** One `@property` block per registered token. */\nfunction registrations(names: readonly string[], initial: Readonly<Record<string, string>>): string {\n return names.map(n => `@property ${n}{syntax:'<color>';inherits:true;initial-value:${initial[n]}}`).join('')\n}\n\n/**\n * The stylesheet for one state: the registrations always, the transition only\n * while a palette change is actually being painted.\n *\n * `durationMs = 0` deliberately emits NO transition rule. That is not only\n * \"instant\": it is what keeps a slider drag instant, because the same call sites\n * rewrite the `body{…}` rule on every frame of a drag and a live transition on\n * those tokens would make the alphas lag behind the pointer.\n */\nexport function paletteFadeCss(input: PaletteFadeInput): string {\n const names = Object.keys(input.initial).filter(n => n.startsWith('--'))\n if (names.length === 0) return ''\n const css = registrations(names, input.initial)\n if (!(input.durationMs > 0) || input.selectors.length === 0) return css\n const list = names.map(n => `${n} ${input.durationMs}ms ${input.easing}`).join(',')\n return `${css}${input.selectors.join(',')}{transition:${list}}`\n}\n\n/**\n * The same fade for an element the plugin paints INLINE (its columns and cards).\n *\n * No custom property is involved there — the element's own `background-color` is\n * what changes — so the standard property is what has to be told. `0` means\n * `none` rather than an empty value: an empty value would leave whatever the host\n * had declared on that element, and the point of the 0 case is that a drag must\n * not fade at all.\n */\nexport function paletteFadeInline(durationMs: number, easing: string): string {\n return durationMs > 0 ? `background-color ${durationMs}ms ${easing}` : 'none'\n}\n","import type { BgState, ColorPalette } from '../types'\r\n\r\n// The wheel works in HSV end to end; storage and genTokens expect HSL, so\r\n// setColor converts HSV → HSL at the boundary and sectionInject converts the\r\n// stored HSL → HSV for the initial wheel props. Conversions never stack.\r\n\r\nexport function hsvToHsl(h: number, s: number, v: number): [number, number, number] {\r\n const l = v * (1 - s / 2)\r\n const sl = l === 0 || l === 1 ? 0 : (v - l) / Math.min(l, 1 - l)\r\n return [h, sl, l]\r\n}\r\n\r\nexport function hslToHsv(h: number, s: number, l: number): [number, number, number] {\r\n const v = l + s * Math.min(l, 1 - l)\r\n const sv = v === 0 ? 0 : 2 * (1 - l / v)\r\n return [h, sv, v]\r\n}\r\n\r\nlet tokensCacheKey = ''\r\nlet tokensCache: { colorScheme: 'light' | 'dark'; tokens: Record<string, string> } | null = null\r\n\r\n/**\r\n * Memoized token generation: the same (hue, sat, lit) input always yields the\r\n * same token set, and applyWp / applyCustomTokens / applySettingsOverrides call\r\n * this repeatedly (slider drags, viewport re-applies), so cache the last result\r\n * and skip the 30+ hsl() string builds when nothing changed.\r\n */\r\nexport function genTokens(hue: number, sat: number, lit: number): { colorScheme: 'light' | 'dark'; tokens: Record<string, string> } {\r\n const key = `${hue}|${sat}|${lit}`\r\n if (tokensCacheKey === key && tokensCache) return tokensCache\r\n tokensCacheKey = key\r\n tokensCache = buildTokens(hue, sat, lit)\r\n return tokensCache\r\n}\r\n\r\nfunction buildTokens(hue: number, sat: number, lit: number): { colorScheme: 'light' | 'dark'; tokens: Record<string, string> } {\r\n const dark = lit < 0.55\r\n const h = (d: number) => ((hue + d) % 360 + 360) % 360\r\n const s = (d: number) => Math.max(0, Math.min(1, sat + d))\r\n const l = (d: number) => Math.max(0, Math.min(1, lit + d))\r\n const hsl = (hh: number, ss: number, ll: number) => `hsl(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%)`\r\n const rgba = (hh: number, ss: number, ll: number, a: number) =>\r\n `hsla(${Math.round(hh)},${Math.round(ss * 100)}%,${Math.round(ll * 100)}%,${a})`\r\n // Ink for anything painted ON the brand fill. One verdict feeds both\r\n // spellings of it: brand-text (which the host defines but never uses) and\r\n // label-primary-foreground, which the HOST's own primary buttons label\r\n // themselves with on --dsw-alias-button-primary-fill — the same color as\r\n // --dsw-alias-brand-primary below. It has to flip with the fill: the dark\r\n // branch deliberately keeps that fill at 50%+ lightness, so a hard-coded white\r\n // label is white on white. The host's own dark scheme is only readable because\r\n // it flips brand-primary AND label-primary-foreground together.\r\n const onBrand = l(0.2) > 0.6 ? '#000' : '#fff'\r\n\r\n if (dark) {\r\n // dsh 0.1.7 splits the menu surface in two: the shared MenuSurface material\r\n // paints `--dsw-menu-surface-fill`, and every other overlay paints\r\n // `--dsw-specific-menu`, which the host aliases to the former\r\n // (`--dsw-specific-menu: var(--dsw-menu-surface-fill)`). Both are generated\r\n // from this one expression so the plugin's override of either can never let\r\n // the pair drift apart — see OPACITY_VARS in wallpaper.ts.\r\n const menuFill = hsl(h(0), s(0), l(0.08))\r\n return {\r\n colorScheme: 'dark',\r\n tokens: {\r\n '--dsw-alias-bg-base': hsl(h(0), s(0), l(-0.04)),\r\n '--dsw-alias-bg-layer-1': hsl(h(0), s(0), l(0.02)),\r\n '--dsw-alias-bg-layer-2': hsl(h(0), s(0), l(0.07)),\r\n '--dsw-alias-bg-layer-3': hsl(h(0), s(-0.05), l(0.12)),\r\n '--dsw-alias-bg-overlay': hsl(h(0), s(-0.05), l(0.12)),\r\n '--dsw-alias-bg-module-platform': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-bg-multi-select': hsl(h(0), s(0), l(0.1)),\r\n '--dsw-alias-bg-skeleton': 'rgba(255,255,255,0.08)',\r\n '--dsw-alias-border-l1': rgba(h(0), s(-0.1), l(0.18), 0.12),\r\n '--dsw-alias-border-l2': rgba(h(0), s(-0.1), l(0.22), 0.22),\r\n '--dsw-alias-border-l3': 'rgba(255,255,255,0.16)',\r\n '--dsw-alias-border-l4': 'rgba(255,255,255,0.2)',\r\n '--dsw-alias-border-inverted': 'rgba(255,255,255,0.06)',\r\n '--dsw-alias-label-primary': hsl(0, 0, 1),\r\n '--dsw-alias-label-secondary': 'rgba(255,255,255,0.85)',\r\n '--dsw-alias-label-tertiary': 'rgba(255,255,255,0.7)',\r\n // Placeholder/dim hint — deliberately weaker than the text tiers so a\r\n // placeholder reads as a hint, never as real input.\r\n '--dsw-alias-label-caption': 'rgba(255,255,255,0.5)',\r\n '--dsw-alias-label-dimmed': 'rgba(255,255,255,0.35)',\r\n '--dsw-alias-label-quaternary': 'rgba(255,255,255,0.25)',\r\n '--dsw-alias-label-primary-dimmed': 'rgba(255,255,255,0.92)',\r\n '--dsw-alias-label-primary-foreground': onBrand,\r\n // Inverted label sits on a light brand/contrast/badge surface in dark\r\n // mode, so it must be dark ink, not white.\r\n '--dsw-alias-label-primary-inverted': hsl(h(0), s(0.08), Math.min(l(0.06), 0.16)),\r\n '--dsw-alias-label-primary-bluish': hsl(0, 0, 1),\r\n '--dsw-alias-brand-primary': hsl(h(0), s(0.1), Math.max(l(0.2), 0.5)),\r\n '--dsw-alias-brand-text': onBrand,\r\n '--dsw-alias-button-primary-fill': hsl(h(0), s(0.1), Math.max(l(0.2), 0.5)),\r\n '--dsw-alias-button-primary-hover': hsl(h(0), s(0.1), Math.max(l(0.28), 0.58)),\r\n '--dsw-alias-button-primary-dimmed': hsl(h(0), s(0), l(0.07)),\r\n '--dsw-alias-button-elevated-fill': hsl(h(0), s(0), l(0.04)),\r\n '--dsw-alias-button-floating-fill': hsl(h(0), s(0), l(0.02)),\r\n '--dsw-alias-button-floating-hover': hsl(h(0), s(0), l(0.1)),\r\n '--dsw-alias-button-tool-bar-fill': 'rgba(255,255,255,0.08)',\r\n '--dsw-alias-button-tool-bar-hover': 'rgba(255,255,255,0.12)',\r\n '--dsw-alias-button-ghost-active-fill': hsl(h(0), s(0), l(0.06)),\r\n '--dsw-alias-button-ghost-active-border': 'rgba(255,255,255,0.16)',\r\n '--dsw-alias-button-ghost-active-hover': hsl(h(0), s(0), l(0.09)),\r\n '--dsw-alias-button-info-fill': '#679efe',\r\n '--dsw-alias-button-info-hover': '#4176e6',\r\n '--dsw-alias-button-contrast-fill': hsl(0, 0, 1),\r\n '--dsw-alias-interactive-bg-hover': rgba(h(0), s(0), Math.max(l(0.15), 0.4), 0.12),\r\n '--dsw-alias-interactive-bg-hover-solid': rgba(h(0), s(0), Math.max(l(0.15), 0.4), 0.16),\r\n '--dsw-alias-interactive-bg-hover-accent': 'rgba(255,255,255,0.24)',\r\n '--dsw-alias-interactive-bg-hover-danger': 'rgba(242,90,90,0.15)',\r\n '--dsw-alias-interactive-bg-active': rgba(h(0), s(0), Math.max(l(0.15), 0.4), 0.2),\r\n '--dsw-alias-markdown-code-block': hsl(h(0), s(0), l(-0.06)),\r\n '--dsw-alias-markdown-code-block-banner': hsl(h(0), s(0), l(-0.02)),\r\n '--dsw-alias-markdown-inline-code': hsl(h(0), s(0), l(0.04)),\r\n '--dsw-alias-markdown-placeholder': hsl(h(0), s(0), l(-0.02)),\r\n '--dsw-alias-markdown-tag': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-markdown-citation': hsl(h(0), s(0), l(0.06)),\r\n '--dsw-alias-markdown-code-segment-selected': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-markdown-code-segment-unselected': hsl(h(0), s(0), l(-0.05)),\r\n '--dsw-alias-state-error-primary': '#ff5c72',\r\n '--dsw-alias-state-error-secondary': '#ff8aa0',\r\n '--dsw-alias-state-success-primary': '#3ddc84',\r\n '--dsw-alias-state-success-secondary': '#69eea4',\r\n // Badge tertiary tokens are the static dark surfaces the UI draws\r\n // over (trajectory tool/context badges, connection pill, plan chip):\r\n // aligning them with the native dark 800/900 steps keeps light fix label\r\n // text readable instead of tint-same-as-background (issue #9).\r\n '--dsw-alias-state-success-tertiary': '#233c2c',\r\n '--dsw-alias-state-warn-primary': '#ffb347',\r\n '--dsw-alias-state-warn-secondary': '#ffc980',\r\n '--dsw-alias-state-warn-tertiary': '#27241f',\r\n '--dsw-alias-state-warn-label': '#dd8629',\r\n '--dsw-alias-state-business-primary': '#679efe',\r\n '--dsw-alias-state-business-tertiary': '#34415b',\r\n '--dsw-specific-sidebar-fill': hsl(h(0), s(0), l(-0.06)),\r\n '--dsw-specific-sidebar-nav-item-active': hsl(h(0), s(0), l(0.04)),\r\n '--dsw-specific-sidebar-nav-item-hover': hsl(h(0), s(0), l(0)),\r\n '--dsw-specific-input-major': hsl(h(0), s(0), l(0.02)),\r\n '--dsw-specific-menu': menuFill,\r\n '--dsw-menu-surface-fill': menuFill,\r\n '--dsw-specific-bubble': hsl(h(0), s(0), l(0.03)),\r\n '--dsw-specific-bubble-highlight': hsl(h(0), s(0), l(0.08)),\r\n '--dsw-specific-selector': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-specific-login-input': hsl(h(0), s(0), l(0.03)),\r\n '--dsw-specific-tip': hsl(h(0), s(0), l(0.05)),\r\n '--dsw-alias-toast-bg': hsl(h(0), s(0), l(0.08)),\r\n '--dsw-alias-tooltip-bg': hsl(h(0), s(0), l(0.08)),\r\n '--dsw-alias-scrollbar-bg-l1': hsl(h(0), s(-0.05), l(0.12)),\r\n '--dsw-alias-scrollbar-bg-l2': hsl(h(0), s(-0.05), l(0.16)),\r\n '--dsw-alias-scrollbar-hover-l1': hsl(h(0), s(-0.05), l(0.22)),\r\n '--dsw-alias-scrollbar-hover-l2': hsl(h(0), s(-0.05), l(0.22)),\r\n },\r\n }\r\n }\r\n // Same one-expression contract as the dark branch above.\r\n const menuFill = hsl(h(0), s(-0.12), l(0.15))\r\n return {\r\n colorScheme: 'light',\r\n tokens: {\r\n '--dsw-alias-bg-base': hsl(h(0), s(-0.08), l(0.03)),\r\n '--dsw-alias-bg-layer-1': hsl(h(0), s(-0.12), l(0.07)),\r\n '--dsw-alias-bg-layer-2': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-alias-bg-layer-3': hsl(h(0), s(-0.08), l(-0.09)),\r\n '--dsw-alias-bg-overlay': hsl(h(0), s(-0.12), l(0.08)),\r\n '--dsw-alias-border-l1': rgba(h(0), s(-0.15), l(-0.35), 0.18),\r\n '--dsw-alias-border-l2': rgba(h(0), s(-0.15), l(-0.35), 0.3),\r\n '--dsw-alias-label-primary': hsl(0, 0, 0),\r\n '--dsw-alias-label-secondary': 'rgba(0,0,0,0.85)',\r\n '--dsw-alias-label-tertiary': 'rgba(0,0,0,0.7)',\r\n // Placeholder/dim hint — deliberately weaker than the text tiers so a\r\n // placeholder reads as a hint, never as real input.\r\n '--dsw-alias-label-caption': 'rgba(0,0,0,0.5)',\r\n '--dsw-alias-label-dimmed': 'rgba(0,0,0,0.35)',\r\n '--dsw-alias-label-quaternary': 'rgba(0,0,0,0.25)',\r\n // Mirror of the dark branch: this branch always paints its brand fill dark\r\n // (45% lightness or less), so the ink ON it is white. Re-emitted rather\r\n // than inherited so the plugin's own palette owns the pair — the plugin's\r\n // settings UI paints every primary button/chip/tile label from this token.\r\n '--dsw-alias-label-primary-inverted': '#fff',\r\n '--dsw-alias-brand-primary': hsl(h(0), s(0.05), Math.min(l(-0.18), 0.45)),\r\n '--dsw-alias-brand-text': '#fff',\r\n '--dsw-alias-button-primary-hover': hsl(h(0), s(0.05), Math.min(l(-0.12), 0.5)),\r\n '--dsw-alias-button-primary-dimmed': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-alias-button-elevated-fill': hsl(h(0), s(-0.1), l(0.1)),\r\n '--dsw-alias-button-floating-hover': hsl(h(0), s(-0.1), l(0.16)),\r\n '--dsw-alias-interactive-bg-hover': rgba(h(0), s(0), l(-0.3), 0.08),\r\n '--dsw-alias-interactive-bg-active': rgba(h(0), s(0), l(-0.3), 0.14),\r\n '--dsw-alias-markdown-code-block': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-alias-markdown-inline-code': hsl(h(0), s(-0.08), l(0.04)),\r\n '--dsw-specific-sidebar-fill': hsl(h(0), s(-0.1), l(-0.03)),\r\n '--dsw-specific-sidebar-nav-item-active': hsl(h(0), s(-0.08), l(0.05)),\r\n '--dsw-specific-sidebar-nav-item-hover': hsl(h(0), s(-0.12), l(0)),\r\n '--dsw-specific-input-major': hsl(h(0), s(-0.12), l(0.1)),\r\n '--dsw-specific-menu': menuFill,\r\n '--dsw-menu-surface-fill': menuFill,\r\n '--dsw-alias-scrollbar-bg-l1': hsl(h(0), s(-0.1), l(-0.08)),\r\n '--dsw-alias-scrollbar-bg-l2': hsl(h(0), s(-0.08), l(-0.12)),\r\n '--dsw-alias-scrollbar-hover-l1': hsl(h(0), s(-0.08), l(-0.16)),\r\n '--dsw-alias-scrollbar-hover-l2': hsl(h(0), s(-0.08), l(-0.16)),\r\n },\r\n }\r\n}\r\n\r\nexport function toRgba(c: string, a: number): string {\r\n const hx = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(c.trim())\r\n if (hx) { let d = hx[1]!; if (d.length === 3) d = d.split('').map(x => x + x).join(''); const n = parseInt(d, 16); return `rgba(${(n >> 16) & 255},${(n >> 8) & 255},${n & 255},${a})` }\r\n const rgb = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*,\\s*([\\d.]+))?\\s*\\)$/i.exec(c.trim())\r\n if (rgb) return `rgba(${rgb[1]},${rgb[2]},${rgb[3]},${a})`\r\n const hsl = /^hsla?\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)%\\s*,\\s*([\\d.]+)%/i.exec(c.trim())\r\n if (hsl) return `hsla(${hsl[1]},${hsl[2]}%,${hsl[3]}%,${a})`\r\n return c.trim()\r\n}\r\n\r\nexport function rgbToHsl(r: number, g: number, b: number): [number, number, number] {\r\n const rn = r / 255, gn = g / 255, bn = b / 255\r\n const max = Math.max(rn, gn, bn), min = Math.min(rn, gn, bn)\r\n const l = (max + min) / 2\r\n if (max === min) return [0, 0, l]\r\n const d = max - min\r\n const s = l > 0.5 ? d / (2 - max - min) : d / (max + min)\r\n let h: number\r\n if (max === rn) h = ((gn - bn) / d) % 6\r\n else if (max === gn) h = (bn - rn) / d + 2\r\n else h = (rn - gn) / d + 4\r\n h *= 60\r\n if (h < 0) h += 360\r\n return [h, s, l]\r\n}\r\n\r\n// Wallpaper color extraction: decode the cached data URL → crop the visible\r\n// (framed) region → downsample to a 64×64 canvas → quantize pixels into 4-bit\r\n// RGB buckets → discard near-gray / near-black / near-white pixels → pick the\r\n// most populous vivid bucket (count × saturation bias) → average its members →\r\n// RGB→HSL → clamp lightness into a band that keeps the light/dark scheme\r\n// decision unambiguous. Purely client-side and memory-bounded.\r\n\r\nconst EXTRACT_SIDE = 64\r\n\r\ninterface Bucket { count: number; r: number; g: number; b: number; s: number }\r\n\r\nfunction bucketsToHsl(b: Bucket): [number, number, number] {\r\n return rgbToHsl(b.r / b.count, b.g / b.count, b.b / b.count)\r\n}\r\n\r\nfunction extractWallpaperPalette(dataUrl: string, bgState: BgState): Promise<ColorPalette | null> {\r\n return new Promise(resolve => {\r\n const img = new Image()\r\n img.onerror = () => resolve(null)\r\n img.onload = () => {\r\n try {\r\n const iw = img.naturalWidth || img.width\r\n const ih = img.naturalHeight || img.height\r\n const bg = bgState\r\n let sx = 0, sy = 0, sw = iw, sh = ih\r\n if (bg.iw === iw && bg.ih === ih && bg.iw > 0) {\r\n const fit = Math.min(window.innerWidth / iw, window.innerHeight / ih)\r\n const w = iw * fit * bg.zoom\r\n const h = ih * fit * bg.zoom\r\n sx = Math.max(0, bg.x * window.innerWidth - w / 2)\r\n sy = Math.max(0, bg.y * window.innerHeight - h / 2)\r\n sw = Math.min(iw - sx, w)\r\n sh = Math.min(ih - sy, h)\r\n if (sw <= 0 || sh <= 0) { sx = 0; sy = 0; sw = iw; sh = ih }\r\n }\r\n const c = document.createElement('canvas')\r\n c.width = EXTRACT_SIDE; c.height = EXTRACT_SIDE\r\n const g = c.getContext('2d', { willReadFrequently: true })!\r\n g.drawImage(img, sx, sy, sw, sh, 0, 0, EXTRACT_SIDE, EXTRACT_SIDE)\r\n const px = g.getImageData(0, 0, EXTRACT_SIDE, EXTRACT_SIDE).data\r\n const counts = new Uint32Array(4096)\r\n const sums = new Float64Array(4096 * 3)\r\n let totalLum = 0\r\n let sampled = 0\r\n for (let i = 0; i < px.length; i += 4) {\r\n const r = px[i], gg = px[i + 1], b = px[i + 2]\r\n const max = Math.max(r, gg, b), min = Math.min(r, gg, b)\r\n const v = max / 255\r\n const s = max === 0 ? 0 : (max - min) / max\r\n // Include all non-extreme pixels in luminance; only vivid pixels in\r\n // palette buckets so we don't theme around gray/black/white.\r\n // Rec.709 luma — the measure a display reads as brightness, and the one\r\n // the light/dark band below is decided with. The HSV value used here\r\n // before counts every saturated pixel as bright (pure blue: v = 1.0,\r\n // luma = 0.072), which pushed dark saturated wallpapers into the light\r\n // band and built a light palette over a dark picture.\r\n totalLum += (0.2126 * r + 0.7152 * gg + 0.0722 * b) / 255\r\n sampled++\r\n if (s < 0.08 || v < 0.12 || v > 0.97) continue\r\n const key = ((r >> 4) << 8) | ((gg >> 4) << 4) | (b >> 4)\r\n counts[key]++\r\n sums[key * 3] += r; sums[key * 3 + 1] += gg; sums[key * 3 + 2] += b\r\n }\r\n const buckets: Bucket[] = []\r\n for (let k = 0; k < 4096; k++) {\r\n if (counts[k] === 0) continue\r\n buckets.push({\r\n count: counts[k],\r\n r: sums[k * 3],\r\n g: sums[k * 3 + 1],\r\n b: sums[k * 3 + 2],\r\n s: (Math.max(sums[k * 3], sums[k * 3 + 1], sums[k * 3 + 2]) - Math.min(sums[k * 3], sums[k * 3 + 1], sums[k * 3 + 2])) / Math.max(sums[k * 3], sums[k * 3 + 1], sums[k * 3 + 2]) || 0,\r\n })\r\n }\r\n if (buckets.length === 0) { resolve(null); return }\r\n // Sort by vivid-weighted count.\r\n buckets.sort((a, b) => b.count * (0.5 + b.s) - a.count * (0.5 + a.s))\r\n const primary = bucketsToHsl(buckets[0]!)\r\n const primaryHue = primary[0]\r\n // Secondary: next bucket that is reasonably separated from primary.\r\n let secondary = primary\r\n for (const b of buckets.slice(1)) {\r\n const [h] = bucketsToHsl(b)\r\n const sep = Math.abs(((h - primaryHue + 540) % 360) - 180)\r\n if (sep > 30) { secondary = bucketsToHsl(b); break }\r\n }\r\n // Tertiary: complementary-ish hue based on primary if no good secondary.\r\n let tertiary: [number, number, number] = [((primaryHue + 180) % 360), Math.min(0.7, primary[1]), Math.min(0.7, primary[2])]\r\n for (const b of buckets.slice(1)) {\r\n const [h] = bucketsToHsl(b)\r\n const sep = Math.abs(((h - primaryHue + 540) % 360) - 180)\r\n if (sep > 90 && sep < 150) { tertiary = bucketsToHsl(b); break }\r\n }\r\n // Surface: neutralized primary (very low saturation).\r\n const surface: [number, number, number] = [primaryHue, Math.min(0.06, primary[1] * 0.3), primary[2]]\r\n // Auto light/dark: use the average luminance of the whole image so a\r\n // bright wallpaper naturally drives a light scheme and vice-versa.\r\n const luminance = sampled > 0 ? totalLum / sampled : primary[2]\r\n // Snap primary lightness out of the ambiguous middle band.\r\n const autoDark = luminance < 0.5\r\n const lc = autoDark ? Math.min(0.44, Math.max(0.2, primary[2])) : Math.max(0.6, Math.min(0.82, primary[2]))\r\n primary[2] = lc\r\n resolve({\r\n primary: [primary[0], Math.min(0.9, Math.max(0.15, primary[1])), primary[2]],\r\n secondary: [secondary[0], Math.min(0.85, Math.max(0.2, secondary[1])), Math.min(0.75, Math.max(0.35, secondary[2]))],\r\n tertiary: [tertiary[0], Math.min(0.8, Math.max(0.2, tertiary[1])), Math.min(0.7, Math.max(0.35, tertiary[2]))],\r\n surface,\r\n luminance,\r\n })\r\n } catch {\r\n resolve(null)\r\n }\r\n }\r\n img.src = dataUrl\r\n })\r\n}\r\n\r\n/** Backward-compatible single-color extraction: returns the primary HSL. */\r\nexport async function extractWallpaperColor(dataUrl: string, bgState: BgState): Promise<[number, number, number] | null> {\r\n const palette = await extractWallpaperPalette(dataUrl, bgState)\r\n return palette ? palette.primary : null\r\n}\r\n\r\n// One-shot frame brightness analysis: called only when a generated background\r\n// is switched (from its captured snapshot), never from the animation loop.\r\n// Decode the frame, downsample to a 32×32 canvas, average Rec.709 luma.\r\n// Dark frame → light fonts, light frame → dark fonts.\r\n\r\nconst ANALYZE_SIDE = 32\r\n\r\n/** Analyze a captured frame's average luminance. Resolves true when the frame\r\n * reads dark (use white fonts), false when light (use black fonts), or null\r\n * when the frame cannot be decoded. */\r\nexport function analyzeFrameDark(dataUrl: string): Promise<boolean | null> {\r\n return new Promise(resolve => {\r\n const img = new Image()\r\n img.onerror = () => resolve(null)\r\n img.onload = () => {\r\n try {\r\n const c = document.createElement('canvas')\r\n c.width = ANALYZE_SIDE; c.height = ANALYZE_SIDE\r\n const g = c.getContext('2d', { willReadFrequently: true })!\r\n g.drawImage(img, 0, 0, ANALYZE_SIDE, ANALYZE_SIDE)\r\n const px = g.getImageData(0, 0, ANALYZE_SIDE, ANALYZE_SIDE).data\r\n let lum = 0\r\n const count = px.length / 4\r\n for (let i = 0; i < px.length; i += 4) {\r\n lum += 0.2126 * px[i]! + 0.7152 * px[i + 1]! + 0.0722 * px[i + 2]!\r\n }\r\n resolve(lum / count / 255 < 0.5)\r\n } catch {\r\n resolve(null)\r\n }\r\n }\r\n img.src = dataUrl\r\n })\r\n}\r\n\r\n/** HSL (h 0-360, s/l 0-1) → RGB (0-255 integers). */\r\nexport function hslToRgb(h: number, s: number, l: number): [number, number, number] {\r\n const c = (1 - Math.abs(2 * l - 1)) * s\r\n const hp = h / 60\r\n const x = c * (1 - Math.abs((hp % 2) - 1))\r\n let r = 0, g = 0, b = 0\r\n if (hp < 1) { r = c; g = x }\r\n else if (hp < 2) { r = x; g = c }\r\n else if (hp < 3) { g = c; b = x }\r\n else if (hp < 4) { g = x; b = c }\r\n else if (hp < 5) { r = x; b = c }\r\n else { r = c; b = x }\r\n const m = l - c / 2\r\n return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)]\r\n}\r\n","/**\r\n * dsh-background-by-model — settings UI design system.\r\n *\r\n * The section is styled entirely through these scoped classes instead of the\r\n * host's inline-style approach: animations (page transitions, staggered\r\n * reveals, the rotating orb ring) and pseudo-element effects cannot be\r\n * expressed as React inline styles. Every color reads the host's\r\n * --dsw-alias-* tokens so the panel follows the user's custom theme color and\r\n * light/dark scheme automatically; `color-mix` tints carry a plain-token\r\n * fallback first for older engines.\r\n */\r\nexport const NAV_ITEM_H = 38\r\nexport const NAV_GAP = 4\r\n\r\nexport const UI_CSS = `\r\n/* The section is rendered INLINE inside the host settings dialog's content\r\n * column: the host provides the modal chrome (backdrop, centering, closing).\r\n * These classes style only the embedded shell; transient fixed layers (toast,\r\n * color picker, background editor) escape through Portals on <html>. */\r\n.dab-root{position:relative;color:var(--dsw-alias-label-primary);animation:dab-fade-in .35s ease both;container-type:inline-size;display:flex;flex-direction:column;align-items:center;width:100%;min-width:0;--dab-mono:ui-monospace,\"Cascadia Mono\",\"SF Mono\",Consolas,\"Courier New\",monospace}\r\n.dab-root *,.dab-root *::before,.dab-root *::after{box-sizing:border-box}\r\n.dab-root button{font-family:inherit}\r\n\r\n/* ── shell: nav rail + page body ─────────────────────────────────────────── */\r\n.dab-shell{display:grid;grid-template-columns:158px minmax(0,1fr);gap:26px;align-items:start;padding-bottom:8px;width:100%;max-width:980px;margin:0 auto}\r\n.dab-nav{position:sticky;top:0;display:flex;flex-direction:column;gap:18px}\r\n.dab-brand{display:flex;align-items:center;gap:10px;padding:2px 6px}\r\n.dab-brand-tile{width:30px;height:30px;flex:none;border-radius:9px;display:grid;place-items:center;color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-brand-primary);box-shadow:0 4px 14px -4px var(--dsw-alias-brand-primary)}\r\n.dab-brand-name{font-size:13px;font-weight:650;letter-spacing:.01em;line-height:1.25}\r\n.dab-brand-tag{font-size:9px;letter-spacing:.16em;font-weight:600;color:var(--dsw-alias-label-quaternary,var(--dsw-alias-label-tertiary));text-transform:uppercase}\r\n.dab-nav-list{position:relative;display:flex;flex-direction:column;gap:${NAV_GAP}px}\r\n.dab-nav-ind{position:absolute;left:0;right:0;top:0;height:${NAV_ITEM_H}px;border-radius:11px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 13%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-brand-primary) 25%,transparent);transition:transform .38s cubic-bezier(.22,1,.36,1)}\r\n.dab-nav-item{position:relative;z-index:1;display:flex;align-items:center;gap:10px;height:${NAV_ITEM_H}px;padding:0 12px;border:0;background:none;border-radius:11px;color:var(--dsw-alias-label-tertiary);font-size:13px;cursor:pointer;text-align:left;transition:color .22s ease}\r\n.dab-nav-item:hover{color:var(--dsw-alias-label-primary)}\r\n.dab-nav-item.is-active{color:var(--dsw-alias-brand-primary);font-weight:600}\r\n.dab-nav-item svg{flex:none;transition:transform .3s cubic-bezier(.34,1.56,.64,1)}\r\n.dab-nav-item:hover svg{transform:scale(1.14) rotate(-5deg)}\r\n\r\n/* ── page chrome ─────────────────────────────────────────────────────────── */\r\n.dab-page{animation:dab-page-in .4s cubic-bezier(.22,1,.36,1) both;min-width:0;display:flex;flex-direction:column;gap:13px}\r\n.dab-head{margin:2px 0 5px}\r\n.dab-overline{font-size:10.5px;font-weight:700;letter-spacing:.18em;text-transform:uppercase;color:var(--dsw-alias-brand-primary);opacity:.9}\r\n.dab-h1{margin:4px 0 0;font-size:21px;font-weight:700;letter-spacing:-.01em}\r\n.dab-desc{margin:6px 0 0;font-size:12.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);max-width:56ch}\r\n.dab-card{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:16px;padding:18px}\r\n.dab-card-hover{transition:transform .28s ease,box-shadow .28s ease,border-color .28s ease}\r\n.dab-card-hover:hover{transform:translateY(-2px);box-shadow:0 10px 28px -12px rgba(0,0,0,.28)}\r\n.dab-rise{animation:dab-rise-in .55s cubic-bezier(.22,1,.36,1) both;animation-delay:calc(var(--d,0) * 62ms)}\r\n\r\n/* ── accent hero (color orb) ─────────────────────────────────────────────── */\r\n.dab-hero-accent{display:flex;align-items:center;gap:24px;flex-wrap:wrap}\r\n.dab-orb-wrap{position:relative;width:118px;height:118px;flex:none}\r\n.dab-orb{position:absolute;inset:11px;border-radius:50%;background:radial-gradient(circle at 32% 28%,rgba(255,255,255,.5),rgba(255,255,255,0) 44%),var(--c,#888);box-shadow:0 16px 36px -10px var(--c-soft,transparent),inset 0 -10px 20px rgba(0,0,0,.16);animation:dab-orb-in .7s cubic-bezier(.22,1,.36,1) both}\r\n.dab-orb-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,transparent 0 30%,var(--c,#888) 46%,transparent 62%,transparent 76%,var(--c,#888) 90%,transparent 100%);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 3.5px),#000 calc(100% - 2.5px));mask:radial-gradient(farthest-side,transparent calc(100% - 3.5px),#000 calc(100% - 2.5px));animation:dab-spin 7s linear infinite;opacity:.9}\r\n.dab-hex{font-family:var(--dab-mono);font-size:24px;font-weight:600;letter-spacing:.02em;line-height:1.2;margin-top:2px}\r\n.dab-hsl-row{display:flex;gap:16px;margin-top:7px;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-hsl-row b{font-weight:600;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n\r\n/* ── swatches ────────────────────────────────────────────────────────────── */\r\n.dab-swatch-title{font-size:12px;font-weight:600;margin-bottom:10px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-swatches{display:flex;flex-wrap:wrap;gap:9px}\r\n.dab-swatch{width:25px;height:25px;border-radius:50%;border:0;padding:0;cursor:pointer;box-shadow:inset 0 0 0 1px rgba(0,0,0,.1);transition:transform .22s cubic-bezier(.34,1.56,.64,1),box-shadow .22s ease}\r\n.dab-swatch:hover{transform:scale(1.2)}\r\n.dab-swatch.is-on{box-shadow:0 0 0 2px var(--dsw-alias-bg-layer-1),0 0 0 4px var(--dsw-alias-brand-primary)}\r\n\r\n/* ── wheel card ──────────────────────────────────────────────────────────── */\r\n.dab-wheel-card{position:relative;display:flex;align-items:center;justify-content:center;gap:28px;flex-wrap:wrap;padding:24px 18px}\r\n.dab-wheel-glow{position:absolute;width:230px;height:230px;border-radius:50%;filter:blur(48px);opacity:.2;background:var(--c,#888);pointer-events:none;transition:background .4s ease}\r\n.dab-wheel{position:relative;cursor:crosshair;border-radius:50%;box-shadow:0 12px 32px -14px rgba(0,0,0,.4)}\r\n.dab-hint{font-size:11.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);padding:0 4px}\r\n/* The \"your edits are being held\" notice: it reports a state the user has to act\r\n on, so it is tinted like a warning rather than left as grey hint text. */\r\n.dab-stale{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent);border:1px solid color-mix(in srgb,var(--dsw-alias-state-error-primary) 35%,transparent);border-radius:9px;padding:8px 10px}\r\n\r\n/* ── precise color inputs ────────────────────────────────────────────────── */\r\n.dab-inputs{display:flex;flex-direction:column;gap:10px;min-width:172px}\r\n.dab-field{display:flex;align-items:center;gap:8px}\r\n.dab-field-label{width:14px;text-align:center;font-family:var(--dab-mono);font-size:11px;font-weight:600;color:var(--dsw-alias-label-tertiary)}\r\n.dab-num{flex:1;min-width:0;height:30px;padding:0 10px;border-radius:9px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-family:var(--dab-mono);font-size:12px;outline:none;transition:border-color .2s,box-shadow .2s}\r\n.dab-num:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}\r\n.dab-num::-webkit-outer-spin-button,.dab-num::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}\r\n.dab-num{-moz-appearance:textfield;appearance:textfield}\r\n.dab-urlinput{flex:1;min-width:180px;height:34px;padding:0 12px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-size:12.5px;outline:none;transition:border-color .2s}\r\n.dab-urlinput::placeholder{color:var(--dsw-alias-label-quaternary)}\r\n.dab-urlinput:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}\r\n/* Prints the current hex on the color itself. Without the value this was an\r\n * empty bordered rectangle sitting in the same column as the H/S/L number\r\n * fields, which made it read as one more — blank — text input; nothing is ever\r\n * typed here, so nothing may look typable. The hover scale went with that\r\n * reading: it advertised an interaction this field does not have. */\r\n.dab-swatch-lg{display:flex;align-items:center;justify-content:center;height:38px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);box-shadow:inset 0 0 14px rgba(0,0,0,.1);font-family:var(--dab-mono);font-size:12.5px;font-weight:600;letter-spacing:.06em;user-select:all}\r\n\r\n/* ── buttons & chips ─────────────────────────────────────────────────────── */\r\n/* Text/icon painted ON --dsw-alias-brand-primary reads\r\n * --dsw-alias-label-primary-inverted, never --dsw-alias-brand-text. The host's\r\n * brand-primary is a CONTRAST ink, not a hue: black in its light scheme and\r\n * near-white (#f9fafb) in its dark one, with brand-text equal to it in BOTH\r\n * (and unused by the host's own CSS). Following the system theme therefore made\r\n * every brand-filled control a filled box with an invisible label — a white\r\n * primary button and a white active chip on a dark dialog. It was only ever\r\n * readable while the plugin owned the palette and generated its own brand pair.\r\n * label-primary-inverted is the host's answer for ink on a brand/contrast fill\r\n * (its sidebar build badge paints exactly this pair) and it flips with the\r\n * scheme: #fff on the light scheme's black fill, #353638 on the dark scheme's\r\n * white one. */\r\n.dab-btn{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:34px;padding:0 14px;border-radius:10px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-button-elevated-fill);color:var(--dsw-alias-label-primary);font-size:12.5px;font-weight:550;cursor:pointer;transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease,opacity .18s ease,background .18s ease}\r\n.dab-btn:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 5px 14px -6px rgba(0,0,0,.32)}\r\n.dab-btn:active:not(:disabled){transform:translateY(0) scale(.97);box-shadow:none}\r\n.dab-btn:disabled{opacity:.5;cursor:not-allowed}\r\n.dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted);border-color:transparent}\r\n.dab-btn-danger{color:var(--dsw-alias-state-error-primary)}\r\n.dab-btn-ghost{background:transparent;border-color:transparent;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-btn-ghost:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2);box-shadow:none}\r\n.dab-btn:focus-visible,.dab-nav-item:focus-visible,.dab-seg-item:focus-visible,.dab-swatch:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\r\n.dab-chip-row{display:flex;flex-wrap:wrap;gap:8px}\r\n.dab-chip{height:30px;padding:0 14px;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary));font-size:12px;cursor:pointer;display:inline-flex;align-items:center;gap:6px;transition:all .22s ease}\r\n.dab-chip:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary)}\r\n.dab-chip.is-active{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted);border-color:transparent}\r\n\r\n/* ── sliders ─────────────────────────────────────────────────────────────── */\r\n.dab-slider-block{display:flex;flex-direction:column;gap:6px}\r\n.dab-slider-block + .dab-slider-block{margin-top:13px}\r\n.dab-slider-label{font-size:12px;font-weight:550;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-slider-val{font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);min-width:44px;text-align:right}\r\n.dab-slider{-webkit-appearance:none;appearance:none;flex:1;min-width:0;height:4px;border-radius:99px;outline:none;cursor:pointer;margin:5px 0;background:linear-gradient(to right,var(--dsw-alias-brand-primary) calc(var(--pct,50) * 1%),var(--dsw-alias-border-l2) calc(var(--pct,50) * 1%));transition:height .15s ease}\r\n.dab-slider:hover{height:5px}\r\n.dab-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:15px;height:15px;border-radius:50%;background:var(--dsw-alias-button-elevated-fill,#fff);border:2px solid var(--dsw-alias-brand-primary);box-shadow:0 1px 5px rgba(0,0,0,.28);transition:transform .16s cubic-bezier(.34,1.56,.64,1)}\r\n.dab-slider:hover::-webkit-slider-thumb,.dab-slider:focus-visible::-webkit-slider-thumb{transform:scale(1.22)}\r\n.dab-slider:active::-webkit-slider-thumb{transform:scale(1.34)}\r\n.dab-slider::-moz-range-thumb{width:13px;height:13px;border-radius:50%;background:var(--dsw-alias-button-elevated-fill,#fff);border:2px solid var(--dsw-alias-brand-primary)}\r\n\r\n/* ── interface part cards ────────────────────────────────────────────────── */\r\n.dab-grid-parts{display:grid;grid-template-columns:repeat(auto-fill,minmax(256px,1fr));gap:13px}\r\n.dab-part-head{display:flex;align-items:center;gap:11px;margin-bottom:14px}\r\n.dab-part-ico{width:32px;height:32px;flex:none;border-radius:10px;display:grid;place-items:center;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 12%,transparent)}\r\n.dab-part-name{font-size:13.5px;font-weight:600}\r\n.dab-part-badge{margin-left:auto;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:99px;padding:3px 9px}\r\n\r\n/* ── segmented control ───────────────────────────────────────────────────── */\r\n.dab-seg{position:relative;display:inline-flex;padding:3px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);border-radius:11px}\r\n.dab-seg-thumb{position:absolute;top:3px;bottom:3px;left:3px;width:var(--w,96px);border-radius:8px;background:var(--dsw-alias-button-elevated-fill);box-shadow:0 2px 8px -2px rgba(0,0,0,.28);transition:transform .32s cubic-bezier(.22,1,.36,1)}\r\n.dab-seg-item{position:relative;z-index:1;display:inline-flex;align-items:center;justify-content:center;gap:6px;width:var(--w,96px);height:30px;border:0;background:none;border-radius:8px;color:var(--dsw-alias-label-tertiary);font-size:12.5px;cursor:pointer;transition:color .25s ease}\r\n.dab-seg-item.is-active{color:var(--dsw-alias-label-primary);font-weight:600}\r\n\r\n/* ── toggle switch ───────────────────────────────────────────────────────── */\r\n.dab-toggle{position:relative;width:42px;height:24px;flex:none;border-radius:99px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);cursor:pointer;padding:0;transition:background .28s ease,border-color .28s ease}\r\n.dab-toggle-knob{position:absolute;top:2.5px;left:2.5px;width:17px;height:17px;border-radius:50%;background:var(--dsw-alias-label-secondary,#999);box-shadow:0 1px 3px rgba(0,0,0,.3);transition:transform .28s cubic-bezier(.22,1,.36,1),background .28s ease}\r\n.dab-toggle.is-on{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}\r\n.dab-toggle.is-on .dab-toggle-knob{transform:translateX(18px);background:var(--dsw-alias-label-primary-inverted)}\r\n\r\n/* ── background preview hero ─────────────────────────────────────────────── */\r\n.dab-hero{position:relative;border-radius:16px;overflow:hidden;aspect-ratio:16/9;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2)}\r\n.dab-hero-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:transform .5s cubic-bezier(.22,1,.36,1)}\r\n.dab-hero:hover .dab-hero-img{transform:scale(1.03)}\r\n.dab-hero-empty{position:absolute;inset:6px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;color:var(--dsw-alias-label-tertiary);font-size:12.5px;border:1.5px dashed var(--dsw-alias-border-l2);border-radius:12px;cursor:pointer;background:transparent;transition:border-color .25s,color .25s,background .25s;width:auto;height:auto}\r\n.dab-hero-empty:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}\r\n.dab-hero-empty.is-over{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent)}\r\n.dab-hero-badge{position:absolute;top:10px;left:10px;display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 11px;border-radius:99px;background:rgba(0,0,0,.45);color:#fff;font-size:11px;backdrop-filter:blur(6px);pointer-events:none}\r\n.dab-hero-veil{position:absolute;left:0;right:0;bottom:0;padding:34px 12px 12px;display:flex;align-items:flex-end;justify-content:flex-end;gap:8px;background:linear-gradient(to top,rgba(0,0,0,.55),rgba(0,0,0,0));opacity:0;transform:translateY(6px);transition:opacity .3s ease,transform .3s ease}\r\n.dab-hero:hover .dab-hero-veil{opacity:1;transform:none}\r\n.dab-hero-veil .dab-btn{background:rgba(255,255,255,.94);color:#14161a;border-color:transparent;height:30px;font-size:12px}\r\n.dab-hero-veil .dab-btn-danger{color:#dc2626}\r\n\r\n/* ── profile page ────────────────────────────────────────────────────────── */\r\n.dab-profile-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(238px,1fr));gap:13px}\r\n/* The switch-effect preview: a two-tone swatch that replays the chosen effect in\r\n the panel. It exists because a wallpaper fading into ITSELF is invisible —\r\n the one thing a transition setting must not leave the user guessing about. */\r\n.dab-tr-preview{position:relative;overflow:hidden;flex:1;min-width:0;height:74px;border-radius:12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);background-image:linear-gradient(120deg,color-mix(in srgb,var(--dsw-alias-label-tertiary) 24%,transparent),transparent 70%)}\r\n.dab-tr-preview-in{position:absolute;inset:0;background-image:linear-gradient(120deg,var(--dsw-alias-brand-primary),color-mix(in srgb,var(--dsw-alias-brand-primary) 50%,var(--dsw-alias-bg-layer-1)))}\r\n.dab-profile-ico{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;margin-bottom:13px;color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 12%,transparent)}\r\n.dab-profile-title{font-size:14px;font-weight:650}\r\n.dab-profile-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);line-height:1.55;margin:5px 0 15px}\r\n.dab-footer{margin-top:6px;padding:14px 4px 0;border-top:1px solid var(--dsw-alias-border-l2);display:flex;align-items:center;justify-content:space-between;font-size:11px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-footer-mono{font-family:var(--dab-mono);letter-spacing:.02em}\r\n\r\n/* ── toast ───────────────────────────────────────────────────────────────── */\r\n.dab-toast{position:fixed;left:50%;bottom:30px;transform:translateX(-50%);display:flex;align-items:center;gap:8px;height:38px;padding:0 16px;border-radius:99px;background:var(--dsw-alias-bg-layer-3,var(--dsw-alias-bg-layer-2));border:1px solid var(--dsw-alias-border-l2);box-shadow:0 10px 30px -8px rgba(0,0,0,.38);font-size:12.5px;z-index:10001;animation:dab-toast-in .32s cubic-bezier(.22,1,.36,1) both}\r\n.dab-toast-ok{color:var(--dsw-alias-brand-primary);display:grid;place-items:center}\r\n.dab-toast-err{color:var(--dsw-alias-state-error-primary);display:grid;place-items:center}\r\n\r\n/* ── modals (editor / eyedropper / crash) ────────────────────────────────── */\r\n/* Pin to the viewport explicitly with vw/vh so ancestor padding/margins on\r\n * body cannot shift or clip the overlay; keep it above host sidebar chrome.\r\n * pointer-events:auto re-enables interaction: these overlays render inside a\r\n * Portal root that is pointer-events:none so it never blocks the page alone. */\r\n.dab-overlay{position:fixed;left:0;top:0;width:100vw;height:100vh;z-index:999999;background:rgba(8,10,14,.62);backdrop-filter:blur(8px);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;animation:dab-fade-in .25s ease both;pointer-events:auto}\r\n.dab-overlay-title{color:#fff;font-size:15px;font-weight:600}\r\n.dab-overlay-hint{color:rgba(255,255,255,.62);font-size:12px}\r\n.dab-modal-card{animation:dab-zoom-in .3s cubic-bezier(.22,1,.36,1) both;max-width:calc(100vw - 40px);max-height:calc(100vh - 120px);overflow:auto}\r\n.dab-overlay .dab-btn{background:rgba(255,255,255,.94);color:#14161a;border-color:transparent}\r\n.dab-overlay .dab-btn-primary{background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-inverted)}\r\n.dab-crash{display:flex;flex-direction:column;gap:10px;align-items:center;padding:28px 18px;border:1px solid var(--dsw-alias-border-l2);border-radius:16px}\r\n.dab-crash-title{font-size:15px;font-weight:650}\r\n.dab-crash-desc{font-size:12px;color:var(--dsw-alias-label-tertiary);text-align:center;line-height:1.5}\r\n\r\n/* ── model rules ─────────────────────────────────────────────────────────── */\r\n.dab-rules{display:flex;flex-direction:column;gap:12px}\r\n.dab-rule{background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);border-radius:16px;padding:14px;transition:border-color .25s,box-shadow .25s,opacity .25s}\r\n.dab-rule.is-active{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 16%,transparent)}\r\n.dab-rule.is-off{opacity:.55}\r\n.dab-rule-head{display:flex;align-items:center;gap:9px;flex-wrap:wrap}\r\n.dab-rule-num{font-family:var(--dab-mono);font-size:11px;font-weight:700;color:var(--dsw-alias-label-tertiary);min-width:16px}\r\n.dab-rule-badge{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 14%,transparent);border-radius:99px;padding:2px 8px}\r\n.dab-rule-match{flex:1;min-width:150px;height:32px;padding:0 11px;border-radius:9px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font-family:var(--dab-mono);font-size:12.5px;outline:none;transition:border-color .2s,box-shadow .2s}\r\n.dab-rule-match::placeholder{color:var(--dsw-alias-label-quaternary)}\r\n.dab-rule-match:focus{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 3px color-mix(in srgb,var(--dsw-alias-brand-primary) 18%,transparent)}\r\n.dab-icon-btn{width:28px;height:28px;flex:none;display:grid;place-items:center;border-radius:8px;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;transition:color .2s,border-color .2s,background .2s}\r\n.dab-icon-btn:hover:not(:disabled){color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-brand-primary)}\r\n.dab-icon-btn:disabled{opacity:.35;cursor:not-allowed}\r\n.dab-icon-btn-danger:hover:not(:disabled){color:var(--dsw-alias-state-error-primary);border-color:var(--dsw-alias-state-error-primary)}\r\n.dab-rule-body{margin-top:13px;display:flex;flex-direction:column;gap:13px}\r\n.dab-rule-thumb{position:relative;border-radius:12px;overflow:hidden;aspect-ratio:16/9;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2)}\r\n.dab-rule-thumb img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}\r\n.dab-rule-thumb-empty{position:absolute;inset:5px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;border:1.5px dashed var(--dsw-alias-border-l2);border-radius:9px;color:var(--dsw-alias-label-tertiary);font-size:12px;text-align:center;padding:0 10px}\r\n/* The empty tile is the upload button while the rule has no picture at all, so\r\n it is a real <button> (focusable, keyboard-reachable) reset down to the box the\r\n plain preview occupies — a button brings its own padding, font and border. The\r\n dashed frame it looks like is .dab-rule-thumb-empty, which is why the hover and\r\n the drag highlight have to reach it through a descendant selector too. */\r\n.dab-rule-thumb-add{display:block;width:100%;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;-webkit-appearance:none;appearance:none;transition:border-color .2s,background .2s}\r\n.dab-rule-thumb-add:hover,.dab-rule-thumb-add.is-over{border-color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 6%,var(--dsw-alias-bg-layer-2))}\r\n.dab-rule-thumb-add:hover .dab-rule-thumb-empty,.dab-rule-thumb-add.is-over .dab-rule-thumb-empty{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}\r\n.dab-rule-thumb-add:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}\r\n.dab-rule-cols{display:grid;grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);gap:18px;align-items:start}\r\n.dab-rule-section-title{font-size:12px;font-weight:600;margin-bottom:9px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n\r\n/* ── image strip (multi-image rules) ─────────────────────────────────────── */\r\n/* A horizontally scrolling row of thumbnails: the one open for editing is\r\n ringed, and the one the wallpaper is actually painting carries a live dot —\r\n but deliberately NO ring of its own. Two tiles ringed at once read as \"two\r\n things are selected\", which is the one question a row of near-identical\r\n thumbnails must not leave open: being on screen is the dot, and nothing\r\n else. FILES dropped here are added, which is why the container's border\r\n reacts to a drag; a TILE dragged across the row reorders it instead, and that\r\n is what the is-dragging / dab-strip-bar pair below is for. */\r\n.dab-strip{display:flex;gap:7px;margin-top:9px;padding:7px;border-radius:12px;border:1.5px dashed var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);overflow-x:auto;scrollbar-width:thin}\r\n.dab-strip.is-over{border-color:var(--dsw-alias-brand-primary);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent)}\r\n.dab-strip-item{position:relative;flex:none;width:62px;height:44px;padding:0;border-radius:8px;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);cursor:grab;user-select:none;transition:border-color .2s,box-shadow .2s,transform .18s}\r\n.dab-strip-item img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}\r\n.dab-strip-item:hover{transform:translateY(-1px);border-color:var(--dsw-alias-brand-primary)}\r\n.dab-strip-item.is-sel{border-color:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--dsw-alias-brand-primary) 40%,transparent)}\r\n/* The tile being dragged out of the row, and the 2px bar that says where it will\r\n land. The bar is drawn INSIDE the tile it precedes (at its left edge) or inside\r\n the last tile (at its right edge, for a drop past the end): a bar as its own flex\r\n item would push the tiles sideways, and a target that slides away as the pointer\r\n approaches it is how a drop ends up one slot off. */\r\n.dab-strip-item.is-dragging{cursor:grabbing;opacity:.45;transform:none;border-style:dashed}\r\n.dab-strip-bar{position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--dsw-alias-brand-primary);z-index:2}\r\n.dab-strip-bar.is-end{left:auto;right:0}\r\n.dab-strip-wait{position:absolute;inset:0;background:repeating-linear-gradient(45deg,transparent 0 4px,color-mix(in srgb,var(--dsw-alias-label-tertiary) 14%,transparent) 4px 8px)}\r\n.dab-strip-num{position:absolute;left:3px;bottom:2px;font-family:var(--dab-mono);font-size:9.5px;line-height:1;padding:1px 4px;border-radius:5px;background:rgba(0,0,0,.45);color:#fff}\r\n.dab-strip-live{position:absolute;right:3px;top:3px;width:7px;height:7px;border-radius:50%;background:var(--dsw-alias-brand-primary);box-shadow:0 0 0 2px rgba(0,0,0,.35);animation:dab-pulse 1.8s ease-in-out infinite}\r\n/* Each image's OWN theme color, when it has one. It shares the right edge with\r\n the live dot but sits at the bottom, where nothing else is: the item number is\r\n bottom-LEFT. Two rings (dark outside, light inside) keep the swatch readable\r\n over a dark and a light thumbnail alike. */\r\n.dab-strip-dot{position:absolute;right:3px;bottom:3px;width:8px;height:8px;border-radius:50%;box-shadow:0 0 0 1.5px rgba(0,0,0,.45),inset 0 0 0 1px rgba(255,255,255,.35)}\r\n.dab-strip-add{flex:none;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;width:62px;height:44px;border-radius:8px;border:1.5px dashed var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);font-size:9.5px;line-height:1.15;cursor:pointer;transition:border-color .2s,color .2s}\r\n.dab-strip-add:hover{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}\r\n.dab-strip-pos{display:inline-flex;align-items:center;font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);padding:0 4px}\r\n\r\n/* ── rotation panel ──────────────────────────────────────────────────────── */\r\n.dab-rot-panel{margin-top:10px;padding:12px;border-radius:12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2)}\r\n.dab-num-sec{flex:none;width:88px;min-width:0}\r\n\r\n@container (max-width:760px){.dab-rule-cols{grid-template-columns:1fr}}\r\n\r\n/* ── host self-check ─────────────────────────────────────────────────────── */\r\n.dab-verdict{display:flex;flex-direction:column;gap:14px;position:relative;overflow:hidden}\r\n.dab-verdict::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;background:linear-gradient(120deg,transparent 55%,color-mix(in srgb,var(--dab-verdict-tone,transparent) 26%,transparent))}\r\n.dab-verdict-ok{--dab-verdict-tone:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 38%,var(--dsw-alias-border-l2))}\r\n.dab-verdict-partial,.dab-verdict-broken{--dab-verdict-tone:var(--dsw-alias-state-error-primary);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 40%,var(--dsw-alias-border-l2))}\r\n.dab-verdict-unknown{--dab-verdict-tone:var(--dsw-alias-label-tertiary)}\r\n.dab-verdict-head{display:flex;align-items:center;gap:13px;flex-wrap:wrap}\r\n.dab-verdict-ico{width:34px;height:34px;flex:none;border-radius:11px;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}\r\n.dab-verdict-ico-ok{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 14%,transparent)}\r\n.dab-verdict-ico-partial,.dab-verdict-ico-broken{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent)}\r\n.dab-verdict-text{flex:1;min-width:170px}\r\n.dab-verdict-title{font-size:14.5px;font-weight:650}\r\n.dab-verdict-sub{margin-top:4px;font-size:12px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-verdict-actions{display:flex;gap:8px;flex-wrap:wrap;margin-left:auto}\r\n.dab-facts{display:flex;flex-wrap:wrap;gap:8px;position:relative;z-index:1}\r\n.dab-fact{display:inline-flex;align-items:center;gap:7px;height:27px;padding:0 11px;border-radius:99px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);max-width:100%}\r\n.dab-fact.is-bad{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 45%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}\r\n.dab-fact-k{font-size:10.5px;font-weight:650;letter-spacing:.06em;text-transform:uppercase;color:var(--dsw-alias-label-tertiary);white-space:nowrap}\r\n.dab-fact-v{font-family:var(--dab-mono);font-size:11.5px;color:var(--dsw-alias-label-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:32ch}\r\n.dab-check-group-title{display:flex;align-items:center;gap:9px;font-size:12.5px;font-weight:650;margin-bottom:11px}\r\n.dab-check-group-count{margin-left:auto;font-family:var(--dab-mono);font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:99px;padding:3px 9px}\r\n.dab-checks{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:2px}\r\n.dab-check{display:flex;gap:10px;padding:9px 10px;border-radius:11px;transition:background .2s ease}\r\n.dab-check:hover{background:var(--dsw-alias-bg-layer-2)}\r\n.dab-check-ico{width:19px;height:19px;flex:none;margin-top:1px;border-radius:50%;display:grid;place-items:center;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2)}\r\n.dab-check-ico-pass{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 15%,transparent)}\r\n.dab-check-ico-fail{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 15%,transparent)}\r\n.dab-check-dot{width:5px;height:5px;border-radius:50%;background:currentColor;opacity:.65}\r\n.dab-check-body{min-width:0;flex:1;display:flex;flex-direction:column;gap:3px}\r\n.dab-check-head{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}\r\n.dab-check-label{font-size:12.5px;font-weight:600}\r\n.dab-check-status{font-size:10px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;padding:1px 7px;border-radius:99px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary)}\r\n.dab-check-status-pass{color:var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary));background:color-mix(in srgb,var(--dsw-alias-state-success-primary,var(--dsw-alias-brand-primary)) 14%,transparent)}\r\n.dab-check-status-fail{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 14%,transparent)}\r\n.dab-check-target{font-family:var(--dab-mono);font-size:10.5px;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-bg-layer-2);border-radius:6px;padding:1px 6px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\r\n.dab-check-detail{font-family:var(--dab-mono);font-size:11px;color:var(--dsw-alias-label-tertiary);line-height:1.5;overflow-wrap:anywhere}\r\n.dab-check-reason{display:flex;flex-direction:column;gap:5px;font-size:12px;line-height:1.55;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-tertiary))}\r\n.dab-check-symptom{color:var(--dsw-alias-state-error-primary)}\r\n.dab-check-where{display:flex;gap:7px;align-items:baseline;flex-wrap:wrap;font-size:11px;color:var(--dsw-alias-label-tertiary)}\r\n.dab-check-where code{font-family:var(--dab-mono);font-size:10.5px;overflow-wrap:anywhere}\r\n.dab-check-note{margin:12px 0 0;font-size:11.5px;line-height:1.55;color:var(--dsw-alias-label-tertiary);position:relative;z-index:1}\r\n\r\n/* ── holiday override (Profile page) ─────────────────────────────────────── */\r\n/* Only a label: the whole feature is one switch, and dab-toggle already exists.\r\n The per-holiday cards that used to live here are gone by design. */\r\n.dab-holiday-label{font-size:13px;font-weight:600;color:var(--dsw-alias-label-primary)}\r\n\r\n/* ── keyframes ───────────────────────────────────────────────────────────── */\r\n@keyframes dab-fade-in{from{opacity:0}to{opacity:1}}\r\n@keyframes dab-page-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}\r\n@keyframes dab-rise-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}\r\n@keyframes dab-orb-in{from{opacity:0;transform:scale(.82)}to{opacity:1;transform:none}}\r\n@keyframes dab-spin{to{transform:rotate(360deg)}}\r\n@keyframes dab-rotate{to{transform:rotate(360deg)}}\r\n@keyframes dab-toast-in{from{opacity:0;transform:translate(-50%,10px)}to{opacity:1;transform:translate(-50%,0)}}\r\n@keyframes dab-zoom-in{from{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:none}}\r\n@keyframes dab-flow{to{background-position:300% 50%}}\r\n/* The strip's \"this is the image on screen\" dot. It is the only marker that says\r\n the rotation is alive, so it breathes rather than merely sitting there. */\r\n@keyframes dab-pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.72)}}\r\n\r\n/* ── responsive & motion preferences ─────────────────────────────────────── */\r\n@container (max-width:620px){\r\n .dab-shell{grid-template-columns:1fr;gap:14px}\r\n .dab-nav{position:static;flex-direction:row;align-items:center;justify-content:space-between;gap:10px}\r\n .dab-nav-list{flex-direction:row;overflow-x:auto;scrollbar-width:none}\r\n .dab-nav-list::-webkit-scrollbar{display:none}\r\n .dab-nav-ind{display:none}\r\n .dab-nav-item{flex:none;padding:0 10px}\r\n .dab-nav-item.is-active{background:var(--dsw-alias-bg-layer-2)}\r\n .dab-types{grid-template-columns:1fr}\r\n .dab-verdict-actions{margin-left:0;width:100%}\r\n .dab-verdict-actions .dab-btn{flex:1}\r\n}\r\n@container (min-width:621px){\r\n .dab-shell{grid-template-columns:158px minmax(0,1fr);gap:26px}\r\n}\r\n@media (prefers-reduced-motion:reduce){\r\n .dab-root *,.dab-root *::before,.dab-root *::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}\r\n}\r\n`\r\n\r\nconst CSS_ID = 'dab-ui-css'\r\n\r\n/**\r\n * The attribute that marks a `<style>` element as OURS.\r\n *\r\n * The host's own CSS modules also set `data-plugin` on their `<style>` elements\r\n * (every one of them), so `data-plugin` cannot distinguish this plugin's sheets\r\n * from the host's — and the host-contract probe has to make exactly that\r\n * distinction: a token this plugin re-emits must never be allowed to make a\r\n * *host* check pass. This attribute is the honest marker, and it is set on every\r\n * stylesheet this plugin injects.\r\n */\r\nexport const OWN_SHEET_ATTR = 'data-dab-side'\r\n\r\n/** Mark a stylesheet this plugin injected, so the host probe can tell it apart. */\r\nexport function markOwnSheet(el: HTMLStyleElement): HTMLStyleElement {\r\n el.setAttribute(OWN_SHEET_ATTR, 'own')\r\n return el\r\n}\r\n\r\n/** Inject the design-system stylesheet once per document (HMR-safe). */\r\nexport function ensureUiCss(): void {\r\n if (typeof document === 'undefined') return\r\n let el = document.getElementById(CSS_ID) as HTMLStyleElement | null\r\n if (!el) {\r\n el = document.createElement('style')\r\n el.id = CSS_ID\r\n markOwnSheet(el)\r\n document.head.appendChild(el)\r\n }\r\n if (el.textContent !== UI_CSS) el.textContent = UI_CSS\r\n}\r\n","import { rWp, rBgState, rBl, rWop, rOps, rSop, rColor, rHasColor, rBlurs, rBgMode, rChatTextOpacity, rTrajectoryOpacity, rRightbarOpacity, rFadeMs, rTransition } from './state'\r\nimport type { PartOpacities, PartBlurs } from './types'\r\n// The switch's decision is pure and checked without a browser\r\n// (scripts/transition-check.ts); this file only applies it to the two layers.\r\nimport { transitionPlan } from './transition'\r\nimport type { LayerStyle } from './transition'\r\nimport { paletteFadeAllowed, paletteFadeCss, paletteFadeInline } from './palette-fade'\r\nimport { genTokens, toRgba } from './utils/color'\r\nimport { markOwnSheet } from './components/ui.css'\r\n\r\n/**\r\n * `data-ds-dark-theme` value the plugin writes while it forces its own dark\r\n * palette. The host treats the attribute as a boolean (`toggleAttribute`), so a\r\n * plugin-specific value still matches every `body[data-ds-dark-theme]` rule\r\n * while staying distinguishable from the host's own write — which is what lets\r\n * `releaseOwnScheme` hand the flag back without clobbering the host's scheme.\r\n */\r\nexport const OWN_SCHEME = 'dsh-background-by-model'\r\nconst DARK_ATTR = 'data-ds-dark-theme'\r\n\r\n/**\r\n * Marker on <html> while the plugin owns a palette. The dialog/trajectory rules\r\n * below redirect NO-fallback tokens (`--dsw-alias-bg-layer-*`) to plugin-owned\r\n * variables, so they may only match while those variables are actually written:\r\n * without the gate a palette-less state would leave them reading a\r\n * guaranteed-invalid value (transparent panels) instead of handing the surface\r\n * back to the host untouched.\r\n */\r\nconst THEMED_ATTR = 'data-dab-themed'\r\n\r\nlet wpEl: HTMLDivElement | null = null\r\nlet appliedTokenNames: string[] = []\r\nlet tokenStyleEl: HTMLStyleElement | null = null\r\n\r\nfunction ensureTokenStyle(): HTMLStyleElement {\r\n if (tokenStyleEl?.isConnected) return tokenStyleEl\r\n tokenStyleEl = document.createElement('style')\r\n tokenStyleEl.dataset.plugin = 'dsh-background-by-model-tokens'\r\n markOwnSheet(tokenStyleEl)\r\n document.head.appendChild(tokenStyleEl)\r\n return tokenStyleEl\r\n}\r\n\r\nfunction clearCustomTokens(): void {\r\n if (tokenStyleEl) tokenStyleEl.textContent = ''\r\n for (const name of appliedTokenNames) document.body.style.removeProperty(name)\r\n appliedTokenNames = []\r\n // Whatever follows must repaint from scratch: the fingerprints that guard the\r\n // token rule and the part opacities describe a stylesheet that no longer exists.\r\n baseTokenKey = ''\r\n lastBgKey = ''\r\n}\r\n\r\n/** Drop every surface the plugin owns: the variables the scoped\r\n * dialog/trajectory rules read, and the inline backgrounds written onto the\r\n * AppFrame columns. Used when no palette is available and at teardown — without\r\n * it the last color's surfaces outlive the color that produced them. */\r\nfunction clearOwnedSurfaces(): void {\r\n discoverParts()\r\n const root = document.documentElement\r\n for (const name of OWNED_SURFACE_VARS) root.style.removeProperty(name)\r\n for (const el of [frameEl, centerEl, detailsEl]) el?.style.removeProperty('background')\r\n}\r\n\r\n// Solid surface tokens grouped by which interface-opacity slider owns them.\r\n// Every member is re-emitted with per-part alpha so surfaces over the wallpaper\r\n// (composer input, elevated buttons, menu panels) can go translucent — not just\r\n// the layered bg/sidebar tokens. The two menu fills are owned by the card slider\r\n// and must always travel together: --dsw-specific-menu is what overlays paint\r\n// (dropdowns, slash-trigger menu, popovers around the dialog) and\r\n// --dsw-menu-surface-fill is what the shared MenuSurface material paints, which\r\n// dsh 0.1.7 aliases the former to. Re-emitting only one of them leaves a menu\r\n// panel on one fill and its sticky group headings on the other — the solid band\r\n// across the model selector's provider rows. The Cordis panel shares\r\n// --dsw-specific-menu but is re-scoped to the input slider via INPUT_BLUR_RULE.\r\nconst OPACITY_TOKEN_GROUPS: Array<{ part: keyof PartOpacities; names: string[] }> = [\r\n { part: 'bg', names: ['--dsw-alias-bg-base'] },\r\n { part: 'sidebar', names: ['--dsw-specific-sidebar-fill'] },\r\n { part: 'card', names: ['--dsw-alias-bg-layer-1', '--dsw-alias-bg-layer-2', '--dsw-alias-bg-layer-3', '--dsw-specific-menu', '--dsw-menu-surface-fill'] },\r\n { part: 'input', names: ['--dsw-specific-input-major'] },\r\n]\r\n\r\n// Plugin-owned variables the opacity-bearing tokens read from. They live as\r\n// inline custom props on <html>, so a slider drag rewrites only those few values\r\n// instead of re-parsing/re-matching the whole body token rule on every tick —\r\n// the difference is critical when a large wallpaper sits under the interface.\r\nconst OPACITY_VARS: Record<string, string> = {\r\n '--dsw-alias-bg-base': '--dsh-any-op-bg',\r\n '--dsw-specific-sidebar-fill': '--dsh-any-op-sidebar',\r\n '--dsw-alias-bg-layer-1': '--dsh-any-op-card-1',\r\n '--dsw-alias-bg-layer-2': '--dsh-any-op-card-2',\r\n '--dsw-alias-bg-layer-3': '--dsh-any-op-card-3',\r\n '--dsw-specific-input-major': '--dsh-any-op-input',\r\n // The MenuSurface material under a menu panel and the overlay fill its sticky\r\n // headings paint are the same value on a 0.1.7 host, so they read the same\r\n // plugin-owned variable — one slider, one alpha, no seam between them.\r\n '--dsw-specific-menu': '--dsh-any-op-menu',\r\n '--dsw-menu-surface-fill': '--dsh-any-op-menu',\r\n}\r\n\r\n// Fingerprint of the non-alpha token base (palette source + color pick +\r\n// scheme verdict). The static body rule is only rebuilt when it changes; a drag\r\n// never touches it.\r\nlet baseTokenKey = ''\r\n\r\n// ── Palette source ────────────────────────────────────────────────────────────\r\n// Every surface is painted from ONE palette at a time:\r\n// * a rule WITH a color → the plugin's generated token set;\r\n// * a rule WITHOUT a color → the host's own alias tokens, read back out of the\r\n// live cascade, so \"follow the system theme\" keeps the wallpaper showing and\r\n// the Interface-page sliders working instead of dropping every surface back\r\n// to the host as an opaque plate.\r\n// Both feed the same writers (the body token rule, the per-part alpha variables,\r\n// the dialog/trajectory scoping), so there is never a state where one surface is\r\n// painted from one palette and another from the other one.\r\nconst HOST_SURFACE_TOKENS: string[] = Object.keys(OPACITY_VARS)\r\n\r\n/** Plugin-owned variables the scoped dialog/trajectory rules read. */\r\nconst SETTINGS_SURFACE_VARS = [\r\n '--dsh-any-bg-settings-surface',\r\n '--dsh-any-bg-settings-layer-1',\r\n '--dsh-any-bg-settings-layer-2',\r\n '--dsh-any-bg-settings-layer-3',\r\n]\r\nconst TRAJECTORY_SURFACE_VARS = [\r\n '--dsh-any-traj-layer-1',\r\n '--dsh-any-traj-layer-2',\r\n '--dsh-any-traj-layer-3',\r\n]\r\nconst OWNED_SURFACE_VARS = [...SETTINGS_SURFACE_VARS, ...TRAJECTORY_SURFACE_VARS]\r\n\r\ninterface Palette {\r\n /** True while the palette is the plugin's own (the rule carries a color). */\r\n own: boolean\r\n tokens: Record<string, string>\r\n}\r\n\r\nlet hostProbe: HTMLElement | null = null\r\n\r\n/** Resolve any color the engine understands (hex, rgb()/hsl(), a var() chain,\r\n * color-mix(), …) to its USED value: only a used color can be re-emitted with\r\n * an alpha. Returns null when the engine rejects the value. */\r\nfunction resolveCssColor(raw: string): string | null {\r\n const value = raw.trim()\r\n if (value === '') return null\r\n if (hostProbe === null) {\r\n hostProbe = document.createElement('span')\r\n hostProbe.setAttribute('aria-hidden', 'true')\r\n hostProbe.style.cssText = 'position:absolute;width:0;height:0;pointer-events:none'\r\n }\r\n if (!hostProbe.isConnected) document.body.appendChild(hostProbe)\r\n // Reset first: a rejected value must not be mistaken for the previous one.\r\n hostProbe.style.color = ''\r\n hostProbe.style.color = value\r\n if (hostProbe.style.color === '') return null\r\n return getComputedStyle(hostProbe).color || null\r\n}\r\n\r\n/** Read the host's own surface colors out of the live cascade. */\r\nfunction readHostPalette(): Palette | null {\r\n const sheet = tokenStyleEl\r\n // Our token rule re-emits the very names being asked for, so it has to be\r\n // muted while reading or the readback would return the palette we are leaving.\r\n // No paint can happen in between: the flag is set and cleared in one task.\r\n const muted = sheet !== null && sheet.isConnected && !sheet.disabled\r\n if (muted) sheet!.disabled = true\r\n try {\r\n const computed = getComputedStyle(document.body)\r\n const tokens: Record<string, string> = {}\r\n for (const name of HOST_SURFACE_TOKENS) {\r\n const used = resolveCssColor(computed.getPropertyValue(name))\r\n if (used !== null) tokens[name] = used\r\n }\r\n // Without a base surface there is no palette to paint from: the caller hands\r\n // every surface back to the host instead.\r\n return tokens['--dsw-alias-bg-base'] === undefined ? null : { own: false, tokens }\r\n } finally {\r\n if (muted) sheet!.disabled = false\r\n }\r\n}\r\n\r\n// The readback costs a style recalculation and applyWp runs on every viewport\r\n// frame, so the last result is reused briefly. The theme-reset watch drops it on\r\n// any scheme change; the TTL covers a host palette rewritten without one.\r\nlet hostPaletteCache: { at: number; palette: Palette | null } | null = null\r\nconst HOST_PALETTE_TTL_MS = 1000\r\n\r\nexport function invalidateHostPalette(): void { hostPaletteCache = null }\r\n\r\nfunction hostPalette(): Palette | null {\r\n const now = Date.now()\r\n if (hostPaletteCache !== null && now - hostPaletteCache.at < HOST_PALETTE_TTL_MS) return hostPaletteCache.palette\r\n const read = readHostPalette()\r\n hostPaletteCache = { at: now, palette: read }\r\n return read\r\n}\r\n\r\n/** The palette every surface is currently painted from. */\r\nfunction palette(): Palette | null {\r\n if (!rHasColor()) return hostPalette()\r\n const [h, s, l] = rColor()\r\n return { own: true, tokens: genTokens(h, s, l).tokens }\r\n}\r\n\r\n/** A resolved color with a new alpha. The plugin's own tokens are `hsl()` and\r\n * the host's alias tokens resolve to hex, both of which `toRgba` parses; a host\r\n * publishing an already-composited value (`color(…)`, `oklab(…)`, …) cannot be\r\n * parsed there, and emitting it unchanged would paint an OPAQUE surface — the\r\n * one outcome the transparent-surface design must never fall back to. Those go\r\n * through `color-mix` instead. */\r\nfunction withAlpha(color: string, alpha: number): string {\r\n const converted = toRgba(color, alpha)\r\n if (/^(rgb|hsl)a?\\(/i.test(converted)) return converted\r\n const pct = Math.round(Math.max(0, Math.min(1, alpha)) * 100)\r\n return `color-mix(in srgb, ${color} ${pct}%, transparent)`\r\n}\r\n\r\n/**\r\n * The color scheme the HOST's own preference resolves to, pushed in by the\r\n * browser half (the theme service knows it, custom themes included). `null`\r\n * means \"unknown\", which is the only case where the plugin falls back to the\r\n * preference the host's boot script published and to the OS query itself.\r\n */\r\nlet hostSchemeDark: boolean | null = null\r\n\r\nexport function setHostScheme(dark: boolean | null): void { hostSchemeDark = dark }\r\n\r\nfunction resolveHostDark(): boolean {\r\n if (typeof hostSchemeDark === 'boolean') return hostSchemeDark\r\n // The host's boot script publishes the preference it resolved\r\n // (`html[data-ds-theme-source]`) before any plugin runs.\r\n const source = document.documentElement.dataset.dsThemeSource\r\n if (source === 'dark') return true\r\n if (source === 'light') return false\r\n try { return window.matchMedia('(prefers-color-scheme: dark)').matches } catch { return false }\r\n}\r\n\r\n/**\r\n * Keep `data-ds-dark-theme` in the HOST's own form (a boolean attribute) while\r\n * the plugin does not own a palette.\r\n *\r\n * The plugin overwrites that flag whenever it owns a palette — including\r\n * REMOVING it to force a light one — and the host only re-projects the flag on a\r\n * theme change. So a flag the plugin dropped can stick: the host keeps painting\r\n * its light palette on a dark system, the readback then hands those light\r\n * surfaces back to the plugin, and the interface stays light until some\r\n * unrelated event happens to re-run an apply. Restoring the flag from the\r\n * resolved scheme closes that hole, and the write is skipped when it already\r\n * matches so this never churns the theme observer.\r\n */\r\nexport function adoptHostScheme(): void {\r\n const dark = resolveHostDark()\r\n const current = document.body.getAttribute(DARK_ATTR)\r\n if (dark) {\r\n if (current !== '') document.body.setAttribute(DARK_ATTR, '')\r\n } else if (current !== null) {\r\n document.body.removeAttribute(DARK_ATTR)\r\n }\r\n}\r\n\r\n/** Re-read the host palette and repaint from it when it moved. Called while a\r\n * color-less rule is active (the host can re-project its palette at any time,\r\n * with no event of ours to hang a repaint on). */\r\nexport function refreshSystemTheme(): void {\r\n adoptHostScheme()\r\n invalidateHostPalette()\r\n applyCustomTokens(rOps())\r\n}\r\n\r\n// Coalesce slider-driven token updates to one rAF: a single drag fires several\r\n// input events per frame, and every full re-apply repaints expensive regions\r\n// over a large wallpaper. Batching keeps at most one update per frame.\r\nlet pendingOps: PartOpacities | null = null\r\nlet tokensRaf: number | null = null\r\n/** When the pending frame was armed, so a frame that never ran can be spotted. */\r\nlet tokensArmedAt = 0\r\n/** A frame outstanding for longer than this is treated as lost (see below). */\r\nconst STALE_TOKENS_RAF_MS = 1_000\r\n\r\n/** The fingerprint of the palette + colour in force; see `applyCustomTokensNow`. */\r\nfunction paletteKey(src: Palette, color: [number, number, number]): string {\r\n return src.own\r\n ? `own:${color[0]}|${color[1]}|${color[2]}`\r\n : `host:${HOST_SURFACE_TOKENS.map(n => src.tokens[n] ?? '').join('|')}`\r\n}\r\n\r\n/**\r\n * Re-emit the interface palette, coalescing a slider drag into one frame.\r\n *\r\n * A PALETTE change is never coalesced, and that distinction is the whole point:\r\n * this call is the only writer of the palette's INK. Every other surface has a\r\n * second, synchronous writer (the dialog's layer tokens come from\r\n * `applySettingsOverrides`, the columns' backgrounds from the view cards, the\r\n * `--dsh-any-op-*` alphas from the same callback as the ink), so a palette update\r\n * that is deferred and then lost leaves the surfaces on the NEW colour and the\r\n * ink on the previous one — a dark palette with dark text, which reads as\r\n * \"the theme colour did nothing\" and only a reload clears it.\r\n *\r\n * Measured in the field: a window that is not rendering can swallow the frame\r\n * (the id stays armed, so every later update parks behind it), and a failure\r\n * inside the write used to be swallowed by an empty `catch`. Both are handled\r\n * here — a changed palette goes through synchronously, a stale frame is dropped\r\n * instead of blocking forever, and the failure is logged (see `applyCustomTokensNow`).\r\n */\r\nexport function applyCustomTokens(ops: PartOpacities): boolean {\r\n pendingOps = ops\r\n const src = palette()\r\n // Synchronous whenever the palette itself moved: that is a model switch, a\r\n // rotation step, a rule edit or an image colour, i.e. exactly the cases where\r\n // ink and surfaces must land together (`applyWp` already runs synchronously).\r\n // The return value is that same fact shortened by one question — may this\r\n // change fade? — for the callers that paint their own surfaces inline and have\r\n // to decide whether to animate them (`paletteFadeAllowed`).\r\n if (src !== null && paletteKey(src, rColor()) !== baseTokenKey) { flushTokens(); return lastFadeable }\r\n if (tokensRaf !== null) {\r\n if (Date.now() - tokensArmedAt <= STALE_TOKENS_RAF_MS) return false\r\n // The frame this id belongs to is never going to run: cancelling it lets the\r\n // update through now instead of parking every later one behind a dead id.\r\n window.cancelAnimationFrame(tokensRaf)\r\n tokensRaf = null\r\n }\r\n tokensArmedAt = Date.now()\r\n tokensRaf = requestAnimationFrame(() => {\r\n tokensRaf = null\r\n flushTokens()\r\n })\r\n return false\r\n}\r\n\r\n/** Run the pending token write now (one funnel, so no path can skip it). */\r\nfunction flushTokens(): void {\r\n if (pendingOps === null) return\r\n const o = pendingOps\r\n pendingOps = null\r\n applyCustomTokensNow(o)\r\n}\r\n\r\n// Only the main-bg slider retints the center/details columns; keys on\r\n// baseTokenKey + ops.bg so a sidebar/card/input drag never rewrites them.\r\nlet lastBgKey = ''\r\n/**\r\n * Whether the palette write in flight may fade — the answer `applyCustomTokens`\r\n * hands back to the callers that paint their own surfaces inline.\r\n *\r\n * It has to travel out of `applyCustomTokensNow` (which is where the decision is\r\n * made) because those callers run AFTER it in the same task, and re-deciding\r\n * there would be a second opinion on the same question.\r\n */\r\nlet lastFadeable = false\r\n\r\nfunction applyCustomTokensNow(ops: PartOpacities): void {\r\n lastFadeable = false\r\n const src = palette()\r\n if (src === null) {\r\n // Nothing to paint from: drop the token rule too, then hand every\r\n // plugin-owned surface — and the scheme flag — back to the host rather than\r\n // leaving the previous palette's values in place.\r\n clearCustomTokens()\r\n clearOwnedSurfaces()\r\n adoptHostScheme()\r\n return\r\n }\r\n const { own, tokens } = src\r\n const [h, s, l] = rColor()\r\n try {\r\n const forceDark = own && l < 0.55\r\n // The fingerprint carries the source, so switching between the two palettes\r\n // always rewrites the rule, even when the numbers happen to coincide.\r\n const key = paletteKey(src, [h, s, l])\r\n const paletteChanged = key !== baseTokenKey\r\n // Which palette family is in force: the plugin's own verdict when it owns the\r\n // palette, the host's scheme when the rule follows the system theme.\r\n const scheme: 'light' | 'dark' = own ? (forceDark ? 'dark' : 'light') : (resolveHostDark() ? 'dark' : 'light')\r\n // A colour change may fade only while the SCHEME stays put — see\r\n // `paletteFadeAllowed`. A light↔dark flip is a different palette, not a tint\r\n // of the same one, and the wallpaper's own animation is unaffected either way.\r\n const fadeable = paletteChanged && paletteFadeAllowed(paletteScheme, scheme)\r\n lastFadeable = fadeable\r\n // BEFORE the tokens are written: whether a colour change may fade at all, and\r\n // for how long, is decided here for both halves of a switch. A palette change\r\n // arms the transition; every other pass (a slider moving the alphas) DISARMS\r\n // it in the same task, so a drag stays glued to the pointer.\r\n applyPaletteFade(fadeable)\r\n if (paletteChanged) {\r\n paletteScheme = scheme\r\n // Drive the base-palette switch with a plugin-specific value so the\r\n // gradient rule never matches a host dark-mode flag; color-scheme makes\r\n // native controls (select popups) follow the forced palette. Both ride the\r\n // stylesheet (not inline styles) so the host presenter clearing body\r\n // inline styles on boot can't drop them, and the !important rule survives\r\n // that clearing too.\r\n if (own) {\r\n if (forceDark) document.body.setAttribute(DARK_ATTR, OWN_SCHEME)\r\n else document.body.removeAttribute(DARK_ATTR)\r\n } else {\r\n adoptHostScheme()\r\n }\r\n const decls: string[] = own ? [`color-scheme:${forceDark ? 'dark' : 'light'}`] : []\r\n for (const [name, value] of Object.entries(tokens)) {\r\n const opVar = OPACITY_VARS[name]\r\n decls.push(`${name}:${opVar !== undefined ? `var(${opVar})` : value}!important`)\r\n }\r\n ensureTokenStyle().textContent = `body{${decls.join(';')}}`\r\n if (own) {\r\n // Drop inline tokens left by earlier builds so the stylesheet is the single source of truth.\r\n for (const name of appliedTokenNames) document.body.style.removeProperty(name)\r\n appliedTokenNames = Object.keys(tokens)\r\n }\r\n // Recorded only once the rule is in: a write that threw must be retried by\r\n // the next apply instead of being skipped by this fingerprint forever.\r\n baseTokenKey = key\r\n }\r\n // Cheap per-drag update: only the surface alpha vars move on <html>.\r\n const root = document.documentElement\r\n for (const g of OPACITY_TOKEN_GROUPS) {\r\n for (const name of g.names) {\r\n root.style.setProperty(OPACITY_VARS[name], withAlpha(tokens[name] ?? '#000', ops[g.part]))\r\n }\r\n }\r\n // The Cordis panel keeps its own input-slider alpha (see INPUT_BLUR_RULE).\r\n root.style.setProperty('--dsh-any-op-menu-cordis', withAlpha(tokens['--dsw-specific-menu'] ?? '#000', ops.input))\r\n const bgKey = `${baseTokenKey}|${ops.bg}`\r\n if (bgKey !== lastBgKey) { lastBgKey = bgKey; applyPartOpacities(ops, fadeable) }\r\n } catch (e) {\r\n // Never silent. This block is the ONLY writer of the palette's ink, and a\r\n // failure swallowed here leaves the interface on the previous palette's text\r\n // colour while every surface follows the new one — a dark panel with dark\r\n // text that no amount of switching models repairs and only a reload clears.\r\n // It used to be `catch {}`, which is why that state was invisible in the log.\r\n console.warn('dsh-background-by-model: could not re-emit the palette tokens', e)\r\n }\r\n}\r\n\r\n// ── Settings panel opacity ─────────────────────────────────────────────────────\r\n// The settings modal is the only aria-modal dialog identifying itself with\r\n// aria-labelledby, so this selector scopes translucency to the settings panel.\r\n// The surface (--dsw-alias-bg-layer-2) is re-emitted with an alpha through a\r\n// plugin-owned variable so the panel keeps its color while fading.\r\n\r\nconst SETTINGS_PANEL_SEL = '[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]'\r\nexport const SETTINGS_STYLE_RULE =\r\n `${SETTINGS_PANEL_SEL}{` +\r\n `background:var(--dsh-any-bg-settings-surface,var(--dsw-alias-bg-layer-2));` +\r\n `backdrop-filter:var(--dsh-any-blur-settings,none);` +\r\n `}` +\r\n // Re-scope the dialog's layer tokens to plugin-owned variables so every\r\n // surface inside the dialog follows the settings opacity slider only. Gated on\r\n // the plugin owning a palette (see THEMED_ATTR): these three declarations have\r\n // no host fallback, so they may only be live while `applySettingsOverrides`\r\n // writes the variables they read.\r\n `html[${THEMED_ATTR}] ${SETTINGS_PANEL_SEL}{` +\r\n `--dsw-alias-bg-layer-1:var(--dsh-any-bg-settings-layer-1);` +\r\n `--dsw-alias-bg-layer-2:var(--dsh-any-bg-settings-layer-2);` +\r\n `--dsw-alias-bg-layer-3:var(--dsh-any-bg-settings-layer-3)}` +\r\n // Option-panel blur inside the dialog, owned by the card blur slider.\r\n `${SETTINGS_PANEL_SEL} .dab-card{backdrop-filter:var(--dsh-any-blur-card-panels,none);-webkit-backdrop-filter:var(--dsh-any-blur-card-panels,none)}`\r\n\r\n// Input/control surface blur. The composer card and the Cordis panel expose\r\n// stable host data attributes ([data-composer-card], [data-cordis-panel]), so\r\n// the backdrop is attached via a stylesheet rule rather than element discovery.\r\n// The Cordis panel shares the --dsw-specific-menu token with the dialog's\r\n// option boxes, but it stays owned by the input slider — the re-scope below\r\n// keeps it there now that the menu token itself follows the card slider. Note\r\n// the input slider must NOT drive the button-elevated-fill /\r\n// button-floating-hover tokens: the settings panel's own controls (slider\r\n// thumbs, .dab-btn, segmented thumb) are painted from those same tokens, so\r\n// tinting them would bleach the panel's own UI.\r\nexport const INPUT_BLUR_RULE =\r\n '[data-composer-card],[data-cordis-panel]{' +\r\n '-webkit-backdrop-filter:var(--dsh-any-input-blur,none);' +\r\n 'backdrop-filter:var(--dsh-any-input-blur,none)}' +\r\n '[data-cordis-panel]{--dsw-specific-menu:var(--dsh-any-op-menu-cordis)!important}'\r\n\r\nfunction applyInputBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-input-blur', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-input-blur')\r\n}\r\n\r\n// Placeholder/hint text inside the composer and the plugin's own input\r\n// surfaces: rendered with the weak caption token (distinct from real input)\r\n// plus italic, so an empty box is never mistaken for typed content.\r\nexport const PLACEHOLDER_RULE =\r\n '[data-composer-card] textarea::placeholder,' +\r\n '[data-composer-card] input::placeholder,' +\r\n '[data-composer-card] [contenteditable]::placeholder,' +\r\n '[data-cordis-panel] input::placeholder,' +\r\n '[data-cordis-panel] textarea::placeholder,' +\r\n '.dab-input::placeholder,' +\r\n '.dab-input textarea::placeholder,' +\r\n '.dab-input input::placeholder' +\r\n '{color:var(--dsh-any-placeholder,var(--dsw-alias-label-caption,#8a8f98))!important;font-style:italic;opacity:.85}'\r\n\r\nexport function applySettingsOverrides(op: number): void {\r\n // Follows whichever palette is in force: the rule's own tokens, or the host's\r\n // own surfaces while the rule follows the system theme. A token the palette\r\n // does not carry has its variable REMOVED — leaving the previous color's value\r\n // behind is exactly the stale surface this used to show.\r\n const tokens = palette()?.tokens ?? {}\r\n const root = document.documentElement\r\n const write = (name: string, token: string): void => {\r\n const value = tokens[token]\r\n if (value === undefined) root.style.removeProperty(name)\r\n else root.style.setProperty(name, withAlpha(value, op))\r\n }\r\n // Always written explicitly (including 100%) — removing them would make\r\n // SETTINGS_STYLE_RULE fall back to the body layer tokens that\r\n // applyCustomTokens rewrites with the homepage card alpha.\r\n write('--dsh-any-bg-settings-surface', '--dsw-alias-bg-layer-2')\r\n // Dialog-scoped layer overrides consumed by SETTINGS_STYLE_RULE; opacity\r\n // follows the settings slider only (the card slider reaches panels via blur).\r\n write('--dsh-any-bg-settings-layer-1', '--dsw-alias-bg-layer-1')\r\n write('--dsh-any-bg-settings-layer-2', '--dsw-alias-bg-layer-2')\r\n write('--dsh-any-bg-settings-layer-3', '--dsw-alias-bg-layer-3')\r\n}\r\n\r\n// ── Trajectory view opacity ──────────────────────────────────────────────\r\n// The trajectory view's own panels fully cover the root, so retinting only the\r\n// root background is invisible. Re-scope the view root's layer tokens to\r\n// plugin-owned variables so every surface follows the trajectory slider.\r\nexport const TRAJECTORY_STYLE_RULE =\r\n // Gated like the settings re-scope: see THEMED_ATTR.\r\n `html[${THEMED_ATTR}] [data-conversation-composer-overlay]{` +\r\n // No fallback inside var(): a self-referential fallback would be a cycle.\r\n '--dsw-alias-bg-layer-1:var(--dsh-any-traj-layer-1);' +\r\n '--dsw-alias-bg-layer-2:var(--dsh-any-traj-layer-2);' +\r\n '--dsw-alias-bg-layer-3:var(--dsh-any-traj-layer-3)}'\r\n\r\nexport function applyTrajectoryOverrides(op: number): void {\r\n // Always written explicitly so the view stays owned by this slider at 100%,\r\n // and removed per token the palette lacks (see applySettingsOverrides).\r\n const tokens = palette()?.tokens ?? {}\r\n const root = document.documentElement\r\n const write = (name: string, token: string): void => {\r\n const value = tokens[token]\r\n if (value === undefined) root.style.removeProperty(name)\r\n else root.style.setProperty(name, withAlpha(value, op))\r\n }\r\n write('--dsh-any-traj-layer-1', '--dsw-alias-bg-layer-1')\r\n write('--dsh-any-traj-layer-2', '--dsw-alias-bg-layer-2')\r\n write('--dsh-any-traj-layer-3', '--dsw-alias-bg-layer-3')\r\n}\r\n\r\n// ── Palette fade (a theme-colour change that interpolates) ────────────────\r\n// Writing the token block is what changes every surface, and by default that\r\n// change is instantaneous: the wallpaper cross-fades while the interface jumps.\r\n// The fade is a REGISTRATION problem, not a declaration one — an unregistered\r\n// custom property cannot interpolate — so the palette's own tokens are registered\r\n// as `<color>`s and the elements that (re)declare them carry a transition for the\r\n// same duration the switch uses. See ./palette-fade for what is registered and why\r\n// a token the host does not publish is left alone.\r\nconst TRAJECTORY_ROOT_SEL = '[data-conversation-composer-overlay]'\r\n\r\n/** Elements whose own token declarations change when the palette does: the body\r\n * (which everything else inherits), and the two surfaces that RE-declare the\r\n * layer tokens instead of inheriting them. */\r\nconst FADE_SELECTORS: readonly string[] = ['body', SETTINGS_PANEL_SEL, TRAJECTORY_ROOT_SEL]\r\n\r\n/** The token names the plugin re-emits. One palette is enough: every branch\r\n * defines the same set, and an unknown name would only be registered when the\r\n * host can answer for it (see `fadeInitials`). */\r\nfunction fadeTokenNames(): string[] {\r\n return Object.keys(genTokens(220, 0.55, 0.25).tokens)\r\n}\r\n\r\nlet fadeStyleEl: HTMLStyleElement | null = null\r\nlet fadeInitials: Record<string, string> | null = null\r\nlet fadeCssCache = ''\r\n/** The scheme the last written palette had, so a FLIP can be told from a tint. */\r\nlet paletteScheme: 'light' | 'dark' | null = null\r\n\r\nfunction ensureFadeSheet(): HTMLStyleElement {\r\n if (fadeStyleEl?.isConnected) return fadeStyleEl\r\n fadeStyleEl = document.createElement('style')\r\n fadeStyleEl.dataset.plugin = 'dsh-background-by-model-fade'\r\n markOwnSheet(fadeStyleEl)\r\n document.head.appendChild(fadeStyleEl)\r\n return fadeStyleEl\r\n}\r\n\r\n/**\r\n * The host's own value for each token — the `initial-value` a registration needs,\r\n * and the test for whether a token may be registered at all.\r\n *\r\n * Read with the plugin's token sheet muted, for the same reason `readHostPalette`\r\n * does it: our rule re-emits the very names being asked for. Cached, because the\r\n * answer only changes with the host's scheme and a stale hint is only ever used\r\n * for a token the host does not publish anyway.\r\n */\r\nfunction fadeInitialsOf(names: readonly string[]): Record<string, string> {\r\n if (fadeInitials !== null) return fadeInitials\r\n const sheet = tokenStyleEl\r\n const muted = sheet !== null && sheet.isConnected && !sheet.disabled\r\n if (muted) sheet!.disabled = true\r\n try {\r\n const computed = getComputedStyle(document.body)\r\n const out: Record<string, string> = {}\r\n for (const name of names) {\r\n // `resolveCssColor` rejects anything the engine will not read as a COLOUR,\r\n // which is exactly the set a `<color>` registration can carry.\r\n const used = resolveCssColor(computed.getPropertyValue(name))\r\n if (used !== null) out[name] = used\r\n }\r\n fadeInitials = out\r\n return out\r\n } catch {\r\n fadeInitials = {}\r\n return fadeInitials\r\n } finally {\r\n if (muted) sheet!.disabled = false\r\n }\r\n}\r\n\r\n/** How long a colour change may take, or `0` for \"do not animate it\".\r\n *\r\n * The same decision the wallpaper layer makes (`transitionPlan` over the global\r\n * effect, the resolved duration and the OS preference), so the two halves of one\r\n * switch can never disagree about whether they are animating. */\r\nfunction paletteFadeMs(): number {\r\n const tr = rTransition()\r\n const plan = transitionPlan({\r\n effect: tr.effect,\r\n easing: tr.easing,\r\n durationMs: rFadeMs(),\r\n canAnimate: true,\r\n reducedMotion: prefersReducedMotion(),\r\n })\r\n return plan.animate ? plan.durationMs : 0\r\n}\r\n\r\n/** Arm the fade for a palette change, or disarm it for anything else.\r\n *\r\n * `animate` is false on every pass that only moves an alpha (a slider drag): the\r\n * tokens are rewritten there too, and a live transition would make the surface\r\n * lag behind the pointer. */\r\nfunction applyPaletteFade(animate: boolean): void {\r\n const initials = fadeInitialsOf(fadeTokenNames())\r\n const css = paletteFadeCss({\r\n selectors: FADE_SELECTORS,\r\n initial: initials,\r\n durationMs: animate ? paletteFadeMs() : 0,\r\n easing: rTransition().easing,\r\n })\r\n if (css === fadeCssCache) return\r\n fadeCssCache = css\r\n ensureFadeSheet().textContent = css\r\n}\r\n\r\n/** Inline `transition` for an element the plugin paints itself; `0` disarms it. */\r\nfunction fadeInlineFor(animate: boolean): string {\r\n return paletteFadeInline(animate ? paletteFadeMs() : 0, rTransition().easing)\r\n}\r\n\r\n// ── File-preview panel (right sidebar) ────────────────────────────────────\r\n// Clicking a file opens the host's right panel, whose visible surface is painted\r\n// from `background: var(--dsw-alias-bg-base)` — the exact token the\r\n// main-background slider re-emits with its own alpha. The panel was therefore a\r\n// second, unnamed copy of the main background with no control of its own; this\r\n// card takes it over, on whichever element the host paints that surface.\r\n//\r\n// dsh 0.1.7 moved the paint off the panel: the container lost its background and\r\n// became the slide / fullscreen viewport, and it stays mounted at its full width\r\n// for the whole session — collapsing it only slides the dock out (`transform` +\r\n// `visibility`, never `display`). A surface (plus a backdrop-filter) written on\r\n// that container therefore covers the empty right half of the frame even with\r\n// the panel closed, which is the permanent frosted plate 0.1.7 shows. The dock's\r\n// own tab hosts are what the host paints now, so the card follows them:\r\n//\r\n// 0.1.7+ the dock's tab hosts — `[data-dockkit-content]` (and the\r\n// `[data-dockkit-empty]` seat of an empty pane), painted by the host\r\n// from the same token and hidden with `visibility`, so the card rides\r\n// the host's own open/close and slide transitions for free. Floating\r\n// panes are excluded exactly as the host excludes them.\r\n// older the panel itself, which used to carry that background on its hashed\r\n// class. `:has()` keeps the two apart, so the alpha is never painted\r\n// twice over on a 0.1.7 host.\r\n//\r\n// The selectors use data attributes (not the hashed CSS-module classes) and\r\n// `!important` outranks the host's class rule. The `var()` fallback keeps the\r\n// host's own value until a rule with a color supplies one, so a color-less rule\r\n// changes nothing here.\r\n//\r\n// backdrop-filter stays on the container — that is where this card has always\r\n// put it, and it keeps the panel to a single filter pass — but only while the\r\n// panel is open: an always-on filter is what turned the collapsed panel into a\r\n// plate.\r\nexport const RIGHTBAR_STYLE_RULE =\r\n 'div[data-sidebar-right-panel]:not(:has([data-dockkit-content],[data-dockkit-empty]))[data-sidebar-right-open],' +\r\n 'div[data-sidebar-right-panel] [data-dockkit-content]:not([data-dockkit-float]),' +\r\n 'div[data-sidebar-right-panel] [data-dockkit-empty]{' +\r\n 'background:var(--dsh-any-bg-rightbar,var(--dsw-alias-bg-base))!important}' +\r\n 'div[data-sidebar-right-panel][data-sidebar-right-open]{' +\r\n '-webkit-backdrop-filter:var(--dsh-any-blur-rightbar,none);' +\r\n 'backdrop-filter:var(--dsh-any-blur-rightbar,none)}'\r\n\r\n/** Paint the file-preview panel's surface from its own slider. */\r\nexport function applyRightbarOverrides(op: number): void {\r\n const root = document.documentElement\r\n // The panel is painted from the palette in force like every other surface;\r\n // only when there is no palette at all (a host publishing none of the tokens\r\n // we re-emit) does it keep the host's own --dsw-alias-bg-base.\r\n const base = palette()?.tokens['--dsw-alias-bg-base']\r\n if (base === undefined) { root.style.removeProperty('--dsh-any-bg-rightbar'); return }\r\n root.style.setProperty('--dsh-any-bg-rightbar', withAlpha(base, op))\r\n}\r\n\r\n/** Extra backdrop frost for the file-preview panel (0 = no frost of its own). */\r\nfunction applyRightbarBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-blur-rightbar', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-blur-rightbar')\r\n}\r\n\r\n// ── Per-part interface blur ───────────────────────────────────────────────────\r\n// The AppFrame columns use hashed CSS-module classes, so parts are located\r\n// structurally: the shell overlay carries a stable data attribute and the\r\n// sidebar/center/details columns are its three preceding siblings.\r\n//\r\n// backdrop-filter must NEVER go directly on a host part: it turns the element\r\n// into a containing block for fixed-positioned descendants, which would trap\r\n// the host's settings dialog inside the column. Each blurred part carries an\r\n// isolated ::before underlay holding the backdrop-filter instead.\r\nlet frameEl: HTMLElement | null = null\r\nlet sidebarEl: HTMLElement | null = null\r\nlet centerEl: HTMLElement | null = null\r\nlet detailsEl: HTMLElement | null = null\r\n\r\nconst PART_BLUR_CLASS = 'dab-part-blur'\r\nconst PART_UNDERLAY_CLASS = 'dab-part-underlay'\r\nconst PART_BLUR_RULE =\r\n `${PART_BLUR_CLASS}{isolation:isolate}` +\r\n `.${PART_UNDERLAY_CLASS}{position:absolute;inset:0;z-index:-1;pointer-events:none;border-radius:inherit;` +\r\n `backdrop-filter:var(--dsh-any-part-blur,none);-webkit-backdrop-filter:var(--dsh-any-part-blur,none)}`\r\n\r\nlet partBlurStyleEl: HTMLStyleElement | null = null\r\n\r\nfunction ensurePartBlurStyle(): void {\r\n if (partBlurStyleEl?.isConnected) return\r\n partBlurStyleEl = document.createElement('style')\r\n partBlurStyleEl.dataset.plugin = 'dsh-background-by-model-parts'\r\n markOwnSheet(partBlurStyleEl)\r\n partBlurStyleEl.textContent = PART_BLUR_RULE\r\n document.head.appendChild(partBlurStyleEl)\r\n}\r\n\r\nfunction discoverParts(): void {\r\n const overlay = document.querySelector<HTMLElement>('[data-shell-overlay]')\r\n if (overlay === null) return\r\n const frame = overlay.parentElement\r\n if (frame === null) return\r\n frameEl = frame\r\n const idx = Array.from(frame.children).indexOf(overlay)\r\n sidebarEl = (frame.children[idx - 3] as HTMLElement | undefined) ?? null\r\n centerEl = (frame.children[idx - 2] as HTMLElement | undefined) ?? null\r\n detailsEl = (frame.children[idx - 1] as HTMLElement | undefined) ?? null\r\n}\r\n\r\nfunction setBlur(el: HTMLElement | null, px: number): void {\r\n if (el === null) return\r\n const underlay = el.querySelector<HTMLDivElement>(`:scope > .${PART_UNDERLAY_CLASS}`)\r\n if (px > 0) {\r\n ensurePartBlurStyle()\r\n // The underlay is position:absolute and needs a positioned host: static\r\n // columns get relative (a layout no-op for flex items) that is restored on\r\n // clear; parts the host already positions keep their own scheme.\r\n if (!el.classList.contains(PART_BLUR_CLASS) && getComputedStyle(el).position === 'static') {\r\n el.style.position = 'relative'\r\n el.setAttribute('data-dab-pos-patched', '1')\r\n }\r\n el.classList.add(PART_BLUR_CLASS)\r\n if (underlay === null) {\r\n const node = document.createElement('div')\r\n node.className = PART_UNDERLAY_CLASS\r\n el.prepend(node)\r\n }\r\n el.style.setProperty('--dsh-any-part-blur', `blur(${px}px)`)\r\n } else {\r\n el.classList.remove(PART_BLUR_CLASS)\r\n el.style.removeProperty('--dsh-any-part-blur')\r\n underlay?.remove()\r\n if (el.getAttribute('data-dab-pos-patched') === '1') {\r\n el.style.removeProperty('position')\r\n el.removeAttribute('data-dab-pos-patched')\r\n }\r\n }\r\n}\r\n\r\nfunction applySettingsBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-blur-settings', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-blur-settings')\r\n}\r\n\r\n/** Apply the main-background opacity to the center/details columns instead of\r\n * the frame. The frame's translucent bg-base sits UNDER the sidebar, so\r\n * reducing the main-bg opacity stacked a second alpha onto the sidebar; moving\r\n * the alpha onto the columns keeps the sidebar owned by its own slider. */\r\nfunction applyPartOpacities(ops: PartOpacities, fade = false): void {\r\n discoverParts()\r\n if (frameEl === null) return\r\n const base = palette()?.tokens['--dsw-alias-bg-base']\r\n if (base === undefined) {\r\n // No palette to paint from: hand the columns back to the host instead of\r\n // leaving the last color's inline background on them.\r\n for (const el of [frameEl, centerEl, detailsEl]) el?.style.removeProperty('background')\r\n return\r\n }\r\n frameEl.style.background = 'transparent'\r\n // The columns are painted INLINE, so they do not read the registered tokens and\r\n // would snap while everything inheriting them fades; `fade` carries the same\r\n // duration, and is false whenever only an alpha moved (a drag must not lag).\r\n // `none` is written in that case rather than '' — an empty value would leave\r\n // whatever the host declared on the element.\r\n const transition = fadeInlineFor(fade)\r\n if (centerEl !== null) {\r\n centerEl.style.transition = transition\r\n centerEl.style.background = withAlpha(base, ops.bg)\r\n }\r\n if (detailsEl !== null) {\r\n detailsEl.style.transition = transition\r\n detailsEl.style.background = withAlpha(base, ops.bg)\r\n }\r\n}\r\n\r\n/** Blur of the option panels inside the settings dialog (.dab-card), owned by\r\n * the \"dialog option panel\" (card) blur slider. Written as a plugin-owned\r\n * variable consumed by SETTINGS_STYLE_RULE — deliberately NOT applied to the\r\n * homepage center/details columns, which this slider must never touch. */\r\nfunction applyCardPanelsBlur(px: number): void {\r\n if (px > 0) document.documentElement.style.setProperty('--dsh-any-blur-card-panels', `blur(${px}px)`)\r\n else document.documentElement.style.removeProperty('--dsh-any-blur-card-panels')\r\n}\r\n\r\n/** Apply per-part interface blur to the AppFrame columns + settings panel. */\r\nexport function applyPartBlurs(blurs: PartBlurs): void {\r\n discoverParts()\r\n // The bg blur frosts the wallpaper behind the main content columns (center +\r\n // details); the frame itself stays unblurred so the sidebar is never\r\n // double-frosted by both the bg and sidebar sliders.\r\n setBlur(frameEl, 0)\r\n setBlur(sidebarEl, blurs.sidebar)\r\n setBlur(centerEl, blurs.bg)\r\n setBlur(detailsEl, blurs.bg)\r\n applyCardPanelsBlur(blurs.card)\r\n applySettingsBlur(blurs.settings)\r\n applyInputBlur(blurs.input)\r\n applyRightbarBlur(blurs.rightbar)\r\n applyViewCards()\r\n}\r\n\r\n/** Live per-part blur update during slider drag (no full re-apply). */\r\nexport function setPartBlur(part: keyof PartBlurs, v: number): void {\r\n if (part === 'settings') { applySettingsBlur(v); return }\r\n if (part === 'card') { applyCardPanelsBlur(v); return }\r\n if (part === 'input') { applyInputBlur(v); return }\r\n if (part === 'rightbar') { applyRightbarBlur(v); return }\r\n if (part === 'chat' || part === 'trajectory') { applyViewCards(); return }\r\n discoverParts()\r\n if (part === 'bg') { setBlur(centerEl, v); setBlur(detailsEl, v) }\r\n else setBlur(sidebarEl, v)\r\n}\r\n\r\n// ── Conversation view treatments ────────────────────────────────────\r\n// The chat message column is styled as a real card (layer-1 surface + border +\r\n// 16px radius + 18px padding); the trajectory view gets NO card decoration —\r\n// its own panels fully cover the view root, so its opacity slider re-scopes the\r\n// layer tokens inside the view and its blur frosts the backdrop through the\r\n// standard root underlay.\r\n//\r\n// Host structure (deepseek-harness ui-conversation / ui-trajectory):\r\n// ConversationRoot\r\n// header — title + tabs, OUTSIDE the scrollport\r\n// [data-conversation-scroll] — the single scrollport\r\n// [data-chat-flow] ← chat column (flow content, NOT scrollable)\r\n// [data-conversation-composer-overlay] ← trajectory view root\r\n// [data-composer-seat] — sticky composer, a sibling\r\n// Cards are ALWAYS styled once their host exists — sliders at zero only turn\r\n// surface/border transparent, so the layout never reflows and the view cannot\r\n// jump when a slider leaves zero. Removal happens only at plugin teardown.\r\ninterface ViewCardSpec {\r\n sel: string\r\n mark: string\r\n /** Dataset key prefix holding the stashed pre-card inline values. */\r\n prev: string\r\n opacity: () => number\r\n blur: () => number\r\n /** Generic heuristic fallback (chat card only, hosts without the marker). */\r\n fallback?: boolean\r\n /** No card decoration — surfaces follow scoped layer tokens; only the blur\r\n * underlay is attached to the host element. */\r\n plain?: boolean\r\n}\r\n\r\nconst VIEW_CARDS: ViewCardSpec[] = [\r\n { sel: '[data-chat-flow]', mark: 'data-dab-chat-card', prev: 'dabChatPrev', opacity: rChatTextOpacity, blur: () => rBlurs().chat, fallback: true },\r\n { sel: '[data-conversation-composer-overlay]', mark: 'data-dab-traj-card', prev: 'dabTrajPrev', opacity: rTrajectoryOpacity, blur: () => rBlurs().trajectory, plain: true },\r\n]\r\n\r\nconst viewTargets: Array<HTMLElement | null> = VIEW_CARDS.map(() => null)\r\n\r\nfunction isScrollableY(el: HTMLElement): boolean {\r\n const oy = getComputedStyle(el).overflowY\r\n // 'overlay' covers Chromium's non-standard overflow value.\r\n return oy === 'auto' || oy === 'scroll' || oy === 'overlay'\r\n}\r\n\r\n/** Whether the subtree hosts the chat input (textarea / contenteditable /\r\n * textbox role) — used to keep the card off the input row. */\r\nfunction containsChatEditor(el: HTMLElement): boolean {\r\n return el.querySelector('textarea,[contenteditable=\"true\"],[contenteditable=\"\"],[contenteditable=\"plaintext-only\"],[role=\"textbox\"]') !== null\r\n}\r\n\r\n/** Walk down from a coarse candidate toward the actual message column. */\r\nfunction refineMessageColumn(start: HTMLElement): HTMLElement {\r\n let cur = start\r\n for (let depth = 0; depth < 10; depth++) {\r\n if (isScrollableY(cur)) break\r\n const kids = Array.from(cur.children).filter((k): k is HTMLElement => k instanceof HTMLElement)\r\n if (kids.length === 0) break\r\n const tallest = kids.reduce((a, b) => (b.clientHeight > a.clientHeight ? b : a))\r\n if (containsChatEditor(cur)) {\r\n const candidates = kids.filter(k => !containsChatEditor(k) && k.clientHeight >= cur.clientHeight * 0.4)\r\n if (candidates.length === 0) break\r\n cur = candidates.reduce((a, b) => (b.clientHeight > a.clientHeight ? b : a))\r\n continue\r\n }\r\n if (kids.length > 1 && tallest.clientHeight >= cur.clientHeight * 0.85) { cur = tallest; continue }\r\n break\r\n }\r\n return cur\r\n}\r\n\r\nfunction discoverViewTarget(idx: number, spec: ViewCardSpec): HTMLElement | null {\r\n if (centerEl === null || !document.body.contains(centerEl)) { viewTargets[idx] = null; return null }\r\n // The host marker always wins over a cached fallback (the view may not be\r\n // mounted yet when the plugin applies early).\r\n const marked = centerEl.querySelector<HTMLElement>(spec.sel)\r\n const cached = viewTargets[idx]\r\n if (marked !== null) {\r\n if (cached !== null && cached !== marked) { setBlur(cached, 0); restoreCardHost(cached, spec.mark, spec.prev, spec.plain === true) }\r\n viewTargets[idx] = marked\r\n return marked\r\n }\r\n if (cached !== null && centerEl.contains(cached)) return cached\r\n viewTargets[idx] = null\r\n if (spec.fallback !== true) return null\r\n // On the harness, an absent [data-chat-flow] just means the chat view is not\r\n // mounted (hero phase, trajectory tab) — settling on the whole scrollport\r\n // there would wrap the entire page in the card.\r\n if (centerEl.querySelector('[data-conversation-scroll]') !== null) return null\r\n // Marker-less hosts keep their layout until a slider moves.\r\n if (spec.opacity() <= 0 && spec.blur() <= 0) return null\r\n let best: HTMLElement | null = null\r\n let bestArea = 0\r\n for (const el of Array.from(centerEl.querySelectorAll<HTMLElement>('*'))) {\r\n if (!isScrollableY(el)) continue\r\n if (el.clientHeight < centerEl.clientHeight * 0.35) continue\r\n const area = el.clientWidth * el.clientHeight\r\n if (area > bestArea) { bestArea = area; best = el }\r\n }\r\n if (best === null) {\r\n for (const el of Array.from(centerEl.children)) {\r\n if (!(el instanceof HTMLElement)) continue\r\n if (el.clientHeight < centerEl.clientHeight * 0.5) continue\r\n if (el.clientHeight > (best?.clientHeight ?? 0)) best = el\r\n }\r\n }\r\n const refined = best !== null ? refineMessageColumn(best) : null\r\n viewTargets[idx] = refined\r\n return refined\r\n}\r\n\r\n/** Stash the host's own inline values so teardown restores them exactly. */\r\nfunction stashCardPrev(el: HTMLElement, prev: string, plain: boolean): void {\r\n const ds = el.dataset as Record<string, string | undefined>\r\n ds[prev + 'Bg'] = el.style.getPropertyValue('background')\r\n if (plain) return\r\n ds[prev + 'Border'] = el.style.getPropertyValue('border')\r\n ds[prev + 'Radius'] = el.style.getPropertyValue('border-radius')\r\n ds[prev + 'Padding'] = el.style.getPropertyValue('padding')\r\n}\r\n\r\n/** Undo the inline styling, restoring the host's previous inline values. */\r\nfunction restoreCardHost(el: HTMLElement, mark: string, prev: string, plain: boolean): void {\r\n if (!el.hasAttribute(mark)) return\r\n const ds = el.dataset as Record<string, string | undefined>\r\n const restore = (prop: string, v: string | undefined): void => {\r\n if (v !== undefined && v !== '') el.style.setProperty(prop, v)\r\n else el.style.removeProperty(prop)\r\n }\r\n restore('background', ds[prev + 'Bg'])\r\n if (!plain) {\r\n restore('border', ds[prev + 'Border'])\r\n restore('border-radius', ds[prev + 'Radius'])\r\n restore('padding', ds[prev + 'Padding'])\r\n delete ds[prev + 'Border']; delete ds[prev + 'Radius']; delete ds[prev + 'Padding']\r\n }\r\n delete ds[prev + 'Bg']\r\n el.removeAttribute(mark)\r\n}\r\n\r\n/** Teardown only: strip every view treatment and hand the hosts back untouched. */\r\nfunction removeViewCards(): void {\r\n VIEW_CARDS.forEach((spec, i) => {\r\n const el = viewTargets[i]\r\n if (el !== null) { setBlur(el, 0); restoreCardHost(el, spec.mark, spec.prev, spec.plain === true) }\r\n viewTargets[i] = null\r\n })\r\n}\r\n\r\n// ── Wide markdown tables ──────────────────────────────────────────────────────\r\n// DSH intentionally lets `.md-table-wide` bleed outside the text column. That\r\n// bleed only becomes visible once the chat surface gains a visible border, i.e.\r\n// when the chat region opacity or blur is non-zero. Under that same condition,\r\n// pull the table back inside the column and let it scroll horizontally.\r\nconst TABLE_FIX_RULE = [\r\n '.md-table-wide {',\r\n ' --dsh-table-spare: 0px !important;',\r\n ' --dsh-table-lead: 0px !important;',\r\n ' box-sizing: border-box !important;',\r\n ' width: 100% !important;',\r\n ' max-width: 100% !important;',\r\n ' margin-left: 0 !important;',\r\n ' padding-left: 0 !important;',\r\n ' padding-bottom: 0 !important;',\r\n ' overflow-x: auto !important;',\r\n '}',\r\n].join('\\n')\r\nlet tableFixStyleEl: HTMLStyleElement | null = null\r\n\r\n/** Toggle the wide-table clamp according to the chat region's opacity & blur. */\r\nfunction syncTableFix(): void {\r\n const needed = rChatTextOpacity() > 0 || rBlurs().chat > 0\r\n if (!needed) {\r\n if (tableFixStyleEl !== null) { tableFixStyleEl.remove(); tableFixStyleEl = null }\r\n return\r\n }\r\n if (tableFixStyleEl === null) {\r\n tableFixStyleEl = document.createElement('style')\r\n tableFixStyleEl.dataset.plugin = 'dsh-background-by-model-table-fix'\r\n markOwnSheet(tableFixStyleEl)\r\n tableFixStyleEl.textContent = TABLE_FIX_RULE\r\n }\r\n if (!tableFixStyleEl.isConnected) document.head.appendChild(tableFixStyleEl)\r\n}\r\n\r\n/** Re-derive the conversation view cards from the current config. */\r\nexport function applyViewCards(fade = false): void {\r\n discoverParts()\r\n if (centerEl === null) return\r\n // The chat card is tinted from the palette in force, so a color-less rule gets\r\n // the host's own surface instead of the seed color's fallback tint.\r\n const surface = palette()?.tokens['--dsw-alias-bg-layer-1']\r\n const transition = fadeInlineFor(fade)\r\n VIEW_CARDS.forEach((spec, i) => {\r\n const target = discoverViewTarget(i, spec)\r\n if (target === null) return\r\n const plain = spec.plain === true\r\n const opacity = spec.opacity()\r\n const blurPx = spec.blur()\r\n if (!plain) {\r\n if (!target.hasAttribute(spec.mark)) stashCardPrev(target, spec.prev, false)\r\n // Mirrors .dab-card (layer-1 background, border, 16px radius, 18px\r\n // padding), written inline so it wins over host stylesheets; the opacity\r\n // slider drives surface alpha and fades the border with it. The transition\r\n // is inline for the same reason the background is: this card does not read\r\n // the registered tokens, so a palette change would otherwise snap here.\r\n const borderAlpha = opacity > 0 ? Math.min(1, opacity * 1.5) : (blurPx > 0 ? 0.35 : 0)\r\n target.style.transition = transition\r\n target.style.background = surface !== undefined ? withAlpha(surface, opacity) : 'transparent'\r\n target.style.border = surface !== undefined ? `1px solid ${withAlpha(surface, borderAlpha)}` : '1px solid transparent'\r\n target.style.borderRadius = '16px'\r\n target.style.padding = '18px'\r\n }\r\n // Plain views write no inline styles — only the blur underlay is hosted here.\r\n target.setAttribute(spec.mark, '1')\r\n setBlur(target, blurPx)\r\n })\r\n syncTableFix()\r\n}\r\n\r\nlet partsObserver: MutationObserver | null = null\r\n\r\n/** Watch for the AppFrame mounting so persisted blurs land even when the shell\r\n * renders after this plugin's apply. */\r\nexport function watchParts(): void {\r\n if (partsObserver !== null || typeof MutationObserver === 'undefined') return\r\n partsObserver = new MutationObserver(() => {\r\n if (frameEl !== null && sidebarEl !== null && centerEl !== null && detailsEl !== null && document.body.contains(frameEl)\r\n // Keep re-applying while any card host is absent or was swapped by the host.\r\n && viewTargets.every(el => el !== null && document.body.contains(el))) return\r\n applyPartBlurs(rBlurs())\r\n applyPartOpacities(rOps())\r\n })\r\n partsObserver.observe(document.body, { childList: true, subtree: true })\r\n}\r\n\r\nexport function stopWatchingParts(): void {\r\n partsObserver?.disconnect()\r\n partsObserver = null\r\n}\r\n\r\n// ── Theme-reset watchdog ──────────────────────────────────────────────────\r\n// The host re-asserts its own :root/body scheme rules on mount, on settings\r\n// adoption and after the plugin's startup assertion, toggling the\r\n// `data-ds-dark-theme` attribute off / to a host value — which would paint a\r\n// frame of light surfaces. Watch that flag and, whenever the plugin's own\r\n// value disappears, re-set it and re-emit the token stylesheet within the same\r\n// frame.\r\nlet themeObserver: MutationObserver | null = null\r\nlet themeRaf = 0\r\n\r\nfunction reassertScheme(): void {\r\n const [, , l] = rColor()\r\n if (l < 0.55) document.body.setAttribute(DARK_ATTR, OWN_SCHEME)\r\n else document.body.removeAttribute(DARK_ATTR)\r\n applyCustomTokens(rOps())\r\n}\r\n\r\n/** Re-assert the plugin's forced scheme whenever the host strips it, so a\r\n * refresh / cold-load / set-change never flashes a light frame. Also the point\r\n * where a host-side scheme flip is noticed while a color-less rule runs: that\r\n * rule paints from the host palette, so the readback is dropped and the\r\n * surfaces are re-emitted from the new one. */\r\nexport function watchThemeResets(): () => void {\r\n if (themeObserver !== null || typeof MutationObserver === 'undefined') return () => undefined\r\n themeObserver = new MutationObserver(() => {\r\n invalidateHostPalette()\r\n if (document.body.getAttribute(DARK_ATTR) === OWN_SCHEME) return\r\n if (!rHasColor()) {\r\n // Nothing to re-assert, but the host's own surfaces just changed under us.\r\n applyCustomTokens(rOps())\r\n return\r\n }\r\n if (themeRaf !== 0) return\r\n themeRaf = requestAnimationFrame(() => {\r\n themeRaf = 0\r\n if (document.body.getAttribute(DARK_ATTR) === OWN_SCHEME) return\r\n reassertScheme()\r\n })\r\n })\r\n themeObserver.observe(document.body, { attributes: true, attributeFilter: [DARK_ATTR] })\r\n themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: [DARK_ATTR] })\r\n return () => {\r\n themeObserver?.disconnect()\r\n themeObserver = null\r\n }\r\n}\r\n\r\n// ── Wallpaper layer: two stacked layers, cross-faded on a rule switch ───────\r\n// The incoming image fades in ON TOP of the outgoing one at full opacity.\r\n// Fading the old one out at the same time would drop the composite below full\r\n// alpha at the midpoint — both images half transparent — and the interface\r\n// behind would flash through.\r\n//\r\n// A layer addresses its image by OBJECT URL (see displayImageOf in state):\r\n// assigning a `url(data:…)` background re-decodes the photo on every switch,\r\n// which is where a large wallpaper's stall comes from, while a blob URL is\r\n// served from the browser's memory cache after the first load.\r\n//\r\n// The duration is the GLOBAL switch effect's (`transition.durationMs`, default\r\n// 320 ms — see DEFAULT_TRANSITION and TRANSITION_MAX_MS in ./schema), the same\r\n// for every switch this plugin performs, and 0 means a hard cut.\r\ninterface WpLayer {\r\n el: HTMLDivElement\r\n /** Display URL of the image painted on this layer; null when empty. */\r\n url: string | null\r\n}\r\n\r\nlet layers: [WpLayer, WpLayer] | null = null\r\n/** Index of the layer the user is looking at. */\r\nlet front = 0\r\n/** Index of the layer fading in right now, if any. */\r\nlet pending: 0 | 1 | null = null\r\nlet fadeTimer: number | null = null\r\n\r\nfunction createLayer(): WpLayer {\r\n const el = document.createElement('div')\r\n el.dataset.dabWpLayer = ''\r\n el.style.cssText = 'position:absolute;inset:0;opacity:0;background-repeat:no-repeat;background-position:center;'\r\n return { el, url: null }\r\n}\r\n\r\nfunction ensureWpContainer(): void {\r\n if (wpEl !== null && layers !== null && document.body.contains(wpEl)) return\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n const a = createLayer()\r\n const b = createLayer()\r\n wpEl = document.createElement('div')\r\n wpEl.dataset.dabWp = ''\r\n wpEl.style.cssText = 'position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden;'\r\n wpEl.append(a.el, b.el)\r\n layers = [a, b]\r\n front = 0\r\n pending = null\r\n document.body.prepend(wpEl)\r\n}\r\n\r\n/** Drop the whole wallpaper layer (no rule carries an image). */\r\nfunction dropWpContainer(): void {\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n front = 0\r\n layers = null\r\n wpEl?.remove()\r\n wpEl = null\r\n}\r\n\r\n/** Release one layer's image — the layer is fully covered when this is called. */\r\nfunction clearLayer(l: WpLayer): void {\r\n if (l.url === null) return\r\n l.url = null\r\n l.el.style.backgroundImage = ''\r\n l.el.style.backgroundSize = ''\r\n l.el.style.backgroundPosition = ''\r\n // The transition's own property is part of what a layer IS, not just how it\r\n // arrived: a layer retired mid-zoom would otherwise keep `scale(1.06)` and\r\n // paint the next wallpaper 6% too large.\r\n l.el.style.transform = 'none'\r\n}\r\n\r\n/** Write the two properties a switch animates. Both are always written, so a\r\n * layer can never keep half of a previous effect. */\r\nfunction applyLayerStyle(el: HTMLElement, style: LayerStyle): void {\r\n el.style.opacity = style.opacity\r\n el.style.transform = style.transform\r\n}\r\n\r\n/** Intrinsic-size cache for the center mode (native pixels of the current image). */\r\nlet imgNat: { url: string; w: number; h: number } | null = null\r\nfunction imageNatSize(url: string, cb: (w: number, h: number) => void): void {\r\n if (imgNat !== null && imgNat.url === url) { cb(imgNat.w, imgNat.h); return }\r\n const img = new Image()\r\n img.onload = () => {\r\n imgNat = { url, w: img.naturalWidth, h: img.naturalHeight }\r\n cb(img.naturalWidth, img.naturalHeight)\r\n }\r\n img.onerror = () => cb(0, 0)\r\n img.src = url\r\n}\r\n\r\n/** Paint one layer's image and its placement. The placement always follows the\r\n * ACTIVE rule: the incoming layer is painted right after a switch, and a\r\n * repaint of the same URL (framing edit, viewport resize) must use the rule's\r\n * current framing. */\r\nfunction paintLayer(l: WpLayer, url: string): void {\r\n const el = l.el\r\n l.url = url\r\n const bg = rBgState()\r\n const mode = rBgMode()\r\n const next = `url(\"${url}\")`\r\n // Skip re-setting the same URL — a redundant assignment can flash the layer\r\n // blank for a frame while it is re-resolved.\r\n if (el.style.backgroundImage !== next) {\r\n el.style.backgroundImage = next\r\n }\r\n if (mode === 'fit') {\r\n el.style.backgroundRepeat = 'no-repeat'\r\n if (bg.iw > 0) {\r\n // Contain-fit at zoom with the image center pinned to the committed\r\n // fractional viewport point, so the framed region survives viewport changes.\r\n const fit = Math.min(window.innerWidth / bg.iw, window.innerHeight / bg.ih)\r\n const w = bg.iw * fit * bg.zoom\r\n const h = bg.ih * fit * bg.zoom\r\n el.style.backgroundSize = `${w}px ${h}px`\r\n el.style.backgroundPosition = `${bg.x * window.innerWidth - w / 2}px ${bg.y * window.innerHeight - h / 2}px`\r\n } else {\r\n // Fresh image: match the editor's initial centered contain view.\r\n el.style.backgroundSize = 'contain'\r\n el.style.backgroundPosition = 'center'\r\n }\r\n } else if (mode === 'fill') {\r\n el.style.backgroundRepeat = 'no-repeat'\r\n el.style.backgroundSize = 'cover'\r\n el.style.backgroundPosition = 'center'\r\n } else if (mode === 'stretch') {\r\n el.style.backgroundRepeat = 'no-repeat'\r\n el.style.backgroundSize = '100% 100%'\r\n el.style.backgroundPosition = 'center'\r\n } else if (mode === 'tile') {\r\n el.style.backgroundRepeat = 'repeat'\r\n // background-size:auto resolves the intrinsic size per tile.\r\n el.style.backgroundSize = 'auto'\r\n el.style.backgroundPosition = '0px 0px'\r\n } else {\r\n // Center: native size, centered. The intrinsic size needs an async decode;\r\n // 'contain' keeps a sensible frame until it lands.\r\n el.style.backgroundRepeat = 'no-repeat'\r\n el.style.backgroundSize = 'contain'\r\n el.style.backgroundPosition = 'center'\r\n imageNatSize(url, (w, h) => {\r\n if (l.url !== url || el.style.backgroundImage !== next || rBgMode() !== 'center') return\r\n if (w > 0 && h > 0) {\r\n el.style.backgroundSize = `${w}px ${h}px`\r\n el.style.backgroundPosition = 'center'\r\n }\r\n })\r\n }\r\n}\r\n\r\n/** Whether there is anything to animate FROM: a wallpaper on screen that is\r\n * actually visible. The duration question belongs to `rFadeMs`, and the\r\n * `reduced-motion` veto to `transitionPlan` — this answers only the layer half,\r\n * so a first paint (no previous image) never fades in from nothing. */\r\nfunction canAnimateFrom(from: WpLayer): boolean {\r\n if (from.url === null) return false\r\n return rWop() > 0.01\r\n}\r\n\r\n/** Whether the OS asks for reduced motion right now. */\r\nfunction prefersReducedMotion(): boolean {\r\n const mm = typeof window.matchMedia === 'function' ? window.matchMedia('(prefers-reduced-motion: reduce)') : null\r\n return mm !== null && mm.matches\r\n}\r\n\r\n/** End an in-flight fade: promote the incoming layer, free the one under it. */\r\nfunction finishFade(idx: 0 | 1): void {\r\n if (layers === null || pending !== idx) return\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n front = idx\r\n const el = layers[idx].el\r\n // Re-asserted so a fade whose frames never ran (background tab) still ends on\r\n // the visible image — and on the END of the effect, not on the frame it was\r\n // interrupted at (a zoom left at 1.06 crops every later wallpaper).\r\n el.style.opacity = '1'\r\n el.style.transform = 'none'\r\n el.style.willChange = ''\r\n // Covered from here on: drop its bytes so a second full-resolution image is\r\n // never left decoded behind the visible one.\r\n clearLayer(layers[idx === 0 ? 1 : 0])\r\n}\r\n\r\n/** Land an in-flight fade on its end state at once (another switch arrived). */\r\nfunction settleFade(): void {\r\n if (layers === null || pending === null) return\r\n const idx = pending\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n front = idx\r\n const el = layers[idx].el\r\n el.style.transition = 'none'\r\n el.style.opacity = '1'\r\n el.style.transform = 'none'\r\n el.style.willChange = ''\r\n clearLayer(layers[idx === 0 ? 1 : 0])\r\n}\r\n\r\n/** Abandon an in-flight fade: the layer it was leaving holds the wanted image. */\r\nfunction cancelFade(): void {\r\n if (layers === null || pending === null) return\r\n const idx = pending\r\n if (fadeTimer !== null) { window.clearTimeout(fadeTimer); fadeTimer = null }\r\n pending = null\r\n const el = layers[idx].el\r\n el.style.transition = 'none'\r\n el.style.opacity = '0'\r\n el.style.transform = 'none'\r\n el.style.willChange = ''\r\n clearLayer(layers[idx])\r\n}\r\n\r\n/** Show `url` on the wallpaper layer, cross-fading from what it paints now. */\r\nfunction applyImageWp(url: string): void {\r\n ensureWpContainer()\r\n const ls = layers!\r\n if (pending !== null) {\r\n // A → B → A inside one fade: keep whichever layer already paints the wanted\r\n // image instead of queueing a third one.\r\n if (ls[pending].url === url) { paintLayer(ls[pending], url); applyWpEffects(); return }\r\n if (ls[front].url === url) { cancelFade(); paintLayer(ls[front], url); applyWpEffects(); return }\r\n settleFade()\r\n }\r\n if (ls[front].url === url) { paintLayer(ls[front], url); applyWpEffects(); return }\r\n const from = ls[front]\r\n const idx: 0 | 1 = front === 0 ? 1 : 0\r\n const target = ls[idx]\r\n const el = target.el\r\n // One decision, from the global effect + the resolved duration + the two vetoes\r\n // (nothing to animate from, reduced motion) — see ./transition.\r\n const tr = rTransition()\r\n const plan = transitionPlan({\r\n effect: tr.effect,\r\n easing: tr.easing,\r\n durationMs: rFadeMs(),\r\n canAnimate: canAnimateFrom(from),\r\n reducedMotion: prefersReducedMotion(),\r\n })\r\n // Rewind the incoming layer before its bytes land, so a stale image from an\r\n // earlier switch can never flash through while the new one rasterizes — and so\r\n // the effect's start state is in place a frame before the transition is armed.\r\n el.style.transition = 'none'\r\n el.style.willChange = plan.willChange\r\n applyLayerStyle(el, plan.from)\r\n el.style.zIndex = '1'\r\n from.el.style.zIndex = '0'\r\n paintLayer(target, url)\r\n applyWpEffects()\r\n if (!plan.animate) {\r\n // No animation: land on the end state at once (`transition` is already\r\n // 'none' from the rewind above), which is both the hard cut and what a\r\n // first paint does.\r\n applyLayerStyle(el, plan.to)\r\n front = idx\r\n clearLayer(from)\r\n return\r\n }\r\n // will-change promotes the layer in this frame, so the fade itself is a pure\r\n // compositor animation that survives the main-thread work a switch triggers\r\n // (theme re-registration, token rewrite, settings-panel re-render).\r\n pending = idx\r\n requestAnimationFrame(() => {\r\n if (pending !== idx || layers === null) return\r\n el.style.transition = plan.transition\r\n applyLayerStyle(el, plan.to)\r\n })\r\n fadeTimer = window.setTimeout(() => finishFade(idx), plan.durationMs + 160)\r\n}\r\n\r\nfunction applyWpEffects(): void {\r\n if (wpEl === null || layers === null) return\r\n wpEl.style.opacity = String(rWop())\r\n // The blur sits on each LAYER rather than on the container: with the filter on\r\n // the parent, every frame of an opacity fade would re-run a full-screen blur\r\n // instead of just re-compositing the blurred surface.\r\n const blur = rBl()\r\n const filter = blur > 0 ? `blur(${blur}px)` : ''\r\n layers[0].el.style.filter = filter\r\n layers[1].el.style.filter = filter\r\n}\r\n\r\n/** Repaint the wallpaper layer, the token palette and every interface part from\r\n * the ACTIVE rule. This is the single entry point a rule switch goes through. */\r\nexport function applyWp(): void {\r\n const url = rWp()\r\n if (url) {\r\n applyImageWp(url)\r\n } else if (wpEl !== null) {\r\n // No background: tear down the layer but keep tokens/blur intact.\r\n dropWpContainer()\r\n }\r\n // A rule without a saved color follows the system theme: the plugin owns no\r\n // color of its own, so the surfaces come from the host's palette (see\r\n // `palette`) with the user's opacities applied — the wallpaper keeps showing\r\n // and the Interface sliders keep doing something, which is what \"follow the\r\n // system theme\" is expected to mean. THREE things have to be true before the\r\n // readback, or it answers with the wrong palette:\r\n // 1. our own body rule is out of the way (it re-emits the tokens being read);\r\n // 2. the scheme flag is the host's own again (we force/remove it while we own\r\n // a palette, and the host only re-projects on a theme change);\r\n // 3. the cached palette is dropped once, on the way in.\r\n if (!rHasColor() && !baseTokenKey.startsWith('host:')) {\r\n clearCustomTokens()\r\n invalidateHostPalette()\r\n }\r\n if (!rHasColor()) adoptHostScheme()\r\n const src = palette()\r\n // Marker for the no-fallback re-scope rules: they may only be live while the\r\n // variables they read are written (see THEMED_ATTR).\r\n document.documentElement.toggleAttribute(THEMED_ATTR, src !== null)\r\n if (src === null) {\r\n // No palette at all (a host publishing none of the surfaces we re-emit):\r\n // give every surface back to the host untouched instead of leaving ours.\r\n clearCustomTokens()\r\n clearOwnedSurfaces()\r\n }\r\n // The return value says whether the PALETTE itself just moved — the one case a\r\n // colour change is allowed to fade (see `applyCustomTokens`) — and it is what\r\n // the inline-painted cards below need to know, since they do not read the\r\n // registered tokens.\r\n const paletteMoved = applyCustomTokens(rOps())\r\n applySettingsOverrides(rSop())\r\n applyTrajectoryOverrides(rTrajectoryOpacity())\r\n applyRightbarOverrides(rRightbarOpacity())\r\n applyPartBlurs(rBlurs())\r\n applyViewCards(paletteMoved)\r\n}\r\n\r\nexport function teardownWp(): void {\r\n dropWpContainer()\r\n clearCustomTokens()\r\n tokenStyleEl?.remove(); tokenStyleEl = null\r\n removeViewCards()\r\n document.documentElement.removeAttribute(THEMED_ATTR)\r\n document.body.style.removeProperty('color-scheme')\r\n // Every plugin-owned surface, including the AppFrame columns' inline\r\n // backgrounds and the palette readback that described them; the scheme flag is\r\n // handed back in the host's own form.\r\n clearOwnedSurfaces()\r\n adoptHostScheme()\r\n invalidateHostPalette()\r\n document.documentElement.style.removeProperty('--dsh-any-blur-settings')\r\n document.documentElement.style.removeProperty('--dsh-any-blur-card-panels')\r\n document.documentElement.style.removeProperty('--dsh-any-input-blur')\r\n document.documentElement.style.removeProperty('--dsh-any-bg-rightbar')\r\n document.documentElement.style.removeProperty('--dsh-any-blur-rightbar')\r\n for (const v of Object.values(OPACITY_VARS)) document.documentElement.style.removeProperty(v)\r\n if (tokensRaf !== null) { cancelAnimationFrame(tokensRaf); tokensRaf = null }\r\n pendingOps = null\r\n tableFixStyleEl?.remove(); tableFixStyleEl = null\r\n setBlur(frameEl, 0); setBlur(sidebarEl, 0); setBlur(centerEl, 0); setBlur(detailsEl, 0)\r\n stopWatchingParts()\r\n}\r\n\r\n/** Live wallpaper-opacity updates during slider drag (no full re-apply). */\r\nexport function setWpOpacity(v: number): void {\r\n if (wpEl) wpEl.style.opacity = String(v)\r\n}\r\n\r\n/** Live wallpaper-blur updates during slider drag (no full re-apply). */\r\nexport function setWpBlur(v: number): void {\r\n if (layers === null) return\r\n const filter = v > 0 ? `blur(${v}px)` : ''\r\n layers[0].el.style.filter = filter\r\n layers[1].el.style.filter = filter\r\n}\r\n","/**\n * Model → rule resolution.\n *\n * Two halves:\n * 1. `matchRule` — a pure function over the ordered rule list.\n * 2. `watchModel` — reports the current model whenever the session's durable\n * model selection changes.\n *\n * Sources, in the order they are consulted:\n *\n * a. **Which session is current** (`resolveMainSessionId` below) — the model is\n * read per session, so this hop answers before any other can. 0.1.7 moved it:\n * `sessions.list` stopped carrying a single `current` id, and the main view's\n * session is published by the `uiSession` service and marked by the list row\n * retained by `mainView`.\n * b. **The session's own durable model selection** —\n * `ctx.sessions.binding(id).session.projections.faceOf('modelSelection')`,\n * the same `{ lastUsed, next }` value the composer model seat and the\n * /model popup read. This is the authoritative per-session answer.\n * c. **`ctx.modelDirectories`** — the shared per-session directory\n * (ui-model-selection). It adds the provider-group catalog, so it is the\n * only source that can supply a display name, but it lives in that plugin's\n * own scope on some builds and is then invisible from here, hence optional.\n * d. **The host default model** — resolved by the CALLER as a last resort\n * (see index.tsx). It is a global default, NOT this session's selection, so\n * it is reported as `default` and the settings page says so.\n *\n * TIMING is load-bearing. `sessions` is published by the api-session-controller\n * client plugin, which this deployment loads AFTER this plugin's client bundle,\n * so `ctx.get('sessions')` is normally still undefined when `apply()` runs.\n * Giving up there — returning a no-op disposer — left the model pinned to the\n * host default for the whole session with nothing to retry it. The service is\n * now polled for until it appears, and `uiSession` (which can mount even later)\n * is picked up by the same poll because the session id is re-resolved on every\n * tick. Every hop reports a `note` when it cannot answer, so the settings page\n * can name the failing one instead of silently showing a value that is not this\n * session's model.\n */\nimport type {\n BgRule, Ctx, ModelDirectoryLike, ModelDirectoryResolverLike, ModelSelectionProjectionLike,\n ObservableFaceLike, SessionListSnapshotLike, SessionsServiceLike, UiSessionLike,\n} from './types'\n// Whether a rule can paint AT ALL is the shared shape's business, not this\n// module's: `ruleCanPaint` is the one answer (enabled, and carrying an image or a\n// theme color), so matching and the panel's copy cannot drift apart.\nimport { ruleCanPaint } from '../schema'\n\n/** Rules that can actually paint: see `ruleCanPaint` (./schema). */\nfunction usable(rules: readonly BgRule[]): BgRule[] {\n return rules.filter(ruleCanPaint)\n}\n\n/**\n * Resolve the rule for one model text.\n *\n * Top→bottom, first case-insensitive substring hit wins; an empty `match` never\n * hits on its own. When nothing hits, the FIRST usable rule is the fallback\n * (rule 1 deliberately doubles as both a matcher and the fallback).\n *\n * \"Usable\" is `ruleCanPaint` — an image, or a theme color of its own — so a rule\n * whose pictures were all removed still holds the models it matches (and paints\n * its color alone) instead of quietly handing them to the next rule.\n */\nexport function matchRule(\n rules: readonly BgRule[],\n modelText: string,\n): { rule: BgRule | null; matched: boolean } {\n const list = usable(rules)\n if (list.length === 0) return { rule: null, matched: false }\n const hay = modelText.toLowerCase()\n if (hay.trim() !== '') {\n for (const rule of list) {\n const needle = rule.match.trim().toLowerCase()\n if (needle === '') continue\n if (hay.includes(needle)) return { rule, matched: true }\n }\n }\n return { rule: list[0]!, matched: false }\n}\n\n/** Human-readable label of the model text an active rule matched against. */\nexport function modelLabelOf(text: string): string {\n const parts = text.split(/\\s+/).filter(p => p !== '')\n // The display name (last token, when the catalog provided one) reads best.\n return parts.length > 0 ? parts[parts.length - 1]! : ''\n}\n\n/** Look the current model's display name up in the shared catalog. */\nfunction displayNameOf(state: {\n groups?: ReadonlyArray<{ id?: string; models?: ReadonlyArray<{ id?: string; name?: string }> }>\n} | undefined, provider: string, model: string): string {\n if (model === '' || !Array.isArray(state?.groups)) return ''\n for (const group of state!.groups!) {\n if (group.id !== provider) continue\n for (const entry of group.models ?? []) {\n if (entry.id === model) return typeof entry.name === 'string' ? entry.name : ''\n }\n }\n return ''\n}\n\n/** Where the reported model text came from. */\nexport type ModelSource = 'session' | 'default'\n\n/**\n * Which hop could not answer when no per-session model was found. Surfaced in\n * the settings readout: without it, a broken hop is indistinguishable from\n * \"this session really is on the host default\".\n */\nexport type ModelNote = '' | 'no-service' | 'no-session' | 'no-projection' | 'empty-selection'\n\n/** How often to look for the sessions service that mounts after this plugin. */\nconst ATTACH_RETRY_MS = 400\n/** Stop looking after this many tries (~2 minutes). */\nconst ATTACH_RETRY_LIMIT = 300\n/** Safety re-read of every source, so a missed notification cannot pin a stale model. */\nconst POLL_MS = 1500\n\n/** One selection out of a `modelSelection` projection value. */\nfunction selectionOf(value: ModelSelectionProjectionLike | undefined): { provider: string; model: string } | null {\n const pick = value?.next ?? value?.lastUsed ?? null\n if (pick === null || typeof pick !== 'object') return null\n const provider = typeof pick.provider === 'string' ? pick.provider : ''\n const model = typeof pick.model === 'string' ? pick.model : ''\n if (provider === '' && model === '') return null\n return { provider, model }\n}\n\n/** A non-empty string id, or null. */\nfunction asId(value: unknown): string | null {\n return typeof value === 'string' && value !== '' ? value : null\n}\n\n/**\n * The id of the session the main view is showing.\n *\n * The model is read per session, so this hop has to answer before any of the\n * others can. 0.1.7 moved the answer: `sessions.list` stopped publishing a single\n * `current` id in favour of a row table (`ids` / `byId` / `phase`), and the main\n * view's session is now whatever holds a `mainView` retention — the same row the\n * host's own `uiSession.current` binding source is built from. Reading only\n * `list.current` therefore finds nothing on 0.1.7, and a plugin with no session\n * id can only ever fall back to rule 1: the background stops following the model.\n *\n * The hops are tried in order of authority and every one is optional, so this\n * answers on both host generations — and while `uiSession` is still mounting.\n */\nexport function resolveMainSessionId(\n uiCurrent: { key?: string } | undefined,\n snapshot: SessionListSnapshotLike | undefined,\n): string | null {\n // 0.1.7: the host's own answer, already resolved from list + retention.\n const fromUiSession = asId(uiCurrent?.key)\n if (fromUiSession !== null) return fromUiSession\n // ≤0.1.6: the list published the current id directly.\n const legacy = asId(snapshot?.current)\n if (legacy !== null) return legacy\n // 0.1.7 without `uiSession` yet: derive it from the retention the host uses.\n const byId = snapshot?.byId\n if (byId !== undefined && byId !== null) {\n for (const row of Object.values(byId)) {\n if ((row?.retainedBy?.mainView ?? 0) > 0) {\n const id = asId(row?.id)\n if (id !== null) return id\n }\n }\n }\n return null\n}\n\n/** Read `uiSession.current` (if that service is on this host) and resolve. */\nfunction mainSessionId(ctx: Ctx, list: ObservableFaceLike<SessionListSnapshotLike> | null): string | null {\n let uiCurrent: { key?: string } | undefined\n try {\n const ui = ctx.get('uiSession') as UiSessionLike | undefined\n uiCurrent = ui?.current?.getSnapshot?.()\n } catch {\n // Service absent (or not mounted yet) — the list retention below still answers.\n }\n return resolveMainSessionId(uiCurrent, list?.getSnapshot())\n}\n\n/**\n * Watch the current session's model selection.\n *\n * @param ctx - client root context.\n * @param onChange - called with the match text (provider + id + display name),\n * the best available label, which source answered, and — when nothing could be\n * read — the hop that failed.\n * @returns disposer.\n */\nexport function watchModel(\n ctx: Ctx,\n onChange: (text: string, label: string, source: ModelSource, note: ModelNote) => void,\n): () => void {\n let service: SessionsServiceLike | null = null\n let list: ObservableFaceLike<SessionListSnapshotLike> | null = null\n let offList: (() => void) | null = null\n let sessionId: string | null = null\n let directory: ModelDirectoryLike | null = null\n let offDirectory: (() => void) | null = null\n /** The session's own `modelSelection` projection face. */\n let projected: ObservableFaceLike<ModelSelectionProjectionLike> | null = null\n let offProjected: (() => void) | null = null\n let lastKey = '\\u0000'\n let poll: number | null = null\n let retry: number | null = null\n let retries = 0\n\n const release = (): void => {\n if (offDirectory !== null) { offDirectory(); offDirectory = null }\n if (offProjected !== null) { offProjected(); offProjected = null }\n directory = null\n projected = null\n }\n\n /** Bind the session's own durable model selection (the authoritative source). */\n const bindProjection = (id: string): void => {\n const svc = service\n if (svc === null) return\n try {\n let binding = typeof svc.binding === 'function' ? svc.binding(id) : undefined\n if (binding === undefined && typeof svc.scope === 'function') {\n // Materialize the scope, then resolve again: a session that is merely\n // listed has no binding yet.\n svc.scope(id)\n binding = typeof svc.binding === 'function' ? svc.binding(id) : undefined\n }\n const face = binding?.session?.projections?.faceOf?.('modelSelection')\n if (face === undefined || typeof face.subscribe !== 'function' || typeof face.getSnapshot !== 'function') return\n projected = face\n offProjected = face.subscribe(() => { emit(false) })\n } catch {\n projected = null\n offProjected = null\n }\n }\n\n const note = (): ModelNote => {\n if (service === null) return 'no-service'\n if (sessionId === null) return 'no-session'\n if (projected === null && directory === null) return 'no-projection'\n return 'empty-selection'\n }\n\n const emit = (force: boolean): void => {\n const state = directory?.store.getSnapshot()\n const fromDirectory = state?.current ?? null\n const sel = fromDirectory !== null\n ? { provider: fromDirectory.provider ?? '', model: fromDirectory.model ?? '' }\n : (() => {\n try { return selectionOf(projected?.getSnapshot()) } catch { return null }\n })()\n const provider = sel?.provider ?? ''\n const model = sel?.model ?? ''\n const name = displayNameOf(state, provider, model)\n const text = [provider, model, name].filter(p => p !== '').join(' ').trim()\n const noteValue: ModelNote = text === '' ? note() : ''\n const key = `${text}\\u0001${name}\\u0001${noteValue}`\n if (!force && key === lastKey) return\n lastKey = key\n onChange(text, name !== '' ? name : (model !== '' ? model : provider), 'session', noteValue)\n }\n\n const bind = (): void => {\n const id = mainSessionId(ctx, list)\n // Already bound to this session and holding at least one live source: only\n // refresh the value. A missing source keeps retrying on the poll below.\n if (id === sessionId && (directory !== null || projected !== null)) { emit(false); return }\n release()\n sessionId = id\n if (id !== null) {\n bindProjection(id)\n if (directory === null) {\n const directories = ctx.get('modelDirectories') as ModelDirectoryResolverLike | undefined\n if (directories !== undefined && typeof directories.directoryFor === 'function') {\n try {\n directory = directories.directoryFor(id)\n offDirectory = directory.store.subscribe(() => { emit(false) })\n // The advisory catalog (display names) loads lazily; a failure only\n // costs us the pretty name, never the match.\n const pending = directory.load?.()\n if (pending !== undefined && pending !== null && typeof (pending as Promise<unknown>).catch === 'function') {\n void (pending as Promise<unknown>).catch(() => undefined)\n }\n } catch {\n directory = null\n offDirectory = null\n }\n }\n }\n }\n // Forced: the sources may have appeared without the text changing (the host\n // default was showing and the session now agrees with it), and the settings\n // page must be able to correct its badge and its note.\n emit(true)\n }\n\n const stopRetry = (): void => {\n if (retry === null) return\n window.clearInterval(retry)\n retry = null\n }\n\n const tick = (): void => {\n if (list === null) return\n if (mainSessionId(ctx, list) !== sessionId || (directory === null && projected === null)) bind()\n else emit(false)\n }\n\n /**\n * Look the sessions service up. It arrives after this plugin's bundle on this\n * deployment, so the first attempt usually fails — which is exactly why this\n * is a retry loop rather than a one-shot lookup.\n */\n const attach = (): boolean => {\n const svc = ctx.get('sessions') as SessionsServiceLike | undefined\n if (svc === undefined || svc === null) return false\n const face = svc.list\n if (face === undefined || typeof face.subscribe !== 'function' || typeof face.getSnapshot !== 'function') return false\n service = svc\n list = face\n offList = face.subscribe(bind)\n if (poll === null) poll = window.setInterval(tick, POLL_MS)\n bind()\n return true\n }\n\n if (!attach()) {\n retry = window.setInterval(() => {\n retries++\n if (attach() || retries >= ATTACH_RETRY_LIMIT) stopRetry()\n }, ATTACH_RETRY_MS)\n }\n\n return () => {\n stopRetry()\n if (poll !== null) { window.clearInterval(poll); poll = null }\n if (offList !== null) { offList(); offList = null }\n service = null\n list = null\n release()\n }\n}\n","import type { ReactNode } from 'react'\r\n\r\n/** Sun glyph, migrated from @deepseek-ai/dsh-client-ui-primitives IconLightOutline16. */\r\nexport const SUN_PATHS = '<path d=\"M11.3496 8C11.3496 6.14985 9.85015 4.65039 8 4.65039C6.14985 4.65039 4.65039 6.14985 4.65039 8C4.65039 9.85015 6.14985 11.3496 8 11.3496C9.85015 11.3496 11.3496 9.85015 11.3496 8ZM12.6504 8C12.6504 10.5681 10.5681 12.6504 8 12.6504C5.43188 12.6504 3.34961 10.5681 3.34961 8C3.34961 5.43188 5.43188 3.34961 8 3.34961C10.5681 3.34961 12.6504 5.43188 12.6504 8Z\" fill=\"currentColor\"/><path d=\"M8.65039 0.5V2.5H7.34961V0.5H8.65039Z\" fill=\"currentColor\"/><path d=\"M8.65039 13.5V15.5H7.34961V13.5H8.65039Z\" fill=\"currentColor\"/><path d=\"M3.15808 2.24035L4.57229 3.65456L3.6525 4.57435L2.23829 3.16014L3.15808 2.24035Z\" fill=\"currentColor\"/><path d=\"M12.3505 11.4327L13.7647 12.8469L12.8449 13.7667L11.4307 12.3525L12.3505 11.4327Z\" fill=\"currentColor\"/><path d=\"M2.24537 12.8469L3.65958 11.4327L4.57937 12.3525L3.16516 13.7667L2.24537 12.8469Z\" fill=\"currentColor\"/><path d=\"M11.4377 3.65455L12.852 2.24033L13.7718 3.16012L12.3575 4.57434L11.4377 3.65455Z\" fill=\"currentColor\"/><path d=\"M0.5 7.35461H2.5V8.6554H0.5L0.5 7.35461Z\" fill=\"currentColor\"/><path d=\"M13.5 7.35461H15.5V8.6554H13.5V8.6554Z\" fill=\"currentColor\"/>'\r\n\r\nexport function SunIcon({ size = 16, className }: { size?: number; className?: string }) {\r\n return (\r\n <svg width={size} height={size} className={className} viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" dangerouslySetInnerHTML={{ __html: SUN_PATHS }} />\r\n )\r\n}\r\n\r\nfunction Glyph({ children, size = 16, className }: { children: ReactNode; size?: number; className?: string }) {\r\n return (\r\n <svg width={size} height={size} className={className} viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\r\n {children}\r\n </svg>\r\n )\r\n}\r\n\r\nexport const DropletIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 1.9c2.4 2.8 4.3 5 4.3 7.1a4.3 4.3 0 1 1-8.6 0C3.7 6.9 5.6 4.7 8 1.9z\" /></Glyph>\r\n)\r\n\r\nexport const LayersIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 2.2 13.2 5 8 7.8 2.8 5 8 2.2z\" /><path d=\"M2.8 8.2 8 11l5.2-2.8\" /><path d=\"M2.8 11.2 8 14l5.2-2.8\" /></Glyph>\r\n)\r\n\r\nexport const PhotoIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2\" y=\"3.2\" width=\"12\" height=\"9.6\" rx=\"2\" /><circle cx=\"5.7\" cy=\"6.3\" r=\"0.9\" /><path d=\"M14 10.4l-2.8-2.8-4.8 4.8\" /></Glyph>\r\n)\r\n\r\nexport const VideoIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"1.5\" y=\"4.2\" width=\"8.8\" height=\"7.6\" rx=\"2\" /><path d=\"M10.3 6.9l4.2-2.4v7l-4.2-2.4\" /></Glyph>\r\n)\r\n\r\nexport const TextIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M3 4.2h10M3 8h10M3 11.8h6.5\" /></Glyph>\r\n)\r\n\r\nexport const TrajectoryIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M2.5 3.2h11M2.5 6.6h11M2.5 10h11\" /><circle cx=\"4.4\" cy=\"3.2\" r=\"1.1\" /><circle cx=\"8\" cy=\"6.6\" r=\"1.1\" /><circle cx=\"11.4\" cy=\"10\" r=\"1.1\" /></Glyph>\r\n)\r\n\r\nexport const SlidersIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M2.5 4.5h4.9M11.6 4.5h1.9M2.5 11.5h1.9M8.6 11.5h4.9\" /><circle cx=\"9.5\" cy=\"4.5\" r=\"1.7\" /><circle cx=\"5.5\" cy=\"11.5\" r=\"1.7\" /></Glyph>\r\n)\r\n\r\nexport const SparkleIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M7.2 1.8l1.2 3.1 3.1 1.2-3.1 1.2-1.2 3.1-1.2-3.1L2.9 6.1 6 4.9l1.2-3.1z\" /><path d=\"M12 10.5l.5 1.2 1.2.5-1.2.5-.5 1.2-.5-1.2-1.2-.5 1.2-.5.5-1.2z\" /></Glyph>\r\n)\r\n\r\nexport const RefreshIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M13.2 8A5.2 5.2 0 1 1 11.5 4.2\" /><path d=\"M13.4 1.8v2.9h-2.9\" /></Glyph>\r\n)\r\n\r\nexport const DownloadIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 2.2v8\" /><path d=\"M4.6 7l3.4 3.4L11.4 7\" /><path d=\"M2.8 13.8h10.4\" /></Glyph>\r\n)\r\n\r\nexport const UploadIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 10.4V2.6\" /><path d=\"M4.6 5.8L8 2.4l3.4 3.4\" /><path d=\"M2.8 13.8h10.4\" /></Glyph>\r\n)\r\n\r\nexport const LinkIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M6.6 9.4 9.4 6.6\" /><path d=\"M5.9 11.1l-1.4 1.4a2.6 2.6 0 0 1-3.7-3.7L3.5 6.8\" /><path d=\"M10.1 4.9l1.4-1.4a2.6 2.6 0 0 1 3.7 3.7l-2.1 2.1\" /></Glyph>\r\n)\r\n\r\nexport const LockIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"3.6\" y=\"7.2\" width=\"8.8\" height=\"6\" rx=\"1.4\" /><path d=\"M5.6 7.2V5.4a2.4 2.4 0 0 1 4.8 0v1.8\" /></Glyph>\r\n)\r\n\r\nexport const TrashIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M2.8 4.4h10.4\" /><path d=\"M6.4 4.4V2.9h3.2v1.5\" /><path d=\"M4.4 4.4l.5 8.6h6.2l.5-8.6\" /></Glyph>\r\n)\r\n\r\nexport const EditIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M9.5 4l2.5 2.5\" /><path d=\"M3 13l.8-3L10 3.8 12.2 6 6 12.2 3 13z\" /></Glyph>\r\n)\r\n\r\nexport const PipetteIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><circle cx=\"8\" cy=\"8\" r=\"4.2\" /><path d=\"M8 1.6v2.6M8 11.8v2.6M1.6 8h2.6M11.8 8h2.6\" /></Glyph>\r\n)\r\n\r\nexport const CheckIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M3.2 8.6l3 3L12.8 5\" /></Glyph>\r\n)\r\n\r\nexport const AlertIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M8 2.6l5.4 9.8H2.6L8 2.6z\" /><path d=\"M8 6.8v2.4M8 11.4v.01\" /></Glyph>\r\n)\r\n\r\nexport const CopyIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"5.4\" y=\"5.4\" width=\"7.6\" height=\"7.6\" rx=\"1.6\" /><path d=\"M10.6 5.4V4.2a1.6 1.6 0 0 0-1.6-1.6H4.2a1.6 1.6 0 0 0-1.6 1.6v4.8a1.6 1.6 0 0 0 1.6 1.6h1.2\" /></Glyph>\r\n)\r\n\r\nexport const CanvasIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"2.2\" width=\"11.6\" height=\"11.6\" rx=\"2\" /></Glyph>\r\n)\r\n\r\nexport const SidebarIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"2.2\" width=\"11.6\" height=\"11.6\" rx=\"2\" /><path d=\"M6.6 2.2v11.6\" /></Glyph>\r\n)\r\n\r\n/** Mirror of SidebarIcon: the file-preview panel docked to the right edge. */\r\nexport const PreviewIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"2.2\" width=\"11.6\" height=\"11.6\" rx=\"2\" /><path d=\"M9.4 2.2v11.6\" /><path d=\"M11 5.6h1.2M11 8h1.2\" /></Glyph>\r\n)\r\n\r\nexport const ChatIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><path d=\"M13.4 4.4v4.4a2 2 0 0 1-2 2H6.2l-3.6 3V4.4a2 2 0 0 1 2-2h6.8a2 2 0 0 1 2 2z\" /></Glyph>\r\n)\r\n\r\nexport const GearIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><circle cx=\"8\" cy=\"8\" r=\"2.1\" /><path d=\"M8 1.7v1.8M8 12.5v1.8M1.7 8h1.8M12.5 8h1.8M3.6 3.6l1.3 1.3M11.1 11.1l1.3 1.3M12.4 3.6l-1.3 1.3M4.9 11.1l-1.3 1.3\" /></Glyph>\r\n)\r\n\r\nexport const InputIcon = ({ size, className }: { size?: number; className?: string }) => (\r\n <Glyph size={size} className={className}><rect x=\"2.2\" y=\"4\" width=\"11.6\" height=\"8\" rx=\"2\" /><path d=\"M8 6.6v2M7 8h2\" /></Glyph>\r\n)\r\n\r\n","import { Component, type ReactNode } from 'react'\r\n\r\ninterface Props {\r\n t: (key: string) => string\r\n onReset?: () => void\r\n children: ReactNode\r\n}\r\n\r\ninterface State {\r\n error: Error | null\r\n}\r\n\r\n/**\r\n * Catches render errors from the theme section subtree (wheel, sliders, editor)\r\n * so a single bad state can never take down the whole settings panel. Shows a\r\n * compact fallback with a reset button; the reset re-renders the section with\r\n * the current saved config, which is enough to recover from most transient\r\n * failures (corrupt transient UI state, stale image decode, etc.).\r\n */\r\nexport class ErrorBoundary extends Component<Props, State> {\r\n override state: State = { error: null }\r\n\r\n static getDerivedStateFromError(error: Error): State {\r\n return { error }\r\n }\r\n\r\n override componentDidCatch(error: Error, info: { componentStack?: string | null }): void {\r\n console.error('dsh-background-by-model: section render crashed', error, info.componentStack)\r\n }\r\n\r\n private reset = (): void => {\r\n this.setState({ error: null })\r\n this.props.onReset?.()\r\n }\r\n\r\n override render() {\r\n if (this.state.error) {\r\n return (\r\n <div className=\"dab-crash\">\r\n <div className=\"dab-crash-title\">{this.props.t('crashTitle')}</div>\r\n <div className=\"dab-crash-desc\">{this.props.t('crashDesc')}</div>\r\n <button type=\"button\" className=\"dab-btn\" onClick={this.reset}>{this.props.t('crashReset')}</button>\r\n </div>\r\n )\r\n }\r\n return this.props.children\r\n }\r\n}\r\n","import { useEffect, useState } from 'react'\r\nimport type { ReactNode } from 'react'\r\nimport { createPortal } from 'react-dom'\r\n\r\n/**\r\n * Render children into a fixed root attached to document.documentElement.\r\n *\r\n * The host's sidebar is often implemented by translating the body or a wrapper\r\n * (margin-left / transform). A fixed element portaled to body would still be\r\n * captured by that transformed ancestor and shift with the sidebar. Attaching\r\n * the portal root directly to <html> escapes body-level transforms so the\r\n * overlay is always painted relative to the viewport and centered correctly.\r\n */\r\nexport function Portal({ children }: { children: ReactNode }) {\r\n const [target, setTarget] = useState<HTMLElement | null>(null)\r\n useEffect(() => {\r\n const el = document.createElement('div')\r\n el.dataset.dabPortal = '1'\r\n el.style.cssText = 'position:fixed;inset:0;pointer-events:none;z-index:999999'\r\n document.documentElement.appendChild(el)\r\n setTarget(el)\r\n return () => { el.remove() }\r\n }, [])\r\n return target ? createPortal(children, target) : null\r\n}\r\n","import { useEffect, useRef } from 'react'\r\nimport type { CSSProperties } from 'react'\r\n\r\n/**\r\n * Zero-lag slider: the thumb and value label update through DOM refs while\r\n * dragging (onInput) so the caller can mutate the live UI directly without a\r\n * React re-render; onChange commits the settled value. Double-click resets to\r\n * the canonical default. The track fill is a gradient driven by the --pct\r\n * custom property, updated imperatively alongside the thumb.\r\n */\r\nexport function LiveSlider({ min, max, step, def, fmt, label, onInput, onChange }: {\r\n min: number; max: number; step: number; def: number\r\n fmt: (v: number) => string; label?: string; onInput?: (v: number) => void; onChange: (v: number) => void\r\n}) {\r\n const inputRef = useRef<HTMLInputElement>(null)\r\n const valRef = useRef<HTMLSpanElement>(null)\r\n\r\n const paint = (el: HTMLInputElement, v: number): void => {\r\n el.style.setProperty('--pct', String(((v - min) / (max - min)) * 100))\r\n }\r\n\r\n // Controlled sync: keep the knob and label aligned with the canonical prop\r\n // so external updates (presets, regeneration, imports) never leave it stale.\r\n useEffect(() => {\r\n if (inputRef.current) {\r\n inputRef.current.value = String(def)\r\n paint(inputRef.current, def)\r\n }\r\n if (valRef.current) valRef.current.textContent = fmt(def)\r\n }, [def, fmt, min, max])\r\n\r\n const apply = (v: number): void => {\r\n if (inputRef.current) {\r\n inputRef.current.value = String(v)\r\n paint(inputRef.current, v)\r\n }\r\n if (valRef.current) valRef.current.textContent = fmt(v)\r\n onInput?.(v)\r\n onChange(v)\r\n }\r\n\r\n return (\r\n <div className=\"dab-slider-block\">\r\n {label ? <span className=\"dab-slider-label\">{label}</span> : null}\r\n <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>\r\n <input\r\n ref={inputRef} type=\"range\" className=\"dab-slider\"\r\n style={{ '--pct': ((def - min) / (max - min)) * 100 } as CSSProperties}\r\n min={min} max={max} step={step} defaultValue={def}\r\n title={label ? `${label} · ${fmt(def)}` : fmt(def)}\r\n onDoubleClick={() => apply(def)}\r\n onInput={e => {\r\n const el = e.target as HTMLInputElement\r\n const v = Number(el.value)\r\n paint(el, v)\r\n onInput?.(v)\r\n if (valRef.current) valRef.current.textContent = fmt(v)\r\n }}\r\n onChange={e => onChange(Number((e.target as HTMLInputElement).value))} />\r\n <span ref={valRef} className=\"dab-slider-val\">{fmt(def)}</span>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import type { CSSProperties, ComponentType } from 'react'\r\nimport type { ThemeSectionProps, PartOpacities, PartBlurs } from '../../types'\r\nimport { cfg, rOps, rSop, rBlurs, rChatTextOpacity, rTrajectoryOpacity, rRightbarOpacity } from '../../state'\r\nimport { saveConfig } from '../../rpc'\r\nimport { applyCustomTokens, applySettingsOverrides, setPartBlur, applyViewCards, applyTrajectoryOverrides, applyRightbarOverrides } from '../../wallpaper'\r\nimport { LiveSlider } from '../LiveSlider'\r\nimport { CanvasIcon, SidebarIcon, ChatIcon, GearIcon, TextIcon, TrajectoryIcon, PreviewIcon, InputIcon } from '../icons'\r\n\r\ninterface PartDef {\r\n labelKey: string\r\n Icon: ComponentType<{ size?: number }>\r\n /** Homepage part key; absent for the settings-panel part. */\r\n opKey?: keyof PartOpacities\r\n isSettings?: boolean\r\n /** Conversation text region: tint opacity + blur over the message column. */\r\n isChat?: boolean\r\n /** Trajectory view: tint opacity + blur over the whole view surface. */\r\n isTrajectory?: boolean\r\n /** File-preview panel: the right sidebar a file click opens. */\r\n isRightbar?: boolean\r\n}\r\n\r\nconst PARTS: PartDef[] = [\r\n { opKey: 'bg', labelKey: 'uiOpacityBg', Icon: CanvasIcon },\r\n { opKey: 'sidebar', labelKey: 'uiOpacitySide', Icon: SidebarIcon },\r\n { isRightbar: true, labelKey: 'uiPreview', Icon: PreviewIcon },\r\n { opKey: 'card', labelKey: 'uiOpacityCard', Icon: ChatIcon },\r\n { opKey: 'input', labelKey: 'uiOpacityInput', Icon: InputIcon },\r\n { isSettings: true, labelKey: 'uiSop', Icon: GearIcon },\r\n { isChat: true, labelKey: 'uiChatRegion', Icon: TextIcon },\r\n { isTrajectory: true, labelKey: 'uiTrajectory', Icon: TrajectoryIcon },\r\n]\r\n\r\nexport function InterfacePage({ p }: { p: ThemeSectionProps }) {\r\n const { t, setOps, setBlurs, setSop, setRightbarOpacity } = p\r\n\r\n return (\r\n <>\r\n <header className=\"dab-head dab-rise\" style={{ '--d': 0 } as CSSProperties}>\r\n <div className=\"dab-overline\">Surfaces</div>\r\n <h2 className=\"dab-h1\">{t('uiTitle')}</h2>\r\n <p className=\"dab-desc\">{t('descInterface')}</p>\r\n </header>\r\n\r\n <div className=\"dab-grid-parts\">\r\n {PARTS.map((part, i) => {\r\n const { labelKey, Icon, isSettings, isChat, isTrajectory, isRightbar } = part\r\n const opKey = part.opKey\r\n // Homepage parts (bg/sidebar/card/input) bind to their own part only;\r\n // the settings panel (isSettings) binds exclusively to the 'settings'\r\n // part (--dsh-any-blur-settings / --dsh-any-bg-settings-surface) and\r\n // must never fall back to a homepage part key — otherwise the dialog\r\n // panel would track the homepage center/card blur and the home-page\r\n // opacities. The chat region (isChat) and the trajectory view\r\n // (isTrajectory) own their own blur keys plus their own tint\r\n // opacities, and the file-preview panel (isRightbar) owns the right\r\n // column's backdrop through the same deal. Every homepage opKey is\r\n // also a PartBlurs key (input included), so the shared blur slider\r\n // dereferences it directly.\r\n const blurKey: keyof PartBlurs = isChat\r\n ? 'chat'\r\n : isTrajectory\r\n ? 'trajectory'\r\n : isRightbar\r\n ? 'rightbar'\r\n : isSettings ? 'settings' : opKey!\r\n const opacity = isChat\r\n ? rChatTextOpacity()\r\n : isTrajectory\r\n ? rTrajectoryOpacity()\r\n : isRightbar ? rRightbarOpacity() : isSettings ? rSop() : rOps()[opKey!]\r\n return (\r\n <section key={blurKey} className=\"dab-card dab-card-hover dab-rise\" style={{ '--d': i + 1 } as CSSProperties}>\r\n <div className=\"dab-part-head\">\r\n <div className=\"dab-part-ico\"><Icon size={16} /></div>\r\n <div className=\"dab-part-name\">{t(labelKey)}</div>\r\n <span className=\"dab-part-badge\">{Math.round(opacity * 100)}%</span>\r\n </div>\r\n\r\n <LiveSlider label={t('uiOpacity')} min={0} max={100} step={1} def={Math.round(opacity * 100)}\r\n fmt={v => `${v}%`}\r\n onInput={v => {\r\n const op = v / 100\r\n if (isChat) {\r\n cfg.chatTextOpacity = op\r\n applyViewCards()\r\n } else if (isTrajectory) {\r\n cfg.trajectoryOpacity = op\r\n applyTrajectoryOverrides(op)\r\n } else if (isRightbar) {\r\n // First drag is what detaches the panel from the main\r\n // background; from then on the card owns it.\r\n cfg.rightbarOpacity = op\r\n applyRightbarOverrides(op)\r\n } else if (isSettings) {\r\n cfg.settingsOpacity = op\r\n applySettingsOverrides(op)\r\n } else {\r\n const ops = { ...rOps() }\r\n ops[opKey!] = op\r\n cfg.opacities = ops\r\n applyCustomTokens(ops)\r\n }\r\n saveConfig()\r\n }}\r\n onChange={v => {\r\n const op = v / 100\r\n if (isChat) {\r\n cfg.chatTextOpacity = op\r\n applyViewCards()\r\n saveConfig()\r\n } else if (isTrajectory) {\r\n cfg.trajectoryOpacity = op\r\n applyTrajectoryOverrides(op)\r\n saveConfig()\r\n } else if (isRightbar) {\r\n setRightbarOpacity(op)\r\n } else if (isSettings) {\r\n setSop(op)\r\n } else {\r\n const ops = { ...rOps() }\r\n ops[opKey!] = op\r\n setOps(ops)\r\n }\r\n }} />\r\n\r\n <LiveSlider label={t('uiBlur')} min={0} max={60} step={1} def={rBlurs()[blurKey]}\r\n fmt={v => `${v}px`}\r\n onInput={v => {\r\n const blurs = { ...rBlurs() }\r\n blurs[blurKey] = v\r\n cfg.blurs = blurs\r\n setPartBlur(blurKey, v)\r\n saveConfig()\r\n }}\r\n onChange={v => {\r\n const blurs = { ...rBlurs() }\r\n blurs[blurKey] = v\r\n setBlurs(blurs)\r\n }} />\r\n </section>\r\n )\r\n })}\r\n </div>\r\n </>\r\n )\r\n}\r\n","/**\r\n * Read a chosen image file as a data URL WITHOUT re-encoding: the original\r\n * pixels are kept as-is (no canvas downscale / JPEG re-compression), so the\r\n * wallpaper is stored and displayed at full fidelity. The tradeoff is a larger\r\n * payload over the RPC channel and on disk for big images.\r\n */\r\nexport function readImg(file: File, cb: (url: string | null) => void): void {\r\n const r = new FileReader()\r\n r.onerror = () => cb(null)\r\n r.onload = () => cb(r.result as string)\r\n r.readAsDataURL(file)\r\n}\r\n","import { useRef, useState, useEffect, useCallback, memo } from 'react'\r\n\r\nconst WHEEL_SIZE = 220\r\nconst CX = WHEEL_SIZE / 2\r\nconst RING_OUTER = 106\r\nconst RING_INNER = 82\r\n// Square inscribed in the ring's inner circle: half-side = RING_INNER / √2,\r\n// so the four corners sit exactly on the inner edge of the hue ring. The\r\n// exact (un-rounded) value keeps the corners tangent to the ring — a rounded\r\n// half-side would push the diagonals past the ring's inner boundary.\r\nconst SQ_HALF = RING_INNER / Math.SQRT2\r\n\r\n/** Static hue ring cached once across all wheels. */\r\nlet ringCache: HTMLCanvasElement | null = null\r\nfunction getRingCache(): HTMLCanvasElement {\r\n if (ringCache) return ringCache\r\n const cvs = document.createElement('canvas')\r\n cvs.width = WHEEL_SIZE; cvs.height = WHEEL_SIZE\r\n const c = cvs.getContext('2d')!\r\n // Instead of 360 separate arc paths, use a single conic gradient clipped to\r\n // the ring. This removes per-frame path overhead and anti-aliasing gaps.\r\n const g = c.createConicGradient(0, CX, CX)\r\n for (let i = 0; i <= 360; i++) g.addColorStop(i / 360, `hsl(${i},100%,50%)`)\r\n c.beginPath()\r\n c.arc(CX, CX, RING_OUTER, 0, Math.PI * 2)\r\n c.arc(CX, CX, RING_INNER, 0, Math.PI * 2, true)\r\n c.fillStyle = g\r\n c.fill()\r\n ringCache = cvs\r\n return ringCache\r\n}\r\n\r\nfunction drawMarkers(ctx: CanvasRenderingContext2D, hue: number, sat: number, lit: number): void {\r\n // Hue marker on ring. Canvas math angles (0 = +x / \"3 o'clock\", positive =\r\n // toward +y) directly match the conic-gradient hue distribution drawn in\r\n // getRingCache (colorStop i/360 → hsl(i)), so NO extra ±90° shift is applied.\r\n // A shift would rotate the picker's indication 90° away from the rendered\r\n // gradient (e.g. picking the top of the wheel would report red while the\r\n // pixels there are blue). hue 0 sits at the right edge, +90° at the bottom.\r\n const hRad = hue * Math.PI / 180\r\n const hR = (RING_OUTER + RING_INNER) / 2\r\n const hmx = CX + Math.cos(hRad) * hR\r\n const hmy = CX + Math.sin(hRad) * hR\r\n ctx.beginPath(); ctx.arc(hmx, hmy, 8, 0, Math.PI * 2)\r\n ctx.fillStyle = 'rgba(0,0,0,0.25)'; ctx.fill()\r\n ctx.beginPath(); ctx.arc(hmx, hmy, 6.5, 0, Math.PI * 2)\r\n ctx.strokeStyle = '#fff'; ctx.lineWidth = 2; ctx.stroke()\r\n\r\n // SL marker (HSV coordinates)\r\n const gx = CX - SQ_HALF, gy = CX - SQ_HALF, sz = SQ_HALF * 2\r\n const smx = gx + sat * sz\r\n const smy = gy + (1 - lit) * sz\r\n ctx.beginPath(); ctx.arc(smx, smy, 7, 0, Math.PI * 2)\r\n ctx.fillStyle = 'rgba(0,0,0,0.25)'; ctx.fill()\r\n ctx.beginPath(); ctx.arc(smx, smy, 5.5, 0, Math.PI * 2)\r\n ctx.strokeStyle = '#fff'; ctx.lineWidth = 2; ctx.stroke()\r\n ctx.beginPath(); ctx.arc(smx, smy, 3.5, 0, Math.PI * 2)\r\n ctx.strokeStyle = '#000'; ctx.lineWidth = 1; ctx.stroke()\r\n}\r\n\r\nfunction drawSquare(c: CanvasRenderingContext2D, hue: number): void {\r\n const gx = CX - SQ_HALF, gy = CX - SQ_HALF, sz = SQ_HALF * 2\r\n c.clearRect(gx - 1, gy - 1, sz + 2, sz + 2)\r\n c.fillStyle = '#fff'; c.fillRect(gx, gy, sz, sz)\r\n const gh = c.createLinearGradient(gx, 0, gx + sz, 0)\r\n gh.addColorStop(0, 'rgba(255,255,255,1)'); gh.addColorStop(1, `hsl(${hue},100%,50%)`)\r\n c.fillStyle = gh; c.fillRect(gx, gy, sz, sz)\r\n const gv = c.createLinearGradient(0, gy, 0, gy + sz)\r\n gv.addColorStop(0, 'rgba(0,0,0,0)'); gv.addColorStop(1, 'rgba(0,0,0,1)')\r\n c.fillStyle = gv; c.fillRect(gx, gy, sz, sz)\r\n}\r\n\r\nfunction hitTest(x: number, y: number): 'ring' | 'square' | null {\r\n if (Math.abs(x - CX) <= SQ_HALF && Math.abs(y - CX) <= SQ_HALF) return 'square'\r\n const dx = x - CX, dy = y - CX\r\n const dist = Math.sqrt(dx * dx + dy * dy)\r\n if (dist >= RING_INNER - 4 && dist <= RING_OUTER + 4) return 'ring'\r\n return null\r\n}\r\n\r\nfunction pickHue(x: number, y: number): number {\r\n // Inverse of drawMarkers: no ±90° shift, matching the conic gradient exactly.\r\n let angle = Math.atan2(y - CX, x - CX) * 180 / Math.PI\r\n if (angle < 0) angle += 360\r\n return angle\r\n}\r\n\r\nfunction pickSL(x: number, y: number): [number, number] {\r\n const gx = CX - SQ_HALF, gy = CX - SQ_HALF, sz = SQ_HALF * 2\r\n return [\r\n Math.max(0, Math.min(1, (x - gx) / sz)),\r\n Math.max(0.02, Math.min(0.98, 1 - (y - gy) / sz)),\r\n ]\r\n}\r\n\r\nexport const ColorWheel = memo(function ColorWheel({ hue, sat, lit, onChange }: {\r\n hue: number; sat: number; lit: number\r\n onChange: (h: number, s: number, l: number) => void\r\n}) {\r\n const cvsRef = useRef<HTMLCanvasElement>(null)\r\n const [col, setCol] = useState({ hue, sat, lit })\r\n const colRef = useRef(col)\r\n colRef.current = col\r\n\r\n // Adopt external changes (e.g. section remount after theme restore).\r\n useEffect(() => {\r\n setCol(c => (c.hue === hue && c.sat === sat && c.lit === lit ? c : { hue, sat, lit }))\r\n }, [hue, sat, lit])\r\n\r\n // Redraw only what changed. The static ring is copied from cache; the square\r\n // only redraws when hue changes; markers redraw on every value change.\r\n useEffect(() => {\r\n const cvs = cvsRef.current\r\n if (!cvs) return\r\n const ctx = cvs.getContext('2d')!\r\n ctx.clearRect(0, 0, WHEEL_SIZE, WHEEL_SIZE)\r\n // Draw the square first, then the ring on top: the ring's opaque pixels\r\n // cover the square's four corners (which are tangent to the ring's inner\r\n // edge), so the corners no longer visually overlap the hue ring.\r\n drawSquare(ctx, col.hue)\r\n ctx.drawImage(getRingCache(), 0, 0)\r\n drawMarkers(ctx, col.hue, col.sat, col.lit)\r\n }, [col])\r\n\r\n // Batch pointer updates in a single rAF so rapid mousemove events do not\r\n // trigger a React state flush + onChange on every pixel.\r\n const pendingRef = useRef<{ h: number; s: number; l: number } | null>(null)\r\n const rafRef = useRef<number | null>(null)\r\n const flushPending = useCallback(() => {\r\n rafRef.current = null\r\n const p = pendingRef.current\r\n if (!p) return\r\n pendingRef.current = null\r\n setCol({ hue: p.h, sat: p.s, lit: p.l })\r\n onChange(p.h, p.s, p.l)\r\n }, [onChange])\r\n\r\n const schedule = useCallback((h: number, s: number, l: number) => {\r\n pendingRef.current = { h, s, l }\r\n if (rafRef.current === null) rafRef.current = requestAnimationFrame(flushPending)\r\n }, [flushPending])\r\n\r\n const onDown = useCallback((e: React.MouseEvent<HTMLCanvasElement>) => {\r\n const r = cvsRef.current!.getBoundingClientRect()\r\n const x = e.clientX - r.left, y = e.clientY - r.top\r\n const region = hitTest(x, y)\r\n if (!region) return\r\n if (region === 'ring') {\r\n schedule(pickHue(x, y), colRef.current.sat, colRef.current.lit)\r\n } else {\r\n const [s, l] = pickSL(x, y)\r\n schedule(colRef.current.hue, s, l)\r\n }\r\n const onMove = (ev: MouseEvent) => {\r\n const rr = cvsRef.current!.getBoundingClientRect()\r\n const mx = ev.clientX - rr.left, my = ev.clientY - rr.top\r\n if (region === 'ring') {\r\n const d = Math.sqrt((mx - CX) ** 2 + (my - CX) ** 2)\r\n if (d >= RING_INNER - 10 && d <= RING_OUTER + 10) schedule(pickHue(mx, my), colRef.current.sat, colRef.current.lit)\r\n } else {\r\n const [s, l] = pickSL(mx, my)\r\n schedule(colRef.current.hue, s, l)\r\n }\r\n }\r\n const onUp = () => { document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp) }\r\n document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp)\r\n }, [schedule])\r\n\r\n return <canvas ref={cvsRef} width={WHEEL_SIZE} height={WHEEL_SIZE} className=\"dab-wheel\" onMouseDown={onDown} />\r\n})\r\n","import { useState, useEffect, useRef } from 'react'\r\nimport type { CSSProperties } from 'react'\r\nimport { hsvToHsl, hslToRgb, rgbToHsl, hslToHsv } from '../utils/color'\r\n\r\ntype Mode = 'hsl' | 'rgb'\r\n\r\nconst SEG_W = 66\r\n\r\nfunction clamp(v: number, min: number, max: number): number {\r\n return Math.min(max, Math.max(min, v))\r\n}\r\n\r\n/** '#rrggbb' for a 0-255 RGB triple, in the caller's case. */\r\nfunction toHex(rgb: [number, number, number]): string {\r\n return '#' + rgb.map(v => Math.round(v).toString(16).padStart(2, '0')).join('')\r\n}\r\n\r\n/**\r\n * A single numeric field that edits one color channel. Keeps its own text\r\n * while focused so typing never gets clobbered by the parent re-rendering the\r\n * canonical value; commits every valid keystroke live and re-normalizes on\r\n * blur. The value prop only pushes back in when the field is not focused\r\n * (wheel drags, wallpaper extraction, mode switches).\r\n */\r\nfunction NumField({ label, value, min, max, step, onChange }: {\r\n label: string; value: number; min: number; max: number; step: number\r\n onChange: (v: number) => void\r\n}) {\r\n const [text, setText] = useState(String(value))\r\n const focused = useRef(false)\r\n\r\n useEffect(() => {\r\n if (!focused.current) setText(String(value))\r\n }, [value])\r\n\r\n return (\r\n <label className=\"dab-field\">\r\n <span className=\"dab-field-label\">{label}</span>\r\n <input\r\n type=\"number\"\r\n min={min} max={max} step={step}\r\n value={text}\r\n className=\"dab-num\"\r\n onFocus={() => { focused.current = true }}\r\n onBlur={() => { focused.current = false; setText(String(value)) }}\r\n onChange={e => {\r\n setText(e.target.value)\r\n const v = Number(e.target.value)\r\n if (Number.isFinite(v)) onChange(clamp(v, min, max))\r\n }}\r\n />\r\n </label>\r\n )\r\n}\r\n\r\n/**\r\n * Precise color entry next to the wheel: a HSL/RGB segmented toggle plus three\r\n * numeric channel fields and a live preview field that prints its own hex. The\r\n * wheel is HSV end-to-end, so this panel converts at the boundary — HSL fields\r\n * map straight onto the stored HSL, RGB fields round-trip through rgbToHsl —\r\n * and both emit HSV via the same onChange the wheel uses, keeping one canonical\r\n * color.\r\n */\r\nexport function ColorInputs({ hue, sat, lit, onChange }: {\r\n hue: number; sat: number; lit: number\r\n onChange: (h: number, s: number, l: number) => void\r\n}) {\r\n const [mode, setMode] = useState<Mode>('hsl')\r\n const [h, s, l] = hsvToHsl(hue, sat, lit)\r\n const [r, g, b] = hslToRgb(h, s, l)\r\n const hex = toHex([r, g, b]).toUpperCase()\r\n // Ink for the hex printed ON the preview field. Rec.709 luma is the\r\n // brightness measure the wallpaper extractor already uses, so the two agree:\r\n // a light color gets dark ink and a dark one light ink, and the value never\r\n // disappears into its own fill.\r\n const ink = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.55 ? 'rgba(0,0,0,.78)' : 'rgba(255,255,255,.92)'\r\n\r\n const setHsl = (nh: number, ns: number, nl: number) => onChange(...hslToHsv(nh, ns, nl))\r\n const setRgb = (nr: number, ng: number, nb: number) => {\r\n const [nh, ns, nl] = rgbToHsl(nr, ng, nb)\r\n onChange(...hslToHsv(nh, ns, nl))\r\n }\r\n\r\n return (\r\n <div className=\"dab-inputs\">\r\n <div className=\"dab-seg\" style={{ '--w': `${SEG_W}px` } as CSSProperties}>\r\n <div className=\"dab-seg-thumb\" style={{ transform: `translateX(${mode === 'hsl' ? 0 : SEG_W}px)` }} />\r\n <button type=\"button\" className={`dab-seg-item${mode === 'hsl' ? ' is-active' : ''}`} onClick={() => setMode('hsl')}>HSL</button>\r\n <button type=\"button\" className={`dab-seg-item${mode === 'rgb' ? ' is-active' : ''}`} onClick={() => setMode('rgb')}>RGB</button>\r\n </div>\r\n <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>\r\n {mode === 'hsl' ? (\r\n <>\r\n <NumField label=\"H\" value={Math.round(h)} min={0} max={360} step={1} onChange={v => setHsl(v, s, l)} />\r\n <NumField label=\"S\" value={Math.round(s * 100)} min={0} max={100} step={1} onChange={v => setHsl(h, v / 100, l)} />\r\n <NumField label=\"L\" value={Math.round(l * 100)} min={0} max={100} step={1} onChange={v => setHsl(h, s, v / 100)} />\r\n </>\r\n ) : (\r\n <>\r\n <NumField label=\"R\" value={r} min={0} max={255} step={1} onChange={v => setRgb(v, g, b)} />\r\n <NumField label=\"G\" value={g} min={0} max={255} step={1} onChange={v => setRgb(r, v, b)} />\r\n <NumField label=\"B\" value={b} min={0} max={255} step={1} onChange={v => setRgb(r, g, v)} />\r\n </>\r\n )}\r\n </div>\r\n {/* Prints its own value. An empty colored rectangle sitting in the same\r\n column as the H/S/L fields reads as one more text input — and there is\r\n nothing to type into it, so the value it is showing has to be visible\r\n on it. Without the hex this was the one control in the panel that\r\n looked editable and was not. */}\r\n <div\r\n className=\"dab-swatch-lg\"\r\n style={{ background: `hsl(${Math.round(h)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%)`, color: ink }}>\r\n {hex}\r\n </div>\r\n </div>\r\n )\r\n}\r\n","import { useRef, useState, useEffect, useCallback } from 'react'\r\nimport { rgbToHsl, hslToHsv } from '../utils/color'\r\nimport { Portal } from './Portal'\r\n\r\nconst MAG_SIZE = 96\r\nconst MAG_ZOOM = 8\r\n\r\nfunction toHex(rgb: [number, number, number]): string {\r\n return '#' + rgb.map(v => v.toString(16).padStart(2, '0')).join('')\r\n}\r\n\r\n/**\r\n * Eyedropper modal: shows the wallpaper full-bleed (no drag/zoom) and lets the\r\n * user click any pixel to adopt it as the theme color. A magnifier circle\r\n * follows the cursor so small details can be picked precisely. The wallpaper\r\n * is a data URL, so sampling is CORS-free: draw it once to an offscreen-sized\r\n * canvas and read pixels via getImageData.\r\n */\r\nexport function ColorPicker({ url, t, onPick, onClose }: {\r\n url: string\r\n t: (key: string) => string\r\n onPick: (hsv: [number, number, number]) => void\r\n onClose: () => void\r\n}) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n const magRef = useRef<HTMLCanvasElement>(null)\r\n const imgRef = useRef<HTMLImageElement | null>(null)\r\n const [ready, setReady] = useState(false)\r\n const [hover, setHover] = useState<{ rgb: [number, number, number] } | null>(null)\r\n const [mag, setMag] = useState<{ x: number; y: number } | null>(null)\r\n\r\n useEffect(() => {\r\n const img = new Image()\r\n img.onload = () => { imgRef.current = img; setReady(true) }\r\n img.src = url\r\n }, [url])\r\n\r\n useEffect(() => {\r\n if (!ready || !canvasRef.current || !imgRef.current) return\r\n const canvas = canvasRef.current\r\n canvas.width = imgRef.current.naturalWidth\r\n canvas.height = imgRef.current.naturalHeight\r\n const ctx = canvas.getContext('2d')\r\n if (ctx) ctx.drawImage(imgRef.current, 0, 0)\r\n }, [ready])\r\n\r\n const sampleAt = useCallback((clientX: number, clientY: number) => {\r\n const canvas = canvasRef.current\r\n if (!canvas) return null\r\n const rect = canvas.getBoundingClientRect()\r\n if (rect.width === 0 || rect.height === 0) return null\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx) return null\r\n const sx = Math.round((clientX - rect.left) * (canvas.width / rect.width))\r\n const sy = Math.round((clientY - rect.top) * (canvas.height / rect.height))\r\n if (sx < 0 || sy < 0 || sx >= canvas.width || sy >= canvas.height) return null\r\n const d = ctx.getImageData(sx, sy, 1, 1).data\r\n return { sx, sy, rgb: [d[0], d[1], d[2]] as [number, number, number] }\r\n }, [])\r\n\r\n const drawMagnifier = useCallback((sx: number, sy: number) => {\r\n const mag = magRef.current\r\n const src = canvasRef.current\r\n if (!mag || !src) return\r\n const ctx = mag.getContext('2d')\r\n if (!ctx) return\r\n const half = MAG_SIZE / MAG_ZOOM / 2\r\n ctx.clearRect(0, 0, MAG_SIZE, MAG_SIZE)\r\n ctx.drawImage(src, sx - half, sy - half, half * 2, half * 2, 0, 0, MAG_SIZE, MAG_SIZE)\r\n ctx.strokeStyle = 'rgba(255,255,255,0.85)'\r\n ctx.lineWidth = 1\r\n ctx.beginPath()\r\n ctx.moveTo(MAG_SIZE / 2, 0); ctx.lineTo(MAG_SIZE / 2, MAG_SIZE)\r\n ctx.moveTo(0, MAG_SIZE / 2); ctx.lineTo(MAG_SIZE, MAG_SIZE / 2)\r\n ctx.stroke()\r\n }, [])\r\n\r\n const onMove = (e: React.MouseEvent) => {\r\n const s = sampleAt(e.clientX, e.clientY)\r\n if (!s) { setHover(null); setMag(null); return }\r\n setHover({ rgb: s.rgb })\r\n drawMagnifier(s.sx, s.sy)\r\n const off = 28\r\n let x = e.clientX + off\r\n let y = e.clientY + off\r\n if (x + MAG_SIZE > window.innerWidth) x = e.clientX - off - MAG_SIZE\r\n if (y + MAG_SIZE > window.innerHeight) y = e.clientY - off - MAG_SIZE\r\n setMag({ x, y })\r\n }\r\n\r\n const onClick = (e: React.MouseEvent) => {\r\n const s = sampleAt(e.clientX, e.clientY)\r\n if (!s) return\r\n const [h, sl, l] = rgbToHsl(s.rgb[0], s.rgb[1], s.rgb[2])\r\n onPick(hslToHsv(h, sl, l))\r\n }\r\n\r\n return (\r\n <Portal>\r\n <div className=\"dab-overlay\">\r\n <div className=\"dab-overlay-title\">{t('pickerTitle')}</div>\r\n <div className=\"dab-overlay-hint\">{t('pickerHint')}</div>\r\n <div className=\"dab-modal-card\" style={{\r\n maxWidth: 'min(90vw, 720px)', maxHeight: '60vh', overflow: 'hidden',\r\n borderRadius: 12, border: '2px solid rgba(255,255,255,0.3)', background: '#000', cursor: 'crosshair',\r\n }}>\r\n <canvas ref={canvasRef} style={{ display: 'block', maxWidth: '100%', maxHeight: '60vh', objectFit: 'contain' }}\r\n onMouseMove={onMove}\r\n onMouseLeave={() => { setHover(null); setMag(null) }}\r\n onClick={onClick} />\r\n </div>\r\n <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 260 }}>\r\n <div style={{ width: 28, height: 28, borderRadius: 8, border: '1px solid rgba(255,255,255,0.4)', background: hover ? toHex(hover.rgb) : 'transparent' }} />\r\n <div style={{ color: '#fff', fontSize: 13, fontFamily: 'var(--dab-mono, monospace)' }}>{hover ? `${toHex(hover.rgb)} · rgb(${hover.rgb.join(', ')})` : '—'}</div>\r\n </div>\r\n <div style={{ display: 'flex', gap: 10 }}>\r\n <button type=\"button\" className=\"dab-btn\" onClick={onClose}>{t('pickerClose')}</button>\r\n </div>\r\n <canvas ref={magRef} width={MAG_SIZE} height={MAG_SIZE}\r\n style={{\r\n position: 'fixed', width: MAG_SIZE, height: MAG_SIZE, borderRadius: '50%',\r\n border: '2px solid rgba(255,255,255,0.7)', boxShadow: '0 4px 16px rgba(0,0,0,0.5)',\r\n zIndex: 10000, background: '#000', pointerEvents: 'none', transition: 'opacity 0.08s',\r\n left: mag?.x ?? 0, top: mag?.y ?? 0, opacity: mag ? 1 : 0,\r\n }} />\r\n </div>\r\n </Portal>\r\n )\r\n}\r\n","import { useRef, useState, useEffect, useCallback } from 'react'\nimport type { BgState } from '../types'\nimport { Portal } from './Portal'\n\n/**\n * Framing editor for one rule's image.\n *\n * The placement state is passed IN rather than read from a global slot: every\n * rule owns its own framing, and editing rule B must never touch rule A.\n */\nexport function BgEditor({ url, state, t, onClose, onCommit }: {\n url: string\n /** The rule's own framing. */\n state: BgState\n t: (key: string) => string; onClose: () => void\n onCommit: (zoom: number, x: number, y: number, iw: number, ih: number) => void\n}) {\n const pw = Math.min(window.innerWidth * 0.75, 860)\n const ph = Math.round(pw * window.innerHeight / window.innerWidth)\n const saved = state\n const [zoom, setZoom] = useState(saved.iw > 0 ? saved.zoom : 1)\n const [pos, setPos] = useState(saved.iw > 0 ? { x: saved.x * pw, y: saved.y * ph } : { x: 0, y: 0 })\n const [imgSize, setImgSize] = useState({ w: 0, h: 0 })\n const containerRef = useRef<HTMLDivElement>(null)\n const imgRef = useRef<HTMLImageElement>(null)\n const dragRef = useRef({ active: false, sx: 0, sy: 0, spx: 0, spy: 0 })\n\n useEffect(() => {\n const img = new Image()\n img.onload = () => {\n const scale = Math.min(pw / img.width, ph / img.height)\n const w = img.width * scale, h = img.height * scale\n setImgSize({ w, h })\n const s = state\n if (s.iw > 0 && s.iw === img.width && s.ih === img.height) {\n setZoom(s.zoom)\n // Saved x, y are CENTER fractions of the preview: the image center\n // lands at (x·pw, y·ph), so the top-left comes from subtracting half\n // the displayed (zoom-scaled) image size.\n setPos({ x: s.x * pw - w * s.zoom / 2, y: s.y * ph - h * s.zoom / 2 })\n } else {\n setZoom(1)\n setPos({ x: (pw - w) / 2, y: (ph - h) / 2 })\n }\n }\n img.src = url\n }, [url, state, pw, ph])\n\n const onDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault()\n dragRef.current = { active: true, sx: e.clientX, sy: e.clientY, spx: pos.x, spy: pos.y }\n const onMove = (ev: MouseEvent) => {\n if (!dragRef.current.active) return\n setPos({ x: dragRef.current.spx + ev.clientX - dragRef.current.sx, y: dragRef.current.spy + ev.clientY - dragRef.current.sy })\n }\n const onUp = () => { dragRef.current.active = false; document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp) }\n document.addEventListener('mousemove', onMove); document.addEventListener('mouseup', onUp)\n }, [pos])\n\n const onWheelCb = useCallback((e: WheelEvent) => {\n e.preventDefault()\n const el = containerRef.current\n if (!el) return\n const rect = el.getBoundingClientRect()\n // Anchor the zoom at the preview center so the mouse position never\n // steers where the image grows/shrinks — the current view stays centered.\n const mx = rect.width / 2, my = rect.height / 2\n // 3% per wheel step (0.97 zoom-out / 1.03 zoom-in).\n const factor = e.deltaY > 0 ? 0.97 : 1.03\n const nz = Math.max(0.1, Math.min(10, zoom * factor))\n const nx = mx - (mx - pos.x) * (nz / zoom)\n const ny = my - (my - pos.y) * (nz / zoom)\n setZoom(nz); setPos({ x: nx, y: ny })\n }, [zoom, pos])\n\n useEffect(() => {\n const el = containerRef.current\n if (!el) return\n el.addEventListener('wheel', onWheelCb, { passive: false })\n return () => el.removeEventListener('wheel', onWheelCb)\n }, [onWheelCb])\n\n const resetView = useCallback(() => {\n if (imgSize.w === 0) return\n setZoom(1); setPos({ x: (pw - imgSize.w) / 2, y: (ph - imgSize.h) / 2 })\n }, [pw, ph, imgSize])\n\n return (\n <Portal>\n <div className=\"dab-overlay\" onClick={e => { if (e.target === e.currentTarget) onClose() }}>\n <div className=\"dab-overlay-title\">{t('editorTitle')}</div>\n <div ref={containerRef} className=\"dab-modal-card\" style={{\n position: 'relative', overflow: 'hidden', border: '2px solid rgba(255,255,255,0.3)',\n borderRadius: 12, background: '#000', cursor: 'grab', width: pw, height: ph,\n }} onMouseDown={onDown}>\n <img ref={imgRef} src={url} alt=\"\" draggable={false} style={{\n position: 'absolute', transformOrigin: '0 0', pointerEvents: 'none',\n width: imgSize.w, height: imgSize.h,\n transform: `translate(${pos.x}px,${pos.y}px) scale(${zoom})`,\n }} />\n </div>\n <div className=\"dab-overlay-hint\">{t('editorHint')}</div>\n <div style={{ display: 'flex', gap: 10 }}>\n <button type=\"button\" className=\"dab-btn\" onClick={resetView}>{t('editorReset')}</button>\n <button type=\"button\" className=\"dab-btn\" onClick={onClose}>{t('editorCancel')}</button>\n <button type=\"button\" className=\"dab-btn\" onClick={() => onCommit(zoom, (pos.x + imgSize.w * zoom / 2) / pw, (pos.y + imgSize.h * zoom / 2) / ph, imgRef.current?.naturalWidth ?? 0, imgRef.current?.naturalHeight ?? 0)}>{t('editorCommit')}</button>\n </div>\n </div>\n </Portal>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { CSSProperties, PointerEvent as ReactPointerEvent } from 'react'\nimport type { BgMode, BgRule, ThemeSectionProps, ThemeStoreState } from '../../types'\nimport { cfg, PALETTE } from '../../state'\nimport { matchRule } from '../../modelbg'\nimport { ROTATE_PRESETS } from '../../rotation'\nimport { readImg } from '../../utils/image'\nimport { hslToHsv, hsvToHsl, hslToRgb } from '../../utils/color'\nimport { ColorWheel } from '../ColorWheel'\nimport { ColorInputs } from '../ColorInputs'\nimport { ColorPicker } from '../ColorPicker'\nimport { BgEditor } from '../BgEditor'\nimport { LiveSlider } from '../LiveSlider'\nimport { DropletIcon, EditIcon, LinkIcon, PipetteIcon, SparkleIcon, SunIcon, TrashIcon, UploadIcon } from '../icons'\n\nconst BG_MODES: Array<{ mode: BgMode; key: string }> = [\n { mode: 'fit', key: 'bgModeFit' },\n { mode: 'fill', key: 'bgModeFill' },\n { mode: 'stretch', key: 'bgModeStretch' },\n { mode: 'tile', key: 'bgModeTile' },\n { mode: 'center', key: 'bgModeCenter' },\n]\n\n/** Seed color a rule starts from when the user picks one for the first time. */\nconst SEED_COLOR: [number, number, number] = [220, 0.55, 0.25]\n\n/**\n * Failing-hop codes the model watcher can report, mapped to their copy. Only\n * these are rendered: `waiting` and `fallback` already have their own hints.\n */\nconst MODEL_NOTE_KEYS: Record<string, string | undefined> = {\n 'no-service': 'statusNoteNoService',\n 'no-session': 'statusNoteNoSession',\n 'no-projection': 'statusNoteNoProjection',\n 'empty-selection': 'statusNoteEmptySelection',\n}\n\nfunction toHex(rgb: [number, number, number]): string {\n return '#' + rgb.map(v => Math.round(v).toString(16).padStart(2, '0')).join('')\n}\n\nexport function ModelBgPage({ p, notify }: { p: ThemeSectionProps; notify: (msg: string, ok?: boolean) => void }) {\n const { t, useStore } = p\n const store = useStore((s: ThemeStoreState) => s)\n const rules = cfg.rules\n\n // Match tester: the field follows the detected model until the user types\n // their own text, so the card is useful the moment it is looked at and never\n // fights the watcher once it is not. It replaced the old \"active now\" readout —\n // the same question (\"what does this model resolve to?\") one step earlier, and\n // it does not go stale between switches.\n const [text, setText] = useState('')\n const [touched, setTouched] = useState(false)\n useEffect(() => { if (!touched) setText(store.model) }, [store.model, touched])\n const probe = text.trim()\n const result = ((): string | null => {\n if (probe === '') return null\n const hit = matchRule(rules, probe)\n const rule = hit.rule\n if (rule === null) return null\n const n = rules.findIndex(r => r.id === rule.id) + 1\n return `${hit.matched ? t('tryoutHit') : t('tryoutFallback')} ${n}`\n })()\n\n return (\n <>\n <header className=\"dab-head dab-rise\" style={{ '--d': 0 } as CSSProperties}>\n <div className=\"dab-overline\">Rules</div>\n <h2 className=\"dab-h1\">{t('pageModelBg')}</h2>\n <p className=\"dab-desc\">{t('descModelBg')}</p>\n </header>\n\n <section className=\"dab-card dab-rise\" style={{ '--d': 1 } as CSSProperties}>\n {/* A host process from before multi-image cannot read this bundle's config\n shape, so writes are held (see canWriteConfig in ../../rpc). Saying it\n out loud is the whole point: edits that silently do not persist are\n worse than a line telling the user to restart DSH. */}\n {store.hostStale ? (\n <p className=\"dab-hint dab-stale\" style={{ marginBottom: 10 }}>{t('hostStaleHint')}</p>\n ) : null}\n <div className=\"dab-swatch-title\">{t('tryoutTitle')}</div>\n <div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>\n <input\n type=\"text\" className=\"dab-urlinput\" value={text}\n placeholder={t('tryoutPlaceholder')}\n onChange={e => { setTouched(true); setText(e.target.value) }} />\n {store.model !== '' ? (\n <button type=\"button\" className=\"dab-btn\" onClick={() => { setTouched(true); setText(store.model) }}>\n {t('tryoutUseCurrent')}\n </button>\n ) : null}\n </div>\n <p className=\"dab-hint\" style={{ marginTop: 9 }}>\n {probe === '' ? t('tryoutEmpty') : result === null ? t('tryoutNone') : result}\n </p>\n {/* Why the pre-filled value is what it is: without these, a host default\n passed off as this session's model, or a sessions service that simply\n is not up yet, is indistinguishable from a correct read. */}\n {store.model === '' ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('statusUnknownHint')}</p> : null}\n {store.model !== '' && store.modelSource === 'default'\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('statusSourceDefaultHint')}</p>\n : null}\n {MODEL_NOTE_KEYS[store.modelNote] !== undefined\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t(MODEL_NOTE_KEYS[store.modelNote]!)}</p>\n : null}\n </section>\n\n <section className=\"dab-rise\" style={{ '--d': 2 } as CSSProperties}>\n {/* No \"rules\" heading and no priority sentence above the list: the panel's\n own title already introduces the rules, and the two lines only pushed\n the first card further down. */}\n {/* Picking an image should just theme the rule; this is the off switch\n for people who want the color to be their own choice every time. */}\n <div className=\"dab-chip-row\" style={{ marginBottom: 12, alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${cfg.autoExtract ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={cfg.autoExtract} title={t('autoExtract')}\n onClick={() => p.setAutoExtract(!cfg.autoExtract)}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-hint\">{t('autoExtract')}</span>\n </div>\n\n <div className=\"dab-rules\">\n {rules.map((rule, i) => (\n <RuleCard\n key={rule.id} p={p} rule={rule} index={i} total={rules.length}\n // Which of THIS rule's images is on screen right now; -1 for every\n // rule that is not the one painting, so a card can never claim to be\n // showing something it is not.\n liveIndex={rule.id === store.activeRuleId ? store.rotIndex : -1}\n active={rule.id === store.activeRuleId} notify={notify} />\n ))}\n </div>\n\n <button type=\"button\" className=\"dab-btn dab-btn-primary\" style={{ marginTop: 12 }} onClick={() => { p.addRule() }}>\n + {t('ruleAdd')}\n </button>\n </section>\n </>\n )\n}\n\nfunction RuleCard({ p, rule, index, total, active, liveIndex, notify }: {\n p: ThemeSectionProps\n rule: BgRule\n index: number\n total: number\n active: boolean\n /** Index of the image on screen (only meaningful while `active`); -1 = none. */\n liveIndex: number\n notify: (msg: string, ok?: boolean) => void\n}) {\n const { t } = p\n // The active rule opens by default so the panel shows the live one first.\n const [open, setOpen] = useState(active)\n const [dragOver, setDragOver] = useState(false)\n // ── Dragging a TILE to reorder the row ─────────────────────────────────────\n // Pointer events with capture rather than HTML5 drag-and-drop: the strip already\n // spends that channel on dropped FILES, and a drag we run ourselves is also the\n // only one that can put the insertion bar where the tile will actually land.\n // A pointerdown is merely a CANDIDATE — a tile is a button and clicking it\n // selects it — so the drag only begins once the pointer has travelled a little.\n const pendingDrag = useRef<{ x: number; y: number; from: number; slot: string; id: number } | null>(null)\n /** Insertion slot of the drag in flight (index of the tile it goes BEFORE). */\n const dragAt = useRef<{ from: number; at: number } | null>(null)\n const [drop, setDrop] = useState<{ from: number; at: number } | null>(null)\n /** Set while a drag is real, so the click that ends it is not also a selection. */\n const draggedRef = useRef(false)\n const [urlOpen, setUrlOpen] = useState(false)\n const [urlVal, setUrlVal] = useState('')\n const [urlBusy, setUrlBusy] = useState(false)\n const [urlErr, setUrlErr] = useState<string | null>(null)\n const [editorOpen, setEditorOpen] = useState(false)\n const [pickerOpen, setPickerOpen] = useState(false)\n const [extracting, setExtracting] = useState(false)\n const [secDraft, setSecDraft] = useState<string | null>(null)\n /** Whether the next file picked replaces the selected image or is added. */\n const [replace, setReplace] = useState(false)\n const fileRef = useRef<HTMLInputElement>(null)\n\n // Which image this card is EDITING — deliberately independent of which image\n // the rule is PAINTING: picking image 3 in the strip to fix its framing must not\n // change the background under the dialog. Clamped on read, because removing an\n // image can leave the selection past the end.\n const [sel, setSel] = useState(0)\n const selIdx = rule.images.length === 0 ? 0 : Math.min(sel, rule.images.length - 1)\n const image = rule.images[selIdx]\n const url = image === undefined ? null : p.imageOf(image.slot)\n\n // ── What the theme-color section edits ─────────────────────────────────────\n // The color belongs to an IMAGE, so the wheel, the swatches, the extractor and\n // the eyedropper all address the image selected in the strip. A rule with no\n // image has only its own color left to offer, and that is not a special case\n // bolted on here: it is the one thing such a rule paints (see `ruleCanPaint`),\n // so the same controls edit it without a second code path.\n //\n // The two targets never mix: an image's color is never inherited from the\n // rule's, which is what makes a rotation through a green, a red and a\n // system-themed picture expressible.\n const ownColor = image === undefined ? rule.color : image.color\n const setColor = (color: [number, number, number] | null): void => {\n if (image === undefined) p.setRule(rule.id, { color })\n else p.setImageColor(rule.id, image.slot, color)\n }\n const [h, s, l] = ownColor ?? SEED_COLOR\n const wheel = hslToHsv(h, s, l)\n\n // Boot only reads a rule's FIRST image, so an expanded card pulls the rest in.\n useEffect(() => {\n if (open) void p.loadRuleImages(rule.id)\n // The count is in the deps on purpose: adding an image to an open card has to\n // hydrate it too (the bytes are already in memory then, so this is a no-op).\n }, [open, rule.id, rule.images.length, p])\n\n const onColor = (nh: number, ns: number, nl: number): void => {\n const [sh, ss, sl] = hsvToHsl(nh, ns, nl)\n setColor([sh, ss, sl])\n }\n\n const onFiles = (files: readonly File[]): void => {\n const list = files.filter(f => f.type.startsWith('image/'))\n if (list.length === 0) return\n // \"Replace\" swaps the SELECTED image's bytes in place, which is what keeps its\n // position in the rotation; \"add\" appends. One input serves both, and the mode\n // is decided by the button that opened it.\n if (replace) {\n const slot = rule.images[selIdx]?.slot\n if (slot !== undefined) readImg(list[0]!, d => { if (d !== null) p.setRuleImage(rule.id, slot, d) })\n return\n }\n // Read every file, then hand them over in one batch: adding N images one at a\n // time would persist a config that references slots whose bytes are still\n // being decoded, and each add repaints the whole interface.\n const out: string[] = []\n // What the card will EDIT once the batch lands: the first picture of it. Adding\n // pictures without moving the selection is what made an upload look like it had\n // gone nowhere — the preview stayed on whatever was selected before, and for a\n // rule that had just been emptied that was nothing at all.\n const first = rule.images.length\n let pending = list.length\n list.forEach((f, i) => {\n readImg(f, d => {\n if (d !== null) out[i] = d\n pending--\n if (pending === 0) {\n p.addRuleImages(rule.id, out.filter((x): x is string => typeof x === 'string'))\n setSel(first)\n }\n })\n })\n }\n\n const onDrop = (e: React.DragEvent): void => {\n e.preventDefault()\n setDragOver(false)\n const files = Array.from(e.dataTransfer.files ?? [])\n if (files.length > 0) onFiles(files)\n }\n\n const applyUrl = async (): Promise<void> => {\n // One URL per line: pasting a list is how people actually collect wallpapers,\n // and making them repeat the dialog once per picture is the kind of friction\n // that keeps a rotation at two images.\n const urls = urlVal.split(/\\s+/).map(u => u.trim()).filter(u => u !== '')\n if (urls.length === 0) { setUrlErr(t('ruleUrlBadHttp')); return }\n if (urls.some(u => !/^https?:\\/\\//i.test(u))) { setUrlErr(t('ruleUrlBadHttp')); return }\n setUrlBusy(true)\n setUrlErr(null)\n // Sequential: the node half downloads each one, and firing them all at once\n // would interleave N downloads with no useful progress to show.\n const first = rule.images.length\n for (const u of urls) {\n const res = await p.addRuleImageFromUrl(rule.id, u)\n if (!res.ok) {\n setUrlBusy(false)\n setUrlErr(res.error === 'invalid url' || res.error === 'unsupported scheme'\n ? t('ruleUrlBadHttp')\n : (res.error ?? t('ruleUrlFail')))\n return\n }\n }\n setUrlBusy(false)\n setUrlOpen(false)\n setUrlVal('')\n // Same rule as the file picker: show the user what they just added.\n setSel(first)\n }\n\n const onExtract = async (): Promise<void> => {\n if (url === null || extracting || image === undefined) return\n setExtracting(true)\n try {\n const ok = await p.extractColor(rule.id, image.slot)\n notify(ok ? t('extractDone') : t('extractFail'), ok)\n } catch {\n notify(t('extractFail'), false)\n } finally {\n setExtracting(false)\n }\n }\n\n /**\n * Leaving \"follow the system theme\" must not hand the user a color that has\n * nothing to do with the wallpaper they just picked, so this tries the image\n * first and only falls back to the seed. (`extractColor` is the same pass the\n * extract button runs and returns false when nothing vivid was found.)\n */\n const onPickColor = async (): Promise<void> => {\n if (url !== null && image !== undefined) {\n setExtracting(true)\n try {\n if (await p.extractColor(rule.id, image.slot)) return\n } catch {\n // fall through to the seed\n } finally {\n setExtracting(false)\n }\n }\n setColor(SEED_COLOR)\n }\n\n const cls = `dab-rule${active ? ' is-active' : ''}${rule.enabled ? '' : ' is-off'}`\n const rotatable = rule.images.length >= 2\n const preset = ROTATE_PRESETS.find(x => x.ms === rule.rotate.intervalMs)\n const selSlot = image?.slot ?? null\n\n // ── Reordering by dragging a tile ──────────────────────────────────────────\n /** How far the pointer must travel before a click turns into a drag. */\n const DRAG_SLOP = 5\n\n const tileDown = (i: number, slot: string) => (e: ReactPointerEvent<HTMLButtonElement>): void => {\n // Mouse and pen only: on a touch screen this same gesture is how the row is\n // scrolled, and taking it over would leave the strip unscrollable by finger.\n if (e.button !== 0 || e.pointerType === 'touch') return\n e.currentTarget.setPointerCapture(e.pointerId)\n pendingDrag.current = { x: e.clientX, y: e.clientY, from: i, slot, id: e.pointerId }\n draggedRef.current = false\n }\n\n const tileMove = (e: ReactPointerEvent<HTMLButtonElement>): void => {\n const pen = pendingDrag.current\n if (pen === null || pen.id !== e.pointerId) return\n const cur = dragAt.current\n if (cur === null) {\n if (Math.abs(e.clientX - pen.x) + Math.abs(e.clientY - pen.y) < DRAG_SLOP) return\n draggedRef.current = true\n }\n // Where the tile would land, read off the live rectangles: the insertion slot\n // is the first tile whose midpoint is to the RIGHT of the pointer, so the left\n // half of a tile means \"before it\" and the right half \"after it\".\n const strip = e.currentTarget.parentElement\n const list = strip === null ? [] : [...strip.querySelectorAll('.dab-strip-item')]\n let at = list.length\n for (let i = 0; i < list.length; i++) {\n const box = list[i]!.getBoundingClientRect()\n if (e.clientX < box.left + box.width / 2) { at = i; break }\n }\n if (cur !== null && cur.at === at) return\n dragAt.current = { from: pen.from, at }\n setDrop({ from: pen.from, at })\n }\n\n /** End a drag: commit the new order, or just forget it on a cancel. */\n const tileUp = (commit: boolean) => (e: ReactPointerEvent<HTMLButtonElement>): void => {\n const pen = pendingDrag.current\n pendingDrag.current = null\n if (pen !== null && e.currentTarget.hasPointerCapture(pen.id)) e.currentTarget.releasePointerCapture(pen.id)\n const end = dragAt.current\n dragAt.current = null\n setDrop(null)\n if (!commit || pen === null || end === null) return\n // `at` counts tiles whose midpoint is left of the pointer, which is an index in\n // the list AS IT IS. The image is lifted out before it is put back, so a drop\n // to the right of its own slot has to lose one — the difference between a drop\n // that feels right and one that lands a slot short.\n const to = end.at > pen.from ? end.at - 1 : end.at\n if (to === pen.from) return\n p.moveRuleImageTo(rule.id, pen.slot, to)\n // Keep the preview on the picture the user just moved, which is where the drag\n // left their attention — the selection is an index, so it has to follow.\n setSel(to)\n }\n const removeSel = (): void => {\n if (selSlot === null) return\n // Removing the LAST image is allowed: the rule simply becomes empty and paints\n // nothing until a picture arrives, which is what the hint under the preview\n // has always said. (Refusing it left a cleared entry behind — see\n // removeRuleImage in ../../index.)\n const at = selIdx\n p.removeRuleImage(rule.id, selSlot)\n setSel(Math.max(0, Math.min(at, rule.images.length - 2)))\n }\n /** Commit the custom dwell time the moment it is typed (seconds → ms). */\n const commitSeconds = (): void => {\n if (secDraft === null) return\n const secs = Number(secDraft.trim())\n setSecDraft(null)\n if (!Number.isFinite(secs) || secs <= 0) return\n // The shared sanitizer clamps to ROTATE_MIN_MS..ROTATE_MAX_MS, so this cannot\n // store a value the next load would rewrite.\n p.setRuleRotation(rule.id, { intervalMs: Math.round(secs * 1000) })\n }\n\n return (\n <section className={cls}>\n <div className=\"dab-rule-head\">\n <button type=\"button\" className=\"dab-icon-btn\" onClick={() => setOpen(o => !o)}\n title={open ? 'Collapse' : 'Expand'} aria-expanded={open}>\n {open ? '▾' : '▸'}\n </button>\n <span className=\"dab-rule-num\">{index + 1}</span>\n {index === 0 ? <span className=\"dab-rule-badge\">{t('ruleFallbackBadge')}</span> : null}\n <input\n className=\"dab-rule-match\" value={rule.match}\n placeholder={t('ruleMatchPlaceholder')}\n onChange={e => p.setRule(rule.id, { match: e.target.value })} />\n <button type=\"button\" className={`dab-toggle${rule.enabled ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={rule.enabled} title={t('ruleEnabled')}\n onClick={() => p.setRule(rule.id, { enabled: !rule.enabled })}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <button type=\"button\" className=\"dab-icon-btn\" disabled={index === 0}\n title={t('ruleUp')} onClick={() => p.moveRule(rule.id, -1)}>↑</button>\n <button type=\"button\" className=\"dab-icon-btn\" disabled={index === total - 1}\n title={t('ruleDown')} onClick={() => p.moveRule(rule.id, 1)}>↓</button>\n <button type=\"button\" className=\"dab-icon-btn dab-icon-btn-danger\"\n title={t('ruleRemove')} onClick={() => p.removeRule(rule.id)}>\n <TrashIcon size={13} />\n </button>\n </div>\n\n {open ? (\n <div className=\"dab-rule-body\">\n <div className=\"dab-rule-cols\">\n {/* ── image strip + layout ───────────────────────────────────── */}\n <div>\n {/* Big preview of the SELECTED image — the card used to show its\n only image here, so the panel keeps the same visual weight. It\n is deliberately inert: dropping onto the strip below ADDS,\n while \"replace\" stays an explicit action on the labelled\n button, and a preview that quietly swallowed a click was the\n one thing this card's users could not predict. */}\n {/* Big preview of the SELECTED image — and, while the rule holds no\n picture at all, the rule's upload target.\n\n With pictures present it is deliberately inert: dropping onto\n the strip below ADDS, while \"replace\" stays an explicit action on\n the labelled button, and a preview that quietly swallowed a click\n was the one thing this card's users could not predict.\n\n With NO picture there is nothing to replace, so the same box is\n the opposite: the one obvious thing to click (\"点这个上传\"), and\n the drop zone as well — the strip is hidden in that state (it\n would hold nothing but a second add tile), and taking drag &\n drop away from the state every rule starts in is not a trade this\n card should make. `dragOver` is shared with the strip on purpose:\n exactly one of the two is ever mounted. */}\n {url !== null ? (\n <div className=\"dab-rule-thumb\">\n <img src={url} alt=\"\" draggable={false} />\n </div>\n ) : rule.images.length === 0 ? (\n <button\n type=\"button\"\n className={`dab-rule-thumb dab-rule-thumb-add${dragOver ? ' is-over' : ''}`}\n title={t('rotAddImage')}\n onDragOver={e => { e.preventDefault(); setDragOver(true) }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n onClick={() => { setReplace(false); fileRef.current?.click() }}>\n <span className=\"dab-rule-thumb-empty\">\n <UploadIcon size={18} />\n <span>{t('rotAddImage')}</span>\n </span>\n </button>\n ) : (\n <div className=\"dab-rule-thumb\">\n <div className=\"dab-rule-thumb-empty\">\n <UploadIcon size={18} />\n <span>{t('ruleNoImage')}</span>\n </div>\n </div>\n )}\n\n {/* The strip. One item per image, in the order the rotation walks\n them; the edited one is ringed, the PAINTED one carries the dot\n while this rule is the live rule — and only the dot, so the\n strip never shows two rings at once. Dropping files anywhere on\n it adds them (several at once — a rotation is built in batches),\n and dragging a TILE along it reorders the rotation.\n\n Hidden while the rule has no picture: a strip holding nothing but\n its own add tile said the same thing as the upload target right\n above it, and a filmstrip is a list of pictures — it has no job\n in a state that has none. */}\n {rule.images.length > 0 ? (\n <div\n className={`dab-strip${dragOver ? ' is-over' : ''}`}\n onDragOver={e => { e.preventDefault(); setDragOver(true) }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}>\n {rule.images.map((img, i) => {\n const thumb = p.imageOf(img.slot)\n return (\n <button\n key={img.slot} type=\"button\"\n // No `is-live` modifier: being on screen is the dot\n // below and nothing more. Ringing this tile as well put\n // two rings in the strip at once — this one and the\n // previewed one — and read as \"two images selected\".\n className={`dab-strip-item${i === selIdx ? ' is-sel' : ''}${drop !== null && drop.from === i ? ' is-dragging' : ''}`}\n title={`${i + 1} / ${rule.images.length} · ${t('rotDragHint')} · ${t('rotDblHint')}`}\n onPointerDown={tileDown(i, img.slot)}\n onPointerMove={tileMove}\n onPointerUp={tileUp(true)}\n onPointerCancel={tileUp(false)}\n onClick={() => {\n // A drag ends with a click on the tile it started from,\n // and that click is not a selection.\n if (draggedRef.current) { draggedRef.current = false; return }\n setSel(i)\n }}\n // Double-click shows this picture: it is the one gesture that\n // says \"THIS one on screen\", which reordering deliberately\n // does not do. It changes no order and saves nothing — the\n // image being shown is runtime state, not a setting.\n onDoubleClick={() => {\n // Only the rule that is painting has a screen to change, and\n // the store no-ops for any other — so say why instead of\n // leaving a double-click that looks broken.\n if (!active) { notify(t('rotNextInactive')); return }\n p.showRuleImage(rule.id, img.slot)\n }}>\n {thumb !== null\n ? <img src={thumb} alt=\"\" draggable={false} />\n : <span className=\"dab-strip-wait\" />}\n <span className=\"dab-strip-num\">{i + 1}</span>\n {/* Where the tile in hand will land: a bar at this tile's\n LEFT edge, or at the last tile's right edge for a drop\n past the end of the row. */}\n {drop !== null && drop.at === i ? <span className=\"dab-strip-bar\" /> : null}\n {drop !== null && drop.at === rule.images.length && i === rule.images.length - 1\n ? <span className=\"dab-strip-bar is-end\" /> : null}\n {/* This image's own theme color, when it has one. The whole\n point of per-image colors is that they differ, and\n without this the only way to find out which pictures\n already carry one is to click through the strip and\n watch the wheel change. Hex on hover, like a swatch. */}\n {img.color !== null ? (\n <span\n className=\"dab-strip-dot\"\n title={toHex(hslToRgb(img.color[0], img.color[1], img.color[2])).toUpperCase()}\n style={{ background: `hsl(${img.color[0]} ${Math.round(img.color[1] * 100)}% ${Math.round(img.color[2] * 100)}%)` }} />\n ) : null}\n {liveIndex === i ? <span className=\"dab-strip-live\" title={t('rotShowing')} /> : null}\n </button>\n )\n })}\n <button type=\"button\" className=\"dab-strip-add\" title={t('rotAddImage')}\n onClick={() => { setReplace(false); fileRef.current?.click() }}>\n <UploadIcon size={16} />\n <span>{t('rotAddImage')}</span>\n </button>\n </div>\n ) : null}\n\n <div className=\"dab-chip-row\" style={{ marginTop: 10 }}>\n {/* No position readout for an empty rule: \"image 0 / 0\" would be a\n number about nothing — the upload target above is the whole\n story there. */}\n {rule.images.length > 0 ? (\n <span className=\"dab-strip-pos\">{t('rotPos')} {selIdx + 1} / {rule.images.length}</span>\n ) : null}\n <button type=\"button\" className=\"dab-btn\" onClick={() => { setReplace(false); fileRef.current?.click() }}>\n <UploadIcon size={13} />{t('rotAddImage')}\n </button>\n <button type=\"button\" className=\"dab-btn dab-btn-ghost\" onClick={() => setUrlOpen(o => !o)}>\n <LinkIcon size={13} />{t('ruleFromUrl')}\n </button>\n {/* Replacing keeps the image's POSITION in the rotation, which\n \"remove + add\" cannot do — and the two actions are labelled\n apart on purpose: the button above appends, this one swaps the\n selected image's bytes. */}\n {selSlot !== null ? (\n <button type=\"button\" className=\"dab-btn dab-btn-ghost\"\n onClick={() => { setReplace(true); fileRef.current?.click() }}>\n <UploadIcon size={13} />{t('rotReplaceImage')}\n </button>\n ) : null}\n {/* No step/first buttons any more: the strip IS the control for\n order. Dragging a tile is the same operation those two arrows\n and \"make first\" were, and a row of five tiles is a list you\n can see — a pair of arrows that nudges the selected one along\n it was a second, worse way to say \"put this one there\". */}\n {/* Always offered, including on the LAST image: the rule is then\n simply empty, and the empty strip above is the honest picture\n of that. Hiding this — the first cut of the feature did —\n left a cleared entry that could never be deleted again. Note\n that \"empty\" is not \"off\": a rule that kept its theme color\n still paints (see `ruleCanPaint`), which the hint above says. */}\n {selSlot !== null ? (\n <button type=\"button\" className=\"dab-btn dab-btn-ghost dab-btn-danger\"\n onClick={removeSel}>\n <TrashIcon size={13} />{t('ruleImageRemove')}\n </button>\n ) : null}\n </div>\n\n {urlOpen ? (\n <div style={{ marginTop: 10, display: 'flex', flexWrap: 'wrap', gap: 8, alignItems: 'center' }}>\n <input\n type=\"text\" className=\"dab-urlinput\" value={urlVal}\n placeholder={t('ruleUrlPlaceholder')} autoFocus\n onChange={e => setUrlVal(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); void applyUrl() } }} />\n <button type=\"button\" className=\"dab-btn dab-btn-primary\" disabled={urlBusy} onClick={() => void applyUrl()}>\n {urlBusy ? t('ruleUrlApplying') : t('ruleUrlApply')}\n </button>\n <button type=\"button\" className=\"dab-btn\"\n onClick={() => { setUrlOpen(false); setUrlVal(''); setUrlErr(null) }}>\n {t('ruleUrlCancel')}\n </button>\n </div>\n ) : null}\n {urlErr !== null ? (\n <p style={{ marginTop: 8, color: 'var(--dsw-alias-state-error-primary)', fontSize: 12 }}>{urlErr}</p>\n ) : null}\n {/* Three states, three sentences — the old single test (`url ===\n null`) told a rule with no pictures and a rule whose picture\n simply has no bytes yet the same story, and only one of them\n was true. A rule with no image but a COLOR of its own is not\n skipped: it paints the interface from that color (see\n `ruleCanPaint`), and saying otherwise is what made its color\n controls look broken. */}\n {rule.images.length === 0 ? (\n <p className=\"dab-hint\" style={{ marginTop: 8 }}>\n {rule.color === null ? t('ruleEmptyHint') : t('ruleColorOnlyHint')}\n </p>\n ) : null}\n {rule.images.length > 0 && url === null ? (\n <p className=\"dab-hint\" style={{ marginTop: 8 }}>{t('ruleImagePendingHint')}</p>\n ) : null}\n\n {/* ── rotation ──────────────────────────────────────────────── */}\n <div style={{ marginTop: 14 }}>\n <div className=\"dab-rule-section-title\">{t('rotTitle')}</div>\n <div className=\"dab-chip-row\" style={{ alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${rule.rotate.enabled ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={rule.rotate.enabled} title={t('rotEnable')}\n disabled={!rotatable}\n onClick={() => p.setRuleRotation(rule.id, { enabled: !rule.rotate.enabled })}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotEnable')}</span>\n {!rotatable ? <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotNeedTwo')}</span> : null}\n </div>\n\n {rotatable && rule.rotate.enabled ? (\n <div className=\"dab-rot-panel\">\n <div className=\"dab-rule-section-title\">{t('rotEvery')}</div>\n <div className=\"dab-chip-row\">\n {ROTATE_PRESETS.map(item => (\n <button key={item.ms} type=\"button\"\n className={`dab-chip${item.ms === rule.rotate.intervalMs ? ' is-active' : ''}`}\n onClick={() => p.setRuleRotation(rule.id, { intervalMs: item.ms })}>\n {t(item.key)}\n </button>\n ))}\n <input\n type=\"number\" className=\"dab-num dab-num-sec\" min={5} max={86_400} step={5}\n // The draft is what is being typed; without it the field\n // would fight the user on every keystroke (and \"5\" on the\n // way to \"50\" is a legal value nobody meant).\n value={secDraft ?? (preset === undefined ? Math.round(rule.rotate.intervalMs / 1000) : '')}\n placeholder={t('rotCustom')}\n onChange={e => setSecDraft(e.target.value)}\n onBlur={commitSeconds}\n onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); commitSeconds() } }} />\n <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotSeconds')}</span>\n </div>\n\n <div className=\"dab-rule-section-title\" style={{ marginTop: 12 }}>{t('rotOrder')}</div>\n <div className=\"dab-chip-row\">\n <button type=\"button\" className={`dab-chip${rule.rotate.order === 'order' ? ' is-active' : ''}`}\n onClick={() => p.setRuleRotation(rule.id, { order: 'order' })}>\n {t('rotOrderSeq')}\n </button>\n <button type=\"button\" className={`dab-chip${rule.rotate.order === 'shuffle' ? ' is-active' : ''}`}\n onClick={() => p.setRuleRotation(rule.id, { order: 'shuffle' })}>\n {t('rotOrderShuffle')}\n </button>\n </div>\n\n <div className=\"dab-chip-row\" style={{ marginTop: 12, alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${rule.rotate.advanceOnSwitch ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={rule.rotate.advanceOnSwitch} title={t('rotOnSwitch')}\n onClick={() => p.setRuleRotation(rule.id, { advanceOnSwitch: !rule.rotate.advanceOnSwitch })}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-hint\" style={{ padding: 0 }}>{t('rotOnSwitch')}</span>\n </div>\n\n <div className=\"dab-chip-row\" style={{ marginTop: 12, alignItems: 'center' }}>\n <button type=\"button\" className=\"dab-btn\" disabled={!active} onClick={() => p.rotateNow(rule.id)}>\n {t('rotNext')}\n </button>\n <span className=\"dab-hint\" style={{ padding: 0 }}>\n {/* \"On screen\" rather than \"image N\": the row above\n already reads \"image N\" for the image being EDITED,\n and two numbers under the same wording would be the\n one place this panel could mislead. */}\n {active ? `${t('rotShowing')} ${rule.images.length === 0 ? 0 : Math.min(liveIndex + 1, rule.images.length)} / ${rule.images.length}` : t('rotNextInactive')}\n </span>\n </div>\n </div>\n ) : null}\n </div>\n\n <div style={{ marginTop: 14 }}>\n <div className=\"dab-rule-section-title\">{t('ruleLayout')}</div>\n <div className=\"dab-chip-row\">\n {BG_MODES.map(m => (\n <button key={m.mode} type=\"button\"\n className={`dab-chip${rule.bgMode === m.mode ? ' is-active' : ''}`}\n onClick={() => p.setRule(rule.id, { bgMode: m.mode })}>\n {t(m.key)}\n </button>\n ))}\n {/* The framing editor sits at the END of this row, not among the\n modes: it is not a sixth mode, and dropping it between two\n chips would read as one (the modes are mutually exclusive,\n this is an action). It belongs here rather than next to the\n upload buttons because what it edits is how the picture fills\n the area — the row it now shares with 适应/填充/…. It stays\n conditional on `fit`: dragging the framing is what \"适应\"\n means, and the other four modes have nothing to drag. */}\n {url !== null && rule.bgMode === 'fit' ? (\n <button type=\"button\" className=\"dab-btn\" onClick={() => setEditorOpen(true)}>\n <EditIcon size={13} />{t('ruleFramingEdit')}\n </button>\n ) : null}\n </div>\n </div>\n </div>\n\n {/* ── color + wallpaper effects ──────────────────────────────── */}\n <div>\n <div className=\"dab-rule-section-title\">{t('ruleColor')}</div>\n {/* Which of the two things below the controls edit. Since a theme\n color belongs to an image, the same wheel means different things\n depending on the strip, and a section that silently retargets is\n exactly how \"I changed the color and nothing happened\" is born. */}\n <p className=\"dab-hint\" style={{ marginTop: 6 }}>\n {image === undefined\n ? t('ruleColorTargetRule')\n : `${t('ruleColorTargetImage')} ${selIdx + 1} / ${rule.images.length}`}\n </p>\n {ownColor === null ? (\n <>\n <div className=\"dab-chip-row\">\n {/* This button LEAVES the system-theme state, so it says so:\n the \"系统主题\" label belongs to the clearing button below. */}\n <button type=\"button\" className=\"dab-btn\" disabled={extracting} onClick={() => void onPickColor()}>\n <DropletIcon size={14} />{extracting ? t('extracting') : t('ruleColorPick')}\n </button>\n <button type=\"button\" className=\"dab-btn\" disabled={url === null || extracting} onClick={() => void onExtract()}>\n <SparkleIcon size={14} />{extracting ? t('extracting') : t('ruleColorExtract')}\n </button>\n </div>\n <p className=\"dab-hint\" style={{ marginTop: 8 }}>{t('ruleColorNoneHint')}</p>\n {/* The extraction promise belongs to a target that HAS bytes:\n next to a disabled \"extract\" button it read as a broken\n feature, not as a hint — and for a rule with no image at all\n the honest sentence is a different one (it has nothing to\n take a color from, but a color of its own is still enough to\n paint the interface). */}\n {url !== null\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('ruleColorPickHint')}</p>\n : image === undefined\n ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('ruleColorNoImageHint')}</p>\n : <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('ruleColorPendingImageHint')}</p>}\n </>\n ) : (\n <>\n <div style={{ display: 'flex', gap: 16, alignItems: 'center', flexWrap: 'wrap' }}>\n <ColorWheel hue={wheel[0]} sat={wheel[1]} lit={wheel[2]} onChange={onColor} />\n {/* No hex caption above the toggle any more: the preview\n field inside ColorInputs prints that same value on the\n color itself, where it also explains what the field is. */}\n <div className=\"dab-inputs\">\n <ColorInputs hue={wheel[0]} sat={wheel[1]} lit={wheel[2]} onChange={onColor} />\n </div>\n </div>\n <div className=\"dab-chip-row\" style={{ marginTop: 12 }}>\n <button type=\"button\" className=\"dab-btn\" disabled={url === null || extracting} onClick={() => void onExtract()}>\n <SparkleIcon size={13} />{extracting ? t('extracting') : t('ruleColorExtract')}\n </button>\n <button type=\"button\" className=\"dab-btn\" disabled={url === null} onClick={() => setPickerOpen(true)}>\n <PipetteIcon size={13} />{t('eyedropper')}\n </button>\n {/* Clears THIS image's color and hands the interface back to\n the host palette for as long as that image is on screen —\n the rule's own color (if it has one) is untouched, because\n it is not this image's fallback. Carries the sun because\n that is the host's own appearance glyph, and reads as the\n action it performs rather than the state it lands in — as a\n bare \"系统主题\" it looked like the label of whatever control\n sat beside it. */}\n <button type=\"button\" className=\"dab-btn dab-btn-ghost\" onClick={() => setColor(null)}>\n <SunIcon size={13} />{t('ruleColorNone')}\n </button>\n </div>\n <div className=\"dab-swatches\" style={{ marginTop: 12 }}>\n {PALETTE.map(([sh, ss, sl], i) => (\n <button\n key={i} type=\"button\" className=\"dab-swatch\"\n style={{ background: `hsl(${sh} ${Math.round(ss * 100)}% ${Math.round(sl * 100)}%)` }}\n title={toHex(hslToRgb(sh, ss, sl)).toUpperCase()}\n onClick={() => setColor([sh, ss, sl])} />\n ))}\n </div>\n </>\n )}\n\n <div style={{ marginTop: 16 }}>\n <LiveSlider\n label={t('ruleOpacity')} min={0} max={100} step={1}\n def={Math.round(rule.wallpaperOpacity * 100)} fmt={v => `${v}%`}\n onChange={v => p.setRule(rule.id, { wallpaperOpacity: v / 100 })} />\n <LiveSlider\n label={t('ruleBlur')} min={0} max={60} step={1}\n def={rule.blur} fmt={v => `${v}px`}\n onChange={v => p.setRule(rule.id, { blur: v })} />\n <p className=\"dab-hint\" style={{ marginTop: 10 }}>{t('ruleBlurHint')}</p>\n </div>\n </div>\n </div>\n </div>\n ) : null}\n\n {/* `multiple` because a rotation is built by picking a handful of pictures\n at once; the strip's drop zone and the URL box take batches too. A\n replacement only ever takes the first file — see onFiles. */}\n <input ref={fileRef} type=\"file\" accept=\"image/*\" multiple style={{ display: 'none' }} onChange={e => {\n const files = Array.from(e.target.files ?? [])\n if (files.length === 0) return\n onFiles(files)\n e.target.value = ''\n setReplace(false)\n }} />\n\n {editorOpen && url !== null && image !== undefined ? (\n <BgEditor\n url={url} state={image.bgState} t={t} onClose={() => setEditorOpen(false)}\n onCommit={(z, x, y, iw, ih) => {\n // Framing belongs to the IMAGE, so the commit is addressed by slot:\n // editing image 3's crop must not rewrite image 1's.\n p.setImageFraming(rule.id, image.slot, { zoom: z, x, y, iw, ih })\n setEditorOpen(false)\n }} />\n ) : null}\n\n {pickerOpen && url !== null ? (\n <ColorPicker url={url} t={t} onClose={() => setPickerOpen(false)}\n onPick={hsv => { onColor(hsv[0], hsv[1], hsv[2]); setPickerOpen(false) }} />\n ) : null}\n </section>\n )\n}\n","import { useEffect, useRef } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { ThemeSectionProps, ThemeStoreState } from '../../types'\nimport { cfg, rFadeMs } from '../../state'\nimport { saveConfig } from '../../rpc'\nimport { normalizeTransition, TRANSITION_EASINGS, TRANSITION_EFFECTS } from '../../../schema'\nimport { transitionPlan } from '../../transition'\nimport type { TransitionEffect, TransitionEasing } from '../../../schema'\nimport { LiveSlider } from '../LiveSlider'\nimport { DownloadIcon, SparkleIcon, UploadIcon } from '../icons'\n\n/** Chip labels, keyed by the value they set — so no chip can be built from a\n * value the schema does not accept, and `check:ui` still sees every key used. */\nconst EFFECT_KEYS: Record<TransitionEffect, string> = {\n fade: 'trEffectFade', none: 'trEffectNone', zoom: 'trEffectZoom', slide: 'trEffectSlide',\n}\nconst EASING_KEYS: Record<TransitionEasing, string> = {\n ease: 'trEasingEase', linear: 'trEasingLinear', 'ease-out': 'trEasingOut', 'ease-in-out': 'trEasingInOut',\n}\n\nexport function ProfilePage({ p, notify }: { p: ThemeSectionProps; notify: (msg: string, ok?: boolean) => void }) {\n const { t, exportTheme, importTheme, setTransition } = p\n const importRef = useRef<HTMLInputElement>(null)\n\n // The section shell renders this page as a plain child and does not subscribe\n // to the store, so the subscription has to live HERE — without it the holiday\n // switch and the switch-effect card would not repaint themselves.\n p.useStore((s: ThemeStoreState) => s.rev + s.rulesRev)\n const holidays = cfg.holidays\n const tr = cfg.transition\n\n // ── switch effect ─────────────────────────────────────────────────────────\n // The decision itself (which effect runs, for how long, and whether it runs at\n // all) is pure and lives in ../../transition, where `scripts/transition-check.ts`\n // can pin it down without a browser. This card only edits the three settings\n // and replays the effect on its own swatch.\n\n const previewRef = useRef<HTMLDivElement>(null)\n /** The OS preference, read at render: it vetoes the real switch (see\n * `transitionPlan`), so the card has to say so rather than show a preview of\n * something the interface will not do. */\n const reduced = typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n && window.matchMedia('(prefers-reduced-motion: reduce)').matches\n\n /**\n * Play the effect on the preview swatch, for the duration a real switch would\n * use right now: the wallpaper fading into ITSELF is invisible, which is the\n * one thing a transition setting must not leave the user guessing about.\n */\n const play = (): void => {\n const el = previewRef.current\n if (el === null) return\n const plan = transitionPlan({\n effect: tr.effect,\n easing: tr.easing,\n durationMs: rFadeMs(),\n canAnimate: true,\n reducedMotion: false,\n })\n el.style.transition = 'none'\n el.style.opacity = plan.from.opacity\n el.style.transform = plan.from.transform\n requestAnimationFrame(() => {\n el.style.transition = plan.transition\n el.style.opacity = plan.to.opacity\n el.style.transform = plan.to.transform\n })\n }\n\n // Picking a different SHAPE replays at once, so the choice is answered where it\n // is made. The duration is left to the button: a slider fires on every frame of\n // a drag, and restarting the animation each time reads as a flicker rather than\n // as the timing being edited.\n useEffect(() => {\n if (!reduced) play()\n // `play` closes over the current `tr`; the two fields below are the ones that\n // change the effect's shape.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tr.effect, tr.easing])\n\n const onImport = async (file: File) => {\n try {\n const ok = await importTheme(file)\n notify(ok ? t('importDone') : t('importFail'), ok)\n } catch {\n notify(t('importFail'), false)\n }\n }\n\n return (\n <>\n <header className=\"dab-head dab-rise\" style={{ '--d': 0 } as CSSProperties}>\n <div className=\"dab-overline\">Profile</div>\n <h2 className=\"dab-h1\">{t('pageProfile')}</h2>\n <p className=\"dab-desc\">{t('descProfile')}</p>\n </header>\n\n {/* The whole holiday override is one switch. There is deliberately no card\n per holiday, no thumbnail and no image picker: the feature is a small\n easter egg, and the panels that used to live here made it look like\n something the user is expected to configure — art included. The\n wallpapers ship in the package and are not swappable at all.\n\n Nor is there a line under the switch explaining it. The label carries\n the meaning, and the control's tooltip carries the windows; a\n paragraph here only made a one-switch feature read as a settings\n block. Do not add one back. */}\n <section className=\"dab-card dab-rise\" style={{ '--d': 1 } as CSSProperties}>\n <div className=\"dab-chip-row\" style={{ alignItems: 'center' }}>\n <button type=\"button\" className={`dab-toggle${holidays.enabled ? ' is-on' : ''}`}\n role=\"switch\" aria-checked={holidays.enabled} title={t('holidayEnable')}\n onClick={() => p.setHolidaysEnabled(!holidays.enabled)}>\n <span className=\"dab-toggle-knob\" />\n </button>\n <span className=\"dab-holiday-label\">{t('holidayTitle')}</span>\n </div>\n </section>\n\n {/* The global switch effect. It paints nothing by itself — it decides what\n the NEXT change looks like — so it carries its own swatch instead of\n pointing at a wallpaper that would only move later. The effect and the\n easing are global (a rule has no notion of either); the duration stays\n each rule's own until it is unified here, which is why the two\n destinations are spelled out rather than shown as one switch. */}\n <section className=\"dab-card dab-rise\" style={{ '--d': 1 } as CSSProperties}>\n <div className=\"dab-part-head\">\n <div className=\"dab-part-ico\"><SparkleIcon size={16} /></div>\n <div className=\"dab-part-name\">{t('trTitle')}</div>\n </div>\n\n <div className=\"dab-swatch-title\">{t('trEffect')}</div>\n <div className=\"dab-chip-row\">\n {TRANSITION_EFFECTS.map(effect => (\n <button key={effect} type=\"button\"\n className={`dab-chip${tr.effect === effect ? ' is-active' : ''}`}\n onClick={() => setTransition({ effect })}>\n {t(EFFECT_KEYS[effect])}\n </button>\n ))}\n </div>\n\n {/* No easing row while nothing is animated: \"instant\" has no curve, and a\n disabled row here would only be a control that does nothing. */}\n {tr.effect === 'none' ? null : (\n <>\n <div className=\"dab-swatch-title\" style={{ marginTop: 12 }}>{t('trEasing')}</div>\n <div className=\"dab-chip-row\">\n {TRANSITION_EASINGS.map(easing => (\n <button key={easing} type=\"button\"\n className={`dab-chip${tr.easing === easing ? ' is-active' : ''}`}\n onClick={() => setTransition({ easing })}>\n {t(EASING_KEYS[easing])}\n </button>\n ))}\n </div>\n </>\n )}\n\n {/* One duration for every switch — the slider IS the setting, with no\n \"where does it come from\" choice in front of it: the per-rule fade\n this could have deferred to had no control anywhere, so offering the\n choice would have been offering a real setting and a phantom one. */}\n <div className=\"dab-swatch-title\" style={{ marginTop: 12 }}>{t('trDuration')}</div>\n <div style={{ marginTop: 2 }}>\n <LiveSlider label={t('trDuration')} min={0} max={3000} step={50} def={tr.durationMs}\n fmt={v => `${v} ms`}\n onInput={v => {\n cfg.transition = normalizeTransition({ ...cfg.transition, durationMs: v })\n saveConfig()\n }}\n onChange={v => setTransition({ durationMs: v })} />\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginTop: 13 }}>\n <div className=\"dab-tr-preview\">\n <div ref={previewRef} className=\"dab-tr-preview-in\" />\n </div>\n <button type=\"button\" className=\"dab-btn\" disabled={reduced} onClick={play}>\n <SparkleIcon size={14} />{t('trPreview')}\n </button>\n </div>\n\n <p className=\"dab-hint\" style={{ marginTop: 10 }}>{t('trHint')}</p>\n {reduced ? <p className=\"dab-hint\" style={{ marginTop: 6 }}>{t('trReducedHint')}</p> : null}\n </section>\n\n <div className=\"dab-profile-grid dab-rise\" style={{ '--d': 3 } as CSSProperties}>\n <section className=\"dab-card dab-card-hover\">\n <div className=\"dab-profile-ico\"><DownloadIcon size={17} /></div>\n <div className=\"dab-profile-title\">{t('exportCardTitle')}</div>\n <div className=\"dab-profile-desc\">{t('exportCardDesc')}</div>\n <button type=\"button\" className=\"dab-btn dab-btn-primary\" onClick={() => { exportTheme(); notify(t('toastExportDone')) }}>\n <DownloadIcon size={14} />{t('exportTheme')}\n </button>\n </section>\n\n <section className=\"dab-card dab-card-hover\">\n <div className=\"dab-profile-ico\"><UploadIcon size={17} /></div>\n <div className=\"dab-profile-title\">{t('importCardTitle')}</div>\n <div className=\"dab-profile-desc\">{t('importCardDesc')}</div>\n <button type=\"button\" className=\"dab-btn\" onClick={() => importRef.current?.click()}>\n <UploadIcon size={14} />{t('importTheme')}\n </button>\n <input ref={importRef} type=\"file\" accept=\"application/json,.json\" style={{ display: 'none' }} onChange={e => {\n const f = e.target.files?.[0]; if (!f) return\n void onImport(f); e.target.value = ''\n }} />\n </section>\n </div>\n\n <footer className=\"dab-footer dab-rise\" style={{ '--d': 4 } as CSSProperties}>\n <span className=\"dab-footer-mono\">dsh-background-by-model</span>\n <span>{t('footerTag')}</span>\n </footer>\n </>\n )\n}\n","/**\n * dsh-background-by-model — settings section shell.\n *\n * The host renders this section only while the settings dialog is open and the\n * section is the active nav entry, so mounting IS being visible. The section is\n * rendered INLINE inside the host settings dialog's content column (the host\n * provides the modal chrome); the shell is a left nav rail + page body. Only\n * the transient toast escapes through a Portal (the shell's container-type\n * containment would otherwise capture its fixed positioning).\n */\nimport { useEffect, useRef, useState } from 'react'\nimport type { ThemeSectionProps } from '../types'\nimport { ensureUiCss, NAV_ITEM_H, NAV_GAP } from './ui.css'\nimport { SunIcon, LayersIcon, PhotoIcon, SlidersIcon, AlertIcon, CheckIcon } from './icons'\nimport { ErrorBoundary } from './ErrorBoundary'\nimport { Portal } from './Portal'\nimport { InterfacePage } from './pages/InterfacePage'\nimport { ModelBgPage } from './pages/ModelBgPage'\nimport { ProfilePage } from './pages/ProfilePage'\n\nexport function ThemeSection(props: ThemeSectionProps) {\n ensureUiCss()\n const { t } = props\n const [page, setPage] = useState(0)\n const [toast, setToast] = useState<{ msg: string; ok: boolean } | null>(null)\n const toastTimer = useRef<number | undefined>(undefined)\n\n useEffect(() => () => window.clearTimeout(toastTimer.current), [])\n\n const notify = (msg: string, ok = true): void => {\n setToast({ msg, ok })\n window.clearTimeout(toastTimer.current)\n toastTimer.current = window.setTimeout(() => setToast(null), 2600)\n }\n\n const pages = [\n { label: t('pageInterface'), Icon: LayersIcon, node: <InterfacePage p={props} /> },\n { label: t('pageModelBg'), Icon: PhotoIcon, node: <ModelBgPage p={props} notify={notify} /> },\n { label: t('pageProfile'), Icon: SlidersIcon, node: <ProfilePage p={props} notify={notify} /> },\n ]\n\n return (\n <ErrorBoundary t={t}>\n <div className=\"dab-root\">\n <div className=\"dab-shell\">\n <nav className=\"dab-nav\">\n <div className=\"dab-brand\">\n <div className=\"dab-brand-tile\"><SunIcon size={15} /></div>\n <div>\n <div className=\"dab-brand-name\">{t('nav')}</div>\n <div className=\"dab-brand-tag\">{t('brandTag')}</div>\n </div>\n </div>\n <div className=\"dab-nav-list\">\n <div className=\"dab-nav-ind\" style={{ transform: `translateY(${page * (NAV_ITEM_H + NAV_GAP)}px)` }} />\n {pages.map((pg, i) => (\n <button\n key={pg.label} type=\"button\"\n className={`dab-nav-item${i === page ? ' is-active' : ''}`}\n onClick={() => setPage(i)}>\n <pg.Icon size={16} />\n <span>{pg.label}</span>\n </button>\n ))}\n </div>\n </nav>\n\n <div className=\"dab-page\" key={page}>\n {pages[page].node}\n </div>\n </div>\n </div>\n\n {toast ? (\n <Portal>\n <div className=\"dab-toast\" role=\"status\">\n <span className={toast.ok ? 'dab-toast-ok' : 'dab-toast-err'}>\n {toast.ok ? <CheckIcon size={14} /> : <AlertIcon size={14} />}\n </span>\n <span>{toast.msg}</span>\n </div>\n </Portal>\n ) : null}\n </ErrorBoundary>\n )\n}\n","/**\n * dsh-background-by-model — browser half entry.\n *\n * Wires the plugin lifecycle: rule resolution against the current model,\n * wallpaper layer, theme skin, viewport watch, i18n, settings-section injection,\n * boot restore and watchdogs. The heavy lifting lives in the sibling modules\n * (state / modelbg / rpc / wallpaper / components).\n */\nimport { defineStore } from './runtime'\nimport type {\n Ctx, RpcResultLike, ThemeSectionProps, PartOpacities, PartBlurs, BgImage, BgRule, BgState, HolidayRule,\n FetchResult, ModelFacts, TransitionConfig,\n} from './types'\nimport { NS, zh, en } from './i18n'\nimport {\n cfg, adoptConfig, imageOf, displayImageOf, setImage, newRule, nextSlot, nextRuleId, ruleById,\n holidayById, normalizeRuleInPlace, patchRotation, ruleSlots, setActive, setModelLabel,\n activeRule, activeColor, activeRuleId, activeMatched, modelLabel, imageIndexOf, setRotIndex, takenSlots,\n rWp, rRightbarOpacity, DEFAULT_BG_STATE,\n} from './state'\nimport { activeHoliday, pickHoliday } from '../holiday'\nimport { normalizeTransition } from '../schema'\nimport { nextIndex, isRotating } from './rotation'\nimport { shouldRepaint } from './repaint'\nimport {\n RPC_CHANNEL, initRpc, saveConfig, flushSave, persistConfig, loadPersisted,\n readImage, writeImage, deleteImage, fetchImageUrl, readDefaultModel, hostIsLegacy,\n} from './rpc'\nimport {\n applyWp, teardownWp, applySettingsOverrides, applyRightbarOverrides, SETTINGS_STYLE_RULE, TRAJECTORY_STYLE_RULE,\n RIGHTBAR_STYLE_RULE, INPUT_BLUR_RULE, PLACEHOLDER_RULE, OWN_SCHEME, setHostScheme, refreshSystemTheme,\n watchParts, watchThemeResets,\n} from './wallpaper'\nimport { genTokens, extractWallpaperColor } from './utils/color'\nimport { matchRule, watchModel } from './modelbg'\nimport { ThemeSection } from './components/ThemeSection'\nimport { markOwnSheet } from './components/ui.css'\nimport { SUN_PATHS } from './components/icons'\n\nexport const name = 'dsh-background-by-model'\nexport const inject = ['slots', 'locale', 'theme', 'connection']\n\nconst CUSTOM_ID = 'custom-color'\n\nexport function apply(ctx: Ctx): void {\n // Bind the dedicated `/dsh-background-by-model` RPC caller so the persistence\n // module can reach the node half's file-backed store.\n initRpc((endpoint, payload) =>\n ctx.connection.rpc.call(RPC_CHANNEL, endpoint, payload).then((res: any) => res as RpcResultLike | undefined)\n )\n\n // ── 1. Custom theme skin, driven by the ACTIVE rule's color ────────────────\n let customDispose: (() => void) | null = null\n // Trailing debounce for the theme-skin switch (see applyActive): a color drag\n // would otherwise dispose + re-register + re-activate the host theme on every\n // pointer move.\n let skinTimer: number | null = null\n const registerCustom = (h: number, s: number, l: number): void => {\n customDispose?.()\n try {\n const { colorScheme, tokens } = genTokens(h, s, l)\n customDispose = ctx.theme.register({ id: CUSTOM_ID, colorScheme, tokens })\n } catch {\n // A live registration from an earlier HMR apply pass cannot be torn down\n // here; keep it and activate it below. Without this the duplicate-id\n // throw would abort apply and skip the wallpaper/opacity restore.\n customDispose = null\n }\n // Only activate the custom theme if it is actually registered.\n if (ctx.theme.getTheme().themes.some(t => t.id === CUSTOM_ID)) {\n ctx.theme.setTheme(CUSTOM_ID)\n }\n }\n /** A rule without a saved color means \"follow the system theme\". */\n const dropCustom = (): void => {\n customDispose?.()\n customDispose = null\n try {\n if (ctx.theme.getTheme().preference === CUSTOM_ID) ctx.theme.setTheme('system')\n } catch {\n // A host build without a `system` preference keeps its own choice.\n }\n }\n\n /**\n * Re-emit the interface palette for whatever is painted RIGHT NOW.\n *\n * Called from two places, and the second one is why this is a function: a\n * model switch (`applyActive`) and a ROTATION STEP (`paintImage`). A theme color\n * belongs to an image since 0.7.1, so stepping to the next picture changes the\n * palette as much as switching models does — and a step that only repainted the\n * wallpaper would leave the previous picture's color on the interface until\n * something else happened to re-run an apply (dragging the wheel, switching\n * models), which is precisely the \"it only updates when I touch the color wheel\"\n * report this plugin already had once.\n *\n * The debounce is for the OTHER caller: a color drag runs a full apply dozens of\n * times per second, and the host-visible skin switch (dispose + register +\n * activate) must not happen on every pointer move. A rotation step pays the same\n * 60 ms, which is invisible next to a dwell time of 5 s or more.\n */\n const applyPalette = (): void => {\n const color = activeColor()\n if (skinTimer !== null) window.clearTimeout(skinTimer)\n if (color === null) {\n // Hand the palette back BEFORE the apply that follows. The theme service's\n // snapshot is what tells the wallpaper layer which scheme the host itself\n // resolves to, and while our custom skin is still active that snapshot\n // reports OUR scheme — the readback would then capture the host's light\n // palette on a dark system and keep painting it (the interface only\n // recovered when some later slider drag happened to re-run an apply).\n // Dropping the skin is idempotent, so it needs none of the debouncing a\n // color drag does.\n skinTimer = null\n dropCustom()\n } else {\n // The skin is a host-visible switch (dispose + register + activate) and is\n // batched; the wallpaper and tokens below land immediately either way.\n skinTimer = window.setTimeout(() => {\n skinTimer = null\n registerCustom(color[0], color[1], color[2])\n }, 60)\n }\n syncHostScheme()\n }\n ctx.effect(() => () => {\n if (skinTimer !== null) window.clearTimeout(skinTimer)\n customDispose?.()\n }, 'dsh-background-by-model: skin dispose')\n\n // ── 2. Gradient CSS (for custom dark themes) + static rules ────────────────\n const styleEl = document.createElement('style')\n styleEl.dataset.plugin = 'dsh-background-by-model'\n markOwnSheet(styleEl)\n // The gradient only applies while applyCustomTokens marks the body with the\n // plugin's own dark-mode value, avoiding matches against the host's attribute.\n styleEl.textContent = `body[data-ds-dark-theme=\"${OWN_SCHEME}\"]::before{content:'';position:fixed;inset:0;z-index:-1;pointer-events:none;background:radial-gradient(ellipse 80% 60% at 50% 0%,rgba(255,255,255,0.03) 0%,transparent 60%)}${SETTINGS_STYLE_RULE}${TRAJECTORY_STYLE_RULE}${RIGHTBAR_STYLE_RULE}${INPUT_BLUR_RULE}` + PLACEHOLDER_RULE\n document.head.appendChild(styleEl)\n ctx.effect(() => () => { styleEl?.parentNode?.removeChild(styleEl) }, 'dsh-background-by-model: gradient')\n\n // ── 3. State store ────────────────────────────────────────────────────────\n let rev = 0\n let rulesRev = 0\n let modelText = ''\n let modelSource: 'session' | 'default' = 'default'\n // Why no per-session model is available yet ('waiting' until the sessions\n // service mounts, then the failing hop, then 'fallback'). Shown by the status\n // readout so a dead hop is never mistaken for a real model.\n let modelNote = 'waiting'\n // Text + source last acted on, so the watch's forced re-emits (and the 1.5 s\n // safety poll) cannot re-run the whole apply while nothing changed.\n let modelKey = '\\u0000'\n const store = defineStore({\n init: () => ({\n url: null as string | null,\n rev: -1,\n rulesRev: -1,\n model: '',\n modelSource: 'session' as 'session' | 'default',\n modelNote: 'waiting',\n activeRuleId: null as string | null,\n matched: false,\n rotIndex: 0,\n rotTotal: 0,\n rotating: false,\n hostStale: false,\n }),\n actions: {\n sync: (d: any, url: string | null, r: number, rr: number, model: string, source: 'session' | 'default', note: string, id: string | null, matched: boolean, rotIndex: number, rotTotal: number, rotating: boolean, hostStale: boolean) => {\n if (r > d.rev) { d.url = url; d.rev = r }\n if (rr > d.rulesRev) d.rulesRev = rr\n d.model = model\n d.modelSource = source\n d.modelNote = note\n d.activeRuleId = id\n d.matched = matched\n d.rotIndex = rotIndex\n d.rotTotal = rotTotal\n d.rotating = rotating\n d.hostStale = hostStale\n },\n },\n })\n let bound: { sync: (...a: any[]) => void } | null = null\n /** Rotation facts of whatever is painted now, for the section's readout. */\n const rotationFacts = (): { index: number; total: number; rotating: boolean } => {\n const rule = activeRule()\n if (rule === null) return { index: 0, total: 0, rotating: false }\n return {\n index: imageIndexOf(rule),\n total: rule.images.length,\n // The badge and the timer read the SAME predicate, so \"rotating\" can never\n // be shown while nothing is scheduled (the failure this feature would\n // otherwise produce silently).\n rotating: isRotating(rule.images.length, rule.rotate.enabled, rule.rotate.intervalMs) && !document.hidden,\n }\n }\n const sync = (): void => {\n rev++\n const rot = rotationFacts()\n bound?.sync(rWp(), rev, rulesRev, modelLabel !== '' ? modelLabel : modelText, modelSource, modelNote, activeRuleId, activeMatched, rot.index, rot.total, rot.rotating, hostIsLegacy())\n }\n\n /**\n * Publish the scheme the host's own preference resolves to. The theme service\n * is the only place that knows it (a custom active theme included); the\n * wallpaper layer needs it to hand `data-ds-dark-theme` back in the host's own\n * form while a color-less rule follows that theme, instead of leaving the flag\n * off — which pins the host to its LIGHT palette on a dark system.\n */\n const syncHostScheme = (): void => {\n try {\n setHostScheme(ctx.theme.getTheme().active.colorScheme === 'dark')\n } catch {\n // A host build without a resolvable snapshot: let the wallpaper layer fall\n // back to the preference the boot script published.\n setHostScheme(null)\n }\n }\n\n /**\n * Which rule wins for the current model RIGHT NOW, and whether it was a\n * substring hit (a holiday override is never a \"match\" of the model).\n *\n * Read by the repaint AND by the panel's write path, which has to know whether\n * an edit changed the answer: `color`, `enabled` and `match` all feed the\n * resolution (a rule with no image still paints from its own color — see\n * `ruleCanPaint`). Without this, editing a rule that was not the active one —\n * giving an emptied rule its first color, typing a match string that should\n * promote it — changed nothing on screen until some unrelated event happened to\n * re-run the resolution.\n */\n const resolveRule = (): { rule: BgRule | null; matched: boolean } => {\n // The holiday override sits ABOVE the rule list: while one is in force the\n // model is irrelevant, which is the whole point of the switch.\n const holiday = activeHolidayRule()\n return holiday !== null\n ? { rule: holiday as BgRule, matched: false }\n : matchRule(cfg.rules, modelText)\n }\n\n /** Id of the rule that would paint right now; `null` = the host's own look. */\n const winnerId = (): string | null => resolveRule().rule?.id ?? null\n\n /**\n * Close a rule edit: repaint when it could have moved what is on screen, and\n * merely refresh the panel's readout when it could not.\n *\n * `winnerBefore` is sampled by the caller BEFORE its mutation (`winnerId()`),\n * and the comparison itself lives in ./repaint, where it is checked on plain\n * node. Every write path below ends here — the old per-path test\n * (`id === activeRuleId`) missed the edit that CREATES the winner, which is the\n * \"上传图片 / 提取主题色之后界面不动,动一下调色盘或切模型才出现\" report.\n */\n const repaintIfMoved = (id: string, winnerBefore: string | null): void => {\n if (shouldRepaint(id, winnerBefore, winnerId())) applyActive()\n else sync()\n }\n\n /**\n * Resolve the active rule for the current model and repaint everything.\n *\n * @param advance - true only on a MODEL switch: the rotation of the rule that\n * took over may then step once (`rotate.advanceOnSwitch`), which is how a\n * model gets \"a different picture every time\" without any timer at all.\n */\n const applyActive = (advance = false): void => {\n const { rule, matched } = resolveRule()\n // Set BEFORE the index is read: `setActive` resets the image index whenever\n // the rule itself changes, so a switch onto a fresh rule starts at its first\n // image (and `advanceOnSwitch` then steps off it — see below).\n setActive(rule === null ? null : rule.id, matched)\n if (advance && rule !== null && rule.rotate.advanceOnSwitch) {\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n if (next !== null) setRotIndex(next)\n }\n scheduleRotation()\n // AFTER the index moved: the palette belongs to the image that is on screen,\n // and `advanceOnSwitch` above may have just changed which one that is.\n applyPalette()\n applyWp()\n sync()\n }\n\n // ── 3a. Multi-image rotation ──────────────────────────────────────────────\n // ONE interval for the whole plugin, always aimed at the ACTIVE rule. A timer\n // per rule would burn wakeups on rules that are not painting anything, and\n // since only one rule's images can be on screen at a time, one timer is all\n // that is needed.\n //\n // `loadSlot` below (section 6) is only CALLED from here, never during this\n // synchronous apply, so the order of these two declarations does not matter.\n let rotTimer: number | null = null\n /** Identity of the schedule currently armed; a change means \"re-arm\". */\n let rotSig = ''\n\n /** Warm one image so a later switch fades toward bytes that are already here. */\n const warmImage = (rule: BgRule, idx: number): void => {\n const slot = rule.images[idx]?.slot\n if (slot !== undefined) void loadSlot(slot)\n }\n\n /** Show the image at `idx` at once, loading it first when it is not in memory. */\n const paintImage = (rule: BgRule, idx: number): void => {\n const slot = rule.images[idx]?.slot\n if (slot === undefined) return\n // The palette first, and always: this image may carry a theme color of its\n // own, and it becomes the one in force the moment the index moves (see\n // `applyPalette`). `setRotIndex` has already run in every caller.\n applyPalette()\n if (imageOf(slot) !== null) { applyWp(); sync(); return }\n // A cold image cannot be cross-faded toward — the outgoing layer would fade\n // to an empty one and the interface would show through for a frame — so the\n // paint happens after the bytes land. Reading the slot over this channel costs\n // one local round trip, which is the price of not shipping every image of\n // every rule at boot.\n void loadSlot(slot).then(() => { applyWp(); sync() })\n }\n\n const rotateTick = (): void => {\n const rule = activeRule()\n if (rule === null) return\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n // Nothing to step to (the list shrank to a single image under us): stop\n // rather than leave a timer firing forever at a rule with one picture.\n if (next === null) { scheduleRotation(true); return }\n setRotIndex(next)\n paintImage(rule, next)\n // Warm the image AFTER the one just shown, so the next tick has decoded bytes\n // to fade toward instead of paying a read at the moment of the switch.\n const after = nextIndex(rule.images.length, rule.rotate.order, next)\n if (after !== null) warmImage(rule, after)\n }\n\n /**\n * Arm (or re-arm) the rotation for the active rule.\n *\n * Idempotent by SIGNATURE rather than by \"already armed\": a slider drag on the\n * active rule re-runs the whole apply dozens of times per second, and restarting\n * the interval on each of those would mean the dwell timer never elapses while\n * the user is dragging (and a 10 s rotation would never advance). The signature\n * carries exactly the inputs the schedule depends on, so a real change — another\n * rule, another interval, the tab becoming visible again — re-arms while a\n * repaint does not.\n */\n const scheduleRotation = (force = false): void => {\n const rule = activeRule()\n // `activeRule()` also answers with a holiday entry, whose images are the\n // package's single picture; `isRotating` turns that into \"no schedule\".\n const sig = rule === null\n ? ''\n : [rule.id, rule.rotate.enabled, rule.rotate.intervalMs, rule.rotate.order, rule.images.length, document.hidden].join('|')\n if (!force && sig === rotSig) return\n rotSig = sig\n if (rotTimer !== null) { window.clearInterval(rotTimer); rotTimer = null }\n if (rule === null || document.hidden) return\n if (!isRotating(rule.images.length, rule.rotate.enabled, rule.rotate.intervalMs)) return\n // Warm the first image this schedule will ask for, so the very first tick is\n // not the one that has to pay for the read.\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n if (next !== null) warmImage(rule, next)\n rotTimer = window.setInterval(rotateTick, rule.rotate.intervalMs)\n }\n ctx.effect(() => () => {\n if (rotTimer !== null) { window.clearInterval(rotTimer); rotTimer = null }\n }, 'dsh-background-by-model: rotation timer')\n // A hidden tab has nothing to paint, so the rotation stops with the pixels and\n // resumes on a fresh interval: coming back to a background that changed three\n // times while nobody was looking is not what \"every 30 seconds\" means to anyone\n // watching it. `sync()` is what moves the \"rotating\" readout with it — the\n // section cannot be seen while the tab is hidden, but the badge must be right the\n // moment it is shown again.\n const onVisibility = (): void => { scheduleRotation(); sync() }\n document.addEventListener('visibilitychange', onVisibility)\n ctx.effect(() => () => document.removeEventListener('visibilitychange', onVisibility), 'dsh-background-by-model: rotation visibility')\n\n /**\n * The holiday the background must follow right now, or null.\n *\n * The decision itself is `pickHoliday` (pure, and covered by\n * `scripts/holiday-check.ts`); this only supplies the two things it cannot\n * know — today's holiday from the calendar, and whether the slot has bytes.\n */\n const activeHolidayRule = (): HolidayRule | null =>\n pickHoliday(cfg.holidays.enabled, cfg.holidays.items, activeHoliday(), slot => imageOf(slot) !== null)\n\n // ── 3b. Holiday theme color ───────────────────────────────────────────────\n // There is nothing to compute: a holiday's color is a fixed part of its\n // definition (see `HOLIDAYS`), forced on every read by ./schema. The extractor\n // that used to run here decoded a full-size festival photo to re-derive a hue\n // that was always going to be the same one.\n\n // ── 4. First paint + the AppFrame watch ───────────────────────────────────\n syncHostScheme()\n applyWp()\n sync()\n watchParts()\n\n // ── 5. Model watch ────────────────────────────────────────────────────────\n // The session's own durable model selection is the authority; the host default\n // is only a last resort, and the settings page labels it as such.\n const offModel = watchModel(ctx, (text, label, source, note) => {\n const key = `${text}\\u0001${source}\\u0001${note}`\n if (key === modelKey) return\n const textChanged = text !== modelText\n modelKey = key\n modelText = text\n modelSource = source\n modelNote = note\n setModelLabel(label !== '' ? label : text)\n // A note-only change (e.g. still waiting for the sessions service) must\n // refresh the readout without repainting the whole interface.\n if (textChanged) applyActive(true)\n else sync()\n })\n ctx.effect(() => () => offModel(), 'dsh-background-by-model: model watch')\n // A trimmed client (or one whose session is not materialized yet) leaves the\n // per-session sources empty; the host's default model is a coarse but honest\n // stand-in, tagged so the UI never claims it is this session's selection.\n void (async () => {\n if (modelText !== '') return\n const fallback = await readDefaultModel()\n if (fallback !== null && modelText === '') {\n modelKey = `${fallback}\\u0001default\\u0001fallback`\n modelText = fallback\n modelSource = 'default'\n modelNote = 'fallback'\n setModelLabel(fallback)\n applyActive()\n }\n })()\n\n // ── 5b. Holiday rollover ──────────────────────────────────────────────────\n // The holiday answer only changes at Beijing midnight — a switch flip calls\n // applyActive directly — so this is a slow tick that does nothing at all until\n // the day key actually moves. 30 s is plenty for a boundary that is a whole day\n // wide, and it costs one `Intl` format per tick.\n //\n // `todayHolidaySlot` / `loadSlot` are declared below, in section 6; both are\n // initialized during this same synchronous apply, long before any tick fires.\n let holidayKey = activeHoliday() ?? ''\n const holidayTimer = window.setInterval(() => {\n const next = activeHoliday() ?? ''\n if (next === holidayKey) return\n holidayKey = next\n // Midnight can land ON a holiday, and that holiday's art was deliberately\n // not fetched at boot (it was not that day yet) — fetch it, then repaint.\n const slot = todayHolidaySlot()\n if (slot === null) applyActive()\n else void loadSlot(slot).then(() => applyActive())\n }, 30_000)\n ctx.effect(() => () => { window.clearInterval(holidayTimer) }, 'dsh-background-by-model: holiday rollover')\n\n // ── 6. Boot restore ───────────────────────────────────────────────────────\n /** Read one slot's bytes into the cache unless they are already there. */\n const loadSlot = async (slot: string): Promise<void> => {\n if (imageOf(slot) !== null) return\n const url = await readImage(slot)\n if (url !== null) setImage(slot, url)\n }\n /**\n * The slot of the holiday that could paint TODAY, or null.\n *\n * Gated on the CALENDAR, not merely on the switch. Now that the override is on\n * by default and invisible, a profile that simply is not on a holiday must not\n * pull ~730 KB of bundled art (≈970 KB of base64 over this channel) at every\n * boot just because the feature is armed.\n */\n const todayHolidaySlot = (): string | null => {\n if (!cfg.holidays.enabled) return null\n const id = activeHoliday()\n if (id === null) return null\n const item = holidayById(id)\n if (item === null || !item.enabled) return null\n return ruleSlots(item)[0] ?? null\n }\n /**\n * The slots boot hydrates, in no particular order: the FIRST image of every\n * rule, today's holiday, and the image the current model paints.\n *\n * That first-image set is exactly what this plugin loaded per rule before\n * multi-image existed — a rule card draws its first image as its thumbnail, so\n * the settings page looks the same as it always did. Everything past the first\n * image of a rule is read ON DEMAND: by the rotation (which warms the image it\n * is about to need as soon as its schedule is armed) and by the settings page\n * when a card is expanded. Hydrating every image of every rule here would mean\n * twenty full-size data URLs over this channel before the first frame on a\n * five-rule setup with four pictures each, which is the one cost this feature\n * must not pay.\n *\n * The slot list the store knows about (`readPersisted().slots`) is deliberately\n * NOT hydrated any more: an orphaned slot that no rule references has no card to\n * appear on, so pulling its bytes over the channel at boot is pure waste. It\n * stays on disk — and is still reported by the node half — until a rule\n * references it again or it is deleted with its rule.\n */\n const bootSlots = (): string[] => {\n const holiday = todayHolidaySlot()\n const firsts = cfg.rules\n .map(r => r.images[0]?.slot)\n .filter((slot): slot is string => slot !== undefined)\n const current = prioritySlot()\n return Array.from(new Set([\n ...firsts,\n ...(holiday === null ? [] : [holiday]),\n ...(current === null ? [] : [current]),\n ]))\n }\n /**\n * The slot that paints before anything else: the holiday in force when there\n * is one, otherwise the FIRST image of the current model's rule. A holiday\n * outranks the rule here for the same reason it outranks it when painting.\n *\n * Always the first image (never the one `advanceOnSwitch` would step to): boot\n * paints without an advance, and hydrating an image the first frame is not going\n * to use would leave the frame blank until the real one arrived.\n */\n const prioritySlot = (): string | null =>\n todayHolidaySlot() ?? matchRule(cfg.rules, modelText).rule?.images[0]?.slot ?? null\n void (async () => {\n const persisted = await loadPersisted()\n if (persisted !== null) {\n adoptConfig(persisted.config)\n const first = prioritySlot()\n // The active rule's bytes paint first; the remaining slots stream in after\n // so a large multi-rule setup never delays the first frame.\n const slots = bootSlots()\n const order = first === null ? slots : [first, ...slots.filter(s => s !== first)]\n for (const slot of order) {\n await loadSlot(slot)\n if (slot === first) applyActive()\n }\n }\n applyActive()\n })()\n\n ctx.effect(() => () => { teardownWp() }, 'dsh-background-by-model: wp cleanup')\n\n ctx.effect(() => ctx.on('theme/change', () => {\n // The custom theme's preference lives in memory, so a host adoption can\n // silently reset it; re-assert it while the active rule has a color. Guard\n // on registry presence — registerCustom disposes the old skin first, so\n // during that transient the registry lacks CUSTOM_ID.\n // The resolved scheme is read first: an OS flip while the preference is\n // `system` arrives exactly here, and a color-less rule has to follow it.\n syncHostScheme()\n if (activeColor() !== null) {\n const snapshot = ctx.theme.getTheme()\n if (snapshot.preference !== CUSTOM_ID && snapshot.themes.some(t => t.id === CUSTOM_ID)) {\n ctx.theme.setTheme(CUSTOM_ID)\n }\n }\n applyWp()\n }), 'dsh-background-by-model: theme change')\n\n // Wallpaper placement is computed in absolute viewport pixels, so watch the\n // viewport itself: a fixed inset:0 sentinel's box always equals the viewport,\n // so a ResizeObserver on it catches any viewport change (window resize,\n // monitor moves, panel splitters, zoom); a resolution media query catches\n // DPI-only moves. Re-applies are coalesced to one per animation frame.\n let frame = 0\n const applySoon = (): void => {\n if (frame !== 0) return\n frame = requestAnimationFrame(() => { frame = 0; applyWp() })\n }\n const sentinel = document.createElement('div')\n sentinel.style.cssText = 'position:fixed;inset:0;pointer-events:none;visibility:hidden'\n document.body.append(sentinel)\n const viewportObserver = new ResizeObserver(applySoon)\n viewportObserver.observe(sentinel)\n const dprQuery = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)\n dprQuery.addEventListener('change', applySoon)\n ctx.effect(() => () => {\n viewportObserver.disconnect()\n dprQuery.removeEventListener('change', applySoon)\n sentinel.remove()\n }, 'dsh-background-by-model: viewport watch')\n\n // ── 7. Locale ─────────────────────────────────────────────────────────────\n ctx.effect(() => ctx.locale.register(NS, { zh, en }) as any, 'dsh-background-by-model: i18n')\n\n /**\n * The automatic half of \"extract from image\": fill an IMAGE's theme color from\n * its own bytes when it has none of its own, and only then — a color the user\n * picked (or a previous extraction produced) is never overwritten, so this\n * cannot fight a deliberate choice.\n *\n * `slot` names the image that just arrived, because a rule's images each carry\n * their own palette since 0.7.1 and the one the user just added is the one they\n * are looking at. Omitted (or unknown) falls back to the rule's first image.\n *\n * The question is asked of the IMAGE, not of the rule: a rule whose pictures\n * were all cleared and then re-filled must theme each new picture, and a rule\n * with a color of its own still has no say over the colors of its pictures.\n *\n * The decode is asynchronous, so the \"still empty?\" question is asked AGAIN on\n * arrival: a color chosen while it ran must win over the one being computed.\n */\n const maybeAutoExtract = async (id: string, slot?: string): Promise<void> => {\n if (!cfg.autoExtract) return\n /** The entry this extraction is about, re-resolved on every read. */\n const target = (rule: BgRule | null): BgImage | undefined => {\n if (rule === null) return undefined\n return (slot === undefined ? undefined : rule.images.find(i => i.slot === slot)) ?? rule.images[0]\n }\n const image = target(ruleById(id))\n if (image === undefined || image.color !== null) return\n const url = displayImageOf(image.slot)\n if (url === null) return\n let hsl: [number, number, number] | null = null\n try { hsl = await extractWallpaperColor(url, image.bgState) } catch { hsl = null }\n if (hsl === null) return\n const current = target(ruleById(id))\n if (current === undefined || current.color !== null) return\n // Same as `extractColor`: this color can be the one that makes the rule\n // paintable, and it arrives AFTER the upload's own repaint — so the winner is\n // sampled here, on arrival, and the interface follows at once.\n const winner = winnerId()\n current.color = hsl\n rulesRev++\n saveConfig()\n repaintIfMoved(id, winner)\n }\n\n /**\n * The batch form, for one upload that carried several pictures.\n *\n * EVERY picture that arrived is themed from its own bytes, the first ones\n * included. The single-slot reading of an upload (\"the last image added is the\n * one being looked at\") is true of the CARD's selection and false of the\n * palette: since a theme color belongs to an image, a batch that themed only\n * its last file left the rest of a fresh rotation on the system theme, with\n * nothing in the interface to say why.\n *\n * Sequential on purpose: a batch is a handful of full-size photos, and ten\n * parallel decodes buy nothing the user can see, while landing the colors in\n * list order does (the card fills in from its first picture).\n */\n const maybeAutoExtractEach = async (id: string, slots: readonly string[]): Promise<void> => {\n for (const slot of slots) await maybeAutoExtract(id, slot)\n }\n\n // ── 8. Section injection ──────────────────────────────────────────────────\n // The section's props are built ONCE by the slot host, so anything that changes\n // at runtime rides the store; the two exceptions are the context (needed by the\n // host self-check probe) and the language (read at build time, refreshed when\n // the section is rebuilt).\n const activeLang = (): 'zh' | 'en' => {\n try {\n const snapshot = ctx.locale.getSnapshot()\n return typeof snapshot?.active === 'string' && snapshot.active.toLowerCase().startsWith('zh') ? 'zh' : 'en'\n } catch {\n return 'en'\n }\n }\n /** The model-resolution facts the host self-check reports, read on demand. */\n const readModelFacts = (): ModelFacts => {\n const rule = activeRuleId === null ? null : ruleById(activeRuleId)\n return {\n text: modelText,\n source: modelSource,\n note: modelNote,\n rule: rule === null ? '' : (rule.match !== '' ? rule.match : rule.id),\n matched: activeMatched,\n }\n }\n const sectionInject = (actions: { sync: (...a: any[]) => void }): Omit<ThemeSectionProps, 'useStore'> => {\n bound = actions\n sync()\n return {\n t: ctx.locale.bind(NS),\n ctx,\n lang: activeLang(),\n readModelFacts,\n imageOf: (slot: string) => displayImageOf(slot),\n addRule: (): string => {\n // No slot is allocated here: a new rule holds no image, so the first free\n // slot is taken when the first picture arrives (see newRule).\n const rule = newRule(nextRuleId())\n cfg.rules.push(rule)\n rulesRev++\n persistConfig()\n applyActive()\n return rule.id\n },\n removeRule: (id: string): void => {\n const idx = cfg.rules.findIndex(r => r.id === id)\n if (idx < 0) return\n const [rule] = cfg.rules.splice(idx, 1)\n if (rule !== undefined) {\n // A slot is released only when NOTHING else points at it — another rule\n // (its own images included, hence the re-scan after the splice) or a\n // holiday entry. Multi-image made this a per-slot question instead of a\n // whole-rule one, and a wrong answer here deletes a picture another\n // card is still showing.\n const stillUsed = takenSlots()\n for (const slot of ruleSlots(rule)) {\n if (stillUsed.has(slot)) continue\n setImage(slot, null)\n void deleteImage(slot)\n }\n }\n rulesRev++\n persistConfig()\n applyActive()\n },\n moveRule: (id: string, dir: -1 | 1): void => {\n const idx = cfg.rules.findIndex(r => r.id === id)\n const to = idx + dir\n if (idx < 0 || to < 0 || to >= cfg.rules.length) return\n const [rule] = cfg.rules.splice(idx, 1)\n cfg.rules.splice(to, 0, rule!)\n rulesRev++\n persistConfig()\n applyActive()\n },\n setRule: (id: string, patch: Partial<BgRule>): void => {\n const rule = ruleById(id)\n if (rule === null) return\n // Text/color/match/slider edits all arrive here, and all of them can move\n // the resolution (see `shouldRepaint`), so the winner is sampled first.\n const winner = winnerId()\n Object.assign(rule, patch)\n // The shared sanitizer, so a live edit can never hold a value the next\n // load would clamp differently (see ./schema).\n normalizeRuleInPlace(rule)\n rulesRev++\n // Text/color/slider edits arrive per keystroke and per pointer move, so\n // the write is coalesced; structural edits below stay immediate.\n saveConfig()\n repaintIfMoved(id, winner)\n },\n addRuleImages: (id: string, dataUrls: readonly string[]): void => {\n const rule = ruleById(id)\n if (rule === null || dataUrls.length === 0) return\n // This is the edit that most often CREATES the winner: a rule that just\n // came out of \"+ 新增规则\" has no picture, so it is not the active rule —\n // and the picture it is being given now is exactly what makes it one.\n const winner = winnerId()\n /** Slots of THIS batch, in list order — the extraction below is per slot. */\n const added: string[] = []\n for (const dataUrl of dataUrls) {\n const slot = nextSlot()\n // `color: null` (not absent): this image has no color of its own YET, and\n // the auto-extraction below is what fills it. An absent key would mean\n // \"written before 0.7.1\" instead, and would be lifted from the rule's color\n // on the next read — which is the opposite of what a new picture wants.\n const image = { slot, bgState: { ...DEFAULT_BG_STATE }, color: null }\n rule.images.push(image)\n added.push(slot)\n setImage(slot, dataUrl)\n // One write per image, immediately: adding a picture is a structural\n // edit, and losing the batch to a page close would leave the config\n // referencing slots the disk never received.\n void writeImage(slot, dataUrl)\n }\n rulesRev++\n persistConfig()\n repaintIfMoved(id, winner)\n // A rule that has never been themed should simply come out themed; an\n // explicit color (or a cleared one the user set on purpose) is left be.\n // Addressed by SLOT and over the whole batch: a rotation is built by\n // picking several files at once and every one of them carries a palette of\n // its own, so the batch is what gets themed — not just the last file, and\n // not just the one the card happens to select.\n void maybeAutoExtractEach(id, added)\n },\n removeRuleImage: (id: string, slot: string): void => {\n const rule = ruleById(id)\n if (rule === null) return\n const idx = rule.images.findIndex(i => i.slot === slot)\n if (idx < 0) return\n // Removing can also move the winner — it is the mirror image of the\n // upload above: the rule that was painting may have just lost the last\n // thing it had to paint with.\n const winner = winnerId()\n // The LAST image can be removed too, and the rule is then simply empty: a\n // rule with a color of its own still paints (the interface, no wallpaper)\n // and one with neither is skipped by `ruleCanPaint` until something\n // arrives. Refusing this (the first cut of the feature did) left a cleared\n // entry behind, and that entry sat at position 1 — so the next upload\n // became image 2 of a rule that kept painting nothing, with no way back.\n rule.images.splice(idx, 1)\n // The painted image may be the one that just went away, so the index has\n // to move with it — and `applyActive` below resets it when the rule itself\n // is the active one.\n if (id === activeRuleId) setRotIndex(0)\n rulesRev++\n persistConfig()\n if (!takenSlots().has(slot)) {\n setImage(slot, null)\n void deleteImage(slot)\n }\n repaintIfMoved(id, winner)\n },\n moveRuleImageTo: (id: string, slot: string, to: number): void => {\n const rule = ruleById(id)\n if (rule === null) return\n const idx = rule.images.findIndex(i => i.slot === slot)\n if (idx < 0) return\n // `to` is an index of the list this move PRODUCES, which is what a drop\n // target is expressed in — so it is clamped against the same length the\n // splice below restores the image into.\n const at = Math.max(0, Math.min(rule.images.length - 1, Math.trunc(to)))\n if (at === idx) return\n const winner = winnerId()\n // What is on screen is a PICTURE, not a position in a list. Reordering is\n // the user tidying the rotation, not a request to change the wallpaper, so\n // the painted slot is remembered here and the index is put back on it\n // after the splice — a reorder can never swap the picture out from under\n // them. (The one-step arrows and \"make first\" used to move the index onto\n // the image they moved, which is exactly the surprise this avoids.)\n const painted = id === activeRuleId ? rule.images[imageIndexOf(rule)]?.slot ?? null : null\n const [image] = rule.images.splice(idx, 1)\n rule.images.splice(at, 0, image!)\n rulesRev++\n // The count is unchanged, so the timer's signature cannot see a reorder —\n // re-arm explicitly, both to pick up the new cycle order and to make sure\n // the index below is what the next step starts from.\n if (id === activeRuleId) {\n // Reordering never removes a picture, so the painted one is always still\n // in the list; the fallback is only there to keep the index in range.\n const keep = painted === null ? -1 : rule.images.findIndex(i => i.slot === painted)\n setRotIndex(keep < 0 ? Math.min(at, rule.images.length - 1) : keep)\n scheduleRotation(true)\n }\n persistConfig()\n repaintIfMoved(id, winner)\n },\n setImageFraming: (id: string, slot: string, bgState: BgState): void => {\n const rule = ruleById(id)\n const image = rule?.images.find(i => i.slot === slot)\n if (image === undefined) return\n const winner = winnerId()\n image.bgState = bgState\n normalizeRuleInPlace(rule!)\n rulesRev++\n saveConfig()\n // Framing is per image, so a repaint of the CURRENT image is what makes\n // the editor's commit visible; `applyWp` re-reads the framing of whatever\n // is painted, which is this image only while it is the current one.\n repaintIfMoved(id, winner)\n },\n setRuleRotation: (id: string, patch: Partial<BgRule['rotate']>): void => {\n const rule = ruleById(id)\n if (rule === null) return\n patchRotation(rule, patch)\n rulesRev++\n persistConfig()\n // Turning the rotation on has to be able to paint at once, and turning it\n // off has to be able to stop the timer at once: both go through the\n // signature check in `scheduleRotation`.\n scheduleRotation()\n sync()\n },\n rotateNow: (id: string): void => {\n const rule = ruleById(id)\n // Only the ACTIVE rule can step: the image index describes what is on\n // screen, and a rule that is not painting has nothing on screen to change.\n if (rule === null || id !== activeRuleId) return\n const next = nextIndex(rule.images.length, rule.rotate.order, imageIndexOf(rule))\n if (next === null) return\n setRotIndex(next)\n paintImage(rule, next)\n // A manual step restarts the dwell, so the tick that was already on its\n // way does not follow the user's click a second later.\n scheduleRotation(true)\n },\n showRuleImage: (id: string, slot: string): void => {\n const rule = ruleById(id)\n // Same rule as `rotateNow` above, and for the same reason: the image index\n // describes what is ON SCREEN, so a rule that is not painting has nothing\n // on screen to change. Pointing it at one of its pictures would be a\n // promise nothing keeps — the index is reset the moment it takes over.\n if (rule === null || id !== activeRuleId) return\n const idx = rule.images.findIndex(i => i.slot === slot)\n if (idx < 0) return\n setRotIndex(idx)\n // Not `applyActive`: this paints the one image the user asked for, and\n // `paintImage` is also what waits for cold bytes before showing them.\n paintImage(rule, idx)\n // A jump is a manual step, so it restarts the dwell as well — otherwise the\n // tick already on its way would carry the picture off a moment later.\n scheduleRotation(true)\n // NOTE: no `persistConfig` and no config field changes here. Which image is\n // being shown is runtime state, not a setting: it is not saved, and it is\n // not restored on the next boot (which starts at the rule's first image).\n },\n loadRuleImages: async (id: string): Promise<void> => {\n const rule = ruleById(id)\n if (rule === null) return\n // Sequential on purpose: an expanded card wants its thumbnails in list\n // order, and firing ten parallel reads over one RPC channel would only\n // race them into the cache in a random order.\n for (const slot of ruleSlots(rule)) await loadSlot(slot)\n sync()\n },\n setRuleImage: (id: string, slot: string, dataUrl: string | null): void => {\n const rule = ruleById(id)\n if (rule === null || !rule.images.some(i => i.slot === slot)) return\n const winner = winnerId()\n setImage(slot, dataUrl)\n void (dataUrl === null ? deleteImage(slot) : writeImage(slot, dataUrl))\n repaintIfMoved(id, winner)\n // A rule that has never been themed should simply come out themed; an\n // explicit color (or a cleared one the user set on purpose) is left be.\n if (dataUrl !== null) void maybeAutoExtract(id, slot)\n },\n addRuleImageFromUrl: async (id: string, url: string): Promise<FetchResult> => {\n const rule = ruleById(id)\n if (rule === null) return { ok: false, error: 'unknown rule' }\n // The slot is allocated before the download so the node half can write\n // straight into it (its `fetchImageUrl` is slot-addressed); a failed\n // download simply leaves the new entry empty, which is removed again\n // right here rather than showing a broken thumbnail.\n const slot = nextSlot()\n const res = await fetchImageUrl(slot, url)\n if (!res.ok) return res\n // Sampled here, not before the download: the list is only touched now.\n const winner = winnerId()\n rule.images.push({ slot, bgState: { ...DEFAULT_BG_STATE }, color: null })\n setImage(slot, res.dataUrl ?? null)\n rulesRev++\n persistConfig()\n repaintIfMoved(id, winner)\n void maybeAutoExtract(id, slot)\n return res\n },\n /**\n * Store ONE image's theme color (null = that image follows the system\n * theme). Addressed by slot exactly like `setImageFraming`, because the\n * color belongs to the image: editing image 3's color must not rewrite\n * image 1's, and it must not touch the RULE's color either — that one is\n * what the rule paints once its last picture is gone, and it is edited only\n * while there is no image to edit (the panel's own branch).\n */\n setImageColor: (id: string, slot: string, color: [number, number, number] | null): void => {\n const rule = ruleById(id)\n const image = rule?.images.find(i => i.slot === slot)\n if (rule === null || rule === undefined || image === undefined) return\n // A color is what a paint is made of, so the winner is sampled first: this\n // can be the edit that makes an unusable rule usable (see repaintIfMoved).\n const winner = winnerId()\n image.color = color\n normalizeRuleInPlace(rule)\n rulesRev++\n // Pointer-move frequency (the wheel, the RGB inputs), so the write is\n // coalesced — the same rule `setRule` follows for its color.\n saveConfig()\n repaintIfMoved(id, winner)\n },\n extractColor: async (id: string, slot?: string): Promise<boolean> => {\n const rule = ruleById(id)\n if (rule === null) return false\n const image = rule.images.find(i => i.slot === slot) ?? rule.images[0]\n if (image === undefined) return false\n const url = displayImageOf(image.slot)\n if (url === null) return false\n const hsl = await extractWallpaperColor(url, image.bgState)\n if (hsl === null) return false\n // Addressed by SLOT, like the framing editor: the extraction belongs to the\n // picture the user pressed the button on, and a rule with several pictures\n // must be able to keep their palettes apart.\n const current = ruleById(id)?.images.find(i => i.slot === image.slot)\n if (current === undefined) return false\n // The color is what makes a picture-less rule paintable at all, so this\n // edit can hand the interface a rule it was not showing (the \"从本图提取\n // 之后色没上来\" half of the report).\n const winner = winnerId()\n current.color = hsl\n rulesRev++\n saveConfig()\n repaintIfMoved(id, winner)\n return true\n },\n setOps: (ops: PartOpacities): void => { cfg.opacities = ops; applyWp(); sync(); saveConfig() },\n setBlurs: (blurs: PartBlurs): void => { cfg.blurs = blurs; applyWp(); sync(); saveConfig() },\n setSop: (v: number): void => { cfg.settingsOpacity = v; applySettingsOverrides(v); saveConfig() },\n // The file-preview panel owns its surface from the first drag on; a null\n // hands it back to the main-background slider.\n setRightbarOpacity: (v: number | null): void => {\n cfg.rightbarOpacity = v\n applyRightbarOverrides(rRightbarOpacity())\n saveConfig()\n },\n setAutoExtract: (v: boolean): void => { cfg.autoExtract = v; saveConfig(); sync() },\n /**\n * Patch the GLOBAL wallpaper-switch transition (effect, easing, where the\n * duration comes from).\n *\n * Deliberately no `applyWp()`: this setting decides what the NEXT switch\n * looks like and nothing on screen changes right now, so re-running the\n * whole apply (token rewrite, every interface part) for something that\n * paints nothing would be the expensive way to say \"saved\". The Config\n * page's own preview plays the effect instead.\n */\n setTransition: (patch: Partial<TransitionConfig>): void => {\n // Through the shared sanitizer, exactly like `patchRotation`: a live edit\n // can never hold a value the next load would clamp differently.\n cfg.transition = normalizeTransition({ ...cfg.transition, ...patch })\n sync()\n saveConfig()\n },\n\n // ── Holiday overrides ─────────────────────────────────────────────────\n setHolidaysEnabled: (v: boolean): void => {\n cfg.holidays.enabled = v\n persistConfig()\n // Switching it back on has to be able to paint immediately, so today's\n // holiday art is fetched if it is not in memory yet. Only TODAY's: the\n // other one cannot paint, and nothing in the UI shows it.\n const slot = todayHolidaySlot()\n if (v && slot !== null) void loadSlot(slot).then(() => applyActive())\n applyActive()\n },\n\n // Download every rule plus its images as one JSON file.\n exportTheme: (): void => {\n const images: Record<string, string> = {}\n // Rule slots only, but ALL of them: a theme file that carried just each\n // rule's first image would silently drop the rest of a rotation on the\n // way out, and the import below would restore a smaller rule set than the\n // one that was exported. A holiday's wallpaper belongs to the package and\n // is served from there, so it is still never written into a theme file —\n // that would ship ~970 KB of base64 every install already has, to a slot\n // nothing could restore it to (it is read-only).\n const slots = cfg.rules.flatMap(ruleSlots)\n for (const slot of slots) {\n const url = imageOf(slot)\n if (url !== null) images[slot] = url\n }\n const payload = {\n // 6 = the global switch transition (`transition`) is part of the config.\n // 5 and older still import: every field this file predates is defaulted\n // by the shared sanitizer, so an older theme restores unchanged.\n //\n // 5 = a theme color belongs to an image (`images[].color`). 4 and older\n // still import: their image entries carry no `color` key at all, which is\n // exactly the shape `normalizeImage` lifts the rule's color onto, so a\n // theme file written before that feature restores its look unchanged.\n version: 6,\n exportedAt: new Date().toISOString(),\n config: cfg,\n images,\n }\n const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'dsh-background-by-model-theme.json'\n a.click()\n URL.revokeObjectURL(url)\n },\n // Import: replaces the whole rule set and every rule image.\n importTheme: async (file: File): Promise<boolean> => {\n try {\n const data: unknown = JSON.parse(await file.text())\n if (!data || typeof data !== 'object') return false\n const d = data as { version?: number; config?: unknown; images?: unknown }\n if (typeof d.config !== 'object' || d.config === null) return false\n adoptConfig(d.config)\n const incoming = (d.images ?? {}) as Record<string, unknown>\n const keep = new Set<string>()\n // Every slot the imported config references — the same set the export\n // writes. A holiday slot that an older theme file still carries falls\n // outside `keep` and is swept below; the node half refuses to write such\n // a slot either way, so it is inert from both directions.\n for (const slot of cfg.rules.flatMap(ruleSlots)) {\n keep.add(slot)\n const raw = incoming[slot]\n if (typeof raw === 'string' && /^data:image\\//.test(raw)) {\n setImage(slot, raw)\n void writeImage(slot, raw)\n } else {\n setImage(slot, null)\n void deleteImage(slot)\n }\n }\n // Slots the imported config no longer references are released.\n for (const slot of Object.keys(incoming)) {\n if (!keep.has(slot) && /^[A-Za-z0-9_-]{1,32}$/.test(slot)) void deleteImage(slot)\n }\n persistConfig()\n applyActive()\n return true\n } catch {\n return false\n }\n },\n }\n }\n ctx.slots.inject('settings.section', () => ctx.slots.register({\n name: 'settings.section', id: 'dsh-background-by-model', order: 35,\n label: () => ctx.locale.bind(NS)('nav'),\n locale: NS, store, inject: sectionInject,\n }, ThemeSection as any))\n\n // ── 9. Settings-nav icon ──────────────────────────────────────────────────\n // The harness derives the nav glyph from the section id (unknown ids fall back\n // to the settings gear) with no plugin hook, so patch the mounted nav cell in\n // place — find the cell whose label matches this section's nav text and swap\n // its svg for the sun glyph.\n const navLabel = (): string => ctx.locale.bind(NS)('nav')\n const applyNavIcon = (): void => {\n const panel = document.querySelector<HTMLElement>('[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]')\n const nav = panel?.querySelector('nav')\n if (!nav) return\n const target = navLabel()\n for (const cell of Array.from(nav.querySelectorAll('button'))) {\n const label = cell.querySelector('span')\n if (label && label.textContent?.trim() === target) {\n const svg = cell.querySelector('svg')\n if (svg && svg.dataset.dshAnyIcon !== '1') {\n const sun = document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n sun.setAttribute('width', '16')\n sun.setAttribute('height', '16')\n sun.setAttribute('viewBox', '0 0 16 16')\n sun.setAttribute('fill', 'none')\n sun.setAttribute('xmlns', 'http://www.w3.org/2000/svg')\n sun.dataset.dshAnyIcon = '1'\n sun.innerHTML = SUN_PATHS\n svg.replaceWith(sun)\n }\n return\n }\n }\n }\n let navIconObserver: MutationObserver | null = null\n const watchNavIcon = (): void => {\n if (navIconObserver !== null || typeof MutationObserver === 'undefined') return\n navIconObserver = new MutationObserver(records => {\n // React only when the settings panel (or its nav) is (re)created, so\n // chat-content mutations don't trigger a scan.\n const relevant = records.some(r => {\n for (const n of r.addedNodes) {\n if (n.nodeType !== 1) continue\n const el = n as Element\n if (el.matches?.('[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]') || el.querySelector?.('[role=\"dialog\"][aria-modal=\"true\"][aria-labelledby]')) return true\n }\n return false\n })\n if (relevant) applyNavIcon()\n })\n navIconObserver.observe(document.body, { childList: true, subtree: true })\n applyNavIcon()\n }\n watchNavIcon()\n ctx.effect(() => () => { navIconObserver?.disconnect(); navIconObserver = null }, 'dsh-background-by-model: nav icon watch')\n\n // ── 10. Deferred boot restore ─────────────────────────────────────────────\n // The theme service and the host settings scope settle asynchronously after\n // this apply, so the synchronous restore can be observed mid-flight — a late\n // host adoption resets the preference, or the presenter re-applies over our\n // overrides. Re-running the restore a few ticks later guarantees the saved\n // records land.\n const restoreSaved = (): void => {\n syncHostScheme()\n const color = activeColor()\n if (color !== null) {\n const snapshot = ctx.theme.getTheme()\n if (!snapshot.themes.some(t => t.id === CUSTOM_ID)) {\n // Theme missing (host adoption dropped it): re-register + activate.\n registerCustom(color[0], color[1], color[2])\n } else if (snapshot.preference !== CUSTOM_ID) {\n // Theme present but inactive: just re-assert the preference. Calling\n // registerCustom here would dispose + re-create the skin, flashing the\n // interface back to the system theme for a frame on every boot.\n ctx.theme.setTheme(CUSTOM_ID)\n }\n }\n applyWp()\n }\n const restoreTimers = [300, 1500].map(delay => window.setTimeout(restoreSaved, delay))\n ctx.effect(() => () => { restoreTimers.forEach(id => window.clearTimeout(id)) }, 'dsh-background-by-model: boot restore')\n\n // ── 11. Theme watchdog ────────────────────────────────────────────────────\n // The theme service keeps only built-in preferences in memory, so ANY\n // host-scope adoption can silently drop the custom theme — reverting the label\n // colors and the inner surfaces to the system palette. While the active rule\n // carries a color, re-register and re-assert on a slow interval.\n //\n // A color-less rule needs the same slow re-check for the opposite reason: it\n // paints from the HOST palette, which the host can re-project (or which the\n // scheme flag can fall behind) with no event of ours to hang a repaint on.\n // Without this, such a rule keeps whatever palette it read first — the light\n // one, if the read happened while the plugin's own light palette was still\n // forcing the flag off — until an unrelated apply happens to run.\n const watchdogId = window.setInterval(() => {\n syncHostScheme()\n const color = activeColor()\n if (color === null) {\n refreshSystemTheme()\n return\n }\n const snapshot = ctx.theme.getTheme()\n let changed = false\n if (!snapshot.themes.some(t => t.id === CUSTOM_ID)) {\n registerCustom(color[0], color[1], color[2])\n changed = true\n } else if (snapshot.preference !== CUSTOM_ID) {\n ctx.theme.setTheme(CUSTOM_ID)\n changed = true\n }\n if (changed) applyWp()\n }, 1000)\n ctx.effect(() => () => { window.clearInterval(watchdogId) }, 'dsh-background-by-model: theme watchdog')\n\n // ── 12. Theme-reset watchdog ──────────────────────────────────────────────\n const disposeThemeResets = watchThemeResets()\n ctx.effect(() => () => { disposeThemeResets() }, 'dsh-background-by-model: theme resets watch')\n\n // ── 13. Flush pending writes on page hide ─────────────────────────────────\n const onPageHide = (): void => flushSave()\n window.addEventListener('pagehide', onPageHide)\n ctx.effect(() => () => window.removeEventListener('pagehide', onPageHide), 'dsh-background-by-model: pagehide flush')\n}\n"],"mappings":"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"}
|