html {
   scroll-behavior: smooth;
}

.app__container {
   grid-template-columns: 244px minmax(0, 1fr);
}

.app__aside-logo {
   width: 125px;
   height: 46px;
}

.app__aside-logo img,
.app__aside-body-logo img {
   display: block;
   width: 125px;
   max-width: 100%;
   height: auto;
}

.notes-brand-lockup {
   display: flex;
   flex-direction: column;
   align-items: center;
   flex: 0 0 auto;
   margin-left: auto;
   margin-right: auto;
}

.app__aside-body-logo img {
   margin: 0 auto;
}

.app__aside-body-logo {
   margin-bottom: 0;
   text-align: center;
}

.notes-brand-slogan {
   margin-top: 14px;
   color: transparent;
   font-size: 15px;
   font-weight: 600;
   line-height: 24px;
   text-align: center;
   background: linear-gradient(90deg, #9d8cff, #73c9ef);
   -webkit-background-clip: text;
   background-clip: text;
}

.notes-brand-slogan span {
   display: block;
}

@media (min-width: 769px) {
   .app__aside-logo {
      margin: 0 auto;
   }
}

.notes-home-link {
   text-decoration: none;
   white-space: nowrap;
}

.notes-nav .app__aside-ai-link {
   width: 100%;
   min-height: 38px;
   margin-bottom: 8px;
   padding: 9px 12px;
   font-size: 18px;
   line-height: 1.45;
   text-align: left;
   cursor: pointer;
}

.notes-nav {
   padding-top: 0 !important;
}

.notes-nav .app__aside-ai-link span {
   min-width: 0;
   overflow-wrap: anywhere;
}

.notes-site-credit {
   flex: 0 0 auto;
   display: flex;
   align-items: center;
   justify-content: center;
   gap: 8px;
   width: 100%;
   padding: 14px 20px 0;
   color: #fff;
   font-size: 13px;
   font-weight: 600;
   letter-spacing: .04em;
   text-align: center;
}

.notes-site-credit img {
   flex: 0 0 24px;
   width: 24px;
   height: 24px;
   object-fit: contain;
}

.notes-category-group {
   margin-left: 8px !important;
}

.notes-category-button {
   position: relative;
   padding-right: 34px !important;
}

.notes-category-button::after {
   content: "";
   position: absolute;
   top: 50%;
   right: 12px;
   width: 12px;
   height: 7px;
   background: url(../img/icons/chevron.svg) center/contain no-repeat;
   transform: translateY(-50%) rotate(-90deg);
   transition: transform .2s ease;
}

.notes-category-group.opened .notes-category-button::after {
   transform: translateY(-50%) rotate(0);
}

.notes-chapter-list {
   display: none;
   margin: -2px 0 10px;
   padding: 2px 0 4px 14px;
   border-left: 1px solid rgba(130, 128, 238, .34);
}

.notes-category-group.opened .notes-chapter-list {
   display: block;
}

.notes-chapter-list li {
   margin-left: 0 !important;
}

.notes-chapter-button {
   width: 100%;
   padding: 7px 10px;
   border-radius: 5px;
   color: rgba(255, 255, 255, .48);
   font-family: Manrope;
   font-size: 18px;
   line-height: 1.45;
   text-align: left;
   cursor: pointer;
   transition: color .2s ease, background .2s ease;
}

.notes-chapter-button:hover {
   color: rgba(255, 255, 255, .82);
   background: rgba(255, 255, 255, .05);
}

.notes-chapter-button.active {
   color: #fff;
   background: rgba(130, 128, 238, .2);
}

.notes-outline__subitem {
   padding-left: 12px !important;
   font-size: 18px !important;
}

.notes-main {
   display: block;
   min-width: 0;
   padding: 0;
   overflow-y: auto;
   overflow-x: hidden;
   scroll-behavior: smooth;
}

.notes-layout {
   position: relative;
   z-index: 2;
   width: min(100%, 1180px);
   margin: 0 auto;
   padding: 56px 48px 100px;
   display: grid;
   grid-template-columns: minmax(0, 760px) 190px;
   justify-content: center;
   gap: 64px;
}

.notes-document {
   min-width: 0;
}

.notes-source-content > :first-child {
   margin-top: 0;
}

.notes-source-content h1 {
   margin-bottom: 32px;
}

.notes-source-content h2,
.notes-source-content h3,
.notes-source-content h4 {
   scroll-margin-top: 90px;
   color: #fff;
}

/*
 * 正文里的三级标题，**`line-height` 必须显式写**。
 *
 * 用户 2026-09-22：「wap 模式下，二级标题的文字上下两行叠在一起」。
 *
 * 根因：这三条规则原来只写了 `font-size`，而 `line-height` 是**继承属性** ——
 * 继承的是**计算值**（不是比例）。祖先某个 14px 的规则写着 `line-height: 1.35`，
 * 算出来 18.9px 一路传下来；h2 自己 28px，行高却还是 18.9px，**两行必然压在一起**。
 *
 * 为什么只有手机上暴露：行高小于字号时，只要标题不换行就看不出异常 ——
 * 桌面 1440 下实测也是 18.9px，只是那几行标题都放得下。
 *
 * `1.35` 是中文标题的常用比例（正文那条是 `1.85`，标题比它紧一档才像标题）。
 * h1 不用管：它有自己的一条行高，实测正常。
 */
.notes-source-content h2 {
   margin: 52px 0 20px;
   font-size: 28px;
   line-height: 1.35;
}

.notes-source-content h3 {
   margin: 36px 0 16px;
   font-size: 22px;
   line-height: 1.35;
}

.notes-source-content h4 {
   margin: 28px 0 14px;
   font-size: 18px;
   line-height: 1.35;
}

.notes-source-content p,
.notes-source-content li {
   color: rgba(255, 255, 255, .74);
   font-size: 16px;
   line-height: 1.85;
}

.notes-source-content p + p {
   margin-top: 14px;
}

.notes-source-content ul,
.notes-source-content ol {
   margin: 18px 0;
   padding-left: 28px;
}

.notes-source-content li + li {
   margin-top: 10px;
}

.notes-source-content a {
   color: #73c9ef;
   text-decoration: underline;
   text-underline-offset: 3px;
}

.notes-source-content img,
.notes-source-content video {
   display: block;
   max-width: 100%;
   height: auto;
   margin: 24px auto;
   border-radius: 8px;
}

/*
 * 「在线咨询」那张横幅（课程正文里，外层是 `<a href="/consult">`）：**撑满正文宽度**。
 *
 * 用户 2026-09-24：「把图放大到正文最大的宽度」。上面那条只给了 `max-width: 100%`，
 * 也就是只挡溢出、不放大 —— 原图 468×101，在一列 760px 的正文里只占一半多。
 *
 * 为什么不给图片自己加 `style`：正文的清洗策略（`packages/contracts` 的
 * `ARTICLE_ALLOWED_ATTRIBUTES`）里 `img` 只允许 `src/alt/width/height`，
 * **`style` 和 `class` 都会被剥掉**，所以只能从 CSS 这侧按外层链接认人。
 * 认 `<a href="/consult">` 而不是认那张图的 `alt` 或文件名 —— 后者是内容里的文案，
 * 改一次文案样式就静默失效。
 *
 * 桌面端的正文列宽是 `.notes-layout` 的 `minmax(0,760px)`；窄屏下容器本来就窄，
 * `width: 100%` 自然跟着缩，不用另写断点。
 */
.notes-source-content a[href="/consult"] img {
   width: 100%;
}

.notes-source-content pre {
   margin: 24px 0;
   padding: 20px 22px;
   overflow-x: auto;
   border: 1px solid rgba(255, 255, 255, .14);
   border-radius: 10px;
   background: rgba(0, 0, 0, .32);
   color: #b9dff2;
   line-height: 1.7;
}

.notes-source-content code {
   padding: 2px 6px;
   border-radius: 4px;
   background: rgba(130, 128, 238, .14);
   color: #c9c2ff;
   font-family: Consolas, "Courier New", monospace;
}

.notes-source-content pre code {
   padding: 0;
   background: transparent;
   color: inherit;
}

.notes-source-content blockquote {
   margin: 24px 0;
   padding: 16px 20px;
   border-left: 3px solid #8280ee;
   background: rgba(130, 128, 238, .1);
}

.notes-source-content table {
   width: 100%;
   margin: 24px 0;
   border-collapse: collapse;
}

.notes-source-content th,
.notes-source-content td {
   padding: 12px 14px;
   border: 1px solid rgba(255, 255, 255, .14);
   color: rgba(255, 255, 255, .72);
   text-align: left;
}

/*
 * ---------- 窄容器（手机）下的正文适配 ----------
 *
 * 这里管两件只在手机上才成立的事：**表格缩到屏幕里**、**标题下的第一张图贴住标题**。
 * 两件事的判定条件都是「正文容器自己有多宽」，不是视口有多宽。
 *
 * ## 为什么用容器查询而不是媒体查询
 *
 * 先写的是 @media (max-width: 767px)：竖屏对了，**手机横屏（844）还是坏的**。
 * 因为视口宽 != 正文宽 —— 844 落在本文件 769-1100 那个区间，被后面那条
 * @media(min-width:769px) 的两列 .notes-layout 压得只剩 302px 正文，
 * 1024 的平板更甚（正文只有 398px）。按视口宽写阈值，要么漏掉横屏，
 * 要么把 768 那种本该正常的也拖下水。按容器实际宽度判断就没有这个歧义。
 *
 * 阈值 560px 是量出来的：768 视口下正文 728px、4 列各 169-202px、行高 96，
 * 本来就正常，不该动它；而 390 竖屏 350px、844 横屏 302px、1024 平板 398px 都挤。
 *
 * ## containment 的副作用：实测没有
 *
 * container-type 会让这个元素成为后代的包含块，理论上会影响绝对/固定定位的后代。
 * 实测正文里这类元素**一个都没有**，而且加上之后各元素的 left/top 逐字不变
 * （只有高度跟着内容变）—— 它只在这一个轴上起作用，不扰动版式。
 */
.notes-source-content {
   container-type: inline-size;
}

@container (max-width: 560px) {
   /*
    * **表格缩到屏幕里，而不是左右滑**（用户 2026-09-22 明确要求：不要横滑）。
    *
    * 手机上的原始症状是**逐字换行**：「1对1指导周期」竖着排成 7 行，
    * 一行正文格撑到 587px 高，完全没法读。两个原因叠在一起：
    *   1. width:100% 把表格压到容器宽（350），4 列各约 87px，
    *      扣掉左右各 14px 内边距只剩 59px —— 一个汉字 14px，一次放不下两个字。
    *   2. 基础规则里还写着 overflow-x: auto，**但它对表格是不生效的**：
    *      overflow 只在块级容器上产生滚动条，而 <table> 的 display 是 table。
    *      那一行是个摆设，也正因为它看着像「已经处理过」，这问题一直没被查。
    *      （那行已删。）
    *
    * 修法：table-layout: fixed 让列宽**均分容器**（不再由内容撑开），
    * 字号与内边距各降一档，换来「整张表一屏放得下」。
    *
    * ⚠️ fixed 布局下**不要再写 white-space: nowrap** —— 那会让每个格子拒绝换行，
    * 列宽被内容顶回去，又变回横滑。这里要的正是让它按规定的列宽换行。
    *
    * 第一列会**自动**保持「每行 10 个字」：shell-fixes.css 里那条
    * `width: 10em`（用户更早的明确要求）在 table-layout: fixed 下才真正生效 ——
    * 在 auto 布局里 width 只是给算法的**建议值**，实测会被内容重算掉。
    * 所以这里不需要再补一条第一列的规则。
    *
    * 实测（390 视口，4 列课程表）。「字数」是**每列每行实际排下的汉字数**，
    * 用 Range 数出来的真实文本行 —— 顺手记两个坑：`td.scrollHeight` 返回的是
    * **整张表**的高度，`td.getBoundingClientRect().height` 返回的是**行高**
    * （同一 tr 里的格子全都等高），两个都量不到「格子里文字排了几行」。
    *
    *   改前（逐字竖排）  表宽 350  scrollW 845  列宽 138/61/63/87   每行 1-2 个字
    *   现在             表宽 350  scrollW 350  列宽 127/74/74/74   5.8/3.4/3.5/2.8 个字
    *
    * 内边距与字号是逐个试出来的：
    *   12px + pad 8/6   整表高 540  列宽 133/72/72/72
    *   12px + pad 6/3   整表高 471  列宽 127/74/74/74   ← 采用（字号不变，矮 13%）
    *   11px + pad 6/4   整表高 471  列宽 119/77/77/77   （字号更小，收益却一样）
    *   10px + pad 6/4   整表高 500  列宽 109/80/80/80   （反而更高：字小了列也没宽多少）
    * 12px 这一档保住了正文字号的可读性，不再往下压。
    *
    * ⚠️ 后三列每行只有 3 个字左右，这是**350px 屏幕放 4 列的物理上限**，不是参数没调好：
    * 350 减去固定 10 个字的第一列（127）只剩 223，三列各 74px，
    * 12px 一个字，扣掉内边距与 emoji 的额外宽度，一行就是 3 个出头。
    * 要更宽只能减少列数或改成纵向卡片，那是内容层的事。
    *
    * 桌面 1440 不命中，逐字不变（表宽 760、列宽 169/213/199/177、行高 96）。
    */
   .notes-source-content table {
      table-layout: fixed;
      width: 100%;
      margin: 20px 0;
   }

   .notes-source-content th,
   .notes-source-content td {
      white-space: normal;
      word-break: break-word;
      padding: 6px 3px;
      font-size: 12px;
      line-height: 1.45;
   }

   /*
    * **标题下的第一张图要贴住标题**（用户 2026-09-22：「wap 模式下正文的标题
    * 和第一个图之间的距离太宽，把这间距去掉」）。
    *
    * 正文顶部实际是 <h1> + <h3><img></h3>，两段空隙叠起来有 60px：
    *   h1 的 margin-bottom 20 与 h3 的 margin-top 36 相邻折叠 → 取大的 36
    *   h3 里面的 img 自己还有 margin-top 24
    * 36 + 24 = 60px。在 390 宽的屏幕上，图看着跟标题不是一回事。
    *
    * 用 :has() 精确锁定「后面紧跟含图块」的 h1，**不去动其它标题**——
    * 正文里 h2/h3 小节之间的留白是正常的排版节奏，不该被一起压掉。
    *
    * h3 自己的 margin-bottom（16px）保留：图和它下面的表格之间要有距离。
    */
   .notes-source-content > h1:first-child:has(+ * > img) {
      margin-bottom: 0;
   }

   /*
    * **正文第一块里的图，上边距也归零。**
    *
    * 案例阅读器的正文顶部是 `<figure><img></figure>` —— 图片在标题**上面**，
    * 与课程阅读器（`<h1>` 在上、图在下）正好相反，所以上面那条「h1 后跟图」的规则
    * 管不到它。而 `.notes-source-content img` 自带 `margin: 24px auto`，
    * 上面那条 `.notes-source-content > :first-child { margin-top: 0 }` 只清掉了
    * `figure` 自己的边距，**清不到里面这张图** ——
    * 实测顶栏底到图片还有 44px（20px 让位余量 + 这张图的 24px）。
    *
    * 用 `> :first-child img` 而不是 `> :first-child > img`：图片可能被包在
    * `<p>` 或 `<a>` 里（不同文章写法不一样），降一层就漏掉。
    */
   .notes-source-content > :first-child img {
      margin-top: 0;
   }

   .notes-source-content > h1:first-child + *:has(> img),
   .notes-source-content > h1:first-child + *:has(> img) > img {
      margin-top: 0;
   }
}

/*
 * **极窄容器下，课程表的第一列要把宽度让出来。**
 *
 * 上面那条 fixed 布局让 shell-fixes.css 的 `width: 10em`（用户更早的明确要求：
 * 每行不超过 10 个字）第一次真正生效。但它生效得太彻底 —— 容器被压到极窄时，
 * 那一列固定吃掉 133px（12px 字号下 10em 加内边距），其余三列就没地方了。
 *
 * 实测 844 横屏正是这种情况：那个视口下正文只有 218px（本文件 769-1100 区间
 * 的既有布局问题 —— `.notes-layout` 被后面那条 @media(min-width:769px) 按两列算，
 * 这点与本次改动无关），10em 占掉 61%，其余三列各剩 28px = **1.3 个字**，
 * 整表还比容器宽 8px，于是又变回横滑 —— 恰好是这次要消掉的东西。
 *
 * 试过写成 `width: min(10em, 36%)` 一次解决，**不行**：`min()` 在这条属性上
 * 被整个忽略掉，第一列退回均分（实测 390 竖屏从 133px 掉到 87px，
 * 每行 6.2 个字），反而把主场景的字数要求弄丢了。
 *
 * 所以拆成两个查询：**宽的那档维持 10 个字，窄到 300px 以下才让位给均分**。
 * 阈值 300 是量出来的 —— 390 竖屏的正文是 350、1024 平板是 398，都还在 10 个字；
 * 只有 218 那种真正放不下四列的容器才触发。
 */
@container (max-width: 300px) {
   .notes-source-content--course > table:first-of-type tr > *:first-child {
      width: auto;
   }
}

.notes-source-content iframe {
   width: 100%;
   min-height: calc(100vh - 180px);
   border: 1px solid rgba(255, 255, 255, .14);
   border-radius: 10px;
   background: #fff;
}

.notes-loading,
.notes-error {
   padding: 60px 0;
   color: rgba(255, 255, 255, .58);
   font-size: 16px;
}

.notes-document__icon {
   width: 52px;
   height: 52px;
   margin-bottom: 28px;
   display: flex;
   align-items: center;
   justify-content: center;
   border: 1px solid rgba(255, 255, 255, .22);
   border-radius: 10px;
   background: rgba(255, 255, 255, .08);
}

.notes-document__kicker {
   margin-bottom: 14px;
   color: #9d8cff;
   font-size: 12px;
   font-weight: 600;
   letter-spacing: .08em;
   text-transform: uppercase;
}

.notes-document h1 {
   margin-bottom: 20px;
   font-size: clamp(34px, 4vw, 52px);
   line-height: 1.16;
   letter-spacing: -.035em;
}

.notes-document__lead {
   max-width: 700px;
   color: rgba(255, 255, 255, .72);
   font-size: 18px;
   line-height: 1.8;
}

.notes-document__meta {
   margin: 24px 0 56px;
   padding-bottom: 24px;
   border-bottom: 1px solid rgba(255, 255, 255, .12);
   color: rgba(255, 255, 255, .38);
   font-size: 12px;
}

.notes-section {
   scroll-margin-top: 90px;
   margin-bottom: 58px;
}

.notes-section h2 {
   margin-bottom: 22px;
   font-size: 28px;
   line-height: 1.35;
}

.notes-section p,
.notes-section li {
   color: rgba(255, 255, 255, .74);
   font-size: 16px;
   line-height: 1.85;
}

.notes-section p + p {
   margin-top: 16px;
}

.notes-callout {
   margin-top: 26px;
   padding: 20px 22px;
   display: flex;
   align-items: flex-start;
   gap: 14px;
   border: 1px solid rgba(130, 128, 238, .45);
   border-radius: 10px;
   background: linear-gradient(135deg, rgba(120, 7, 205, .2), rgba(43, 174, 223, .08));
}

.notes-callout img {
   margin-top: 4px;
}

.notes-callout strong {
   display: block;
   margin-bottom: 4px;
}

.notes-callout p {
   font-size: 14px;
}

.notes-list {
   margin-top: 18px;
   padding-left: 22px;
}

.notes-list li {
   margin-bottom: 12px;
}

.notes-list li::marker {
   color: #8280ee;
}

.notes-steps {
   display: grid;
   gap: 12px;
}

.notes-steps li {
   padding: 16px 18px;
   display: flex;
   gap: 16px;
   list-style: none;
   border: 1px solid rgba(255, 255, 255, .12);
   border-radius: 8px;
   background: rgba(255, 255, 255, .05);
}

.notes-steps li > span {
   flex: 0 0 34px;
   width: 34px;
   height: 34px;
   display: flex;
   align-items: center;
   justify-content: center;
   border-radius: 6px;
   background: linear-gradient(131.19deg, #a324b0, #514fd8, #2baedf);
   color: #fff;
   font-size: 11px;
   font-weight: 700;
}

.notes-steps strong {
   display: block;
   color: #fff;
}

.notes-steps p {
   font-size: 14px;
}

.notes-code {
   margin: 24px 0;
   padding: 22px 24px;
   overflow-x: auto;
   border: 1px solid rgba(255, 255, 255, .14);
   border-radius: 10px;
   background: rgba(0, 0, 0, .32);
   color: #b9dff2;
   font-family: Consolas, "Courier New", monospace;
   font-size: 14px;
   line-height: 1.8;
}

.notes-checklist {
   display: grid;
   grid-template-columns: 1fr 1fr;
   gap: 12px;
}

.notes-checklist > div {
   padding: 16px;
   display: flex;
   align-items: center;
   gap: 12px;
   border-bottom: 1px solid rgba(255, 255, 255, .12);
   color: rgba(255, 255, 255, .74);
   font-size: 14px;
}

.notes-checklist span {
   width: 8px;
   height: 8px;
   flex: 0 0 8px;
   border-radius: 50%;
   background: #8280ee;
   box-shadow: 0 0 18px rgba(130, 128, 238, .9);
}

/*
 * **这两个面板上不能写 `overscroll-behavior: contain`**（2026-09-19 去掉）。
 *
 * 背景：它们是**自己的滚动容器**（`overflow-y:auto`），同时带 `data-lenis-prevent`
 * —— 也就是「滚轮在这里时 Lenis 不管，交给浏览器原生滚」。加了 `contain` 之后，
 * 面板**滚不动的时候也不会把滚动交给页面**：
 *
 * - 右侧「本页目录」的内容基本永远不超出（实测每页可滚范围都是 0），
 *   于是鼠标停在它上面时**滚轮彻底失灵**（实测滚 18 次 `pageY` 一直是 0）；
 * - 左侧目录滚到它自己的末尾之后，同样卡死。
 *
 * 去掉 `contain` 之后：面板能滚就先滚面板，滚到末尾**自然接上页面滚动**。
 * 代价是接上那一段走浏览器原生滚动（不经过 Lenis），与页面的平滑滚动略有差异 ——
 * 比「滚轮完全没反应」可接受得多。
 *
 * 弹窗面板（`.notes-all-modal__panel` / `.site-lib-modal__panel`）**保留 `contain`**：
 * 那是浮层，盖子打开时本来就不该把滚动漏给后面的页面。
 */
.notes-outline-shell {
   position: sticky;
   top: 92px;
   align-self: start;
}

.notes-outline {
   padding-left: 20px;
   border-left: 1px solid rgba(255, 255, 255, .12);
}

.notes-course-ads {
   display: grid;
   gap: 12px;
   margin-bottom: 24px;
}

.notes-course-ad {
   display: block;
   width: 190px;
   height: 107px;
   border-radius: 12px;
   object-fit: cover;
}

.notes-outline__title {
   margin-bottom: 16px;
   color: rgba(255, 255, 255, .9);
   font-size: 18px;
   font-weight: 600;
}

.notes-outline a {
   display: block;
   padding: 7px 0;
   color: rgba(255, 255, 255, .45);
   font-size: 18px;
   line-height: 1.45;
   transition: color .2s ease;
}

.notes-outline a:hover,
.notes-outline a.active {
   color: #73c9ef;
}

@media (max-width: 1100px) {
   .notes-layout {
      grid-template-columns: minmax(0, 760px);
   }

   .notes-outline-shell {
      display: none;
   }
}

@media (max-width: 768px) {
   .notes-brand-lockup {
      align-items: center;
   }

   .app__aside-logo {
      margin-left: 0;
      margin-right: auto;
   }

   .app__aside-body-logo {
      padding-left: 0;
      text-align: center;
   }

   .app__container {
      grid-template-columns: 1fr;
   }

   .notes-layout {
      padding: 38px 20px 80px;
   }

   .notes-document__icon {
      margin-bottom: 22px;
   }

   .notes-document h1 {
      font-size: 34px;
   }

   .notes-document__lead {
      font-size: 16px;
   }

   .notes-document__meta {
      margin-bottom: 42px;
   }

   .notes-section {
      margin-bottom: 46px;
   }

   .notes-section h2 {
      font-size: 24px;
   }

   .notes-section p,
   .notes-section li {
      font-size: 15px;
   }

   .notes-checklist {
      grid-template-columns: 1fr;
   }
}

/*
 * ---------- 阅读器正文紧跟固定顶栏（手机） ----------
 *
 * 去掉标题上方那段空白（用户 2026-09-22：「wap 详情正文页的标题和上面的间距太大，
 * 去掉这个间距。一部分是正文顶部距离，还有一部分是顶部导航向下伸出的距离」）。
 *
 * 他说的两部分，390 视口实测出来正好是这条链：
 *   .wrapper 的 padding-top        74px   ← 给固定顶栏让位
 *   .app__aside 的占位高度          60px   ← 左栏在单列布局里占掉的一整行
 *   .notes-layout 的 padding-top    38px   ← 正文自己的上边距（「正文顶部距离」）
 *   ───────────────────────────────────
 *   合计                           172px
 *
 * 而顶栏（header）底部只到 **113.9px** —— 富余的 58px 全部落在标题上方，
 * 这就是那截看起来莫名其妙的空白。
 *
 * 这里收掉正文自己那 38px（`padding-top: 0`），**留 20px** 作顶栏与标题之间的呼吸：
 * 实测标题顶从 172 → 134，顶栏底 113.9，净空白 58.1 → 20.1，且不会被顶栏盖住。
 *
 * ## 为什么不再往下压到 0
 *
 * 剩下的 20px 只能从另外两处拿，各有代价，都不该顺手做：
 *
 *   - **`.app__aside` 的 60px 占位**：它看着像空的，其实**不是** —— 里面是阅读器的
 *     左栏目录（`.app__aside-body` 190x844，超出父高、靠溢出显示；资料库那边还多一条
 *     `app__aside-head`，装「返回首页」和菜单按钮）。把这一行的高度收掉会连目录一起
 *     弄坏，而目录在手机上就是唯一的章节入口。
 *   - **全局 `.wrapper` 的 74px**：那是 `SiteShell` 给**所有**公开页面让位的量
 *     （`/about`、`/cooperation` 等没有左栏的页面也吃这一条），改它会让那些页面整体下移。
 *
 * 两条都是「为了这 20px 动一个影响面更大的东西」，按最小改动原则停在这里。
 *
 * ## 为什么只包 767
 *
 * 桌面与平板上顶栏是另一套让位量（`.wrapper` 在 769 以上走的是 `SiteShell` 的基础值），
 * 那里的标题间距本来就是对的，实测 1440 下 `.notes-layout` 的 padding-top 是 56px 且不显宽。
 * 767 这个断点与本仓既有口径一致（平板按桌面）。
 */
@media (max-width: 767px) {
   .notes-layout {
      padding-top: 0;
   }

   /*
    * **左栏那一行改成按内容撑 —— 正文就贴上顶栏了**（用户 2026-09-22）。
    *
    * ## 先说清楚修的是哪个 bug
    *
    * 资料库左栏头部条里的「菜单」按钮点不动，实测它的中心点在 y=90，
    * 而固定顶栏占的是 0-113.9 —— **整个按钮都压在顶栏底下**。
    * 根因在上面那条 `.wrapper` 的让位量：74px 让开的是顶栏的**内容**高度，
    * 而顶栏的总高是 114（内容 74 + 上下各 20 的内边距），差的那 40px 谁都没让。
    * 所以这一处和 `.wrapper` 那条是同一个修复的两半，不能只改一边。
    *
    * ## 这一行为什么原来动不了
    *
    * 它被 `style.min.css` 的 `.app__container { grid-template-rows: 1fr }` 钉住：
    * `1fr` 的最小值是 `auto`（= min-content），**由 item 的内容决定，不看 item 的
    * height**。实测给 `.app__aside` 加 `height: 40px; min-height: 0`，aside 自己确实
    * 矮了，**行高却纹丝不动**（仍是 `60px`），正文也就没动。必须直接改轨道。
    *
    * 改成 `auto 1fr` 之后每一行按内容撑：
    *   - 课程 / 案例：左栏里没有可见内容（抽屉在屏幕外，实测 `left: -190`）→
    *     这一行 0px，正文直接顶到顶栏下沿；
    *   - 资料库：左栏里有那条头部条 → 这一行按它撑开，正文排在它下面。
    *
    * 用 `auto` 而不是写死 `40px` / `60px`：写死就是两页两条规则，而且以后任何一边的
    * 内容高度一变就错位（这一版之前就是写死的，正因为如此才没发现让位量本身是错的）。
    */
   .app__container {
      grid-template-rows: auto 1fr;
   }

   /*
    * **抽屉底部那层模糊装饰不该接事件**（用户 2026-09-22：「点击菜单下半部分的标题
    * 不能切换对应的文章」）。
    *
    * `.app__aside-body-blur` 是 `position: absolute; bottom: 0; 300x300; filter: blur(100px)`
    * 的一层渐变，纯装饰。但 `style.min.css` 里那条**没写 `pointer-events`** ——
    * 默认的 `auto` 让它实打实地盖住了抽屉**下半部分 300px**，下面的章节链接全部点不到。
    *
    * 实测复现：抽屉里 19 个可点元素，`elementFromPoint` 落在 y>600 的那些全被它接走；
    * 点上半部分的章节能切换、点下半部分的没反应 —— 正是用户描述的现象。
    *
    * 选择器带一层 `.app__aside` 是为了压过基线：两个都是 (0,1,0) 的话，
    * `shell-fixes.css` / `app-notes.css` 排在 `style.min.css` 之前，压不动。
    */
   .app__aside .app__aside-body-blur {
      pointer-events: none;
   }

   /*
    * **资料库左栏那条头部条脱离文档流，浮到正文左上角**（用户 2026-09-22：
    * 「文章菜单的按钮 不要单独 占一大块。把其固定放在正文显示部分的左上角即可，
    * 这样就可以减少正文与顶部导航之间的空白」）。
    *
    * 它原本是 `.app__container` 那行的内容：头部条有 63px 高，把 grid 第一行撑到 77px，
    * 正文因此被推到 191px（顶栏底才 113.9）—— 那 77px 就是用户看到的那一大块空白。
    *
    * 改成 `absolute` 之后它不再占流，grid 第一行塌成 0，正文直接顶到顶栏下沿；
    * 而按钮本身浮在正文左上角，仍然点得到（`z-index` 高于正文）。
    *
    * ⚠️ **`pointer-events` 必须分开写**：这一条横跨正文的左上角，如果整块都可点，
    * 它会在标题上盖出一片透明的死区（文字选不中、链接点不到）。
    * 所以整块 `none`、只让里面的按钮 `auto`。
    *
    * ⚠️ 去掉 `width: 100%`（原来那条在 `style.min.css` 里是撑满整行的）——
    * 保持整行宽的话，即使脱离流也会横着盖住正文顶部一整条。
    */
   .app__aside-head {
      /*
       * **`fixed` 而不是 `absolute`**（用户 2026-09-22：「不要随正文网上滚动，
       * 固定在最初的位置，不随正文滚动」）。
       *
       * 两者都不占文档流（这一点是上一版解决的），区别只在参照物：
       * `absolute` 挂在左栏那一格上，页面一滚就跟着走；`fixed` 挂在视口上，
       * 正文滚到哪儿它都停在同一个屏幕位置。
       *
       * 120px = 顶栏底边 113.9 + 6 的间隙。**这个数是量出来的**：详情页顶栏是
       * `.header__body`（上下各 20px 内边距 + 74px 内容 = 114）。顶栏自己也是
       * `fixed`，所以两者一起钉住、不会错位。
       *
       * ⚠️ 换了参照物之后 `padding` 也就没意义了（原来那 6px 是相对左栏那一格的
       * 缩进），位置全由 `top` / `left` 决定，所以这里归零。
       */
      position: fixed;
      top: 120px;
      left: 6px;
      width: auto;
      height: auto;
      margin: 0;
      padding: 0;
      z-index: 5;
      pointer-events: none;
   }

   .app__aside-head > * {
      pointer-events: auto;
   }

   /*
    * `.app__aside` 仍要 `position: relative` —— 头部条虽然改成了 `fixed`，
    * 但**抽屉**（`.app__aside-body`，靠 `left: -190` 滑出）还是 `absolute`，
    * 它要相对这一格定位。
    */
   .app__aside {
      position: relative;
   }}
/* Shared prototype layout overrides */
.header{position:fixed!important;top:0;left:0;background:transparent!important}
.wrapper{padding-top:86px}
.app__aside-head .notes-brand-lockup,.app__aside-body-logo,.notes-site-credit{display:none!important}
.notes-case-button{flex:0 0 auto;width:auto;min-height:44px;margin:0 16px 12px;padding:10px 14px;box-sizing:border-box;text-decoration:none;font-size:14px}

.footer{position:relative;z-index:101;background:#05010d}
@media(min-width:769px){.app{width:100%;height:auto;max-height:none;overflow:visible}.app__container{width:min(calc(100% - 80px),1360px);height:auto;margin:0 auto;grid-template-columns:244px minmax(0,1fr);align-items:start}.app__aside{position:sticky;top:100px;height:auto;max-height:calc(100vh - 120px);overflow-y:auto;align-self:start;background:transparent}.app__aside-head{display:none}.app__aside-body{display:block}.app__aside-ai{padding:0 16px 0 0}.app__aside-ai-list{max-height:none!important;overflow:visible}.app__aside-ai-list li{margin-left:0}.notes-main{overflow:visible}.notes-layout{width:100%;margin:0;padding:28px 0 100px 48px;grid-template-columns:minmax(0,760px) 190px;justify-content:end}.notes-outline-shell{position:fixed!important;top:100px;right:max(40px,calc((100vw - 1360px)/2));width:190px;max-height:calc(100vh - 120px);overflow-y:auto}}
@media(max-width:767px){.wrapper{padding-top:114px}}