@charset "UTF-8";
/* ==========================================================================
   hub.css · 姜的演示厅
   --------------------------------------------------------------------------
   这个文件有两个使用场景，写法上必须同时满足：

   1) 独立访问：https://abitginger.top/WebDemos/
      此时本文件在 <head> 里正常引入，负责整站的页眉、页脚、背景。

   2) 被主站「静默跳转」接进 ABitGinger.github.io 的 <main>
      主站只会替换 <main> 节点、不会加载新样式，所以主站首页的 <head>
      里也引了本文件（它是从 /WebDemos/assets/hub.css 直接引的）。这种情况下只允许 .dm-* 的规则生效。

   因此约定（改动时务必遵守）：
   · 演示厅自己的组件样式，一律以 .dm- 前缀命名；
   · 页眉/页脚/背景等「独立访问才需要」的样式，全部包在 body.dm-standalone 下。
   两条加起来可以保证本文件挂在任何页面上都不会污染该页面原有样式。

   颜色沿用主站：金色 rgba(223,182,95,1)、毛玻璃黑卡 rgba(0,0,0,.45)、
   文字阴影 0 2px 4px rgba(0,0,0,1)。主站改版时记得同步下面的基础段。
   ========================================================================== */

/* ==========================================================================
   0. 设计变量
   ========================================================================== */
:root {
    --dm-gold: #dfb65f;
    --dm-gold-faint: rgba(223, 182, 95, 0.18);
    --dm-card-bg: rgba(0, 0, 0, 0.45);
    --dm-card-bg-hover: rgba(0, 0, 0, 0.58);
    --dm-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
    --dm-shadow-lg: 0 24px 60px -18px rgba(0, 0, 0, 0.85);
    --dm-text: #ffffff;
    --dm-text-dim: rgba(255, 255, 255, 0.85);
    --dm-text-faint: rgba(255, 255, 255, 0.58);
    --dm-text-shadow: 0 2px 4px rgba(0, 0, 0, 1);
    --dm-radius: 20px;
    --dm-viewer-radius: 18px;
    --dm-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ==========================================================================
   1. 独立访问时的整站基础样式（与主站 /css/style.css 对齐，仅 body.dm-standalone 生效）
   ========================================================================== */
body.dm-standalone {
    min-height: 100vh;
    margin: 8px;
    font-family: Arial, sans-serif;
    color: var(--dm-text);
    background-color: #06080d;
    background-image: url("https://abitginger-1327459979.cos.ap-beijing.myqcloud.com/pic/%E8%B6%8A%E8%B6%8A%E5%AE%B6.webp");
    background-size: cover;
    background-attachment: fixed;
    background-position: center center;
    display: flex;
    flex-direction: column;
}

body.dm-standalone main {
    flex: 1;
    margin: 15px 0;
    padding: 20px;
    box-sizing: border-box;
}

body.dm-standalone header {
    background-color: rgba(223, 182, 95, 0.8);
    color: #fff;
    padding: 15px 0;
    margin: 0;
    border: 0;
    border-radius: 10px;
}

body.dm-standalone footer {
    background-color: rgba(223, 182, 95, 0.8);
    color: #fff;
    text-align: center;
    padding: 20px 0;
    margin: 0;
    margin-top: auto;
    flex-shrink: 0;
    border-radius: 10px;
}

body.dm-standalone footer a {
    text-decoration: none;
    color: #fff;
}

body.dm-standalone nav ul {
    list-style: none;
    text-align: center;
    margin: 0;
    padding: 0;
}

body.dm-standalone nav ul li {
    display: inline;
    margin-right: 20px;
}

body.dm-standalone nav ul li a {
    color: #fff;
    text-decoration: none;
}

body.dm-standalone .email-text {
    cursor: pointer;
    transition: color 0.3s ease;
}

body.dm-standalone .email-text:hover {
    color: #fff;
}

/* 滚动锁定：查看器打开期间禁止页面滚动 */
html.dm-lock,
body.dm-lock {
    overflow: hidden;
}

/* ==========================================================================
   2. 演示厅容器
   ========================================================================== */
.dm-root,
.dm-root *,
.dm-root *::before,
.dm-root *::after,
.dm-viewer,
.dm-viewer *,
.dm-viewer *::before,
.dm-viewer *::after {
    box-sizing: border-box;
}

.dm-root {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    color: var(--dm-text);
}

/* ---------- 页头：返回 + 标题同一行，计数行在下面 ----------
   版式刻意与主站「仓库展示」页（/repos/ 的 .repos-toolbar + #repo-summary）一致：
   返回按钮在标题左边、整行居中，标题用普通白色文字 + 文字阴影（不做渐变），
   计数行是居中灰字。两边看起来才像一套东西。 */
.dm-toolbar {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 16px;
}

.dm-title {
    margin: 0;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.3;
    color: #fff;
    text-shadow: var(--dm-text-shadow);
}

.dm-backlink {
    color: #fff;
    text-decoration: none;
    background: rgba(0, 0, 0, 0.35);
    padding: 6px 16px;
    border-radius: 999px;
    box-shadow: var(--dm-shadow);
    transition: background-color 0.3s, transform 0.3s;
}

.dm-backlink:hover {
    background-color: var(--dm-gold);
    transform: scale(1.03);
}

/* 计数行：␣共 N 个演示 · 提示␣（由 hub.js 填，格式同 #repo-summary） */
.dm-summary {
    margin: 12px 0 20px;
    text-align: center;
    color: var(--dm-text-dim);
    text-shadow: var(--dm-text-shadow);
    font-size: 0.95rem;
}

/* ---------- 筛选行：标签 + 搜索 ---------- */
.dm-filters {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0 0 20px;
}

.dm-search {
    position: relative;
    flex: 0 1 230px;
    min-width: 170px;
}

.dm-search input {
    width: 100%;
    padding: 9px 34px 9px 14px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: rgba(0, 0, 0, 0.42);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    color: #fff;
    font: inherit;
    font-size: 0.88rem;
    outline: none;
    transition: border-color 0.25s, background-color 0.25s, box-shadow 0.25s;
}

.dm-search input::placeholder {
    color: rgba(255, 255, 255, 0.45);
}

.dm-search input:focus {
    border-color: var(--dm-gold);
    background: rgba(0, 0, 0, 0.6);
    box-shadow: 0 0 0 3px var(--dm-gold-faint);
}

.dm-search-clear {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 22px;
    height: 22px;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--dm-text-faint);
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.2s, color 0.2s, background-color 0.2s;
}

