/* ── 锁屏 (js/apps/lockscreen.js) ──
   The sheet carries the wallpaper, clock and notifications and slides up off the page underneath; the swipe zone is the
   lower-middle band, ending above the real phone's bottom system edge. Same column as the app (max 430px). */
.lockscreen{position:fixed;inset:0;left:0;right:0;margin:0 auto;max-width:430px;z-index:95;overflow:hidden}
.lockscreen[hidden]{display:none}
.lockscreen:focus{outline:none}
.lock-sheet{position:absolute;inset:0;display:flex;flex-direction:column;background:var(--bg);will-change:transform;box-shadow:0 12px 32px rgba(46,62,80,calc(.22 * var(--lock-progress,0)))}
.lock-wallpaper{z-index:0}
.lock-sheet>:not(.lock-wallpaper){position:relative;z-index:1}
.lock-clock-wrap{flex-shrink:0;text-align:center;padding:calc(72px + env(safe-area-inset-top,0px)) 24px 0}
.lock-date{margin-bottom:4px;font-size:14px;color:var(--wall-ink2,var(--ink2));letter-spacing:.04em;text-shadow:var(--wall-shadow,none)}
.lock-time{font-size:clamp(92px,32.3vw,126px)}   /* 字体与玻璃效果: .glass-clock (styles/desktop.css); 126px keeps "22:14" whole */
/* 照 iPhone: the clock and the notifications scroll together (pushed up, the clock leaves with them - nothing is ever cut
   off under it), the notifications sit at the bottom, and the list runs to the screen's edge under the floating bar. */
.lock-scroll{flex:1;min-height:0;display:flex;flex-direction:column;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none}
.lock-scroll::-webkit-scrollbar{display:none}
.lock-notifs{margin-top:auto;padding:22px 10px calc(76px + var(--sab))}
.lock-sheet>.lock-swipe-zone{position:absolute;left:50%;bottom:0;width:200px;margin-left:-100px;height:calc(46px + var(--sab));padding-bottom:var(--sab);box-sizing:border-box;z-index:2;display:flex;align-items:flex-end;justify-content:center;touch-action:none;cursor:grab;user-select:none;-webkit-user-select:none}
.lock-unlock-btn{display:flex;align-items:center;justify-content:center;border:none;background:none;padding:14px 34px 12px;border-radius:16px;cursor:pointer}
.lock-bar{width:130px;height:5px;border-radius:3px;background:var(--ns-bar);animation:lockNudge 2.4s ease-in-out infinite}
@keyframes lockNudge{0%,70%,100%{transform:translateY(0)}80%{transform:translateY(-5px)}90%{transform:translateY(0)}}

/* ── Pull-down notification panel (js/apps/notifications.js) ──
   Opens straight to full screen: it fills the app's own column (max 430px wide, the whole height) whatever the list's
   length, an empty list included. Plain dim + solid surface (no backdrop blur) so dragging never re-blurs the page every
   frame. touch-action:none only where a drag is ours: the desktop's status row (pull down to open), the panel head and
   handle (push up to close), and the list while it has nothing to scroll (.is-static); a list that scrolls keeps pan-y. */
#v-home .status-bar{touch-action:none}
.notif-panel-root{position:fixed;inset:0;left:0;right:0;margin:0 auto;max-width:430px;z-index:90;overflow:hidden}
.notif-panel-root[hidden]{display:none}
.notif-panel-scrim{position:absolute;inset:0;background:rgba(30,40,52,.3);opacity:var(--panel-progress,0)}
.notif-panel-root.animating .notif-panel-scrim{transition:opacity .3s ease}
.notif-panel{position:absolute;inset:0;display:flex;flex-direction:column;background:var(--bg);color:var(--ns-ink);box-shadow:0 18px 40px rgba(46,62,80,.18);padding-top:env(safe-area-inset-top,0px);will-change:transform;outline:none;overflow:hidden}
/* 背景: the desktop wallpaper under a static CSS blur (.np-wall; rasterised once, then only moved with the panel), veiled.
   No wallpaper: the theme background under a soft dark veil. */
