/* responsive + accessibility + print */
    /* ── 响应式 ── */
    @media (max-width: 1180px) {
      .page-section .container { grid-template-columns: minmax(0, 1fr) minmax(0, 19rem); column-gap: 3rem; }
      .hero-shell { grid-template-columns: minmax(0, 1fr) 380px; gap: 2.5rem; }
      .hero-content { max-width: 100%; }
      .hero-visual { width: 380px; min-width: 0; }
    }
    @media (max-width: 1024px) {
      /* 头部改回上下堆叠 */
      .page-section .container { display: block; }
      .section-label { margin-bottom: 1.2rem; }
      .hero { padding-bottom: 6rem; }
      .hero-shell { grid-template-columns: 1fr; gap: 3.1rem; }
      .hero-visual { justify-self: center; width: min(440px, 90vw); min-width: 0; margin: 0 auto; height: 390px; }
      .window-body { height: 260px; }
      .specimen-window.is-back { --deck-x: 22px; --deck-y: 26px; }
      /* 原「标本标牌 ≤1024 收起提示语」的 .plate-tip 规则已随单卡版标牌一起下线
         （2026-10-27 换成双层视窗，提示语改挂在 .window-footer 里）。 */
      .portfolio-card.layout-large,
      .portfolio-card.layout-narrow,
      .portfolio-card.layout-half { grid-column: span 6; }
      .portfolio-card.layout-wide { grid-column: 1 / -1; grid-template-columns: 1fr; }
      .layout-wide .card-image { aspect-ratio: 16/10; min-height: 0; }
      .layout-wide .card-body { padding: 1.8rem 1.9rem 2rem; }
      .travel-item, .travel-item.has-photo { gap: 1.6rem; }
      .travel-item.has-photo { grid-template-columns: 98px 148px minmax(0, 1fr) auto; }
    }
    @media (max-width: 768px) {
      .container, .nav-inner { padding-inline: 1rem; }
      .nav { padding: 0.9rem 0; }
      .nav.scrolled { padding: 0.55rem 0; }
      .nav.scrolled .nav-inner { max-width: 100%; padding: 0.32rem 0.9rem; }
      .nav-inner { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.7rem; }
      .nav-logo { font-size: 1.16rem; flex: 0 0 auto; }
      .nav-actions { justify-content: flex-end; gap: 0.48rem; min-width: 0; }
      .nav-links { display: flex; gap: 0.1rem; flex: 0 1 auto; min-width: 0; }
      /* 2026-09-23 补回：窄屏靠缩字号/内边距给三个中文标签让位（此条曾被误删，
         导致导航标签在窄窗口下逐字换行竖排）。 */
      .nav-links a { font-size: 0.82rem; padding: 0.36rem 0.58rem; }
      .nav-search, .theme-toggle, .lang-toggle { width: 36px; height: 36px; flex: 0 0 36px; }
      .nav-search svg { width: 18px; height: 18px; }
      .theme-toggle svg { width: 16.5px; height: 16.5px; }
      .lang-toggle { min-width: 36px; font-size: 0.8rem; }
      .lang-toggle .lang-text.is-zh { font-size: 0.88rem; }
      .hero { min-height: auto; padding-top: 5.5rem; padding-bottom: 4rem; }
      body.home-page .hero { min-height: auto; padding-top: 5.5rem; padding-bottom: 3.5rem; }
      .hero-shell { gap: 2.6rem; }
      .hero-eyebrow-wrap { margin-bottom: 1.15rem; }
      .hero-eyebrow { font-size: 0.63rem; letter-spacing: 0.13em; padding: 0.36rem 0.78rem 0.36rem 0.64rem; }
      .hero-title {
        font-size: clamp(2.05rem, 9.4vw, 2.5rem);
        line-height: 1.09; margin-bottom: 1.05rem; letter-spacing: -0.022em;
      }
      /* 窄屏放回自动折行：这一档字号由 vw 给（见上），行宽小于容器，
         若还锁单行会直接溢出屏幕。 */
      .hero-title > .hero-title-line,
      .hero-title > span { white-space: normal; }
      .hero-desc { font-size: 0.97rem; line-height: 1.72; max-width: 32rem; margin-left: 0.55rem; overflow-wrap: anywhere; }
      .hero-desc::before { left: -0.55rem; }
      .hero-actions { margin: 1.85rem 0 0; gap: 0.6rem; }
      .btn-solid, .btn-line { height: 46px; font-size: 0.88rem; padding: 0 1.15rem; }
      .hero-visual {
        justify-self: center;
        width: min(390px, calc(100vw - 2rem));
        max-width: 100%;
        margin: 1.2rem auto 0;
        height: 310px;
      }
      .hero-visual .specimen-window {
        width: calc(100% - 16px);
      }
      .hero-visual .window-bar {
        height: 32px;
        padding: 0 0.65rem;
        gap: 0.4rem;
      }
      .hero-visual .window-dots { gap: 4px; }
      .hero-visual .window-dots i { width: 7px; height: 7px; }
      .hero-visual .window-title { font-size: 0.58rem; letter-spacing: 0.06em; white-space: nowrap; }
      .hero-visual .window-badge { font-size: 0.5rem; padding: 1px 4px; }
      .hero-visual .window-body { height: 200px; }
      .hero-visual .window-footer {
        height: 30px;
        padding: 0 0.65rem;
        font-size: 0.56rem;
      }
      .hero-visual .footer-action { font-size: 0.56rem; padding: 1px 5px; }
      .hero-visual .footer-deck-tag { font-size: 0.54rem; }
      .hero-visual .specimen-window.is-back {
        --deck-x: 16px;
        --deck-y: 18px;
      }
      body.home-page .footer { padding: 1.7rem 0 1.9rem; }
      /* ⚠️ 原窄屏覆盖 `.footer-links{gap:0.5rem}` 与 `.footer-links a{padding:.4rem .85rem}`
         是「药丸按钮」时代的取值，早已被下方 ⑩ 的同名规则按文档顺序压死（两处都零生效），
         2026-09-21 收尾时删除；这里只留 ⑩ 没有重新声明的两条。 */
      .footer-links { margin-bottom: 1rem; }
      .footer-links a { font-size: 0.82rem; }
      body.content-page .page-section { min-height: calc(100vh - 150px); padding-top: 6.5rem; }
      .section { padding: 4.5rem 0; }
      .portfolio-grid { grid-template-columns: 1fr; gap: 1.25rem; }
      .portfolio-card.layout-large,
      .portfolio-card.layout-narrow,
      .portfolio-card.layout-half,
      .portfolio-card.layout-wide { grid-column: 1 / -1; }
      .portfolio-card .card-image,
      .layout-large .card-image,
      .layout-narrow .card-image,
      .layout-half .card-image { aspect-ratio: 16/10; }
      .card-body, .layout-wide .card-body { padding: 1.4rem 1.45rem 1.55rem; }
      /* 窄屏下元信息不再做成会溢出的胶囊，直接换行成一行说明。
         （状态图标组同样无底色无内边距，这里一并透明化即可） */
      .card-meta { gap: 0.28rem 0.6rem; }
      .card-meta span { white-space: normal; overflow: visible; text-overflow: clip; background: transparent; padding: 0; }
      /* 旅途：时间轴整体收窄 + 左移（2026-09-24 用户反馈「时间线和字有点重合」）。
         圆点的外光环常态就有 4px（悬停 7px），原来圆点右缘到日期文字只剩 9.9px，
         光环一撑几乎贴住字。这里让整条时间轴（虚线 + 圆点）左移 0.4rem：
           · 虚线 left 1.4rem → 1.0rem；
           · .travel-date 自身 margin-left -0.4rem（圆点随之左移）；
           · 同时把 gap 从 0.62rem 加到 1.02rem，**恰好抵消**圆点的左移量
             ⇒ 日期文字的位置纹丝不动（左缘仍在 39.3px），
                变的只有「圆点 ↔ 文字」的间距：9.9px → 16.3px。
         圆点中心（16 + 3.5 = 19.5）与虚线（1.0rem + 3px = 19）仍然同心。 */
      .travel-list::before { left: calc(1.0rem + 3px); top: 1.8rem; bottom: 2rem; }
      .travel-date { margin-left: -0.4rem; gap: 1.02rem; }
      .travel-item, .travel-item.has-photo { display: block; padding: 1.45rem 0.9rem 1.45rem 1.4rem; }
      /* 日期列整体下移一点，间距由 .travel-date-col 承担（原来是 .travel-date） */
      .travel-date-col { margin-bottom: 0.85rem; }
      /* 堆叠在窄屏改为通栏。三个系数各收各的（见 .travel-stack 注释）——
         手机端容器 329×206，旋转照搬桌面 6° 会被切出屏幕（右内边距只有 0.9rem）。
         上下留白同步加大：竖向外露也有十来个像素，原来的 0.85/0.95rem 间距不够，
         纸角会压到上面的日期图标和下面的正文标题。
         实测（pile_measure.mjs）：外露横向 ~12px、纵向 ~13px，四边余量都还有 ≥3px。 */
      .travel-stack {
        /* ⚠️ 这里的上下 margin 会和相邻块（.travel-date-col / .travel-info）**塌陷**，
           取两者最大值而不是相加 —— 所以想让间距真的变大，必须写一个大于对方的数。
           1.35rem 是「大于日期列的 0.85rem」才生效的，写 0.85rem 等于没加。 */
        width: 100%; aspect-ratio: 16/10; margin: 1.35rem 0 1.25rem;
        --pile-tx: 0.92; --pile-ty: 0.36; --pile-r: 0.64;
      }
      /* 「第一条不许朝上错开」是桌面端专属（用户：「手机端没事就是电脑端」）——
         窄屏还原成不设限。这里必须写成 .travel-stack.is-no-up-over（0,2,0），
         否则被上面那条 .travel-stack（0,1,0）按顺序盖掉、根本压不住。 */
      .travel-stack.is-no-up-over { --pile-ty-floor: -9999px; }
      .travel-info h3 { font-size: 1.16rem; }
      .travel-item .item-meta-actions { justify-content: flex-start; min-width: 0; margin-top: 0.9rem; }
      /* 启发 */
      .inspo-item { margin-bottom: 1.35rem; padding: 0.6rem 0.6rem 0; }
      /* 启发卡片：窄屏内边距收窄，按钮跟着往内挪一点 */
      .inspo-item .item-actions { top: 1.05rem; right: 1.05rem; }
      .inspo-info { padding: 0.95rem 0.55rem 0.1rem; }
      .inspo-item .item-meta-actions { padding: 0.85rem 0.55rem 0.95rem; }
      .section-header { align-items: flex-start; }
      .item-meta-actions { min-width: 0; }
      .modal { padding: 0; }
      .modal-body { padding: 0.25rem 1.4rem 0.4rem 1.4rem; }
      .modal-actions { padding: 0.95rem 1.4rem 1.25rem 1.4rem; }
      /* ── ㊺ 弹窗头部 · 窄屏（2026-10-01）────────────────────────────
         两类弹窗共用同一组头部令牌，窄屏只改这几个数。
         🔴 `.modal:not(.detail-modal)` 与 `.modal.detail-modal` 权重相同
            （都是 0,2,0），**靠源码顺序决胜** —— 详情版必须写在后面。 */
      .modal:not(.detail-modal) {
        --modal-head-pad-top: 1.4rem;
        --modal-head-pad-x: 1.4rem;
        --modal-head-pad-bottom: 0.85rem;
      }
      .modal-header { align-items: flex-start; }
      /* ── ㊹/㊺ 详情弹层 · 窄屏 ──
         详情版头部横向内边距**恒为 0**（内缩交给 --detail-pad-x），
         所以 ✕ 的位置会自动跟着 --detail-pad-x / --detail-pad-top 走，
         与普通弹窗（上面那组）保持同一套口径，不必再单独对齐一次。 */
      .modal.detail-modal {
        --detail-pad-x: 1.4rem;
        --detail-pad-top: 1.4rem;
        --detail-pad-bottom: 1.4rem;
        /* 纵向内缩**恒为 0**（由 --detail-pad-top 提供），见桌面段说明 */
        --modal-head-pad-top: 0;
        --modal-head-pad-bottom: 0.85rem;
        /* 窄屏的普通弹窗 ✕ 已经是 flex-start（基准 = 头部内容顶边），
           与详情弹层同基准 ⇒ 补偿量归零，两边上距才会相等（实测都是 23.4）。 */
        --detail-close-nudge: 0px;
        /* 高度上限换成弹窗自身的高度：vh 在手机上会随工具栏收展跳变，
           dvh 才是稳定值；下限抬到 240px，免得小屏上照片被压成一条 */
        --detail-photo-h: clamp(240px, 46dvh, 440px);
        --detail-title-wrap: wrap;
      }
      .modal.detail-modal .detail-title { font-size: clamp(1.5rem, 6.2vw, 2rem); }
      .modal.detail-modal .detail-desc { font-size: 0.95rem; line-height: 1.75; }
      .form-row { grid-template-columns: 1fr; }
      .photo-uploader { grid-template-columns: 1fr; }
      .photo-preview { max-width: 180px; }
      .search-overlay { padding-inline: 1rem; }
      .search-result { grid-template-columns: 1fr; gap: 0.55rem; }
    }
    @media (max-width: 640px) {
      .inspo-list { columns: 1; }
    }
    @media (max-width: 390px) {
      .container, .nav-inner { padding-inline: 0.8rem; }
      .nav-inner { gap: 0.5rem; }
      .nav-logo { font-size: 1rem; }
      .nav-logo::before { width: 6px; height: 6px; }
      .nav-actions { gap: 0.36rem; }
      .nav-links { gap: 0.05rem; }
      .nav-links a { font-size: 0.75rem; padding: 0.32rem 0.45rem; }
      .nav-search, .theme-toggle, .lang-toggle { width: 34px; height: 34px; flex-basis: 34px; }
      .nav-search svg { width: 17px; height: 17px; }
      .theme-toggle svg { width: 15.5px; height: 15.5px; }
      .lang-toggle { min-width: 34px; font-size: 0.76rem; }
      .lang-toggle .lang-text.is-zh { font-size: 0.84rem; }
      .hero-title { font-size: clamp(1.92rem, 9vw, 2.14rem); }
      .hero-desc { font-size: 0.93rem; margin-left: 0.2rem; }
      .hero-desc::before { display: none; }
      .hero-actions { gap: 0.5rem; }
      .btn-solid, .btn-line { height: 44px; font-size: 0.85rem; padding: 0 1rem; }
      .hero-visual {
        width: min(350px, calc(100vw - 1.6rem));
        height: 295px;
      }
      .hero-visual .specimen-window {
        width: calc(100% - 14px);
      }
      .hero-visual .window-body {
        height: 190px;
      }
      .hero-visual .specimen-window.is-back {
        --deck-x: 14px;
        --deck-y: 16px;
      }
      .portfolio-card { border-radius: var(--radius-lg); }
      .card-title { font-size: 1.24rem; }
    }
    /* ── 无障碍：尊重减弱动效偏好 ── */
    @media (prefers-reduced-motion: reduce) {
      html { scroll-behavior: auto; }
      *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
      }
      .reveal { opacity: 1 !important; transform: none !important; }
      .portfolio-card:hover { transform: none; }
    }

    /* ── 无障碍：统一键盘焦点环 ── */
    a:focus-visible,
    button:focus-visible,
    [role="button"]:focus-visible {
      outline: 2px solid color-mix(in srgb, var(--blue-500) 62%, transparent);
      outline-offset: 3px;
      border-radius: 4px;
    }

    /* ── 打印 ── */
    @media print {
      .nav, .grain, .ambient-bg, .toast, .search-overlay, .modal-overlay { display: none !important; }
      html, body { background: #fff !important; background-image: none !important; }
    }
  
    /* 暗色：实心按钮与卡片 ↗ 图标反相 —— 暗色令牌下 blue-500/600 是浅色，
       白字对比度仅约 1.7:1，改为浅蓝底 + 深色文字（约 8.7:1）。
       ㉚ 渐变本身已交给 --grad-solid 在暗色令牌里重写（那里写了为什么必须重写），
          此处**只反相文字色**。别再补一条 background —— 它会盖掉令牌，
          暗色就又变回「没有过渡的两色」。 */
    html[data-theme="dark"] .btn-solid,
    html[data-theme="dark"] .btn-submit {
      color: var(--bg);
    }
    html[data-theme="dark"] .portfolio-card.has-github:hover::after {
      background: linear-gradient(130deg, var(--blue-500), var(--blue-400));
      color: var(--bg);
    }