.dm-search.has-value .dm-search-clear {
    opacity: 1;
    pointer-events: auto;
}

.dm-search-clear:hover {
    color: #fff;
    background: rgba(255, 255, 255, 0.12);
}

.dm-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 0; /* 外边距交给 .dm-filters 统一控制 */
}

.dm-tag-chip {
    padding: 5px 14px;
    border-radius: 999px;
    border: 1px solid rgba(223, 182, 95, 0.45);
    background: rgba(223, 182, 95, 0.12);
    color: #fff;
    font: inherit;
    font-size: 0.78rem;
    cursor: pointer;
    transition: background-color 0.22s, color 0.22s, transform 0.22s, border-color 0.22s;
}

.dm-tag-chip:hover {
    background: rgba(223, 182, 95, 0.28);
    transform: translateY(-1px);
}

.dm-tag-chip[aria-pressed="true"] {
    background: var(--dm-gold);
    border-color: var(--dm-gold);
    color: #241c05;
    font-weight: 700;
    box-shadow: 0 0 16px rgba(223, 182, 95, 0.4);
}

/* ==========================================================================
   3. 卡片网格
   ========================================================================== */
.dm-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr));
    gap: 22px;
    align-items: stretch;
}

.dm-card {
    position: relative;
    display: flex;
    flex-direction: column;
    border-radius: var(--dm-radius);
    background: var(--dm-card-bg);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    border: 2px solid transparent;
    box-shadow: var(--dm-shadow);
    overflow: hidden;
    transition: transform 0.35s var(--dm-ease), border-color 0.35s, background-color 0.35s,
        box-shadow 0.35s;
}

/* 入场动画：只做一次，用 backwards 填充，动画结束后不再占用 transform，
   这样 hover 的位移/缩放过渡不会被 animation-fill-mode 顶掉。 */
.dm-card.dm-enter {
    animation: dm-card-in 0.55s var(--dm-ease) backwards;
    animation-delay: var(--dm-delay, 0ms);
}