.np-bg{position:absolute;inset:0;z-index:0;pointer-events:none;background:var(--bg)}
/* frosted glass over the real desktop wallpaper (#np-wallpaper, painted by the theme engine): a CSS blur of the full-size picture,
   bled past the panel's clipped edge so the blur never shows a light rim */
.np-wall{display:none;position:absolute;inset:-96px;filter:blur(32px) saturate(1.05)}
.notif-panel-root.has-wall .np-wall{display:block}
.np-bg::after{content:"";position:absolute;inset:0}
/* only a wallpaper is dimmed; the plain theme background stays as it is (no grey wash) */
.notif-panel-root.has-wall .np-bg::after{background:rgb(18 26 38/30%)}
/* a bright wallpaper (dark ink) gets a light veil, a dark one a dark veil - never a grey wash */
.notif-panel-root[data-wall-tone="dark"] .np-bg::after{background:rgb(240 245 252/38%)}
.notif-panel>:not(.np-bg){position:relative;z-index:1}
.notif-panel-head{flex-shrink:0;display:flex;align-items:center;gap:10px;padding:14px 16px 6px 20px;touch-action:none;user-select:none;-webkit-user-select:none}
.notif-panel-head h2{flex:1;margin:0;font-family:var(--font-display);font-size:22px;font-weight:600;color:var(--ns-ink);text-shadow:var(--ns-tshadow,none)}
.notif-panel-list{flex:1 1 auto;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none;padding:6px 10px calc(60px + var(--sab))}
.notif-panel-list::-webkit-scrollbar{display:none}
.notif-panel-list.is-static{touch-action:none}
.notif-panel-empty{padding:34px 20px 26px}
.notif-panel-empty svg{box-sizing:content-box;width:30px;height:30px;padding:16px;margin-bottom:12px;border-radius:50%;border:1px solid var(--ns-edge);background:var(--ns-fill);color:var(--ns-ink2)}
.notif-panel-empty h3{color:var(--ns-ink)}
/* the bar floats over the list's lower end like the lock screen's, above the real phone's bottom system edge */
.notif-panel>.notif-panel-handle{position:absolute;left:50%;bottom:0;width:200px;margin-left:-100px;z-index:2;height:calc(44px + var(--sab));padding:0 0 calc(12px + var(--sab));box-sizing:border-box;border:none;background:none;display:flex;align-items:flex-end;justify-content:center;touch-action:none;cursor:grab}
.notif-panel-handle i{display:block;width:120px;height:5px;border-radius:3px;background:var(--ns-bar)}

/* Short screens (a 320×568 phone, landscape): a smaller clock and less air, so the notifications keep usable room. */
@media (max-height:600px){
  .lock-clock-wrap{padding-top:calc(22px + env(safe-area-inset-top,0px))}
  .lock-date{font-size:12.5px}
  .lock-time{font-size:clamp(44px,13vh,64px)}
  .lock-notifs{padding-top:14px}
}

@media (prefers-reduced-motion:reduce){
  .lock-bar{animation:none}
  .notif-panel-root.animating .notif-panel-scrim{transition:none}
}

/* ── 通知叠放 (notifications.js notifStacksHtml): the lock screen and the notification center, 照 iPhone ──
   Clear glass: the wallpaper shows through, a bright rim and a slight lift tell the card apart; no drop shadows anywhere.
   On a dark surface (a dark wallpaper, or dark mode without one) the glass is clearer and the text white. */
