/* ==========================================================================
   下载分发 · 前台样式
   --------------------------------------------------------------------------
   设计意图：这个页面是给刚到手的 iPhone 用户用的，他们多半从微信点进来、
   只想赶紧把 App 装上。所以它应该像 iOS 系统的一部分，而不是一个网页。
   整页只有「安装」这一个动作是重音，其余一律安静。
   ========================================================================== */

/* ==========================================================================
   设计令牌
   后台的 admin.css 里有一份相同副本，改这里记得同步那边。
   ========================================================================== */
:root {
    color-scheme: light;

    /* 底色：偏冷的纸白，不是灰紫 */
    --paper: #f6f8fc;
    --card: #ffffff;
    --ink: #16203a;
    --ink-2: #4d5a75;
    --muted: #8791a7;
    --line: #e5eaf3;
    --line-strong: #d3dce9;

    /* 主色：iOS 安装动作的蓝。刻意比通用 SaaS 蓝深一档 */
    --accent: #0a6ae0;
    --accent-lift: #2b7ef0;
    --accent-deep: #0857bd;
    --accent-tint: #eaf2ff;
    --accent-line: #bcd6ff;

    --ok: #12a150;
    --ok-tint: #e9f9f0;
    --ok-line: #b6e8cb;

    --warn: #8a6420;
    --warn-tint: #fdf6e7;
    --warn-line: #f0dfb4;

    --danger: #d93a3f;
    --danger-tint: #fdeeee;
    --danger-line: #f5c9ca;

    /* 圆角只留三档：控件 / 卡片 / 药丸，不再到处写任意值 */
    --r-control: 12px;
    --r-card: 22px;
    --r-card-sm: 16px;
    --r-pill: 999px;

    /* 投影只留三档，各自有明确用途 */
    --sh-1: 0 1px 2px rgba(20, 35, 68, .06);
    --sh-2: 0 6px 18px rgba(20, 35, 68, .07), 0 1px 3px rgba(20, 35, 68, .05);
    --sh-3: 0 20px 50px rgba(20, 35, 68, .13), 0 2px 8px rgba(20, 35, 68, .05);
    --sh-accent: 0 8px 18px rgba(10, 106, 224, .24);

    --ease: cubic-bezier(.2, .7, .3, 1);

    /* 系统字体是刻意的选择：页面要贴着 iOS 走，SF Pro + 苹方就是它本来的样子 */
    --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC",
                 "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    font-family: var(--font-sans);
}

* { box-sizing: border-box; }
html { background: var(--paper); }
html, body { min-height: 100%; }

body {
    margin: 0;
    /* 顶部一层柔光，给整页一个光源方向，比均匀渐变有意图 */
    background: radial-gradient(115% 55% at 50% 0%, #ffffff 0%, rgba(255, 255, 255, 0) 58%);
    color: var(--ink);
    font-size: 16px;
    line-height: 1.55;
    -webkit-text-size-adjust: 100%;
    -webkit-font-smoothing: antialiased;
}

/* ==========================================================================
   布局
   ========================================================================== */
.page-shell {
    width: min(100%, 480px);
    min-height: 100vh;
    min-height: 100dvh;
    margin: 0 auto;
    padding: 36px 18px 32px;
    display: flex;
    flex-direction: column;
    gap: 14px;
    justify-content: center;
}

.app-card {
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--r-card);
    box-shadow: var(--sh-2);
    padding: 26px 24px 24px;
}
/* 未验证时下方的应用预览，刻意压低存在感 */
.app-card.is-locked {
    box-shadow: none;
    opacity: .68;
    padding: 16px 18px;
}

.app-head { display: flex; align-items: center; gap: 16px; }
.app-icon {
    width: 84px;
    height: 84px;
    border-radius: 20px;
    display: block;
    object-fit: cover;
    flex: none;
    box-shadow: 0 8px 18px rgba(18, 34, 65, .16);
}
.app-summary { min-width: 0; flex: 1; }

h1, h2 {
    margin: 0;
    font-size: clamp(1.35rem, 4.4vw, 1.7rem);
    font-weight: 700;
    letter-spacing: -.025em;
    line-height: 1.2;
}
.is-locked h2 { font-size: 1.05rem; font-weight: 600; }

.meta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 12px;
    margin-top: 8px;
    color: var(--ink-2);
    font-size: .86rem;
}
.updated { margin: 6px 0 0; color: var(--muted); font-size: .76rem; }