@keyframes dm-card-in {
    from {
        opacity: 0;
        transform: translateY(14px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.dm-card:hover,
.dm-card:focus-within {
    transform: translateY(-4px) scale(1.014);
    border-color: var(--dm-gold);
    background: var(--dm-card-bg-hover);
    box-shadow: var(--dm-shadow-lg);
}

/* 悬停时掠过卡片的一道金色高光 */
.dm-card::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(115deg, transparent 38%, rgba(255, 255, 255, 0.13) 50%, transparent 62%);
    transform: translateX(-120%);
    transition: transform 0.85s var(--dm-ease);
}

.dm-card:hover::after {
    transform: translateX(120%);
}

/* ---------- 封面 ---------- */
.dm-card-cover {
    position: relative;
    aspect-ratio: 2 / 1;
    background: #05080f;
    overflow: hidden;
}

.dm-cover-art {
    display: block;
    width: 100%;
    height: 100%;
    transition: transform 0.6s var(--dm-ease);
}

.dm-card:hover .dm-cover-art {
    transform: scale(1.05);
}

.dm-card-glyph {
    position: absolute;
    right: 12px;
    bottom: 4px;
    font-size: 2.5rem;
    line-height: 1;
    filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.85));
    opacity: 0.92;
    pointer-events: none;
    transition: transform 0.5s var(--dm-ease);
}

.dm-card:hover .dm-card-glyph {
    transform: scale(1.12) rotate(-4deg);
}

.dm-card-tags {
    position: absolute;
    left: 10px;
    top: 10px;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    max-width: calc(100% - 58px);
    pointer-events: none;
}

.dm-chip {
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 0.71rem;
    color: rgba(255, 255, 255, 0.92);
    background: rgba(0, 0, 0, 0.6);
    border: 1px solid rgba(255, 255, 255, 0.18);
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}

/* 卡片封面右上角的独立打开按钮 */
.dm-card-open {
    position: absolute;
    right: 10px;
    top: 10px;
    z-index: 3;
    width: 32px;
    height: 32px;
    display: grid;
    place-items: center;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    background: rgba(0, 0, 0, 0.6);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    color: #fff;
    font-size: 0.95rem;
    text-decoration: none;
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.28s, transform 0.28s, background-color 0.22s, border-color 0.22s;
}

.dm-card:hover .dm-card-open,
.dm-card:focus-within .dm-card-open {
    opacity: 1;
    transform: translateY(0);
}

.dm-card-open:hover {
    background: var(--dm-gold);
    border-color: var(--dm-gold);
    color: #241c05;
}

/* ---------- 卡片正文 ---------- */
.dm-card-body {
    display: flex;
    flex-direction: column;
    gap: 9px;
    padding: 15px 17px 16px;
    flex: 1;
}

.dm-card-title {
    margin: 0;
    font-size: 1.1rem;
    line-height: 1.35;
    word-break: break-word;
}

/* 铺满整张卡片的点击热区（stretched link），保证键盘与读屏可用，JS 关闭时也能正常跳转 */
.dm-card-hit {
    color: inherit;
    text-decoration: none;
}

.dm-card-hit::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: inherit;
}

.dm-card-hit:focus-visible {
    outline: none;
}

.dm-card:focus-within {
    border-color: var(--dm-gold);
}

.dm-card-desc {
    margin: 0;
    color: var(--dm-text-dim);
    font-size: 0.9rem;
    line-height: 1.62;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.dm-card-foot {
    margin-top: auto;
    padding-top: 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    font-size: 0.8rem;
    color: var(--dm-text-faint);
}

.dm-card-hint {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--dm-gold);
    opacity: 0.85;
    transition: opacity 0.25s, transform 0.25s;
}

.dm-card:hover .dm-card-hint {
    opacity: 1;
    transform: translateX(2px);
}

/* ---------- 骨架屏 / 状态卡 ---------- */
.dm-skeleton {
    border-radius: var(--dm-radius);
    min-height: 300px;
    background: rgba(0, 0, 0, 0.35);
    animation: dm-skeleton 1.4s ease-in-out infinite;
}

@keyframes dm-skeleton {

    0%,
    100% {
        opacity: 0.55;
    }

    50% {
        opacity: 1;
    }
}

.dm-status {
    max-width: 560px;
    margin: 34px auto 10px;
    padding: 26px 24px;
    text-align: center;
    border-radius: var(--dm-radius);
    background: var(--dm-card-bg);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    box-shadow: var(--dm-shadow);
    color: #fff;
    line-height: 1.7;
}

.dm-status[hidden] {
    display: none;
}

.dm-empty {
    grid-column: 1 / -1;
    padding: 40px 20px;
    text-align: center;
    color: var(--dm-text-dim);
    text-shadow: var(--dm-text-shadow);
}

/* ==========================================================================
   4. 内嵌查看器（卡片放大占满屏幕 =「就地展开」）
   ========================================================================== */
