/* Small, explicit SSR repairs. The original page stylesheet remains in charge. */
.framer-ghRYx { --case-prose-gap: 24px; }

/* Match 5.2's paragraph spacing at the prose-container level. Reflection copy
   has its own stack so its heading spacing and responsive variants stay intact. */
.framer-ghRYx .local-prose-stack {
  display: flex;
  flex-direction: column;
  row-gap: var(--case-prose-gap);
  width: 100%;
  min-width: 0;
}
/* Direct paragraphs use the stack gap instead of adding Framer's paragraph margin. */
.framer-ghRYx .local-prose-stack > p.framer-text { margin: 0; }

/* Reflection observations are prose, not single-line option labels. Let all
   three rows shrink and wrap within their column in either language. */
.framer-ghRYx .local-reflection-metrics > div,
.framer-ghRYx .local-reflection-metrics .framer-Cn5xZ,
.framer-ghRYx .local-reflection-metrics .framer-pWYlH,
.framer-ghRYx .local-reflection-metrics .framer-1xz6lu7,
.framer-ghRYx .local-reflection-metrics .framer-f6yym7 {
  width: 100%;
  min-width: 0;
}
.framer-ghRYx .local-reflection-metrics .framer-Cn5xZ {
  align-items: flex-start;
}
.framer-ghRYx .local-reflection-metrics .framer-l6fpcs-container {
  flex: 1 1 0;
  min-width: 0;
}
.framer-ghRYx .local-reflection-metrics .framer-f6yym7,
.framer-ghRYx .local-reflection-metrics .framer-text {
  white-space: normal;
  overflow-wrap: anywhere;
}
.framer-ghRYx .local-reflection-metrics .framer-1t9cysw-container {
  margin-top: 4px;
}

.local-static-site section[id],
.local-static-site #intro,
.local-static-site #main { scroll-margin-top: 96px; }