.card-title { font-size: 1.3rem; }
.card-sub {
    color: var(--muted);
    font-size: .85rem;
    margin: 8px 0 20px;
    line-height: 1.6;
}

.lock-badge {
    align-self: flex-start;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    color: var(--muted);
    flex: none;
    font-size: .72rem;
    padding: 4px 10px;
}

.device-note {
    align-items: center;
    background: var(--accent-tint);
    border: 1px solid var(--accent-line);
    border-radius: var(--r-control);
    color: var(--accent-deep);
    display: flex;
    font-size: .85rem;
    gap: 8px;
    justify-content: center;
    margin: 22px 0 14px;
    padding: 12px 14px;
    text-align: center;
}
.device-note svg { flex: none; }

/* ==========================================================================
   按钮
   一套系统，四种语气：主 / 次 / 静默 / 危险。
   前台的 .install-button 和后台的 .btn 共用同一套视觉语言。
   ========================================================================== */

.install-button,
.btn,
.modal-ok,
.admin-login button {
    align-items: center;
    border: 0;
    border-radius: var(--r-control);
    cursor: pointer;
    display: inline-flex;
    font-family: inherit;
    font-weight: 600;
    gap: 8px;
    justify-content: center;
    letter-spacing: -.005em;
    position: relative;
    overflow: hidden;
    text-decoration: none;
    transition: background-color .16s var(--ease),
                box-shadow .16s var(--ease),
                border-color .16s var(--ease),
                transform .1s var(--ease);
    -webkit-tap-highlight-color: transparent;
}

.install-button:focus-visible,
.btn:focus-visible,
.modal-ok:focus-visible,
.admin-login button:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* ── 主按钮：整页唯一的重音 ──────────────────────────────────────────────
   用垂直微渐变而不是对角线渐变：那是「受光」的意思，不是装饰。
   顶部一道内高光让它是块按得下去的实体，而不是一张平面色卡。 */