.dm-viewer {
    position: fixed;
    inset: 0;
    z-index: 9000;
}

.dm-viewer-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(3, 6, 12, 0.74);
    -webkit-backdrop-filter: blur(7px);
    backdrop-filter: blur(7px);
    opacity: 0;
}

.dm-viewer-shell {
    position: absolute;
    inset: clamp(6px, 1.4vw, 18px);
    display: flex;
    flex-direction: column;
    border-radius: var(--dm-viewer-radius);
    border: 1px solid rgba(223, 182, 95, 0.38);
    background: #070a11;
    box-shadow: 0 30px 90px -20px rgba(0, 0, 0, 0.95), 0 0 0 1px rgba(0, 0, 0, 0.6);
    overflow: hidden;
    opacity: 0;
}

.dm-viewer-bar {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 46px;
    padding: 0 10px 0 14px;
    border-bottom: 1px solid rgba(223, 182, 95, 0.22);
    background: linear-gradient(180deg, rgba(38, 32, 18, 0.95), rgba(12, 15, 22, 0.95));
}

.dm-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    height: 30px;
    padding: 0 13px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.16);
    background: rgba(255, 255, 255, 0.06);
    color: #fff;
    font: inherit;
    font-size: 0.82rem;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.22s, border-color 0.22s, color 0.22s;
}

.dm-btn:hover {
    background: var(--dm-gold);
    border-color: var(--dm-gold);
    color: #241c05;
}

.dm-viewer-title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.92rem;
    font-weight: 700;
    color: #fff;
}

.dm-viewer-title small {
    font-weight: 400;
    color: var(--dm-text-faint);
    margin-left: 8px;
    font-size: 0.78rem;
}

.dm-viewer-body {
    position: relative;
    flex: 1 1 auto;
    min-height: 0;
    background: #05070a;
}

.dm-viewer-frame {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    border: 0;
    background: #05070a;
}

/* 加载幕：与卡片同款程序化封面，iframe 就绪后淡出 */
.dm-viewer-cover {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: #05080f;
    transition: opacity 0.36s ease;
}

.dm-viewer.is-ready .dm-viewer-cover {
    opacity: 0;
    pointer-events: none;
}

.dm-viewer-cover canvas {
    display: block;
    width: 100%;
    height: 100%;
}

.dm-viewer-loading {
    position: absolute;
    left: 50%;
    bottom: 26px;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    color: var(--dm-text-dim);
    font-size: 0.82rem;
    text-shadow: var(--dm-text-shadow);
}

.dm-viewer.is-ready .dm-viewer-loading {
    opacity: 0;
    transition: opacity 0.3s ease;
}

.dm-loadbar {
    width: 148px;
    height: 3px;
    border-radius: 3px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.14);
    position: relative;
}

.dm-loadbar::after {
    content: "";
    position: absolute;
    top: 0;
    left: -40%;
    width: 40%;
    height: 100%;
    border-radius: 3px;
    background: linear-gradient(90deg, transparent, var(--dm-gold), transparent);
    animation: dm-loadbar 1.15s linear infinite;
}

@keyframes dm-loadbar {
    to {
        left: 100%;
    }
}

/* 飞行层：卡片封面 → 查看器区域的放大动画载体 */
.dm-flyer {
    position: fixed;
    z-index: 9500;
    overflow: hidden;
    pointer-events: none;
    background: #05080f;
    will-change: transform;
}

.dm-flyer canvas {
    display: block;
    width: 100%;
    height: 100%;
}

/* ==========================================================================
   5. 响应式与无障碍
   ========================================================================== */
@media (max-width: 560px) {
    .dm-grid {
        gap: 15px;
    }

    .dm-card-body {
        padding: 13px 14px 15px;
    }

    .dm-viewer-shell {
        inset: 0;
        border-radius: 0;
        border: 0;
    }

    .dm-viewer-bar {
        height: 44px;
        padding: 0 8px;
        gap: 6px;
    }

    .dm-viewer-bar .dm-btn {
        padding: 0 10px;
        font-size: 0.78rem;
    }
}

@media (prefers-reduced-motion: reduce) {

    .dm-card,
    .dm-card::after,
    .dm-cover-art,
    .dm-card-glyph,
    .dm-card-open,
    .dm-backlink,
    .dm-tag-chip,
    .dm-card-hint {
        transition: none !important;
        animation: none !important;
    }

    .dm-card {
        opacity: 1;
    }

    .dm-loadbar::after {
        animation-duration: 2.6s;
    }
}