.lockscreen,.notif-panel-root{--ns-fill:rgb(255 255 255/60%);--ns-edge:rgb(255 255 255/85%);--ns-ink:var(--ink);--ns-ink2:var(--ink2);--ns-ink3:var(--ink2);--ns-blur:blur(14px) saturate(130%);--ns-bar:color-mix(in srgb,var(--ink) 42%,transparent);--ns-tshadow:none}
.lockscreen.has-wall,.notif-panel-root.has-wall{--ns-fill:rgb(255 255 255/40%);--ns-edge:rgb(255 255 255/90%);--ns-blur:blur(5px) saturate(120%)}
.lockscreen[data-wall-tone="light"],.lockscreen.icons-on-dark:not([data-wall-tone="dark"]),.notif-panel-root[data-wall-tone="light"],.notif-panel-root.icons-on-dark:not([data-wall-tone="dark"]){--ns-fill:rgb(255 255 255/14%);--ns-edge:rgb(255 255 255/40%);--ns-ink:#FFFFFF;--ns-ink2:rgb(255 255 255/88%);--ns-ink3:rgb(255 255 255/70%);--ns-blur:blur(5px) saturate(150%) brightness(.9);--ns-bar:rgb(255 255 255/92%);--ns-tshadow:0 1px 2px rgb(0 0 0/25%)}
/* the panel's background is already the blurred wallpaper (.np-wall), so its cards are plain translucent fill: a live blur on
   every card would be redone on every frame of the pull */
.notif-panel-list.ns-host{--ns-blur:none}
.notif-panel-list .ns-av.dock-icon{-webkit-backdrop-filter:none;backdrop-filter:none}
.ns-grp{margin-bottom:8px;transition:height .28s cubic-bezier(.4,0,.2,1),margin .28s}
.ns-row{position:relative;transition:height .28s cubic-bezier(.4,0,.2,1),margin .28s}
.ns-row:has(>.ns-layer){padding-bottom:18px}   /* the two cards peeking out under a stack are part of its own height */
.ns-expanded .ns-row{margin-bottom:8px}
.ns-grp.ns-gone,.ns-row.ns-gone{margin:0!important;height:0!important;overflow:hidden}
.ns-gone .ns-card,.ns-gone .ns-layer,.ns-gone .ns-ghead{opacity:0;transition:opacity .2s}
.ns-card{position:relative;z-index:2;display:flex;gap:11px;align-items:flex-start;padding:13px 14px;border:1px solid var(--ns-edge);border-radius:24px;background:var(--ns-fill);-webkit-backdrop-filter:var(--ns-blur);backdrop-filter:var(--ns-blur);box-shadow:inset 0 1px 0 rgb(255 255 255/22%);color:var(--ns-ink);text-shadow:var(--ns-tshadow);touch-action:pan-y;cursor:pointer;outline:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
.ns-card:focus-visible{border-color:var(--ns-ink)}
.ns-card:active{scale:.97;transition:scale .12s}
.ns-layer{position:absolute;z-index:1;height:40px;border:1px solid var(--ns-edge);border-radius:20px;background:var(--ns-fill);-webkit-backdrop-filter:var(--ns-blur);backdrop-filter:var(--ns-blur);pointer-events:none}
.ns-l1{left:2.5%;right:2.5%;bottom:9px;opacity:.85;clip-path:inset(calc(100% - 10px) -2px -2px -2px)}
.ns-l2{left:5%;right:5%;bottom:0;opacity:.65;clip-path:inset(calc(100% - 10px) -2px -2px -2px)}
.ns-av{position:relative;flex:none;width:38px;height:38px;border-radius:12px;overflow:hidden;display:flex;align-items:center;justify-content:center}
.ns-av img,.ns-av .character-avatar-fallback,.ns-av .avatar-placeholder{width:100%;height:100%;object-fit:cover;display:flex;align-items:center;justify-content:center}
/* an App's own desktop icon (desk-glyphs.js on the .dock-icon glass), made see-through: white lines on a dark surface */
.ns-av.dock-icon{width:38px;height:38px;border-radius:12px;box-shadow:inset 0 1.5px 0 rgb(255 255 255/70%)}
.ns-av.dock-icon svg:not(.glass-glyph){width:20px;height:20px}
.lockscreen.has-wall .ns-av.dock-icon,.notif-panel-root.has-wall .ns-av.dock-icon{background:linear-gradient(160deg,rgb(255 255 255/45%),rgb(255 255 255/18%) 60%,rgb(255 255 255/32%));border-color:rgb(255 255 255/75%)}
.lockscreen.has-wall .ns-av.dock-icon .glass-glyph .f1,.notif-panel-root.has-wall .ns-av.dock-icon .glass-glyph .f1{fill:rgb(255 255 255/55%)}
.lockscreen.has-wall .ns-av.dock-icon .glass-glyph .f2,.notif-panel-root.has-wall .ns-av.dock-icon .glass-glyph .f2{fill:color-mix(in srgb,var(--pri-pale) 55%,transparent)}
:is(.lockscreen[data-wall-tone="light"],.lockscreen.icons-on-dark:not([data-wall-tone="dark"]),.notif-panel-root[data-wall-tone="light"],.notif-panel-root.icons-on-dark:not([data-wall-tone="dark"])) .ns-av.dock-icon{--ln:rgb(255 255 255/95%);color:var(--ln);background:linear-gradient(160deg,rgb(255 255 255/22%),rgb(255 255 255/6%) 60%,rgb(255 255 255/12%));border-color:rgb(255 255 255/28%);box-shadow:inset 0 1px 0 rgb(255 255 255/40%)}
:is(.lockscreen[data-wall-tone="light"],.lockscreen.icons-on-dark:not([data-wall-tone="dark"]),.notif-panel-root[data-wall-tone="light"],.notif-panel-root.icons-on-dark:not([data-wall-tone="dark"])) .ns-av.dock-icon::before{opacity:.25}
:is(.lockscreen[data-wall-tone="light"],.lockscreen.icons-on-dark:not([data-wall-tone="dark"]),.notif-panel-root[data-wall-tone="light"],.notif-panel-root.icons-on-dark:not([data-wall-tone="dark"])) .ns-av.dock-icon .glass-glyph .f1{fill:rgb(255 255 255/28%)}
:is(.lockscreen[data-wall-tone="light"],.lockscreen.icons-on-dark:not([data-wall-tone="dark"]),.notif-panel-root[data-wall-tone="light"],.notif-panel-root.icons-on-dark:not([data-wall-tone="dark"])) .ns-av.dock-icon .glass-glyph .f2{fill:rgb(255 255 255/12%)}
.ns-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.ns-top{display:flex;align-items:baseline;gap:8px}
.ns-top b{flex:1;min-width:0;font-size:15px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ns-top time{flex:none;font-size:12px;color:var(--ns-ink3)}
.ns-body{font-size:15px;line-height:1.3;color:var(--ns-ink2);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
/* 打开 / 清除 behind a card, revealed by the sideways swipe */
.ns-acts{position:absolute;inset:0 0 auto;height:100%;z-index:0;display:flex;align-items:center;justify-content:space-between;padding:0 4px;pointer-events:none}
.ns-row:has(>.ns-layer)>.ns-acts{height:calc(100% - 18px)}
.ns-row:not(.ns-sliding)>.ns-acts{visibility:hidden}
.ns-open{opacity:var(--ns-r,0);font-size:13px;color:var(--ns-ink);text-shadow:var(--ns-tshadow);padding-left:14px}
.ns-clear{opacity:var(--ns-l,0);pointer-events:auto;width:76px;height:calc(100% - 8px);border:1px solid var(--ns-edge);border-radius:20px;background:var(--ns-fill);-webkit-backdrop-filter:var(--ns-blur);backdrop-filter:var(--ns-blur);color:var(--ns-ink);font:inherit;font-size:13.5px;cursor:pointer}
/* headings: an opened stack's App · 收起 · ×, and the lock screen's 通知中心 over the older ones */
.ns-ghead,.ns-sec{display:flex;align-items:center;gap:8px;color:var(--ns-ink);text-shadow:var(--ns-tshadow)}
.ns-ghead{padding:2px 4px 8px 8px}
.ns-ghead b{flex:1;min-width:0;font-size:15px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ns-sec{padding:16px 4px 10px 8px}
.ns-sec b{flex:1;font-family:var(--font-display);font-size:20px;font-weight:600}
.ns-sec-acts{display:flex;gap:6px}
.ns-ghead button,.ns-sec button,.notif-clear-all,.ns-older-pill{height:30px;min-width:30px;padding:0 13px;border:1px solid var(--ns-edge);border-radius:999px;background:var(--ns-fill);-webkit-backdrop-filter:var(--ns-blur);backdrop-filter:var(--ns-blur);color:var(--ns-ink);font:inherit;font-size:13px;text-shadow:none;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:padding .3s cubic-bezier(.3,1.35,.5,1)}
.ns-ghead .ns-gx,.ns-sec .ns-sec-x,.notif-clear-all{padding:0;width:auto}
.ns-ghead .ns-gx svg,.ns-sec .ns-sec-x svg,.notif-clear-all svg{width:14px;height:14px}
.ns-sec .ns-sec-x.armed,.notif-clear-all.armed{padding:0 14px}
.notif-clear-all:disabled{opacity:.45;cursor:default}
.ns-older-pill{display:flex;margin:6px auto 0;padding:0 16px;color:var(--ns-ink2)}
.ns-older-pill:active{transform:scale(.93)}
/* rubber band (notifRubberScroll) */
/* only while pulling / springing back: a resting list gets no transform (it would put every row on its own layer) */
.ns-rb-on>*,.ns-rb-back>*{transform:translateY(var(--ns-rb,0px))}
.ns-rb-back>*{transition:transform .5s cubic-bezier(.25,1.3,.4,1)}
/* 动效: always on the glass itself, never on a parent (a half-transparent parent turns the glass blur off) */
.ns-row.ns-pop>.ns-card,.ns-row.ns-pop>.ns-layer,.ns-ghead.ns-pop>*{animation:nsPop .42s cubic-bezier(.3,1.35,.5,1) backwards;animation-delay:calc(var(--i,0)*35ms)}
@keyframes nsPop{from{transform:translateY(calc(var(--i,0)*-62px)) scale(.94);opacity:0}}
.ns-row.ns-fold>.ns-card,.ns-row.ns-fold>.ns-layer,.ns-ghead.ns-fold>*{animation:nsFold .2s ease-in forwards;animation-delay:calc(var(--i,0)*15ms)}
@keyframes nsFold{to{transform:translateY(calc(var(--i,0)*-62px)) scale(.94);opacity:0}}
.ns-row.ns-new>.ns-card,.ns-row.ns-new>.ns-layer{animation:nsNew .45s cubic-bezier(.3,1.35,.5,1)}
@keyframes nsNew{from{transform:translateY(-14px) scale(.96);opacity:0}}
.ns-casc>.ns-grp .ns-card,.ns-casc>.ns-grp .ns-layer{animation:nsCasc .55s cubic-bezier(.3,1.35,.5,1) backwards;animation-delay:calc(var(--i,0)*70ms)}
@keyframes nsCasc{from{transform:translateY(-46px) scale(.9);opacity:0}}
.ns-uncasc>.ns-grp .ns-card,.ns-uncasc>.ns-grp .ns-layer{animation:nsUncasc .22s ease-in forwards;animation-delay:calc(var(--j,0)*40ms)}
@keyframes nsUncasc{to{transform:translateY(-36px) scale(.9);opacity:0}}
.ns-sec-in>*{animation:nsSecIn .35s ease-out}
@keyframes nsSecIn{from{opacity:0;transform:translateY(-6px)}}
.ns-sec-out>*{animation:nsSecOut .2s ease-in forwards}
@keyframes nsSecOut{to{opacity:0;transform:translateY(-6px)}}
.ns-older-pill.ns-go{animation:nsPillGo .2s ease-in forwards}
@keyframes nsPillGo{to{transform:scale(.6);opacity:0}}
.ns-older-pill.ns-pill-in{animation:nsPillIn .5s cubic-bezier(.3,1.4,.5,1)}
@keyframes nsPillIn{from{transform:scale(.55);opacity:0}}
@media (prefers-reduced-motion:reduce){
  .ns-row>.ns-card,.ns-row>.ns-layer,.ns-ghead>*,.ns-sec>*,.ns-older-pill{animation:none!important}
  .ns-grp,.ns-row,.ns-rb-back>*,.ns-card:active{transition:none}
}


/* ── 锁屏时钟和桌面时钟一样大 (hand-written, keep LAST): the same size rule as .home-clock (index.html), so unlocking does
   not make the time jump. ── */
.lock-time{font-size:clamp(56px,11.4vh,96px)}