/* Lenis 1.1.9: reference scroll curve, with native scrolling inside panels. */
html.lenis { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-scrolling iframe { pointer-events: none; }
.local-scroll-focus:focus { outline: none; }
.local-scroll-focus:focus-visible { outline: 2px solid #7f6cf6; outline-offset: 4px; }

/* 移动端下文章高度固定为 18060px，内容可编辑。 */
@media (max-width: 809.98px) {
  .framer-ghRYx .framer-111su8j { height: auto !important; min-height: 0; }
}

.local-nav-link { text-decoration: none; color: inherit; cursor: pointer; }
.local-nav-link [data-framer-name="Hover - ellipse"] { transition: background-color 180ms ease; }
.local-nav-link:hover [data-framer-name="Hover - ellipse"],
.local-nav-link:focus-visible [data-framer-name="Hover - ellipse"] { background-color: rgba(12, 20, 28, .07) !important; }
.local-nav-link:focus-visible,
.local-toc-link:focus-visible,
.local-audio-control:focus-visible,
nav[data-framer-name="Misc/Menu Bar - tab or mobile"]:focus-visible {
  outline: 2px solid #7f6cf6;
  outline-offset: 4px;
}
nav[data-framer-name="Misc/Menu Bar - tab or mobile"] { cursor: pointer; }

.local-navigation-menu {
  position: fixed;
  z-index: 10000;
  left: 50%;
  bottom: max(88px, calc(env(safe-area-inset-bottom) + 76px));
  transform: translateX(-50%);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  width: min(320px, calc(100vw - 32px));
  padding: 10px;
  border: 1px solid rgba(12, 19, 27, .1);
  border-radius: 20px;
  background: #fff;
  box-shadow: 0 10px 30px rgba(12, 19, 27, .12);
  color: #0c131b;
  font: 14px/1.4 "Inter Display", Inter, system-ui, sans-serif;
}
.local-navigation-menu[hidden], .local-video-cover[hidden] { display: none !important; }
.local-navigation-menu a { display: block; padding: 12px 14px; border-radius: 12px; color: inherit; text-decoration: none; }
.local-navigation-menu a:hover, .local-navigation-menu a:focus-visible { background: #f1f2f5; outline: none; }
.local-toc-link { text-decoration: none; transition: transform 220ms cubic-bezier(.22, 1, .36, 1), color 220ms cubic-bezier(.22, 1, .36, 1); }
.local-toc-link:hover,
.local-toc-link:focus-visible { color: #0c131b !important; }
.local-toc-link:hover .local-toc-label,
.local-toc-link:focus-visible .local-toc-label,
.local-toc-link[aria-current="location"] .local-toc-label { opacity: 1 !important; }
.local-toc-link > .local-toc-marker {
  opacity: 0 !important;
  transform: scaleX(.25) !important;
}
.local-toc-link[aria-current="location"] > .local-toc-marker {
  opacity: 1 !important;
  transform: scaleX(1) !important;
}
/* The return icon's SVG and circular border share this source color token. */
a.framer-7O6Gi:hover,
a.framer-7O6Gi:focus-visible {
  --token-3175e621-00d0-4a31-966e-23433a978eb9: #0c131b;
  --border-color: #0c131b !important;
}
a.framer-7O6Gi:focus-visible {
  outline: 2px solid #7f6cf6;
  outline-offset: 4px;
}
.local-audio-control { cursor: pointer !important; }
.framer-default-slider input[type="range"]:focus-visible + div { outline: 2px solid #7f6cf6; outline-offset: 4px; }

@media (prefers-reduced-motion: reduce) {
  .local-static-site { scroll-behavior: auto !important; }
  .local-nav-link [data-framer-name="Hover - ellipse"], .local-toc-link { transition: none !important; }
  .local-toc-marker, .local-toc-label { transition: none !important; }
}

/* 项目卡副标题：源站该节点是 --framer-text-alignment:left，盒子收缩到文字宽度时
   看起来居中。换成更长的中文文案后盒子撑到满宽，左对齐就和居中的标题错开了。
   这里显式居中，恢复源站的观感。 */
[data-i18n$="-description"] {
  --framer-text-alignment: center !important;
  text-align: center !important;
}
/* 副标题的外层是 shrink-to-fit 且 max-width:none，英文单行会顶穿卡片左右沿。
   限到卡片内容宽（868 − 24×2），超长时改为换行而不是溢出。 */
div:has(> [data-i18n$="-description"]) {
  max-width: 820px !important;
  margin-left: auto !important;
  margin-right: auto !important;
}

/* Canvo and B.Duck share the same monitor frame and responsive placement. */
.framer-H10g5 .project-desktop-mockup {
  position: absolute;
  z-index: 1;
  width: 410px !important;
  height: auto !important;
  aspect-ratio: 5968 / 5120;
  bottom: -178px !important;
  left: 50% !important;
  transform: translateX(-50%);
}
.project-desktop-frame { position: absolute; inset: 0; display: block; width: 100%; height: 100%; }
.project-desktop-screen {
  position: absolute;
  /* Screen opening measured from the shared 2048 × 1757 frame. */
  left: 3.955078125%;
  top: 3.471826978%;
  width: 92.333984375%;
  height: 61.297666477%;
  overflow: hidden;
  background: #eef0f2;
}
.project-desktop-screen img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: center top; }
@media (min-width: 1400px) {
  .framer-H10g5 .project-desktop-mockup { width: 550px !important; bottom: -245px !important; }
}
@media (max-width: 809.98px) {
  .framer-H10g5 .project-desktop-mockup { width: 333px !important; bottom: -104px !important; left: 51% !important; }
}

/* Canvo 首屏产品视频：保持原始 16:9 画幅，完整显示画面。 */
.local-demo-video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: contain;
  border-radius: inherit;
  background: #f8fafc;
}

/* 详情页标题前的 Canvo 标记：用 em 跟着标题字号缩放，
   基线微调让它与中文字面的视觉中心对齐。 */
/* 详情页标题前的 Canvo 标记：viewBox 是 641×688（偏高），
   所以只钉高度、宽度交给比例，避免被压扁或裁到。overflow 放开防父级裁切。 */
.canvo-title-mark {
  display: inline-block;
  width: auto;
  height: .74em;
  margin-right: .24em;
  vertical-align: -.04em;
  overflow: visible;
  color: var(--token-8056d279-4388-496c-b0ab-8ec93edb0b33, #0c131b);
}

/* ── canvoai.com 按钮 ────────────────────────────────────────────────
   源站效果：hover 时黑块从右端 40px 向左延伸，铺满整个按钮（左右各留 2px）。
   canvo.css 里两个变体本来就有，但 rest 是 width:40px/left:auto、
   hover 是 width:unset/left:2px —— 两端都落在 auto 上，CSS 无法插值 auto，
   而且那个黑块元素的宽度被别处钉死（内联 !important 都改不动）。
   所以黑块改由 <a> 的伪元素来画，只动它的 width，两端都是具体长度。 */
.local-visit-btn { position: relative; }
.local-visit-btn::before {
  content: "";
  position: absolute;
  top: 2px;
  bottom: 2px;
  right: 2px;
  width: 40px;
  border-radius: 100px;
  background: var(--token-419394a1-565d-4952-8ba3-b4f1eb92339c, #050505);
  transition: width .5s cubic-bezier(.22, 1, .36, 1);
  z-index: 0;
}
.local-visit-btn:hover::before,
.local-visit-btn.hover::before { width: calc(100% - 4px); }

/* 原来的黑圆退成透明容器，只负责给箭头定位；文字与箭头压在伪元素之上 */
/* 黑块交给伪元素后，这里只当箭头的定位容器。
   容器 40px、图标 20px，右内边距要 (40-20)/2 = 10px 才居中
   （源站是 16px 图标配 12px，放大图标后必须同步改）。 */
.local-visit-btn .framer-4o639u {
  background: transparent !important;
  padding-right: 10px !important;
  z-index: 1;
}
.local-visit-btn .framer-i0sywo { position: relative; z-index: 1; }

/* 箭头。容器是 flex-end + padding-right:12px，黑块变宽时箭头自己钉在右侧不动。 */
.local-visit-icon {
  position: relative;
  z-index: 1;
  width: 20px !important;
  height: 20px !important;
  flex: none;
  color: #fff;
}
.local-visit-icon svg {
  position: absolute;
  inset: 0;
  width: 20px;
  height: 20px;
  transition: transform .5s cubic-bezier(.22, 1, .36, 1),
              opacity   .34s linear;
}
.local-visit-icon svg:nth-of-type(2) { transform: translateX(-140%); opacity: 0; }
.local-visit-btn:hover .local-visit-icon svg:nth-of-type(1),
.local-visit-btn.hover .local-visit-icon svg:nth-of-type(1) { transform: translateX(140%); opacity: 0; }
.local-visit-btn:hover .local-visit-icon svg:nth-of-type(2),
.local-visit-btn.hover .local-visit-icon svg:nth-of-type(2) { transform: none; opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .local-visit-btn::before,
  .local-visit-icon svg,
  .local-skill-icon svg { transition: none !important; }
}

/* Recording layout follows its section: full-frame demos, a compact cap crop,
   and a bottom-aligned resize demo inside the Other Designs frame. */
.framer-ghRYx .local-recording-media { height: auto; aspect-ratio: 4 / 3; }
.framer-ghRYx .local-vid-wide { max-width: 100%; }
.framer-ghRYx .local-media-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: 32px;
  width: 100%;
  min-width: 0;
  order: 0;
}
.framer-ghRYx .local-media-copy {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}
.framer-ghRYx .local-media-copy > div {
  width: 100%;
  height: auto;
  min-width: 0;
  order: 0;
}
.framer-ghRYx .local-media-visual { width: 100%; min-width: 0; }
/* In 4.2 the editable-plan explanation stacks above the video so the recording
   gets the whole column. Beside it the video was 502px wide — a 26% downscale of
   the 1920px source, which left the plan card's prompt text unreadable. */
.framer-ghRYx .framer-13y32dm.local-plan-flow > * { order: 0; }
@media (min-width: 1200px) {
  .framer-ghRYx .local-plan-flow .local-media-row {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* The 4:3 source spends its top band on the project bar and idle canvas, so 4.2
   crops the recording to 16:9 and holds the bottom — the plan card stays whole. */
.framer-ghRYx .local-plan-flow .local-recording-media video {
  object-position: center 85%;
}

/* 4.2: the prepared-node path, with annotations outside the untouched screenshot. */
.framer-ghRYx .local-prepared-figure {
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  container-type: inline-size;
  font-family: "Inter Display", Inter, system-ui, sans-serif;
}
.local-prepared-diagram { position: relative; width: 100%; aspect-ratio: 840 / 310; }
.local-prepared-picture { position: relative; top: 5.16129%; width: 57.142857%; }
.local-prepared-picture img { display: block; width: 100%; height: auto; border-radius: 12px; }
.local-prepared-leaders { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.local-prepared-caption { position: absolute; inset: 0; }
.local-prepared-notes { margin: 0; padding: 0; list-style: none; }
.local-prepared-note {
  position: absolute;
  left: 67.857143%;
  width: 32.142857%;
  box-sizing: border-box;
  padding: 12px 14px;
  transform: translateY(-50%);
  border: 1px solid #d7cdec;
  border-radius: 10px;
  background: #f2eefb;
  color: #65558a;
  font-size: 14px;
  line-height: 1.55;
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.local-prepared-note-change { top: 48.387097%; }
.local-prepared-note-undo { top: 14.516129%; }
.local-prepared-note-generate { top: 82.258065%; }
.local-prepared-pin, .local-prepared-number { display: none; }

/* Keep the screenshot readable when a side annotation column would make it tiny. */
@container (max-width: 699.98px) {
  .local-prepared-diagram { aspect-ratio: auto; }
  .local-prepared-picture { top: 0; width: min(100%, 440px); margin: 0 auto; }
  .local-prepared-leaders { display: none; }
  .local-prepared-caption { position: static; margin-top: 16px; }
  .local-prepared-notes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
  .local-prepared-note { position: static; width: auto; padding: 12px; transform: none; }
  .local-prepared-pin, .local-prepared-number {
    display: grid;
    place-items: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #8c73ca;
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
  }
  .local-prepared-number { margin-bottom: 8px; }
  .local-prepared-pin { position: absolute; transform: translate(-50%, -50%); box-shadow: 0 0 0 2px #f8fafc; }
  .local-prepared-pin-change { left: 93.3%; top: 49.92%; }
  .local-prepared-pin-params { left: 51.8%; top: 91.2%; }
  .local-prepared-pin-undo { left: 92.5%; top: 8.75%; }
  .local-prepared-pin-generate { left: 95.5%; top: 91.3%; }
}
@container (max-width: 479.98px) {
  .local-prepared-notes { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .local-prepared-note { display: flex; align-items: flex-start; gap: 10px; }
  .local-prepared-number { flex: 0 0 20px; margin: 1px 0 0; }
}

.framer-ghRYx .local-cap-media {
  aspect-ratio: 3 / 1;
  border-radius: 16px;
  overflow: hidden;
}
.local-cap-media video { object-fit: cover; object-position: 50% 75%; }
.framer-ghRYx .local-resize-media { height: 277px; aspect-ratio: auto; }
.local-resize-media video { object-fit: cover; object-position: center bottom; }

@media (max-width: 1199.98px) {
  .framer-ghRYx .local-media-row { grid-template-columns: minmax(0, 1fr); gap: 24px; }
}
@media (max-width: 809.98px) {
  .framer-ghRYx .local-resize-media { height: auto; aspect-ratio: 16 / 9; }
}

/* 4.3 的「方案」卡。这一栏靠 flex order 排版（0…12 依次占满），
   而这张卡是从 4.2 复制过来的，本身没有 order —— 不指定会掉到 order:0，
   整张卡跑到小节最前面。 */

/* Keep the paired 5.1 screenshots equal despite their different source sizes. */
.framer-ghRYx .local-composer-media {
  height: auto;
  aspect-ratio: 1820 / 1534;
  overflow: hidden;
}

/* 5.2 compares the popover screenshot with the inline-parameter recording.
   Equal frames keep labels and captions aligned while showing both in full. */
.framer-ghRYx .local-composer-compare,
.framer-ghRYx .local-s42-compare { align-items: flex-start; }
.framer-ghRYx :is(.local-composer-compare, .local-s42-compare)
  :is(.framer-3y5v59, .framer-1ffb6id) .framer-text {
  text-align: center;
}
.framer-ghRYx .local-param-media {
  border-radius: 16px;
  overflow: hidden;
  background: #eceef1;
}
.framer-ghRYx .local-param-popover { background: #0d0d0d; }

/* Reserved media slots elsewhere remain collapsed until content is supplied. */
.local-slot { display: block; width: 100%; height: 0; }

/* 4.3 触及上限时那张确认卡。原来这里是一段用 HTML 排的对话演示：Agent 用文字
   复述额度不够，再让用户自己去别处调。现在换成产品里那张卡本身 —— 拒绝之后
   不经过转述，需要多少、当前上限、调完还剩多少都在卡上，用户就地处理完。
   order:11 沿用旧块的位置：这一栏在 ≥1400px 时靠 flex order 排版，
   不写 order 会掉到 0 那一组、跑到小节最前面。 */
/* 4.3 的一组对照：左边是撞上上限之后（对话里就地处理的确认卡），
   右边是这道闸设在哪（设置里的单轮上限录屏）。两块各自带图注，
   脱离正文也读得懂。整组紧跟「我加入了单轮生成上限」那段。
   order 只在 ≥1400px 生效 —— 这一栏宽屏靠 flex order 排版，
   9 夹在方案段(8)与细节说明框(10)之间；窄屏走 DOM 顺序，不要写死 order。 */
.framer-ghRYx .local-cap-pair {
  flex: none;
  width: 100%;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: 14px;
  padding: 8px 0;
}
@media (min-width: 1400px) {
  .framer-ghRYx .local-cap-pair { order: 9; }
}
.local-cap-pair .local-cap-item { margin: 0; min-width: 0; }

/* 两块统一到卡图的原始比例（1079 : 724）。录屏源是 4:3，本来就靠 cover 裁着显示，
   跟着卡图走不会比现在裁得更多；比例一致，两块才像一组而不是两张随手摆的图。 */
.local-cap-pair .local-cap-item > img,
.local-cap-pair .local-cap-item .framer-jft23r {
  aspect-ratio: 1079 / 724;
  width: 100%;
  max-width: 100%;
  height: auto;
  border-radius: 12px;
  overflow: hidden;
}
.local-cap-pair .local-cap-item > img { object-fit: cover; }

/* 图注与正文同字号，居中对齐各自的图。 */
.local-cap-pair figcaption {
  --framer-text-color: var(--token-3175e621-00d0-4a31-966e-23433a978eb9, rgba(12, 19, 27, .6));
  color: var(--framer-text-color);
  margin-top: 12px;
  text-align: center;
  font-size: 16px;
  line-height: 1.6;
}
.local-cap-item img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
}

/* 窄屏两列会把卡上的文字压到看不清，改成上下。 */
@media (max-width: 809.98px) {
  .framer-ghRYx .local-cap-pair { grid-template-columns: 1fr; gap: 24px; }
}

/* ── 4.3 的「细节说明」框 ─────────────────────────────────────────────
   这一节的主线是 问题 → 方案 → 兜底。「为什么按整轮算，而不是按单次算」
   是支撑方案的一层推理：放进正文会把三段主线撑成四段，删掉又丢了这节
   最技术的一段。所以降一级 —— 左侧竖线 + 浅底，读者跳过它不影响主线，
   愿意读的能拿到理由。

   卡片类的组件（提问卡、方案卡）用的是站内那套圆角描边卡，这里刻意不用：
   那套是「结论」的形状，这段是注解，视觉重量必须比它们轻一档。 */
.framer-ghRYx .local-note {
  flex: none;
  width: 100%;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 20px;
  border-left: 2px solid var(--token-c4ece689-c50c-4150-9ac6-a1501e869801, rgba(127, 108, 246, 0.6));
  border-radius: 0 8px 8px 0;
  background: var(--token-5977f71f-2f3d-47ea-9060-b0d7206223d8, rgb(248, 250, 252));
}
/* 标题与正文同字号，靠墨色分层：标题用满墨，正文是站内正文的 60% 墨。
   不用小标签那一档字号，也不用紫色 —— 紫色在这一页是「方案 / 取舍」
   两枚结论标签的专属色，注解借了会跟它们抢同一级。 */
.local-note .local-note-t {
  color: var(--token-8056d279-4388-496c-b0ab-8ec93edb0b33, rgb(12, 19, 27));
}

/* 这一栏只在 ≥1400px 时改用 flex order 排版（0…12 依次占满），窄屏走 DOM 顺序。
   录屏原本是 order:10（canvo.css），注解框排在它后面 —— 先看见界面长什么样，
   再读为什么这么算。两个 order 在这里对调：录屏 9，注解 10。 */
@media (min-width: 1400px) {
  .framer-ghRYx .local-note { order: 10; }
}

/* Supporting screenshot grids follow the section body. */
.framer-ghRYx .local-shots {
  order: 12;
  flex: none;
  width: 100%;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
/* 4.1 用同一套待补样式，只是两格：左边对话里的工作状态，右边输入区上方的
   状态条。这一节原来在这儿留的是零高度的 .local-slot，占位可见之后就用不上了。
   order 沿用上面的 12 —— 4.1 那一栏正文最大是 8（≥1400px 才生效），
   12 在两个断点下都落在正文后面。 */
.framer-ghRYx .local-shots-2 { grid-template-columns: repeat(2, 1fr); }

.local-shots .local-shot { margin: 0; }
.local-shots .local-shot-frame {
  aspect-ratio: 4 / 3;
  border: 1px dashed rgba(12, 19, 27, .22);
  border-radius: 12px;
  background: #fbfdff;
}
/* 同 4.3 的图注：正文字号，靠 60% 墨色退到正文之后，不再降一档字号。 */
.local-shots figcaption {
  margin-top: 8px;
  font-family: "Inter Display", Inter, system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  color: rgba(12, 19, 27, .6);
}

/* 窄屏三格并排每格不到 100px，状态之间的差别就看不出来了，改成竖排。 */
@media (max-width: 809.98px) {
  .framer-ghRYx .local-shots { grid-template-columns: 1fr; }
}

/* Other Designs 第一条「输入区尺寸可调」的录屏。
   这一栏原本装的是 Framer 的画廊组件（自带背景与圆角），换成一段裸录屏后
   要自己补上底和圆角，否则视频四角是直的、跟右边几条对不齐。 */
.framer-ghRYx .local-od-media {
  border-radius: 16px;
  overflow: hidden;
  background: var(--token-5977f71f-2f3d-47ea-9060-b0d7206223d8, rgb(248, 250, 252));
}

/* Other Designs 第二条：预览与原图按需切换。
   出图工具生成完整线稿和四处英文短标，容器按图片比例自然展开。 */
.framer-ghRYx .local-od-figure {
  height: auto;
}
.local-od-figure img { display: block; width: 100%; height: auto; }

/* 03 Design Strategy：面板复用原组件的 cardHeader / cardDesc / emphasis，
   字号、编号、段落间距及淡入沿用 canvo.css，仅补静态页交互和章节引用。 */
.local-ds-highlight {
  background-color: rgb(255, 228, 92);
  color: var(--token-8056d279-4388-496c-b0ab-8ec93edb0b33, rgb(12, 19, 27));
  border-radius: 4px;
  padding: 2px 4px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
/* 组件宽度跟随章节，避免中文提示与详情的内容宽度改变金字塔尺寸和位置。 */
#designstrategy .framer-1n4b9p9-container { width: 100%; min-width: 0; }
.ds_R6ujkelp .strategyContent { min-width: 0; }
.ds_R6ujkelp .contentViewport { display: grid; align-items: center; height: auto; min-height: 260px; overflow: visible; }
.ds_R6ujkelp .local-ds-panel[hidden] { display: none; }
.local-ds-footer { margin-top: 12px; }
.local-ds-hint { display: flex; align-items: flex-start; gap: 7px; margin: 0; color: var(--muted); font-size: 12px; line-height: 1.7; }
.local-ds-hint > svg { flex: none; width: 17px; height: 17px; margin-top: 2px; opacity: .6; }
.ds_R6ujkelp .local-tier.is-active { filter: brightness(1.08); }
/* 鼠标点击不显示浏览器默认外框；键盘聚焦沿层级轮廓显示紫色描边。 */
.ds_R6ujkelp .local-tier { transition-property: filter; }
.ds_R6ujkelp .local-tier:focus { outline: none; }
.ds_R6ujkelp .local-tier:focus-visible { stroke: rgb(127, 108, 246); stroke-width: 3; }
.local-ds-maps { margin: 24px 0 0; padding: 0; list-style: none; display: grid; gap: 8px; }
/* 章节引用排在结论之后，作为辅助信息。 */
.local-ds-map { display: flex; gap: 8px; align-items: baseline; font-size: 12px; line-height: 1.6; }
.local-ds-map b {
  flex: 0 0 auto; font-weight: 500;
  color: var(--token-3175e621-00d0-4a31-966e-23433a978eb9, rgba(12, 19, 27, .6));
  font-variant-numeric: tabular-nums;
}
.local-ds-map span { color: var(--token-3175e621-00d0-4a31-966e-23433a978eb9, rgba(12, 19, 27, .72)); }
/* 章节引用可点击，跳到 04 里对应的小节。 */
.local-ds-link {
  display: flex; gap: 8px; align-items: baseline;
  text-decoration: underline; text-underline-offset: 4px;
  text-decoration-color: rgba(127, 108, 246, .35);
  transition: text-decoration-color .2s ease;
}
.local-ds-link b, .local-ds-link span { transition: color .2s ease; }
.local-ds-link:hover { text-decoration-color: rgb(127, 108, 246); }
.local-ds-link:hover b, .local-ds-link:hover span {
  color: var(--token-7cbca512-b5c6-4555-b418-4fbe2df8fc9a, rgb(127, 108, 246));
}
.local-ds-link:focus { outline: none; }
.local-ds-link:focus-visible {
  outline: 2px solid rgb(127, 108, 246); outline-offset: 4px; border-radius: 3px;
}
/* 04 小节作为跳转目标，留出顶部余量。 */
.local-decision { scroll-margin-top: 48px; }
@media (prefers-reduced-motion: reduce) {
  .ds_R6ujkelp .local-ds-panel { animation: none; opacity: 1; transform: none; }
  .ds_R6ujkelp .local-tier { transition: none; }
  .local-ds-link, .local-ds-link b, .local-ds-link span { transition: none; }
}

/* 02 三张问题卡：只留「Problem N + 结论标题」。
   中间那栏「按操作者设计 / ↓ 对审批者失效成」已撤掉 —— 那三句在图下面的
   引言里已经按同样的顺序说过一遍，卡片里再摆一次是重复。
   卡片是 gap:0 的 flex 列，原来的间距是靠灰块的外边距撑的，撤掉之后
   由标题自己接管。三张卡的标题容器 class 各不相同（Framer 按原文案命名），
   统一挂 .local-pc-title 定位。 */
.framer-ghRYx .local-pc-title { margin-top: 16px; }

/* 02 卡组的高度链。
   Framer 把这一节的高度逐级写死了：卡片 349px、卡组 288px、外层 1128px，
   而且外层是 overflow:clip、整节 overflow:hidden —— 内容一变长既不会把
   后面的元素推下去，也不会撑开容器，而是直接压在下一段文字上。
   所以不是给卡片补高度，是把这条链上的高度交还给内容。 */
.framer-ghRYx [data-framer-name="3 problems"] {
  height: auto;
  /* 原站是死高 288px + 卡内 space-between：Problem N 和标题之间那段留白
     是高度撑出来的，不是写死的间距。死高换成最小高度 —— 留白照旧，
     中文标题比英文长的时候卡片还能自己长高，不会压到下一段。 */
  min-height: 288px;
  align-items: stretch;   /* 原为 center，三张卡各自居中、高度不齐 */
}
.framer-ghRYx [data-framer-name="3 problems"] > div[data-border] {
  height: auto;
  justify-content: space-between;   /* 标题贴卡片底，空当留给上面 */
}

/* 02 角色变化：已选的英文手绘图按原比例随正文栏展示。 */
/* Framer 这一节的容器都是 flex 且不拉伸子元素：本地新增的块不写 width
   就会缩到 0 或缩到内容宽。凡是往这些容器里插的块，都要显式撑满。 */
.local-roleshift {
  display: block;
  align-self: center; flex: 0 0 auto;
  width: 80%;
  margin: 20px auto 8px;
}
.local-roleshift img { display: block; width: 100%; height: auto; }
@media (max-width: 599.98px) {
  .local-roleshift { width: 100%; }
}

/* 01 About Canvo: retain the chapter typography, with one responsive copy tree. */
#background .local-about-block {
  width: 100%;
  min-width: 0;
  align-items: stretch;
  gap: 24px;
  overflow: visible;
}
#background .local-about-block > h3,
#background .local-about-block > p { width: 100%; margin: 0; }
/* 职责标签：Canvo 1.2 与商业影像 02 共用。文字取页面强调色 token，
   底色走 --local-tag-bg（默认 Canvo 紫的浅底，其他页面在各自样式里覆盖）。 */
.local-about-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 9px;
  width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
}
.local-about-tags li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: 100%;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--local-tag-bg, rgb(217, 209, 252));
  color: var(--token-7cbca512-b5c6-4555-b418-4fbe2df8fc9a, rgb(127, 108, 246));
  font-family: "Inter Display", Inter, system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}
@media (max-width: 809.98px) {
  .local-about-tags li { font-size: 14px; }
}

/* 06 Building with AI: shared prose rhythm, two case illustrations, one design-system board. */
.framer-ghRYx #vibecoding.local-engineering {
  align-items: stretch;
  overflow: visible;
}
#vibecoding .local-engineering-intro {
  display: flex;
  flex-direction: column;
  gap: var(--case-prose-gap);
  width: 100%;
  min-width: 0;
}
#vibecoding .local-engineering-sections {
  display: flex;
  flex-direction: column;
  gap: 64px;
  width: 100%;
  min-width: 0;
  margin-top: 16px;
}
#vibecoding .local-engineering-block {
  display: flex;
  flex-direction: column;
  gap: 24px;
  width: 100%;
  min-width: 0;
}
#vibecoding .local-engineering-intro > p,
#vibecoding .local-engineering-block > h3,
#vibecoding .local-engineering-block > p {
  width: 100%;
  margin: 0;
}
#vibecoding .local-engineering-figure {
  width: 100%;
  max-width: 1100px;
  margin: 8px auto;
}
/* The link, not the image, carries the radius, so the corners are actually clipped. */
#vibecoding .local-engineering-figure > a { display: block; border-radius: 12px; overflow: hidden; }
#vibecoding .local-engineering-figure img { display: block; width: 100%; height: auto; border-radius: inherit; }
#vibecoding .local-engineering-figure > a:focus-visible,
.local-skill-link a:focus-visible { outline: 2px solid var(--token-7cbca512-b5c6-4555-b418-4fbe2df8fc9a, #7f6cf6); outline-offset: 4px; }

/* 案例正文里的「在 GitHub 查看…」链接：Canvo 6.2 与商业影像 03 共用。颜色取页面强调色 token。 */
.local-skill-link { margin: 4px 0 0; }
.local-skill-link a {
  display: inline-flex;
  align-items: center;
  gap: .3em;
  color: var(--token-7cbca512-b5c6-4555-b418-4fbe2df8fc9a, rgb(127, 108, 246));
  font-size: inherit;
  line-height: inherit;
  text-decoration: none;
  overflow-wrap: anywhere;
}
/* The underline stays on the words; the arrow sits outside it. */
.local-skill-link a > span:first-child {
  border-bottom: 1px solid transparent;
  transition: border-color .2s ease;
}
.local-skill-link a:hover > span:first-child { border-bottom-color: currentColor; }

/* Twin-arrow swap on the same curve as the canvoai.com button, rolled vertically.
   The box clips, and the arrows only translate — no cross-fade, so exactly one
   arrow is ever inside the frame instead of two ghosting past each other. */
.local-skill-icon {
  position: relative;
  width: 1em;
  height: 1em;
  flex: none;
  overflow: hidden;
}
.local-skill-icon svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transition: transform .5s cubic-bezier(.22, 1, .36, 1);
}
.local-skill-icon svg:nth-of-type(2) { transform: translateY(100%); }
.local-skill-link a:hover .local-skill-icon svg:nth-of-type(1) { transform: translateY(-100%); }
.local-skill-link a:hover .local-skill-icon svg:nth-of-type(2) { transform: none; }

/* A single white board displays the palette and two uses of the actual type scale. */
#vibecoding .local-ds {
  width: 100%;
  min-width: 0;
  margin: 16px 0 12px;
  color: #18181b;
  font-family: Inter, "Inter Display", "PingFang SC", "Microsoft YaHei", sans-serif;
}
#vibecoding .local-ds *,
#vibecoding .local-token-check * { box-sizing: border-box; }
#vibecoding .local-ds h4 { margin: 0 0 24px; font-size: 18px; line-height: 1.5; font-weight: 500; }
/* Keep the approved code-panel treatment and body-size reflection. */
#vibecoding .local-token-check { width: 100%; min-width: 0; margin-top: 8px; }
#vibecoding .local-token-check-intro p { margin: 0; font-size: 16px; line-height: 1.6; color: #6b7078; }
#vibecoding .local-token-check-intro h4 { margin: 8px 0 14px; font-size: 20px; font-weight: 500; line-height: 1.4; color: #0c131b; }
#vibecoding .local-token-code { width: 100%; min-width: 0; margin: 24px 0 0; border: 1px solid #e0e2e7; border-radius: 16px; overflow: hidden; background: #fff; }
#vibecoding .local-token-code figcaption { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; padding: 20px 24px 12px; color: #525866; font: 12px/1.5 "Inter Display", Inter, system-ui, sans-serif; }
#vibecoding .local-token-code-file { display: inline-flex; align-items: center; gap: 10px; font-size: 16px; line-height: 1.6; }
#vibecoding .local-token-code-file svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
#vibecoding .local-token-code figcaption > span:last-child { color: #707784; }
#vibecoding .local-token-code pre { margin: 0; padding: 16px 0 24px; overflow-x: auto; color: #394150; font: 12px/2 "SFMono-Regular", Consolas, "Liberation Mono", monospace; tab-size: 2; }
#vibecoding .local-token-code pre:focus-visible { outline: 2px solid #7f6cf6; outline-offset: -3px; }
#vibecoding .local-token-code code { display: block; width: max-content; min-width: 100%; font: inherit; }
#vibecoding .local-code-line { display: inline-block; min-width: 100%; padding: 0 20px 0 0; }
#vibecoding .local-code-gutter { display: inline-block; width: 48px; margin-right: 16px; text-align: right; color: #88919d; user-select: none; }
#vibecoding .local-code-fn { color: #6d48a3; }
#vibecoding .local-code-string { color: #267653; }
#vibecoding .local-token-check-note { margin: 16px 0 0; color: #6b7078; font-size: 16px; line-height: 1.6; }
@media (max-width: 809.98px) {
  #vibecoding .local-engineering-sections { gap: 48px; }

}
@media (max-width: 599.98px) {
  #vibecoding .local-token-code figcaption { padding: 18px 18px 10px; }
  #vibecoding .local-code-gutter { width: 28px; margin-right: 12px; }
}


/* ── 底部联系条 · hover 抬起 ─────────────────────────────────
   原状态：四个 chip 的 transition 是 `all`，没有时长，hover 没有任何
   过渡可插值，抬起是瞬跳。改用 transitions.dev 的 avatar group hover：
   悬停项抬起并微放大，左右邻居按幂次衰减跟着抬一点，移出时用
   过冲弹簧回位。方向不同用不同缓动，由 local.js 在写变量前内联设置。
   ───────────────────────────────────────────────────────── */
:root {
  --avatar-lift: -4px;
  --avatar-dur: 320ms;
  --avatar-scale: 1.05;
  --avatar-falloff: 0.45;
  --avatar-ease-in: cubic-bezier(0.22, 1, 0.36, 1);
  --avatar-ease-out: cubic-bezier(0.34, 3.85, 0.64, 1);
}

/* Hover-spring transition only — bring your own avatar/chip
   styling (size, shape, border, stacking, background). */
.t-avatar {
  transform-origin: center;
  /* translateY before scale so scale doesn't amplify the lift offset. */
  transform:
    translateY(var(--shift, 0px))
    scale(var(--scale-active, 1));
  transition: transform var(--avatar-dur) var(--avatar-ease-in);
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .t-avatar { transition: none !important; transform: none !important; }
}

/* 抬起会超出行盒。Framer 给这一行写了 overflow:hidden，行高又正好等于
   chip 高度，不解除就会把抬起后露出来的上边框切掉。同名类选择器权重相同，
   谁在后面谁赢，顺序不可控，所以这里用 !important 定死。 */
.t-avatar-group { overflow: visible !important; }


/* ── 精选项目卡：hover 浮出淡阴影 ──────────────────────────
   描边保留（2026-09-11 方铧要求撤回去描边那版）。

   静止态撤掉了原有的三层投影，卡片是平的；hover 才浮出一层淡的。
   投影写在 Framer 的行内 style 上，普通规则赢不过行内，所以用
   !important 压掉。曲线和底部联系条是同一条，首页只保持一种动效语言。
   ──────────────────────────────────────────────────────── */
[data-framer-name="Thumbnail"] {
  box-shadow: none !important;
  transition: box-shadow 320ms var(--avatar-ease-in) !important;
}

[data-framer-name="Thumbnail"]:hover,
[data-framer-name="Thumbnail"]:focus-within {
  box-shadow:
    0 2px 8px -4px rgba(12, 19, 27, 0.08),
    0 16px 32px -12px rgba(12, 19, 27, 0.12) !important;
}

@media (prefers-reduced-motion: reduce) {
  [data-framer-name="Thumbnail"] { transition: none !important; }
}

/* ────────────────────────────────────────────────────────
   首页第三张项目牌指向 /commercial。前两张 Framer 本来就是链接，
   生成的 CSS 里带 text-decoration:none；第三张原稿是 div，
   改成 <a> 之后浏览器默认的下划线就冒了出来，标题、描述和
   三枚标签全被划一道。按前两张的写法补上同一条声明。
   ──────────────────────────────────────────────────────── */
a.framer-2BuYz { text-decoration: none; }

/* Commercial work: reuse the reel posters in one landscape and one portrait device. */
.framer-H10g5 #project { height: auto !important; }
.framer-1t4x343-container:has(> .commercial-project-card),
a.commercial-project-card { height: auto !important; }
.commercial-project-card .framer-166s48u {
  height: auto !important;
  flex: none !important;
  padding: 32px 24px 24px;
  background: #fff !important;
}
.commercial-project-card .framer-12fp15r { padding: 0 !important; gap: 12px !important; }
.commercial-project-card .framer-9pznv3 { width: 100% !important; white-space: normal !important; }
.commercial-cover {
  --cover-gap: 24px;
  --frame-inset: 6px;
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: var(--cover-gap);
  container-type: inline-size;
  order: 3;
  flex: none;
  width: min(88%, 540px);
  margin: 18px auto 0;
}
.commercial-device {
  /* Share screen height, allowing for both bezels and the gap; preserve each poster ratio. */
  --screen-height: calc((100cqw - var(--cover-gap) - 4 * var(--frame-inset)) / 2.340693163);
  position: relative;
  flex: none;
  box-sizing: border-box;
  width: calc(var(--screen-height) * var(--screen-ratio) + 2 * var(--frame-inset));
  height: calc(var(--screen-height) + 2 * var(--frame-inset));
  padding: calc(var(--frame-inset) - 1px);
  border: 1px solid #52565e;
  border-radius: 20px;
  background: #15181d;
  box-shadow: none;
}
.commercial-device img { display: block; width: 100%; height: 100%; object-fit: contain; border-radius: 14px; }
.commercial-device--landscape { --screen-ratio: 1.778656126; }
.commercial-device--portrait { --screen-ratio: 0.562037037; }
.commercial-device::after {
  content: "";
  position: absolute;
  width: 16%;
  height: 4px;
  border-radius: 8px;
  background: #fff9;
  bottom: 8px;
  left: 42%;
}
@media (max-width: 809.98px) {
  .commercial-project-card .framer-166s48u { padding: 28px 18px 22px; }
  .commercial-cover { --cover-gap: 16px; --frame-inset: 4px; margin-top: 12px; }
  .commercial-device { border-radius: 13px; }
  .commercial-device img { border-radius: 9px; }
  .commercial-device::after { height: 2px; bottom: 5px; }
}

/* 小节分隔线（Canvo 1.2 / 4.2…、商业影像 3.2…）：放在同一章里第二个起的小节标题之前。
   做成独立的 <hr> 而不是给小节加 border/padding：Canvo 有几块 Framer 容器高度写死、
   overflow:clip，改它们的内边距会裁掉内容。线上下的留白来自父容器的 gap（32px）；
   gap 不是 32px 的地方用 --rule-offset 补齐。 */
.local-subsection-rule {
  flex: none;
  align-self: stretch;
  width: 100%;
  height: 1px;
  margin: var(--rule-offset, 0) 0;
  padding: 0;
  border: 0;
  /* 线色取页面主题色：Canvo 紫、商业影像蓝。 */
  background: var(--token-7cbca512-b5c6-4555-b418-4fbe2df8fc9a, rgb(127, 108, 246));
}
/* 父容器 gap 不是 32px 的两处：06 反思是 24px；07 两篇文章之间桌面 64px、窄屏 48px。 */
.local-subsection-rule--gap24 { --rule-offset: 8px; }
.local-subsection-rule--engineering { --rule-offset: -32px; }
@media (max-width: 809.98px) {
  .local-subsection-rule--engineering { --rule-offset: -16px; }
}
/* 1.2 与 6.2 的小节在 ≥1400px 时被 Framer 排到 order:2，线要跟着排在它前面。 */
@media (min-width: 1400px) {
  .local-subsection-rule--order2 { order: 2; }
}