.install-button,
.modal-ok,
.btn {
    background: linear-gradient(180deg, var(--accent-lift), var(--accent));
    box-shadow: var(--sh-accent), inset 0 1px 0 rgba(255, 255, 255, .2);
    color: #fff;
}
.install-button:hover,
.modal-ok:hover,
.btn:hover {
    background: linear-gradient(180deg, #3b88f2, var(--accent-lift));
    box-shadow: 0 10px 24px rgba(10, 106, 224, .3), inset 0 1px 0 rgba(255, 255, 255, .2);
}
.install-button:active,
.modal-ok:active,
.btn:active {
    background: linear-gradient(180deg, var(--accent), var(--accent-deep));
    box-shadow: 0 3px 8px rgba(10, 106, 224, .22), inset 0 1px 0 rgba(255, 255, 255, .12);
    transform: translateY(1px);
}

/* ── 次按钮：白色描边，安静但仍是可点的实体 ───────────────────────────── */
.install-button.is-secondary,
.btn.ghost {
    background: #fff;
    border: 1.5px solid var(--line-strong);
    box-shadow: var(--sh-1);
    color: var(--ink-2);
}
.install-button.is-secondary:hover,
.btn.ghost:hover {
    background: var(--accent-tint);
    border-color: var(--accent-line);
    box-shadow: none;
    color: var(--accent-deep);
}
.install-button.is-secondary:active,
.btn.ghost:active {
    background: #dcebff;
    box-shadow: none;
    transform: translateY(1px);
}

/* ── 危险按钮：刻意不填红。实心红按钮会招来误点，
      真正的保护是操作前的确认弹窗。 ─────────────────────────────────── */
.btn.danger {
    background: #fff;
    border: 1.5px solid var(--danger-line);
    box-shadow: none;
    color: var(--danger);
}
.btn.danger:hover {
    background: var(--danger-tint);
    border-color: var(--danger);
}
.btn.danger:active { background: #fbdcdc; transform: translateY(1px); }

/* ── 尺寸：前台两档（56 / 48），后台一档（38）───────────────────────── */
.install-button {
    font-size: 1.05rem;
    margin-top: 22px;
    min-height: 56px;
    padding: 0 20px;
    width: 100%;
}
.modal-ok { font-size: 1rem; min-height: 48px; width: 100%; }
.btn { font-size: .9rem; min-height: 38px; padding: 0 16px; }
.admin-login button { font-size: 1rem; margin-top: 18px; min-height: 46px; width: 100%; }

.form-stack { display: flex; flex-direction: column; gap: 12px; }
.form-stack .install-button { margin-top: 4px; }
.form-stack label { color: var(--ink-2); display: block; font-size: .84rem; }

/* ── 通用输入控件 ────────────────────────────────────────────────────────
   用 :where() 把权重压到 0，这样下面的 .code-input 那套专门样式不会被这里覆盖。
   （没有 :where() 的老浏览器会整条跳过，退化成浏览器默认外观，不会错乱。） */
:where(input, select, textarea):where(:not(
    [type="checkbox"], [type="radio"], [type="submit"],
    [type="button"], [type="reset"], [type="file"], [type="range"]
)) {
    background: var(--paper);
    border: 1.5px solid var(--line);
    border-radius: var(--r-control);
    color: var(--ink);
    font-family: inherit;
    font-size: 1rem;
    margin-top: 7px;
    padding: 13px 14px;
    width: 100%;
    transition: border-color .16s var(--ease),
                box-shadow .16s var(--ease),
                background-color .16s var(--ease);
}
:where(input, select, textarea):where(:not(
    [type="checkbox"], [type="radio"], [type="submit"],
    [type="button"], [type="reset"], [type="file"], [type="range"]
)):focus {
    background: #fff;
    border-color: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-tint);
    outline: none;
}
:where(input, textarea)::placeholder { color: #b3bccd; }
:where(textarea) { line-height: 1.7; resize: vertical; }
:where(input[type="checkbox"]) { accent-color: var(--accent); }

.button-icon { font-size: 1.35rem; line-height: 1; }

/* ── 状态 ─────────────────────────────────────────────────────────────── */
/* 处理中：一道横扫的柔光。动效是用来回答「刚才那一下发生了什么」的 */
.install-button.is-loading,
.btn.is-loading {
    cursor: progress;
    pointer-events: none;
}
.install-button.is-loading::after {
    animation: btn-sweep 1.1s linear infinite;
    background: linear-gradient(100deg, transparent 25%, rgba(255, 255, 255, .3) 50%, transparent 75%);
    content: '';
    inset: 0;
    position: absolute;
}
@keyframes btn-sweep {
    from { transform: translateX(-100%); }
    to { transform: translateX(100%); }
}

.install-button[aria-disabled="true"],
.btn:disabled,
.modal-ok:disabled {
    box-shadow: none;
    cursor: not-allowed;
    opacity: .55;
    transform: none;
}

.install-hint {
    color: var(--muted);
    font-size: .78rem;
    line-height: 1.6;
    margin: 10px 0 0;
    text-align: center;
}

/* ==========================================================================
   表单与「机器文本」
   下载码是用户唯一需要核对的数据，给它一套独立的排版语气：
   等宽、拉开字距、居中、凹进去。和正文形成明确对比。
   ========================================================================== */

.code-input {
    background: var(--paper);
    border: 1.5px solid var(--line);
    border-radius: var(--r-control);
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: 1.28rem;
    letter-spacing: .14em;
    margin-top: 0;
    padding: 15px 16px;
    text-align: center;
    text-transform: uppercase;
    width: 100%;
    transition: border-color .16s var(--ease), box-shadow .16s var(--ease), background-color .16s var(--ease);
}
.code-input::placeholder { color: #b3bccd; letter-spacing: .14em; }
.code-input:focus {
    background: #fff;
    border-color: var(--accent);
    box-shadow: 0 0 0 4px var(--accent-tint);
    outline: none;
}

.code-display {
    background: var(--paper);
    border: 1.5px dashed var(--line-strong);
    border-radius: var(--r-control);
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: 1.3rem;
    letter-spacing: .14em;
    margin: 0 0 20px;
    padding: 16px;
    text-align: center;
}

/* ==========================================================================
   提示条
   ========================================================================== */
.notice {
    border-radius: var(--r-card-sm);
    font-size: .85rem;
    line-height: 1.6;
    margin: 0;
    padding: 13px 16px;
}
.notice.error { background: var(--danger-tint); border: 1px solid var(--danger-line); color: #a52c31; }
.notice.ok { background: var(--ok-tint); border: 1px solid var(--ok-line); color: #0d7b3d; }
.notice.warn { background: var(--warn-tint); border: 1px solid var(--warn-line); color: var(--warn); }

.card-sub code,
.install-hint code {
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 6px;
    font-family: var(--font-mono);
    font-size: .86em;
    padding: 1px 6px;
    word-break: break-all;
}

/* ==========================================================================
   环境检查清单（setup.php）
   ========================================================================== */
.checklist { list-style: none; margin: 0 0 20px; padding: 0; }
.checklist li {
    align-items: center;
    display: flex;
    font-size: .86rem;
    gap: 10px;
    padding: 7px 0;
}
/* ✓/✕ 做成小圆徽标，比裸字符更像控件的状态指示 */
.checklist .check {
    align-items: center;
    border-radius: 50%;
    display: inline-flex;
    flex: none;
    font-size: .7rem;
    font-weight: 700;
    height: 19px;
    justify-content: center;
    line-height: 1;
    width: 19px;
}
.checklist .ok .check { background: var(--ok-tint); color: var(--ok); }
.checklist .bad .check { background: var(--danger-tint); color: var(--danger); }
.checklist .bad { color: #a52c31; }

/* 检查失败时给出具体怎么改。换行由 PHP 侧的 nl2br 负责，
   这里不依赖 white-space，否则样式表一旦被缓存旧版整段就会塌成一坨。 */
.checklist-lg li { align-items: flex-start; line-height: 1.5; }
.checklist-lg li > div { flex: 1; min-width: 0; }
.check-hint {
    color: var(--muted);
    font-size: .78rem;
    line-height: 1.75;
    margin-top: 7px;
    overflow-wrap: anywhere;
}

/* ==========================================================================
   二维码
   ========================================================================== */
.scan-panel { align-items: center; display: flex; flex-direction: column; gap: 12px; }
.qr-box {
    align-items: center;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: var(--r-card-sm);
    box-shadow: var(--sh-1);
    display: flex;
    justify-content: center;
    max-width: 230px;
    padding: 12px;
    width: 100%;
}
.qr-box canvas { border-radius: 6px; display: block; }
.scan-panel p { color: var(--ink-2); font-size: .85rem; margin: 0; text-align: center; }
.scan-panel .qr-expire { color: var(--muted); font-size: .74rem; }

.logout-row { margin: 4px 0 0; text-align: center; }
.logout-row a {
    color: var(--muted);
    font-size: .8rem;
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color .16s var(--ease), border-color .16s var(--ease);
}
.logout-row a:hover { color: var(--ink-2); border-bottom-color: var(--line-strong); }

/* ==========================================================================
   错误页
   ========================================================================== */
.setup-title { margin-bottom: 20px; }
.error-title { font-size: 1.25rem; }
.error-text { color: var(--ink-2); font-size: .9rem; line-height: 1.7; margin: 12px 0 0; }

/* ==========================================================================
   弹窗
   ========================================================================== */
body.modal-open { overflow: hidden; }

.modal-mask {
    align-items: center;
    animation: modal-fade .16s ease-out;
    background: rgba(18, 28, 48, .48);
    display: flex;
    inset: 0;
    justify-content: center;
    padding: 24px;
    position: fixed;
    z-index: 50;
    backdrop-filter: blur(2px);
}
.modal-mask[hidden] { display: none; }

.modal-box {
    animation: modal-pop .2s var(--ease);
    background: #fff;
    border-radius: var(--r-card);
    box-shadow: var(--sh-3);
    max-width: 320px;
    padding: 26px 22px 20px;
    text-align: center;
    width: 100%;
}
.modal-text { font-size: 1rem; line-height: 1.6; margin: 0 0 20px; }

@keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-pop {
    from { opacity: 0; transform: translateY(10px) scale(.97); }
    to { opacity: 1; transform: none; }
}

/* ==========================================================================
   只允许 Safari 打开
   样式沿用独立模板 safari 浏览器.html，类名保持一致，方便两边对照。
   ========================================================================== */
html.browser-restriction-open { overflow: hidden; }

.browser-restriction-dialog {
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    animation: fadeInOverlay 0.4s ease-out;
    padding: 20px;
    min-height: 100vh;
}
.browser-restriction-dialog[hidden] {
    display: none;
}
.browser-restriction-content {
    width: 100%;
    max-width: 480px;
    padding: 0;
    border-radius: 32px;
    background: #fff;
    box-shadow: 0 40px 120px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(255, 255, 255, 0.1);
    animation: slideUpDialog 0.5s cubic-bezier(0.16, 1, 0.3, 1);
    text-align: center;
    position: relative;
    overflow: hidden;
}
.browser-restriction-header {
    background: linear-gradient(135deg, #ff4757 0%, #ff6348 100%);
    padding: 40px 32px 28px 32px;
    position: relative;
}
.browser-restriction-header::after {
    content: '';
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 1px;
    background: rgba(255, 255, 255, 0.2);
}
.browser-restriction-subtitle {
    margin-bottom: 24px;
    color: #ffffff;
    font-size: 22px;
    font-weight: 600;
    line-height: 1.4;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
    letter-spacing: 0;
}
.browser-restriction-icon-wrapper {
    width: 140px;
    height: 140px;
    margin: 0 auto 20px;
    background: rgba(255, 255, 255, 0.15);
    border: 3px solid rgba(255, 255, 255, 0.3);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    backdrop-filter: blur(10px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
.browser-restriction-icon {
    width: 100px;
    height: 100px;
    object-fit: contain;
    filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.2));
}
.browser-restriction-header-note {
    margin-top: 0;
    padding: 16px 20px;
    color: rgba(255, 255, 255, 0.95);
    font-size: 14px;
    line-height: 1.7;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 12px;
    backdrop-filter: blur(8px);
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
.browser-restriction-header-note strong {
    color: #ffffff;
    font-weight: 600;
}
.browser-restriction-body {
    padding: 40px 32px;
}
.browser-restriction-title {
    margin-bottom: 0;
    color: #ff4757;
    font-size: 32px;
    font-weight: 700;
    line-height: 1.3;
}
/* App 内置浏览器（微信/QQ 等）里额外补一句怎么跳出去 */
.browser-restriction-tip {
    margin-top: 16px;
    padding: 12px 16px;
    color: #8a5a00;
    font-size: 14px;
    line-height: 1.7;
    background: #fff8e6;
    border: 1px solid #ffe2a8;
    border-radius: 12px;
    text-align: left;
}
.browser-restriction-tip[hidden] {
    display: none;
}
@keyframes fadeInOverlay {
    from { opacity: 0; }
    to { opacity: 1; }
}
@keyframes slideUpDialog {
    from {
        opacity: 0;
        transform: translateY(28px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}
@media (max-width: 768px) {
    .browser-restriction-content {
        max-width: 420px;
        border-radius: 28px;
    }
    .browser-restriction-header {
        padding: 36px 28px 28px 28px;
    }
    .browser-restriction-subtitle {
        margin-bottom: 20px;
        font-size: 20px;
    }
    .browser-restriction-icon-wrapper {
        width: 120px;
        height: 120px;
        margin-bottom: 16px;
    }
    .browser-restriction-icon {
        width: 85px;
        height: 85px;
    }
    .browser-restriction-header-note {
        padding: 14px 18px;
        border-radius: 10px;
        font-size: 13px;
    }
    .browser-restriction-body {
        padding: 36px 28px;
    }
    .browser-restriction-title {
        font-size: 28px;
    }
}
@media (max-width: 480px) {
    .browser-restriction-content {
        max-width: 360px;
        border-radius: 24px;
    }
    .browser-restriction-header {
        padding: 32px 24px 24px 24px;
    }
    .browser-restriction-subtitle {
        margin-bottom: 18px;
        font-size: 18px;
    }
    .browser-restriction-icon-wrapper {
        width: 110px;
        height: 110px;
        margin-bottom: 14px;
    }
    .browser-restriction-icon {
        width: 75px;
        height: 75px;
    }
    .browser-restriction-header-note {
        padding: 12px 16px;
        border-radius: 10px;
        font-size: 12px;
    }
    .browser-restriction-body {
        padding: 32px 24px;
    }
    .browser-restriction-title {
        font-size: 24px;
    }
}

/* ==========================================================================
   无障碍与降级
   ========================================================================== */
.sr-only {
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

@media (max-width: 430px) {
    .page-shell { padding: 22px 14px 28px; }
    .app-card { border-radius: 20px; padding: 24px 20px 22px; }
    .app-icon { border-radius: 17px; height: 74px; width: 74px; }
    .app-head { gap: 14px; }
}
