/* Vue 3 v2.8 – single shared core stylesheet.
   Contains layout primitives, theme tokens, responsive rules, and animations only.
   Each pages/*.css file is page-specific geometry kept for existing business screens. */

/* == feedback.css == */
/* =====================================================
   全局操作反馈 & 页面过渡 & 骨架屏 & 加载遮罩
   + 移动端适配 & 选项卡横向滑动增强
   ===================================================== */

/* -------- 1. 页面过渡 -------- */
.container,
.navbar,
.login-card,
.login-prompt,
.app-header {
  animation: contentEnter 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes contentEnter {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Vue RouterGuard uses native navigation; never hide document on exit. */


/* -------- 2. 骨架屏 -------- */
.skeleton {
  background: linear-gradient(90deg,
    #eef2f7 0%,
    #e2e8f0 50%,
    #eef2f7 100%);
  background-size: 200% 100%;
  animation: skeletonShine 1.4s ease-in-out infinite;
  border-radius: 12px;
}
@keyframes skeletonShine {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton-card {
  height: 130px;
  border-radius: 24px;
}
.skeleton-line {
  height: 14px;
  margin-bottom: 10px;
  border-radius: 8px;
}
.skeleton-line.short  { width: 40%; }
.skeleton-line.medium { width: 65%; }
.skeleton-line.long   { width: 90%; }

/* -------- 3. 按钮点击波纹 -------- */
.btn, .refresh-btn, .btn-submit, .upload-cancel-btn, .toggle-btn,
.tab-btn, .submission-tab, .login-btn, .btn-back, .app-card, .msg-item,
.login-card .btn, .login-card button[type="submit"] {
  position: relative;
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
}

.btn:not(:disabled):active,
.refresh-btn:not(:disabled):active,
.btn-submit:not(:disabled):active,
.upload-cancel-btn:not(:disabled):active,
.toggle-btn:not(:disabled):active,
button[type="submit"]:not(:disabled):active {
  transform: scale(0.97);
  transition: transform 0.08s ease;
}

.ripple-effect {
  position: absolute;
  border-radius: 50%;
  transform: scale(0);
  animation: rippleAnim 0.6s cubic-bezier(0.22, 1, 0.36, 1);
  pointer-events: none;
  z-index: 1;
}
@keyframes rippleAnim {
  to { transform: scale(2.8); opacity: 0; }
}

/* -------- 4. 按钮 loading spinner -------- */
.is-loading {
  pointer-events: none;
  opacity: 0.85;
}
.loading-spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spinnerSpin 0.7s linear infinite;
  margin-right: 8px;
  vertical-align: -2px;
}
@keyframes spinnerSpin { to { transform: rotate(360deg); } }

/* -------- 5. 成功/失败脉冲 -------- */
.pulse-success { animation: pulseGreen 0.9s ease; }
.pulse-error   { animation: pulseRed 0.9s ease; }
@keyframes pulseGreen {
  0%   { background-color: rgba(16, 185, 129, 0); }
  35%  { background-color: rgba(16, 185, 129, 0.28); }
  100% { background-color: rgba(16, 185, 129, 0); }
}
@keyframes pulseRed {
  0%   { background-color: rgba(239, 68, 68, 0); }
  35%  { background-color: rgba(239, 68, 68, 0.28); }
  100% { background-color: rgba(239, 68, 68, 0); }
}

/* -------- 7. 卡片点击 -------- */
.app-card:active { transform: translateY(-2px) scale(0.99); }

/* =====================================================
   全新选项卡：胶囊分段控件（Segmented Control）
   ===================================================== */
.tabs-wrap {
  display: flex;
  justify-content: center;
  margin-bottom: 24px;
  position: relative;   /* 用于左右渐变遮罩定位 */
}
.tabs {
  display: inline-flex;
  background: rgba(226, 232, 240, 0.65);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 999px;
  padding: 5px;
  gap: 4px;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05);
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  /* ---- 移动端横向滑动增强 ---- */
  -webkit-overflow-scrolling: touch;   /* iOS 惯性滚动 */
  overscroll-behavior-x: contain;      /* 横向滚动不传递给父元素 */
  touch-action: pan-x;                 /* 允许横向触摸滑动 */
}
.tabs::-webkit-scrollbar { display: none; }

.tab-btn {
  padding: 10px 26px;
  border: none;
  background: transparent;
  font-size: 15px;
  font-weight: 600;
  color: #64748b;
  cursor: pointer;
  border-radius: 999px;
  transition: all 0.28s cubic-bezier(0.4, 0, 0.2, 1);
  white-space: nowrap;
  font-family: inherit;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  position: relative;
}
.tab-btn:hover:not(.active) {
  color: #334155;
  background: rgba(255, 255, 255, 0.6);
}
.tab-btn.active {
  background: #ffffff;
  color: #2a6df4;
  box-shadow:
    0 2px 10px rgba(42, 109, 244, 0.18),
    0 1px 2px rgba(0, 0, 0, 0.04);
}

.tabs:not(.tabs-wrap) { margin-left: auto; margin-right: auto; }

@media (max-width: 640px) {
  .tab-btn { padding: 9px 18px; font-size: 14px; }
}

/* =====================================================
   移动端适配 & 选项卡横向滑动增强
   ===================================================== */

:root {
  /* 页面背景色，用于左右渐变提示，各页面可覆盖 */
  --tabs-fade-bg: #f0f4ff;
}

/* 移动端：防止 iOS 横屏字体自动放大 */
html.is-mobile {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* 移动端：禁用点击高亮，触摸响应更干脆 */
html.is-mobile body {
  -webkit-tap-highlight-color: transparent;
}

/* iOS：输入框 font-size 小于 16px 会触发聚焦缩放，这里兜底 */
html.is-ios input,
html.is-ios textarea,
html.is-ios select,
html.is-ios .form-control {
  font-size: max(16px, 1em);
}

/* 触摸设备：tabs 可拖动光标提示（桌面触屏也有意义） */
html.is-touch .tabs {
  cursor: grab;
}
html.is-touch .tabs:active {
  cursor: grabbing;
}

/* ===== 溢出提示：左右渐变遮罩 ===== */
.tabs-wrap.has-overflow::before,
.tabs-wrap.has-overflow::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 24px;
  pointer-events: none;
  z-index: 2;
  opacity: 0;
  transition: opacity 0.2s ease;
}

/* 不在最左端时，左侧显示渐变（提示可向左滑） */
.tabs-wrap.has-overflow:not(.at-start)::before {
  left: 0;
  background: linear-gradient(to right, var(--tabs-fade-bg), transparent);
  opacity: 1;
}

/* 不在最右端时，右侧显示渐变（提示可向右滑） */
.tabs-wrap.has-overflow:not(.at-end)::after {
  right: 0;
  background: linear-gradient(to left, var(--tabs-fade-bg), transparent);
  opacity: 1;
}

/* ===== 尊重"减少动画"偏好 ===== */
@media (prefers-reduced-motion: reduce) {
  .skeleton,
  .skeleton-card,
  .skeleton-line,
  .skeleton-grid .skeleton-card,
  .skeleton-table-row,
  .skeleton-item {
    animation: none;
  }
}

/* == assets/design.css == */
/* 学分服务中心 - adaptive dual-device design system. Applies after old view CSS. */
:root{color-scheme:light;--bg:#f4f7fc;--surface:#fff;--ink:#182940;--muted:#718198;--blue:#215cda;--blue-strong:#1749b7;--sky:#eaf2ff;--border:#e5ebf4;--shadow:0 12px 40px rgba(17,43,85,.055);--radius:18px;--sidebar-width:248px;font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft Yahei",sans-serif}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;min-height:100%;background:var(--bg)}
body{margin:0!important;min-height:100vh;min-height:100dvh;background:var(--bg)!important;color:var(--ink)!important;font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft Yahei",sans-serif!important;line-height:1.6;-webkit-font-smoothing:antialiased}
button,input,select,textarea{font:inherit}
button{cursor:pointer;touch-action:manipulation}a{text-decoration:none}a,button,input,textarea{ -webkit-tap-highlight-color:transparent}
:focus-visible{outline:3px solid rgba(37,99,235,.48)!important;outline-offset:3px}
::selection{background:#c9ddff;color:#0b3f94}
#app{min-height:100dvh}.first-paint{display:flex;align-items:center;justify-content:center;flex-direction:column;gap:18px;min-height:100dvh;color:#63758d;font-weight:600;font-size:14px}.first-paint-logo,.topbar-emblem{display:inline-grid;place-items:center;background:linear-gradient(150deg,#1764e3,#418cf4);color:#fff;border-radius:15px;font-size:22px;font-weight:800;width:52px;height:52px;box-shadow:0 12px 24px #215cda3b}.first-paint-bar{width:140px;height:4px;background:linear-gradient(90deg,#d6e4fa 0 20%,#3677e4 45%,#d6e4fa 75%);border-radius:10px;background-size:200% 100%;animation:shimmer 1.3s ease-in-out infinite}.fatal-error{margin:20vh auto;max-width:400px;text-align:center;padding:25px;background:#fff;color:#c53030;border-radius:18px}
@keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
.app-frame{min-height:100dvh;display:flex;align-items:stretch;background:var(--bg)}
.app-sidebar{background:#fff;width:var(--sidebar-width);position:fixed;inset:0 auto 0 0;height:100dvh;border-right:1px solid var(--border);z-index:80;display:flex;flex-direction:column;padding:30px 14px 18px;box-shadow:3px 0 22px rgba(23,50,95,.018)}
.brand{display:flex;align-items:center;gap:12px;color:#1c2e49!important;padding:3px 12px 33px}.brand-mark{display:grid;place-items:center;width:41px;height:41px;border-radius:13px;background:linear-gradient(155deg,#1662d9,#5b93f7);color:white;font-size:21px;font-weight:900;box-shadow:0 7px 14px #2e73e534}.brand-copy{display:flex;flex-direction:column;line-height:1.32;white-space:nowrap}.brand-copy b{font-size:16px;letter-spacing:-.3px}.brand-copy small{margin-top:5px;font-weight:700;letter-spacing:1px;font-size:8px;color:#a6b2c2}.sidebar-section-label{font-size:11px;font-weight:750;letter-spacing:2px;color:#98a7ba;margin:6px 16px 12px}.side-nav{display:flex;flex-direction:column;gap:5px;overflow-y:auto;padding:1px 0}.side-link{display:flex;align-items:center;gap:13px;height:47px;padding:0 12px;color:#63738a!important;font-weight:630;font-size:13.5px;border-radius:12px;position:relative;transition:background .16s,color .16s,transform .16s}.side-link:hover{background:#f3f7ff;color:#2b5fbc!important;transform:translateX(2px)}.side-link.selected{background:#edf4ff;color:#1c59c8!important;font-weight:740}.side-icon{display:grid;place-items:center;width:31px;height:31px;border-radius:10px;background:#f1f5fb;font-size:18px;color:#6981a3}.side-link.selected .side-icon{background:#d9e8ff;color:#185bd0}.side-current{position:absolute;right:9px;width:5px;height:18px;background:#2a70ed;border-radius:9px}.sidebar-footer{margin-top:auto;padding:12px 6px 0;border-top:1px solid #ebeff5}.sidebar-footnote{padding:4px 7px 13px;font-size:11px;color:#8b9bae;display:flex;gap:8px;align-items:center}.online-dot{width:7px;height:7px;border-radius:50%;background:#20b78a;box-shadow:0 0 0 4px #e0f7ee;display:inline-block;flex-shrink:0}.online-dot.offline{background:#de8c36;box-shadow:0 0 0 4px #fff1dc}.sidebar-account{display:flex;align-items:center;gap:11px;background:#f7f9fd;border:1px solid #e9eef7;padding:11px;border-radius:15px}.account-avatar{width:35px;height:35px;border-radius:11px;display:grid;place-items:center;background:#dceafd;color:#235ab3;font-weight:800}.sidebar-account>span:last-child{display:flex;flex-direction:column;line-height:1.3;min-width:0}.sidebar-account b{font-size:12px;max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sidebar-account small{margin-top:4px;font-size:10px;color:#91a0b1}
.app-main{width:calc(100% - var(--sidebar-width));margin-left:var(--sidebar-width);min-width:0;display:flex;flex-direction:column;min-height:100dvh}.app-topbar{display:flex;align-items:center;justify-content:space-between;gap:15px;height:75px;min-height:75px;background:rgba(255,255,255,.84);border-bottom:1px solid var(--border);backdrop-filter:blur(18px);padding:0 clamp(19px,3vw,45px);position:sticky;top:0;z-index:50}.topbar-left,.topbar-right{display:flex;align-items:center;gap:16px;min-width:0}.breadcrumb{display:flex;gap:12px;align-items:center;font-size:13px;color:#9aa8bc}.breadcrumb b{font-size:14px;color:#233a57}.breadcrumb-sep{color:#c9d1e0}.topbar-right{font-size:12px;color:#7890a8}.status-indicator{display:flex;align-items:center;gap:10px}.topbar-identity{padding:6px 14px;background:#f1f5fb;border-radius:20px;color:#355076;font-weight:700}.menu-trigger{border:1px solid #e2e8f4;border-radius:11px;background:white;padding:4px 12px;color:#2856a2;font-size:22px}.app-stage{padding:clamp(22px,2.8vw,43px) clamp(16px,3vw,45px) 35px;flex:1;min-width:0}.page-view{width:100%;min-width:0}.desktop-footer{text-align:center;padding:12px 10px 18px;color:#a5b0c3;font-size:11px;letter-spacing:.4px}.desktop-footer span{margin:0 8px}.nav-shade,.mobile-dock{display:none}
/* normalize original layouts under the new viewport */
.page-view .container{max-width:1290px!important;width:100%!important;padding:0!important;margin:0 auto!important;min-height:0!important;background:transparent!important;box-shadow:none!important}
.page-view>.navbar,.page-view>nav.navbar,.page-view .navbar{position:relative!important;left:auto!important;right:auto!important;top:auto!important;z-index:2!important;min-height:0!important;height:auto!important;background:transparent!important;box-shadow:none!important;border:0!important;padding:0 0 25px!important;margin:0 auto!important;max-width:1290px!important;display:flex!important;align-items:center!important;justify-content:space-between!important;gap:16px!important;flex-wrap:wrap}
.page-view .navbar h1,.page-view .page-header h1,.page-view .app-header h1{font-size:clamp(24px,2.5vw,31px)!important;line-height:1.35!important;letter-spacing:-.9px!important;font-weight:800!important;color:#172b48!important;margin:0!important;background:none!important;-webkit-text-fill-color:initial!important}
.page-view .navbar h1 small{font-size:12px!important;display:inline-flex;margin-left:8px;color:#8396b2!important;background:#e9eef7!important;padding:2px 8px;border-radius:8px;vertical-align:middle}.page-view .logo{color:#21334e!important;font-weight:800!important;font-size:19px!important}.page-view .logo .icon{background:#296ce3!important;color:#fff!important;border-radius:12px!important}
.page-view .page-header{padding:0!important;margin:0 0 22px!important;background:transparent!important;border:0!important;box-shadow:none!important}.page-view .app-header{padding:0!important;margin:0 0 18px!important;background:transparent!important;border:0!important}.page-view .app-header h1 span{font-size:12px!important;letter-spacing:.1px;color:#3470c4!important;background:#dfeafc!important;padding:5px 10px!important;border-radius:20px!important;vertical-align:middle}
.page-view .card,.page-view .detail-card,.page-view .login-card,.page-view .app-card,.page-view .audit-card,.page-view .settings-card{background:var(--surface)!important;border:1px solid var(--border)!important;border-radius:var(--radius)!important;box-shadow:var(--shadow)!important;color:var(--ink)!important;overflow-wrap:anywhere}
.page-view .card{padding:clamp(18px,2.2vw,29px)!important;margin-bottom:20px!important}.page-view .card h2,.page-view .back-row h2{font-size:18px!important;color:#1e314a!important;font-weight:800!important;letter-spacing:-.3px!important;margin-bottom:20px!important}.page-view .app-card:hover,.page-view .card:hover{border-color:#d9e5f8!important}.page-view .empty-state,.page-view .empty{padding:35px 18px!important;text-align:center!important;color:#90a0b5!important;background:#fff!important;border:1px dashed #d6e0ee!important;border-radius:14px!important}
.page-view .tabs-wrap{margin-bottom:22px!important;background:transparent!important;box-shadow:none!important;border:0!important;border-radius:0!important;max-width:100%!important;overflow-x:auto;scrollbar-width:thin}.page-view .tabs{display:flex!important;align-items:center!important;flex-wrap:nowrap!important;gap:6px!important;border-radius:14px!important;background:#e9eef8!important;padding:5px!important;width:max-content!important;max-width:100%!important;border:0!important;box-shadow:none!important;overflow-x:auto}.page-view .tab-btn{border:0!important;white-space:nowrap!important;background:transparent!important;color:#697e9c!important;padding:11px 20px!important;font-weight:690!important;font-size:13px!important;border-radius:10px!important;min-height:43px!important;box-shadow:none!important;transition:background .17s,box-shadow .17s,color .17s!important}.page-view .tab-btn.active{background:white!important;color:#1f58b7!important;box-shadow:0 3px 8px rgba(44,76,122,.09)!important;border:0!important}.page-view .tab-btn:after,.page-view .tab-btn.active:after{display:none!important}.page-view .tab-content{display:none!important}.page-view .tab-content.active{display:block!important;animation:soft-in .2s ease-out}.page-view .app-grid{display:grid!important;grid-template-columns:repeat(auto-fill,minmax(min(100%,310px),1fr))!important;gap:16px!important}
@keyframes soft-in{0%{opacity:.45;transform:translateY(5px)}100%{opacity:1;transform:translateY(0)}}
.page-view input:not([type=checkbox]):not([type=radio]):not([type=file]),.page-view select,.page-view textarea,.page-view .form-control{max-width:100%!important;min-height:45px;border:1px solid #dce5f1!important;background:#fff!important;color:#22354e!important;border-radius:11px!important;padding:10px 14px!important;box-shadow:inset 0 1px 2px #10274706!important;outline:0;transition:border-color .18s,box-shadow .18s!important;font-size:14px!important}.page-view textarea{min-height:90px!important;resize:vertical}.page-view input:focus,.page-view select:focus,.page-view textarea:focus{border-color:#72a0f5!important;box-shadow:0 0 0 4px #3070e41d!important}.page-view input[readonly]{background:#f3f6fb!important;color:#64758d!important}.page-view input[type=file]{max-width:100%;font-size:12px;color:#5d738d}.page-view label{font-weight:640!important;color:#405471!important;font-size:13px!important}.page-view .form-group{margin-bottom:17px!important;min-width:0}.page-view .form-row,.page-view .row{gap:16px!important}.page-view .form-row>* ,.page-view .row>*{min-width:0}
.page-view button,.page-view .btn,.page-view a.btn,.page-view .refresh-btn,.page-view .btn-submit,.page-view button[type=submit]{border-radius:11px!important;font-weight:700!important;letter-spacing:0!important;transition:background .17s,box-shadow .17s,transform .17s!important;box-shadow:none;line-height:1.35}.page-view button:hover:not(:disabled),.page-view .btn:hover:not(:disabled){transform:translateY(-1px)}.page-view button:active,.page-view .btn:active{transform:scale(.985)}.page-view button:disabled{cursor:wait;opacity:.65}.page-view .btn-primary,.page-view .btn-submit,.page-view button[type=submit],.page-view .refresh-btn{background:#2569dc!important;color:#fff!important;border:1px solid #2569dc!important;box-shadow:0 6px 15px #2569dc1f!important}.page-view .btn-primary:hover,.page-view .btn-submit:hover,.page-view button[type=submit]:hover,.page-view .refresh-btn:hover{background:#1754be!important}.page-view .btn-outline,.page-view .btn-back{background:white!important;border:1px solid #dbe5f2!important;color:#41628d!important}.page-view .btn-danger,.page-view .btn-logout{background:#fff1f1!important;border:1px solid #ffdadd!important;color:#c0424d!important}.page-view .btn-success{background:#e6f8f1!important;border:1px solid #c5ecdc!important;color:#167658!important}.page-view .btn-system{background:#edf3ff!important;color:#285dc7!important}.page-view .nav-actions,.page-view .actions{display:flex!important;align-items:center!important;gap:9px!important;flex-wrap:wrap!important}
.page-view .search-bar{display:flex!important;align-items:center!important;gap:12px!important;margin:0 0 25px!important;padding:0!important;background:transparent!important;border:0!important;box-shadow:none!important}.page-view .search-bar input{flex:1!important;min-width:0!important;background:white!important;max-width:640px!important;border:1px solid #dce5f1!important}.page-view .search-bar .refresh-btn{min-width:78px!important}.page-view table{width:100%!important;border-spacing:0!important;border-collapse:separate!important;font-size:13px!important;background:#fff!important;border-radius:12px!important;color:#2d415c!important}.page-view th{background:#f7f9fd!important;color:#61758e!important;padding:12px 15px!important;font-size:12px!important;font-weight:740!important;border-bottom:1px solid #e7edf5!important;white-space:nowrap!important}.page-view td{border-bottom:1px solid #edf1f6!important;padding:12px 15px!important;vertical-align:middle!important}.page-view tr:last-child td{border-bottom:0!important}.page-view tr:hover td{background:#fbfcff!important}.page-view .table-wrap,.page-view .table-responsive{max-width:100%;overflow-x:auto;border:1px solid #e7ecf4;border-radius:12px}.page-view .permission-bar{border:1px solid #e7edf7!important;border-radius:13px!important;background:#fff!important;margin:0 0 24px!important;padding:12px 16px!important;box-shadow:none!important;display:flex!important;flex-wrap:wrap!important;gap:9px!important;color:#53677f!important}.page-view .permission-badge{border-radius:30px!important;padding:4px 9px!important}.page-view .back-row{display:flex!important;align-items:center!important;flex-wrap:wrap!important;gap:14px!important;margin:0 0 22px!important}.page-view .back-row h2{margin:0!important}.page-view .upload-wrapper{border:1px dashed #b7ccea!important;background:#f8fbff!important;border-radius:16px!important;padding:16px!important}.page-view .upload-hint{color:#8da0b4!important}.page-view .toast{z-index:9999!important}.page-view .skeleton,.page-view .skeleton-item,.page-view .skeleton-card,.page-view .skeleton-table-row{background:linear-gradient(105deg,#eff3f9 15%,#e3eaf5 40%,#eff3f9 65%)!important;background-size:200% 100%!important;animation:shimmer 1.6s linear infinite!important;border-radius:14px!important}.page-view .btn-back{display:inline-flex;align-items:center;gap:6px;padding:9px 14px!important;font-size:13px!important}.page-view .btn-back svg{width:16px;height:16px}
/* login and information pages */
.app-frame.is-auth{display:block;background:#f5f8fd}.is-auth .app-main{margin-left:0;width:100%}.is-auth .app-topbar{background:rgba(255,255,255,.8);height:75px;min-height:75px}.is-auth .app-stage.auth-stage{flex:1;display:grid;grid-template-columns:minmax(270px,1fr) minmax(350px,1fr);gap:clamp(35px,6vw,110px);align-items:center;max-width:1340px;width:100%;margin:auto;padding:clamp(30px,4vw,70px)}.is-auth .desktop-footer{margin-top:auto}.topbar-home{display:flex;align-items:center;gap:12px;font-size:15px;font-weight:800;color:#1e3551}.topbar-emblem{width:30px;height:30px;border-radius:10px;font-size:14px;box-shadow:none}.auth-intro{position:relative;align-self:stretch;display:flex;justify-content:center;flex-direction:column;overflow:hidden;padding:28px 2vw;min-height:540px}.intro-chip{display:inline-flex;align-items:center;gap:10px;background:#e4efff;color:#1b64cd;padding:9px 15px;border-radius:50px;font-weight:700;font-size:12px;align-self:flex-start}.intro-chip-dot{background:#2c78ed;border-radius:50%;width:7px;height:7px}.auth-intro h1{font-size:clamp(37px,4.4vw,64px);line-height:1.3;letter-spacing:-1.5px;margin:26px 0 22px;color:#153052;font-weight:850}.auth-intro h1 em{font-style:normal;color:#256cde}.auth-intro p{color:#8190a7;font-size:15px;max-width:410px;line-height:2}.intro-features{display:flex;flex-wrap:wrap;gap:10px;margin:23px 0}.intro-features span{color:#436fa4;background:#fff;border:1px solid #e5edfb;padding:6px 12px;border-radius:20px;font-size:12px;font-weight:670}.intro-deco{position:absolute;right:7%;bottom:14%;width:180px;height:160px;pointer-events:none;opacity:.5}.deco-sheet{position:absolute;width:112px;height:140px;border:1px solid #c7dcff;border-radius:15px;background:linear-gradient(135deg,#d4e4ff,#fff);transform:rotate(15deg);right:5px;top:5px;box-shadow:0 15px 35px #4e91e51c}.deco-sheet.d2{right:60px;top:18px;transform:rotate(-16deg);background:linear-gradient(150deg,#fff,#d3e8ff)}.deco-check{position:absolute;right:55px;top:63px;font-size:40px;color:#3072df}.is-auth .page-view{display:flex;align-items:center;justify-content:center;min-width:0}.is-auth .page-view .login-card,.is-auth .page-view>.container{max-width:490px!important;width:100%!important;border:1px solid #e5ebf6!important;border-radius:22px!important;box-shadow:0 16px 60px rgba(34,62,113,.08)!important;background:#fff!important;padding:clamp(25px,3.8vw,47px)!important;margin:0!important;min-height:0!important;transform:none!important}.is-auth .page-view .login-card h2,.is-auth .page-view>.container h2{font-size:27px!important;line-height:1.3!important;letter-spacing:-.7px!important;font-weight:800!important;color:#1b2f4c!important;text-align:left!important;margin:10px 0 8px!important}.is-auth .page-view .subtitle{color:#93a1b5!important;font-size:13px!important;margin-bottom:26px!important;text-align:left!important}.is-auth .page-view .btn,.is-auth .page-view button[type=submit]{min-height:46px!important}.is-auth .page-view .form-group label{font-size:13px!important}.is-auth .page-view .form-group input{width:100%!important}.is-auth .page-view .back-row{margin-top:22px!important}.is-auth .page-view #messageText{line-height:2!important;color:#6c819b!important}.is-auth .page-view>.container>.icon{background:#e9f1ff!important;border-radius:20px!important;color:#296add!important}
/* content-friendly page specific refinements */
.page-index .page-view .app-card,.page-detail .page-view .detail-card{padding:24px!important}.page-index .page-view .page-header{margin-bottom:23px!important}.page-index .page-view .search-bar{margin-bottom:28px!important}.page-upload .page-view form,.page-file-upload .page-view form{max-width:920px!important;margin:0 auto!important;background:#fff!important;border-radius:20px!important;border:1px solid var(--border)!important;padding:clamp(22px,3vw,38px)!important;box-shadow:var(--shadow)!important}.page-upload .page-view .container,.page-file-upload .page-view .container{max-width:980px!important}.page-upload .page-view .app-header,.page-file-upload .page-view .app-header{margin-bottom:25px!important}.page-dashboard .page-view .permission-bar{max-width:1290px!important}.page-messages .page-view .msg-list{display:grid!important;gap:13px!important}.page-messages .page-view .msg-item{background:#fff!important;border:1px solid var(--border)!important;border-radius:14px!important;box-shadow:var(--shadow)!important}.page-admin .page-view .tabs{max-width:100%!important}
/* phones and tablets */
@media(max-width:1024px){:root{--sidebar-width:220px}.app-stage{padding:23px 22px}.app-topbar{padding:0 23px}.brand-copy small{font-size:7px}.side-link{gap:9px}}
@media(max-width:820px){
 :root{--sidebar-width:0px}.app-sidebar{width:260px;transform:translateX(-105%);transition:transform .22s ease;box-shadow:12px 0 40px #16335c20;z-index:105}.app-sidebar.opened{transform:translateX(0)}.nav-shade{display:block;position:fixed;inset:0;z-index:100;background:rgba(15,32,58,.38);backdrop-filter:blur(2px)}.app-main{width:100%;margin:0;min-height:100dvh}.app-topbar{height:62px;min-height:62px;padding:0 16px}.breadcrumb{font-size:12px;gap:8px}.breadcrumb b{font-size:13px}.topbar-right .topbar-identity{display:none}.status-indicator{font-size:11px}.app-stage{padding:23px 16px 108px}.desktop-footer{display:none}.mobile-dock{display:flex;justify-content:space-around;align-items:stretch;position:fixed;left:0;right:0;bottom:0;z-index:90;min-height:70px;padding:7px 6px calc(8px + env(safe-area-inset-bottom));border-top:1px solid #e0e8f3;background:rgba(255,255,255,.96);box-shadow:0 -8px 32px #1f406011;backdrop-filter:blur(15px)}.mobile-dock a{min-width:0;flex:1;color:#91a1b3;display:flex;flex-direction:column;gap:2px;align-items:center;justify-content:center;font-weight:650;border-radius:11px;padding:4px 2px}.mobile-dock a.active{color:#2265d6}.mobile-dock small{font-size:10px;line-height:1.3;white-space:nowrap}.dock-icon{font-size:23px;line-height:1.4}.page-view>.navbar,.page-view>nav.navbar,.page-view .navbar{padding-bottom:17px!important;gap:12px!important}.page-view .navbar h1,.page-view .page-header h1,.page-view .app-header h1{font-size:24px!important}.page-view .navbar .nav-actions{gap:7px!important}.page-view .nav-actions .btn,.page-view .nav-actions button{padding:8px 11px!important;font-size:12px!important}.page-view .card{padding:17px!important}.page-view .tabs{width:100%!important;max-width:100%!important;scrollbar-width:none}.page-view .tab-btn{padding:10px 12px!important;flex-shrink:0}.page-view .app-grid{grid-template-columns:1fr!important}.page-view .search-bar{gap:8px!important}.page-view .search-bar .refresh-btn{min-width:60px!important}.page-view .form-row,.page-view .row{flex-wrap:wrap!important}.page-view .form-row .form-group,.page-view .row .form-group{flex:1 1 100%!important;max-width:100%!important}.page-view .table-wrap{width:100%!important;overflow-x:auto!important}.page-view table{min-width:450px!important}.page-view .table-wrap table{min-width:530px!important}.page-view .permission-bar{gap:7px!important;font-size:12px!important}.page-upload .page-view form,.page-file-upload .page-view form{padding:18px!important}.page-view .audit-modal-card,.page-view .msg-detail-card{max-height:85dvh!important;overflow-y:auto!important;margin:10px!important;width:calc(100vw - 20px)!important}.is-auth .app-stage.auth-stage{grid-template-columns:1fr;gap:0;padding:20px 16px 52px;min-height:calc(100dvh - 65px)}.is-auth .auth-intro{display:none}.is-auth .app-topbar{min-height:63px;height:63px}.is-auth .page-view .login-card,.is-auth .page-view>.container{padding:30px 23px!important;max-width:490px!important;border-radius:18px!important}.is-auth .page-view{align-self:center}.is-auth .desktop-footer{display:block}
}
@media(max-width:390px){.status-indicator{font-size:0}.status-indicator .online-dot{font-size:11px}.page-view .tab-btn{font-size:12px!important;padding:9px!important}.page-view .btn{font-size:12px!important}.topbar-home{font-size:13px}.is-auth .page-view .login-card h2{font-size:23px!important}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important;transition-duration:.001ms!important}}

/* v1.1: keep disabled-upload notice visible even if legacy entrance animations do not run. */
.page-close .is-auth .page-view > .service-notice{
 opacity:1!important; visibility:visible!important; transform:none!important; animation:none!important;
 display:flex!important; flex-direction:column; align-items:flex-start; justify-content:center;
 min-height:300px!important; position:relative; isolation:isolate;
}
.page-close .is-auth .page-view .notice-symbol{display:grid;place-items:center;width:54px;height:54px;
 border-radius:17px;background:#fff1e8;color:#d37021;font-size:28px;font-weight:800;line-height:1;margin-bottom:19px}
.page-close .is-auth .page-view .notice-label{color:#bd6728;font-weight:700;font-size:12px;letter-spacing:.1em;margin-bottom:4px}
.page-close .is-auth .page-view .service-notice #noticeTitle{margin:8px 0 12px!important;font-size:clamp(23px,2.6vw,30px)!important;
 color:#203855!important;line-height:1.4!important}
.page-close .is-auth .page-view .service-notice #messageText{font-size:17px!important;font-weight:650;color:#3c526d!important;
 overflow-wrap:anywhere;white-space:pre-wrap;margin:0 0 12px!important;text-align:left!important}
.page-close .is-auth .page-view .service-notice .notice-help{font-size:13px;color:#7c8da4!important;line-height:1.8;
 text-align:left!important;margin:0 0 28px!important}
.page-close .is-auth .page-view .service-notice .btn{background:#2569dc!important;color:#fff!important;
 border:1px solid #2569dc!important;padding:12px 21px!important;min-height:45px!important}
/* Page heading holds account-only actions; the sidebar owns site navigation. */
.page-index .page-view .page-header{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}
.page-index .page-view #navActions{flex:0 0 auto;margin-left:auto}
.page-index .page-view #navActions:empty{display:none!important}
/* Sidebar and phone navigation notification badges. */
.side-link,.mobile-dock a{position:relative}
.app-sidebar .msg-badge,.mobile-dock .msg-badge{position:absolute;top:3px;right:7px;min-width:18px;height:18px;
 display:inline-flex;align-items:center;justify-content:center;border-radius:99px;padding:0 4px;
 background:#ef4444;color:#fff;border:2px solid #fff;font-size:10px;font-weight:750;line-height:1}
.app-sidebar .msg-badge.hidden,.mobile-dock .msg-badge.hidden{display:none}

/* v1.3: request-aware refresh feedback, visible on desktop and touch devices */
.page-view button.is-refreshing,.page-view button.refresh-complete,.page-view button.refresh-failed{display:inline-flex!important;align-items:center;justify-content:center;gap:8px;opacity:1!important;cursor:progress!important}
.page-view button.is-refreshing::before{content:"";display:inline-block;flex:0 0 14px;width:14px;height:14px;border-radius:50%;border:2px solid currentColor;border-right-color:transparent;animation:credit-refresh-spin .7s linear infinite}
.page-view button.refresh-complete::before{content:"✓";font-size:14px;font-weight:900;line-height:1}
.page-view button.refresh-failed::before{content:"!";font-size:14px;font-weight:900;line-height:1}
@keyframes credit-refresh-spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.page-view button.is-refreshing::before{animation-duration:2s!important}}
.route-checking{position:fixed;bottom:24px;right:24px;z-index:9999;background:#fff;color:#2655a1;border:1px solid #dde7f6;border-radius:16px;padding:14px 20px;box-shadow:0 12px 45px #203f6620;font-size:13px;font-weight:750;display:flex;align-items:center;gap:12px}
.route-checking::before{content:"";display:block;width:17px;height:17px;border-radius:50%;border:2px solid #3579e7;border-right-color:transparent;animation:credit-refresh-spin .75s linear infinite}
.preflight-error{min-height:80dvh;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:25px;background:#f5f8fc;color:#263958;gap:13px}
.preflight-error h2{font-size:23px;margin:4px}.preflight-error p{font-size:14px;color:#768aa5;line-height:1.8;max-width:430px}
.preflight-error-icon{border-radius:18px;padding:13px;background:#fff0e2;color:#c9772b;font-weight:900;font-size:23px}
.preflight-error button{border:0;border-radius:11px;padding:12px 25px;background:#2569dc;color:white;font-weight:750;cursor:pointer}
.preflight-error a{color:#406faf;font-size:13px}
@media(max-width:820px){.route-checking{left:16px;right:16px;bottom:95px;justify-content:center}}

/* Shared NBS icon for desktop sidebar and mobile dock. */
.music-side-icon{width:25px;height:25px;display:inline-block;object-fit:contain;vertical-align:middle}
.dock-icon .music-side-icon{width:22px;height:22px}

/* v2.3 supplied icon and account imagery */
.brand-mark{background:#ecf3ff;overflow:hidden;padding:5px;box-shadow:0 7px 14px #2e73e51a}
.brand-mark img{width:100%;height:100%;object-fit:contain}
.side-icon .nav-image-icon{width:27px;height:27px;max-width:100%;object-fit:contain}
.dock-icon .nav-image-icon{width:25px;height:25px;object-fit:contain;vertical-align:middle}
.sidebar-account img.account-avatar{object-fit:cover;background:#eaf2ff;padding:1px;flex-shrink:0}
.topbar-emblem{background:#eaf2ff;box-shadow:none;padding:3px;overflow:hidden}
.topbar-emblem img{width:100%;height:100%;object-fit:contain}

.auth-role-icon{width:54px;height:54px;object-fit:contain;display:block;margin:4px 0 12px;filter:drop-shadow(0 3px 7px #395b8228)}

/* v2.4: brand icon in preflight/loading, no truncated account portraits. */
.route-checking::before{width:26px;height:26px;border:0;border-radius:7px;background:url('/assets/icons/网页选项卡标题，网站logo.webp') center/contain no-repeat;animation:credit-logo-breathe 1.2s ease-in-out infinite}
@keyframes credit-logo-breathe{50%{opacity:.55;transform:scale(.9)}}
.preflight-error-icon{background:transparent!important;color:transparent!important;position:relative}
.preflight-error-icon::after{content:'';position:absolute;inset:2px;background:url('/assets/icons/网页选项卡标题，网站logo.webp') center/contain no-repeat}


/* == assets/mobile-fixes.css == */
/* v1.4: responsive overflow, form sizing & bfcache state restoration. Loaded last. */
/* Old standalone HTML styles set 12-20px body padding and display:flex; the
   Vue shell must be allowed to occupy the complete viewport on every page. */
html { width:100%; max-width:100%; }
body { display:block!important; padding:0!important; width:100%!important; max-width:100%; margin:0!important; }
#app, .app-frame, .app-main, .app-stage, .page-view { min-width:0; }
.app-frame { width:100%; }
.page-view .container,.page-view .card,.page-view .tab-content,.page-view .navbar { min-width:0; max-width:100%; }
.page-view :is(input[type=file],textarea,select,input[type=datetime-local]) { max-width:100%; }
/* A cached upload page may be restored after upload was disabled. Hide only the
   form while revalidating; do not hide <html> or the whole application. */
.history-checking .page-file-upload .page-view #uploadForm { visibility:hidden!important; }
/* Password/login panels have their own page-level layout, never inherit fixed
   widths or flex-centering from the legacy body declaration. */
.is-auth .page-view .login-card { margin-inline:auto!important; }
@media (max-width:820px) {
 html, body, #app { max-width:100%; overflow-x:clip; }
 .app-frame,.app-main,.app-stage,.page-view { width:100%; max-width:100%; min-width:0; }
 .app-stage { padding:18px 12px calc(102px + env(safe-area-inset-bottom))!important; }
 .page-view .container,.page-view .tab-content,.page-view .card { width:100%!important; min-width:0!important; }
 .page-view .card { padding:16px 14px!important; border-radius:16px!important; }
 .page-view .card h2 { font-size:17px!important; margin-bottom:15px!important; }
 .page-view .navbar { align-items:flex-start!important; gap:9px!important; }
 .page-view .navbar h1,.page-view .page-header h1 { font-size:clamp(20px,5.6vw,25px)!important; }
 .page-view .tabs-wrap { width:100%; max-width:100%; overflow-x:auto!important; -webkit-overflow-scrolling:touch; overscroll-behavior-x:contain; }
 .page-view .tabs { width:max-content!important; max-width:none!important; overflow:visible!important; }
 .page-view .tab-btn { min-width:max-content; min-height:43px!important; }
 .page-view .row,.page-view .form-row { display:grid!important; grid-template-columns:minmax(0,1fr)!important; }
 .page-view .row>*,.page-view .form-row>*,.page-view .form-group { min-width:0!important; }
 .page-view .toolbar,.page-view .nav-actions,.page-view .modal-toolbar { max-width:100%; gap:8px!important; }
 .page-view .toolbar :is(button,a),.page-view .nav-actions :is(button,a) { max-width:100%; white-space:normal!important; }
 .page-view :is(input,textarea,select) { min-width:0; }
 .page-view input[type=file] { width:100%!important; max-width:100%!important; overflow:hidden; }
 .page-view .file-upload-wrap,.page-view .upload-wrapper { max-width:100%; min-width:0; }
 .page-view :is(.table-wrap,.log-table-wrap,.data-table-scroll,div[style*="overflow-x:auto"],div[style*="overflow-x: auto"]) {
   display:block; width:100%; max-width:100%; overflow-x:auto!important;
   -webkit-overflow-scrolling:touch; overscroll-behavior-x:contain;
 }
 .page-view table { min-width:550px!important; width:100%!important; }
 .page-view th,.page-view td { padding:9px 10px!important; font-size:12px!important; vertical-align:middle; }
 .page-view :is(.modal-overlay,.msg-detail-overlay) { padding:10px!important; align-items:center!important; }
 .page-view .modal-card { width:100%!important; max-width:100%!important; max-height:calc(100dvh - 36px)!important; border-radius:18px!important; min-width:0; }
 .page-view .modal-header,.page-view .modal-body,.page-view .modal-tabs { padding-left:14px!important; padding-right:14px!important; min-width:0; }
 .page-view .modal-tabs { overflow-x:auto; }
 .page-view .modal-body > div[style*="overflow-x:auto"] { overflow-x:auto!important; }
 .page-view .stat-grid { grid-template-columns:minmax(0,1fr)!important; }
 .page-view .msg-item .msg-main { min-width:0!important; width:100%; }
 .page-view .msg-item .msg-meta { min-width:0; flex-wrap:wrap; }
 .page-view .msg-item .msg-time { white-space:normal!important; overflow-wrap:anywhere; }
 .page-view :is(.app-item,.detail-card,.msg-item,.app-card) { max-width:100%; min-width:0; }
 .page-view :is(.student-id,.pwd-code,.file-link,.msg-detail-content) { overflow-wrap:anywhere; word-break:break-word; }
 .mobile-dock small { max-width:100%; white-space:normal!important; text-align:center; overflow-wrap:anywhere; font-size:10px; }
 .mobile-dock { gap:2px; }
 .is-auth .app-stage.auth-stage { display:flex!important; align-items:center; justify-content:center; padding:22px 14px 30px!important; min-height:calc(100dvh - 63px); }
 .is-auth .page-view { width:100%!important; max-width:520px!important; display:block!important; align-self:auto!important; }
 .is-auth .page-view .login-card { width:100%!important; max-width:520px!important; min-height:min(540px,calc(100dvh - 112px)); padding:clamp(27px,6.5vw,38px) clamp(21px,5.5vw,34px)!important; display:flex!important; flex-direction:column; justify-content:center; border-radius:22px!important; }
 .is-auth .page-view .login-card h2 { font-size:clamp(23px,6vw,28px)!important; margin-bottom:16px!important; }
 .is-auth .page-view .login-card .form-group { margin-bottom:19px!important; }
 .is-auth .page-view .login-card :is(input,button[type=submit],.btn-submit) { min-height:48px!important; }
 .is-auth .page-view .login-card .btn-back { min-height:38px; }
 /* Administrative and student management lists become true, one-column cards;
    other report tables retain a consciously scrollable data region. */
 .page-admin #adminTable { max-width:100%; min-width:0; }
 .page-admin #adminTable table, .page-admin #tab-students table { display:block!important; min-width:0!important; width:100%!important; border-collapse:separate!important; }
 .page-admin #adminTable table>tbody,.page-admin #tab-students table>tbody { display:grid!important; gap:10px; width:100%; min-width:0; }
 .page-admin #adminTable table tr:first-child,.page-admin #tab-students table>thead { display:none!important; }
 .page-admin #adminTable table>tbody>tr:not(:first-child),.page-admin #tab-students table>tbody>tr {
   display:block!important; min-width:0; width:100%; padding:8px 12px!important;
   border:1px solid #e1e9f5; background:#f8faff; border-radius:13px;
 }
 .page-admin #adminTable table>tbody>tr>td,.page-admin #tab-students table>tbody>tr>td {
   min-width:0; width:100%; min-height:36px; border:0!important;
   padding:7px 0!important; display:grid!important;
   grid-template-columns:minmax(72px,30%) minmax(0,1fr); align-items:start;
   column-gap:12px; overflow-wrap:anywhere; word-break:break-word;
 }
 .page-admin #adminTable table>tbody>tr>td:not(:last-child),.page-admin #tab-students table>tbody>tr>td:not(:last-child) {
   border-bottom:1px dashed #e5ecf5!important;
 }
 .page-admin #adminTable table td::before,.page-admin #tab-students table td::before { color:#72829a;font-size:12px;font-weight:650;white-space:normal;align-self:center; }
 .page-admin #adminTable table td:nth-child(1)::before { content:"编号"; }
 .page-admin #adminTable table td:nth-child(2)::before { content:"用户名"; }
 .page-admin #adminTable table td:nth-child(3)::before { content:"角色"; }
 .page-admin #adminTable table td:nth-child(4)::before { content:"审核权限"; }
 .page-admin #adminTable table td:nth-child(5)::before { content:"封禁权限"; }
 .page-admin #adminTable table td:nth-child(6)::before { content:"操作"; }
 .page-admin #tab-students table td:nth-child(1)::before { content:"选择"; }
 .page-admin #tab-students table td:nth-child(2)::before { content:"姓名"; }
 .page-admin #tab-students table td:nth-child(3)::before { content:"学号"; }
 .page-admin #tab-students table td:nth-child(4)::before { content:"密码"; }
 .page-admin #tab-students table td:nth-child(5)::before { content:"状态"; }
 .page-admin #tab-students table td:nth-child(6)::before { content:"操作"; }
 .page-admin #adminTable table td:last-child,.page-admin #tab-students table td:last-child { display:flex!important; flex-wrap:wrap; align-items:center; gap:6px; }
 .page-admin #adminTable table td:last-child::before,.page-admin #tab-students table td:last-child::before { flex:0 0 30%; }
 .page-admin #tab-students table td:last-child .btn { margin:0!important; min-height:34px; }
 .page-admin #tab-students table>tbody>tr>td[colspan],.page-admin #adminTable table td[colspan] { display:block!important; }
 .page-admin #tab-students table>tbody>tr>td[colspan]::before { display:none!important; }
 .page-admin .student-option { min-width:0; }
 .page-admin .student-option .student-id { overflow-wrap:anywhere; }
 .page-admin .modal-overlay table { min-width:520px!important; }
}
@media(max-width:380px) {
 .app-stage { padding-left:10px!important; padding-right:10px!important; }
 .app-topbar { padding-left:12px!important; padding-right:12px!important; }
 .page-view .card { padding:14px 11px!important; }
 .page-view .nav-actions { gap:5px!important; }
 .page-view .btn { max-width:100%; }
 .page-admin #adminTable table>tbody>tr>td,.page-admin #tab-students table>tbody>tr>td { grid-template-columns:70px minmax(0,1fr);gap:7px; }
}
@media (prefers-reduced-motion:reduce) { .app-sidebar,.mobile-dock { scroll-behavior:auto!important; } }

/* tablet / small laptop: retain a usable table scroller beside the sidebar */
@media (min-width:821px) and (max-width:1100px) {
 .page-admin #adminTable { width:100%;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch; }
 .page-admin #adminTable table { min-width:760px; }
 .page-view :is(.table-wrap,.log-table-wrap,div[style*="overflow-x:auto"]) { max-width:100%;overflow-x:auto!important; }
 .app-stage { padding-inline:18px; }
}
/* Never allow long file names or codes to expand a flex item beyond viewport */
@media(max-width:820px) {
 .page-dashboard .page-view .app-item .info { min-width:0!important; }
 .page-index .page-view .search-bar { flex-wrap:wrap!important;width:100%!important; }
 .page-index .page-view .search-bar input { flex:1 1 160px!important;max-width:100%!important;min-width:0!important; }
 .page-view :is(.audit-modal-card,.confirm-card,.requirement-modal-card,.msg-detail-card) { max-width:calc(100vw - 24px)!important;min-width:0!important; }
 .page-detail .page-view .action-bar { flex-wrap:wrap; }
 .page-detail .page-view .action-bar .btn { min-width:0!important;flex:1 1 135px; }
 .page-upload .page-view form,.page-file-upload .page-view form { width:100%!important;max-width:100%!important;padding:18px 15px!important; }
}


/* == assets/mobile-v15.css == */
/* v1.5 — unified responsive layout, no fixed-width legacy navigation. */
.admin-tab-switcher { width:100%;min-width:0;max-width:100%; }
.admin-mobile-tab-select { display:none; }
.page-admin .tabs-wrap {max-width:100%;width:100%;min-width:0;}
/* System management uses an accessible native dropdown on small screens, not
   a horizontally oversized row of seven legacy buttons. */
@media(max-width:1024px) {
  .page-admin .admin-tab-switcher {display:block;width:100%;min-width:0;max-width:100%;margin-bottom:18px;}
  .page-admin .admin-tab-switcher .tabs-wrap {display:none!important;}
  .page-admin .admin-mobile-tab-select {display:flex;flex-direction:column;gap:7px;width:100%;min-width:0;
    padding:14px;background:#fff;border:1px solid #e1eaf7;border-radius:15px;
    color:#4c627e;font-size:12px;font-weight:750;letter-spacing:.03em;box-shadow:0 6px 18px #2539570a;}
  .page-admin .admin-mobile-tab-select select {display:block;appearance:auto!important;width:100%!important;min-width:0!important;
    max-width:100%!important;min-height:47px!important;border:1px solid #ccd9ee;border-radius:10px;
    color:#1b3a66;background-color:#f7faff;padding:10px 12px;font-size:15px;font-weight:700;}
  .page-admin .page-view > .container {width:100%!important;min-width:0!important;max-width:100%!important;}
  .page-admin .tab-content {width:100%;max-width:100%;min-width:0;}
}
@media(max-width:820px) {
  .page-admin .page-view :is(.card,.container,.tab-content,.admin-tab-switcher) {min-width:0!important;max-width:100%!important;}
  .page-admin .page-view :is(.card,.tab-content) > * {max-width:100%;min-width:0;}
  .page-admin .page-view table {max-width:100%;}
  .page-admin .page-view :is(.log-table-wrap,.table-wrap,#adminTable) {max-width:100%;min-width:0;}
  .page-admin .page-view .modal-overlay .modal-card{min-width:0!important;max-width:calc(100vw - 24px)!important;}
  .page-admin .page-view :is(.row,.form-row) {grid-template-columns:minmax(0,1fr)!important;}
  .page-view :is(input,textarea,select) {font-size:16px;}
  .page-view :is(.navbar h1,.card h2) {overflow-wrap:anywhere;}
}
@media(min-width:821px) and (max-width:1100px) {
  .page-admin .page-view .container {min-width:0!important;}
}
/* Avoid stacking the old body/page leaving animations on Vue route changes. */
body.page-leaving {opacity:1!important;visibility:visible!important;transform:none!important;}
.btn-wait-spinner{display:inline-block;width:16px;height:16px;margin-right:8px;vertical-align:-3px;
  border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:vue-login-spin .65s linear infinite;}
@keyframes vue-login-spin{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){.btn-wait-spinner{animation-duration:1.2s}}
/* Vue table has a real <thead>; the old selector accidentally hid the first
   tbody record because the pre-Vue table had its header as table>tr. */
@media(max-width:820px) {
 .page-admin #adminTable table.vue-admin-table>tbody>tr,
 .page-admin #adminTable table.vue-admin-table>tbody>tr:first-child {
   display:block!important; width:100%; min-width:0; padding:8px 12px!important;
   background:#f8faff; border:1px solid #e1e9f5; border-radius:13px;
 }
 .page-admin #adminTable table.vue-admin-table>thead {display:none!important;}
}


/* == Vue system initialization / login layout == */
/* v1.6: system initialization state rendered by Vue, not hidden by pre-Vue CSS. */
.page-login .setup-state{margin-top:18px;min-width:0}
.page-login .setup-checking{display:flex;align-items:center;justify-content:center;gap:7px;min-height:30px;color:#7d8fa7;font-size:13px}
.page-login .create-system{display:block;border:1px solid #c9dcff;background:#f0f6ff;border-radius:14px;padding:18px 16px;margin-top:0;text-align:center}
.page-login .create-system strong{display:block;font-size:17px;color:#17498a;margin-bottom:7px}
.page-login .create-system p{font-size:13px;line-height:1.75;color:#59708c;margin:0 0 12px}
.page-login .create-system .setup-link{display:flex;align-items:center;justify-content:center;gap:8px;min-height:44px;border-radius:11px;background:#2165df;color:white;text-decoration:none;font-weight:800;font-size:14px}
.page-login .create-system .setup-link:hover{background:#1854bd}
.page-login .setup-status-error{border-radius:12px;background:#fff4eb;border:1px solid #f4d4b6;padding:13px;color:#8d501d;font-size:13px;text-align:center}
.page-login .setup-status-error p{margin:0 0 8px;line-height:1.6}
.page-login .setup-status-error button{font:inherit;border:1px solid #d19d64;border-radius:9px;background:white;padding:7px 17px;cursor:pointer;color:#985720;font-weight:700}
.page-create-system #formContainer .alert{display:block}
.page-login #errorBox,.page-student-login #errorBox{display:block}
@media(max-width:480px){.page-login .create-system{padding:14px 12px}}

/* == assets/vue-theme.css == */
/* Vue 3 design tokens v2.7.
 * JavaScript/Vue owns the [data-theme] state.  CSS owns geometry and presentation.
 * This is the ONE page palette layer, replacing theme.css and visual-unified.css. */
:root,html[data-theme="light"]{
 color-scheme:light;
 --bg:#f4f7fc;--surface:#fff;--ink:#192e4a;--muted:#61758f;--blue:#266bdf;--blue-strong:#1657c4;--sky:#eaf2ff;--border:#dae5f2;--shadow:0 12px 35px #162f5314;
 --ui-canvas:#f4f7fc;--ui-card:#fff;--ui-card-hover:#fbfdff;--ui-soft:#edf3fb;--ui-control:#f9fbff;
 --ui-text:#192e4a;--ui-muted:#62768f;--ui-stroke:#dbe5f2;--ui-primary:#286ee4;--ui-highlight:#ebf3ff;
 --ui-highlight-text:#1c58b9;--ui-danger:#bb334a;--ui-success:#117453;--ui-surface-on:#fff;
 --ui-glass:rgba(255,255,255,.92);--ui-hover:#e9f2ff;--ui-focus:0 0 0 3px #307deb35;
}
html[data-theme="dark"]{
 color-scheme:dark;
 --bg:#101927;--surface:#1c2b40;--ink:#e9f2ff;--muted:#b2c2d8;--blue:#7caeff;--blue-strong:#98c0ff;--sky:#253a58;--border:#39516d;--shadow:0 12px 35px #0004;
 --ui-canvas:#101927;--ui-card:#1c2b40;--ui-card-hover:#243650;--ui-soft:#263952;--ui-control:#142338;
 --ui-text:#e9f2ff;--ui-muted:#b2c2d8;--ui-stroke:#3b5370;--ui-primary:#70a9ff;--ui-highlight:#26528d;
 --ui-highlight-text:#fff;--ui-danger:#ff8792;--ui-success:#5bd6a7;--ui-surface-on:#fff;
 --ui-glass:rgba(27,42,62,.94);--ui-hover:#294468;--ui-focus:0 0 0 3px #7baaff38;
}
html,body,.app-frame,.app-main{background:var(--ui-canvas)!important;color:var(--ui-text)!important}
/* Shell: one shared component material palette in both themes. */
.app-sidebar,.app-topbar,.mobile-dock{background:var(--ui-glass)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
.app-topbar{backdrop-filter:blur(18px)}
.app-sidebar .brand,.brand-copy b,.breadcrumb b,.topbar-home,.topbar-right,.topbar-identity{color:var(--ui-text)!important}
.brand-copy small,.sidebar-section-label,.sidebar-footnote,.breadcrumb,.sidebar-account small,.desktop-footer{color:var(--ui-muted)!important}
.app-sidebar .side-link{color:var(--ui-muted)!important}
.app-sidebar .side-link.selected,.app-sidebar .side-link:hover{background:var(--ui-highlight)!important;color:var(--ui-highlight-text)!important}
.app-sidebar .side-link .side-icon,.sidebar-account,.topbar-identity,.menu-trigger,.theme-toggle{background:var(--ui-soft)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
.app-sidebar .side-link.selected .side-icon{background:var(--ui-hover)!important;color:var(--ui-highlight-text)!important}
.sidebar-footer{border-color:var(--ui-stroke)!important}
.mobile-dock a{color:var(--ui-muted)!important}
.mobile-dock a.active{background:var(--ui-highlight)!important;color:var(--ui-highlight-text)!important}
/* Page-scale surfaces and typography. Text colors never depend on a gradient of another theme. */
.page-view{color:var(--ui-text)!important;background:transparent!important}
.page-view :is(.container,.navbar,.page-header,.app-header,.tabs-wrap,.tab-content){color:var(--ui-text)!important}
.page-view :is(.app-card,.about-public-card,.about-metadata>div,.about-state,.about-public-loading,.card,.stat-card,.detail-card,.login-card,.settings-card,.audit-card,.record-card,.message-card,.msg-item,.music-manager-card,.music-manager-track,.modal-card,.modal-content,.msg-detail-card,.service-notice,.submission-panel,.student-row,.file-row,.music-task-dialog,.music-delete-dialog,.user-dropdown){
 background:var(--ui-card)!important;color:var(--ui-text)!important;border:1px solid var(--ui-stroke)!important;
 box-shadow:var(--shadow)!important;border-radius:17px!important;
}
.page-view :is(.app-card,.about-public-card,.card,.detail-card,.record-card,.music-manager-card):hover{border-color:var(--ui-primary)!important}
.page-view :is(.page-header h1,.app-header h1,.navbar h1,.logo,.about-public-heading h1,.about-public-card h1,.about-public-card h2,.about-public-card h3,.app-title,.stat-value,.music-manager-head h1,.card h2,.login-card h2,.detail-card h2){
 color:var(--ui-text)!important;-webkit-text-fill-color:currentColor!important;
}
.page-view :is(.about-description,.about-subtitle,.about-updated,.about-kicker,.about-metadata span,.about-metadata a,.app-student,.app-meta,.app-card .date,.app-card .meta,.app-card .timestamp,.stat-label,.subtitle,.music-manager-head p){
 color:var(--ui-muted)!important;-webkit-text-fill-color:currentColor!important;
}
.page-view :is(.empty-state,.empty,.preview-item,.form-section,.about-state,.about-metadata>div,.music-cache-controls,.upload-wrapper,.countdown-box,.music-now,.student-select-list,.permission-bar,.music-file-row,.music-select-row){
 background:var(--ui-soft)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important;
}
.page-view :is(.search-bar,.search-container,.navbar,.page-header,.app-header){background:transparent!important;border-color:var(--ui-stroke)!important}
.page-view :is(.table-wrap,.table-responsive,table,td,th,.modal-tabs,.modal-header,.modal-body){border-color:var(--ui-stroke)!important}
.page-view :is(table,td){background:var(--ui-card)!important;color:var(--ui-text)!important}
.page-view th,.page-view tr:hover td{background:var(--ui-soft)!important;color:var(--ui-text)!important}
.page-view :is(input:not([type=checkbox]):not([type=radio]):not([type=file]),textarea,select,.form-control,.search-bar input){
 background:var(--ui-control)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important;
}
.page-view :is(input,textarea)::placeholder{color:var(--ui-muted)!important;opacity:.88}
.page-view :is(input,textarea,select):focus-visible{border-color:var(--ui-primary)!important;box-shadow:var(--ui-focus)!important}
.page-view label,.page-view :is(.about-public-card,.app-card,.card,.detail-card,.login-card) :is(b,strong){color:var(--ui-text)!important}
/* Tabs: identical border/padding dimensions regardless of palette or current page. */
html[data-theme] .page-view .tabs-wrap{width:100%!important;max-width:100%!important;min-height:54px!important;display:flex!important;align-items:center!important;justify-content:center!important;gap:0!important;margin:0 0 23px!important;padding:0!important;overflow-x:auto!important;background:transparent!important;border:0!important;box-shadow:none!important;scrollbar-width:thin}
html[data-theme] .page-admin .page-view .tabs-wrap{justify-content:flex-start!important}
html[data-theme] .page-view .tabs{box-sizing:border-box!important;display:inline-flex!important;align-items:stretch!important;gap:5px!important;flex-wrap:nowrap!important;width:max-content!important;max-width:100%!important;min-height:54px!important;margin:0!important;padding:5px!important;background:var(--ui-soft)!important;border:1px solid var(--ui-stroke)!important;border-radius:14px!important;box-shadow:none!important;overflow-x:auto!important;scrollbar-width:none}
html[data-theme] .page-view .tab-btn{box-sizing:border-box!important;flex:0 0 auto!important;white-space:nowrap!important;height:42px!important;min-height:42px!important;margin:0!important;padding:0 17px!important;border:1px solid transparent!important;border-radius:9px!important;background:transparent!important;color:var(--ui-muted)!important;font-size:13px!important;font-weight:750!important;box-shadow:none!important;outline:0!important}
html[data-theme] .page-view .tab-btn.active,html[data-theme] .page-view .tab-btn[aria-selected=true]{background:var(--ui-highlight)!important;color:var(--ui-highlight-text)!important;border-color:var(--ui-primary)!important;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ui-primary) 18%,transparent)!important}
html[data-theme] .page-view .tab-btn:hover:not(.active){background:var(--ui-hover)!important;color:var(--ui-text)!important}
.page-view :is(.modal-tabs){background:var(--ui-soft)!important}
.page-view .modal-tab,.page-view .submission-tab{background:transparent!important;color:var(--ui-muted)!important;min-height:45px!important;border-color:transparent!important}
.page-view .modal-tab.active,.page-view .submission-tab.active{background:transparent!important;color:var(--ui-primary)!important;border-bottom:3px solid var(--ui-primary)!important}
/* Buttons preserve original actions without hardcoded light-only white surfaces. */
.page-view :is(.btn-back,.btn-outline,.btn-secondary,.music-secondary-btn,.refresh-btn-outline,.music-cache-controls button,.music-delete-actions button:not(.music-delete-confirm),.about-retry){background:var(--ui-soft)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
.page-view :is(.btn-primary,.btn-submit,button[type=submit],.refresh-btn,.music-primary-btn){background:#286de0!important;color:#fff!important;border-color:#286de0!important}
.page-view :is(.btn-danger,.music-danger-btn){color:var(--ui-danger)!important}
.page-view :is(.tag.time,.time-tag,.about-pill,.status-tag){background:var(--ui-soft)!important;color:var(--ui-muted)!important;border-color:var(--ui-stroke)!important}
/* Auth geometry is shared; prevent old design.css hard-coded white login cards. */
.is-auth .page-view .login-card,.is-auth .page-view>.container{background:var(--ui-card)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important;box-shadow:var(--shadow)!important}
.is-auth .page-view .login-card h2,.is-auth .page-view>.container h2{color:var(--ui-text)!important}
.is-auth .page-view .subtitle,.auth-intro p{color:var(--ui-muted)!important}
.is-auth .page-view .service-notice #messageText{color:var(--ui-text)!important}
.is-auth .page-view .service-notice .notice-help{color:var(--ui-muted)!important}
.page-upload .page-view form,.page-file-upload .page-view form{background:var(--ui-card)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
/* Focus, transitions: only paint properties animate; layout remains steady. */
.page-view :is(.card,.app-card,.about-public-card,.tab-btn,.btn,.login-card,.detail-card),.app-sidebar,.app-topbar,.theme-toggle{transition-property:background-color,color,border-color,box-shadow!important;transition-duration:.2s!important;transition-timing-function:ease!important}
.theme-toggle,.topbar-identity,.sidebar-account{color:var(--ui-text)!important}
@media(max-width:820px){html[data-theme] .page-view .tabs-wrap{justify-content:flex-start!important}html[data-theme] .page-view .tab-btn{padding:0 12px!important;font-size:12px!important}}
@media(prefers-reduced-motion:reduce){.page-view :is(.card,.app-card,.about-public-card,.tab-btn,.btn,.login-card,.detail-card),.app-sidebar,.app-topbar{transition:none!important}}
/* Shared custom assets, independent of the selected theme. */
.first-paint-logo{overflow:hidden;background:transparent!important;box-shadow:none!important}
.first-paint-logo img{width:100%;height:100%;object-fit:contain;display:block}
.sidebar-account img.account-avatar{width:46px!important;height:58px!important;min-width:46px!important;object-fit:contain!important;object-position:center!important;padding:0!important;background:transparent!important;border-radius:8px!important;flex-shrink:0!important}
.theme-toggle{position:relative;display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;min-width:38px;padding:0;border-radius:12px;border:1px solid var(--ui-stroke)!important;cursor:pointer;line-height:1}
.theme-toggle:active{transform:scale(.93)}
.theme-glyph{width:20px;height:20px;display:inline-block;position:relative;flex-shrink:0;border-radius:50%;transition:transform .45s cubic-bezier(.24,.86,.24,1);transform:rotate(0deg)}
.theme-glyph:before{content:"";position:absolute;inset:4px;border-radius:50%;background:#f5a923;box-shadow:0 -10px 0 -4px #f5a923,0 10px 0 -4px #f5a923,10px 0 0 -4px #f5a923,-10px 0 0 -4px #f5a923,7px 7px 0 -4px #f5a923,-7px -7px 0 -4px #f5a923,7px -7px 0 -4px #f5a923,-7px 7px 0 -4px #f5a923;transition:background .4s,box-shadow .4s,transform .4s}
.theme-glyph:after{content:"";position:absolute;width:12px;height:12px;top:-1px;left:13px;background:transparent;border-radius:50%;transition:background .35s,transform .45s}
html[data-theme=dark] .theme-glyph{transform:rotate(220deg)}
html[data-theme=dark] .theme-glyph:before{background:#d9ecff;box-shadow:none;transform:scale(1.25)}
html[data-theme=dark] .theme-glyph:after{background:var(--ui-soft);transform:translate(-6px,6px)}
.loading-overlay-spinner{width:52px!important;height:52px!important;border:0!important;border-radius:13px!important;background:url('/assets/icons/网页选项卡标题，网站logo.webp') center/contain no-repeat!important;animation:credit-logo-breathe 1.2s ease-in-out infinite!important}
@keyframes credit-logo-breathe{50%{opacity:.7;transform:scale(.94)}}
@media(max-width:540px){.theme-toggle{width:34px;height:34px;min-width:34px}.sidebar-account img.account-avatar{width:44px!important;height:56px!important}}
@media(prefers-reduced-motion:reduce){.theme-glyph,.theme-glyph::before,.theme-glyph::after{transition:none!important}}

/* Specific legacy sections migrated to tokens instead of one-off dark patches. */
.auth-intro h1,.intro-chip{color:var(--ui-text)!important}
.intro-features span,.intro-chip,.page-view .navbar h1 small,.page-view .app-header h1 span{background:var(--ui-soft)!important;color:var(--ui-highlight-text)!important;border-color:var(--ui-stroke)!important}
.about-public-heading p,.page-view .about-metadata strong,.page-view .about-metadata a{color:var(--ui-muted)!important}
.page-view .about-metadata a{text-decoration-color:var(--ui-primary)!important}
.page-view .about-divider{background:var(--ui-stroke)!important}
.page-view :is(.search-bar,.search-container) input{background:var(--ui-control)!important}
.page-view .loading-overlay-card,.page-view .preflight-error,.route-checking{background:var(--ui-card)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
.page-view :is(.form-row,.form-group,.form-section,.upload-field,.music-now) :is(p,small){color:var(--ui-muted)!important}
.page-view :is(.msg-item,.music-manager-track,.file-row,.record-card) :is(strong,b){color:var(--ui-text)!important}
.page-view .music-delete-actions button:not(.music-delete-confirm){background:var(--ui-soft)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
.page-view .music-task-dialog,.page-view .music-delete-dialog{background:var(--ui-card)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
.page-view :is(.user-dropdown,.music-task-dialog,.music-delete-dialog,.about-public-card,.music-manager-card) :is(p,small){color:var(--ui-muted)!important}


/* == assets/vue-core-additions.css == */
/* The only purpose of this sheet is Vue-managed component geometry and animations. */
.credit-dialog-mask{position:fixed;inset:0;z-index:99999;background:rgba(5,12,24,.58);backdrop-filter:blur(6px);display:grid;place-items:center;padding:16px;}
.credit-dialog-card{width:min(100%,440px);max-height:min(85dvh,720px);overflow:auto;padding:26px 24px 22px;background:var(--ui-card,#fff);color:var(--ui-text,#192e4a);border:1px solid var(--ui-stroke,#dbe5f2);border-radius:20px;box-shadow:0 24px 75px #0004;animation:creditDialogEnter .18s ease-out;}
.credit-dialog-card h3{font-size:20px;font-weight:750;margin:0 0 12px;text-align:center;color:inherit;}
.credit-dialog-card p{margin:0 0 20px;line-height:1.65;white-space:pre-wrap;overflow-wrap:anywhere;color:var(--ui-text,#192e4a);}
.credit-dialog-card input{display:block;width:100%;padding:12px 14px;margin-bottom:20px;font-size:16px;border:1px solid var(--ui-stroke,#dbe5f2);background:var(--ui-control,#f9fbff);color:var(--ui-text,#192e4a);border-radius:11px;box-sizing:border-box;}
.credit-dialog-card input:focus-visible{outline:2px solid var(--ui-primary,#286ee4);outline-offset:2px;}
.credit-dialog-actions{display:flex;gap:12px;}
.credit-dialog-actions button{min-height:44px;flex:1;border-radius:11px;font-size:15px;font-weight:700;border:1px solid transparent;cursor:pointer;}
.credit-dialog-cancel{background:var(--ui-soft,#edf3fb);color:var(--ui-text,#192e4a);border-color:var(--ui-stroke,#dbe5f2)!important;}
.credit-dialog-accept{background:#286de0;color:#fff;}
.credit-dialog-actions button:focus-visible{outline:3px solid var(--ui-primary,#286ee4);outline-offset:2px;}
@keyframes creditDialogEnter{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}
.vue-index .user-dropdown{display:block;position:absolute;}
.vue-index .user-dropdown-item{display:flex;width:100%;border:0;text-align:left;background:transparent;font:inherit;cursor:pointer;}
.vue-index .user-dropdown-item:focus-visible{outline:2px solid var(--ui-primary,#286ee4);outline-offset:-2px;}
.vue-index .vue-rejection{margin-top:8px;padding:9px 12px;border-radius:10px;font-size:13px;line-height:1.55;background:color-mix(in srgb,var(--ui-danger,#bb334a) 9%,var(--ui-card,#fff));color:var(--ui-danger,#bb334a);}
.vue-index .index-refresh-spinning{display:inline-block;animation:indexRefresh .75s linear infinite;}
@keyframes indexRefresh{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.credit-dialog-card,.vue-index .index-refresh-spinning{animation:none!important}}


/* Vue-managed global feedback; stylesheet only describes layout and colors. */
.credit-vue-toasts{position:fixed;top:20px;right:20px;z-index:100002;display:grid;gap:9px;width:min(340px,calc(100vw - 32px));pointer-events:none}
.credit-vue-toast{display:flex;align-items:center;gap:10px;border-radius:13px;padding:13px 16px;background:var(--ui-card,#fff);color:var(--ui-text,#192e4a);border:1px solid var(--ui-stroke,#dbe5f2);box-shadow:0 10px 35px #0003;overflow-wrap:anywhere;font-weight:600}
.credit-vue-toast>span:first-child{display:grid;place-items:center;flex:none;width:23px;height:23px;border-radius:50%;background:var(--ui-success,#117453);color:#fff;font-weight:800}
.credit-vue-toast.error>span:first-child{background:var(--ui-danger,#bb334a)}
.credit-toast-enter-active,.credit-toast-leave-active{transition:transform .18s ease,opacity .18s ease}
.credit-toast-enter-from,.credit-toast-leave-to{opacity:0;transform:translateY(-10px)}
.credit-vue-busy-overlay{position:fixed;inset:0;display:grid;place-items:center;z-index:100000;background:rgba(8,19,34,.58);backdrop-filter:blur(5px);padding:20px}
.credit-vue-busy-card{display:grid;place-items:center;gap:16px;max-width:350px;width:100%;padding:32px;background:var(--ui-card,#fff);color:var(--ui-text,#192e4a);border:1px solid var(--ui-stroke,#dbe5f2);border-radius:18px;box-shadow:0 22px 50px #0005;text-align:center}
.credit-vue-busy-card img{width:53px;height:53px;object-fit:contain;animation:credit-logo-breathe 1.2s ease-in-out infinite}
.credit-vue-busy-card p{margin:0;line-height:1.5;font-weight:700;overflow-wrap:anywhere}
@media (max-width:480px){.credit-vue-toasts{top:max(16px,env(safe-area-inset-top));left:16px;right:16px;width:auto}}
@media (prefers-reduced-motion:reduce){.credit-vue-busy-card img{animation:none}.credit-toast-enter-active,.credit-toast-leave-active{transition:none}}


/* == v3.4.1: zero-white-flash bootstrap and lightweight entrance motion == */
/* Bootstrap, asynchronous skeletons, route preflights and error views must use
   the same theme as the eventual Vue-rendered page. */
html,body,#app,.app-frame,.app-main,.app-stage{background-color:var(--ui-canvas,#f4f7fc)!important}
.first-paint{background:var(--ui-canvas,#f4f7fc)!important;color:var(--ui-muted,#62768f)!important}
.first-paint-bar{background-image:linear-gradient(90deg,var(--ui-stroke,#dae5f2) 0%,var(--ui-primary,#286ee4) 48%,var(--ui-stroke,#dae5f2) 100%)!important;background-size:200% 100%}
.fatal-error,.preflight-error,.route-checking{background:var(--ui-card,#fff)!important;color:var(--ui-text,#192e4a)!important;border-color:var(--ui-stroke,#dae5f2)!important}
.preflight-error p{color:var(--ui-muted,#62768f)!important}
/* Cover old as well as new skeleton variants (including tables and progress cards). */
.page-view :is(.skeleton,.skeleton-card,.skeleton-line,.skeleton-item,.skeleton-table-row,.loading-skeleton),
.skeleton,.skeleton-card,.skeleton-line,.skeleton-item,.skeleton-table-row{
 background-image:linear-gradient(105deg,var(--ui-soft,#edf3fb) 10%,var(--ui-hover,#e9f2ff) 48%,var(--ui-soft,#edf3fb) 85%)!important;
 background-color:var(--ui-soft,#edf3fb)!important;background-size:200% 100%!important;animation:skeletonShine 1.5s linear infinite!important
}
/* Status areas should never briefly flash as bright paper in dark mode. */
.page-view :is(.about-public-loading,.music-manager-loading,.music-manager-empty,.setup-checking,.page-loading,.loading-state,.loading-card,.loading-placeholder){color:var(--ui-muted,#62768f)!important}
html[data-theme="dark"] .page-view :is(.loading-card,.loading-placeholder,.loading-state){background:var(--ui-soft)!important;border-color:var(--ui-stroke)!important}
/* Motion is composited only; no layout-changing transitions or scale on modal dialogs. */
@keyframes creditSidebarReveal{from{opacity:.55;transform:translate3d(-12px,0,0)}to{opacity:1;transform:translate3d(0,0,0)}}
@keyframes creditStageReveal{from{opacity:.25}to{opacity:1}}
@keyframes creditTopbarReveal{from{opacity:.65;transform:translate3d(0,-7px,0)}to{opacity:1;transform:translate3d(0,0,0)}}
@keyframes creditNavShadeIn{from{opacity:0}to{opacity:1}}
@media(min-width:821px){
 .app-sidebar{animation:creditSidebarReveal .42s cubic-bezier(.19,1,.22,1) both}
 .app-topbar{animation:creditTopbarReveal .36s cubic-bezier(.19,1,.22,1) both}
}
.page-view > :first-child{animation:creditStageReveal .38s cubic-bezier(.19,1,.22,1) both}
@media(hover:hover) and (pointer:fine){
 .app-sidebar .side-link{transition:transform .2s cubic-bezier(.2,.8,.2,1),background-color .2s ease,color .2s ease!important}
 .app-sidebar .side-link:hover:not(.selected){transform:translateX(4px)}
 .app-sidebar .side-link .side-icon img{transition:transform .25s cubic-bezier(.2,.85,.2,1),filter .25s ease;transform-origin:center}
 .app-sidebar .side-link:hover .side-icon img{transform:translateY(-1px) scale(1.09);filter:drop-shadow(0 3px 4px #164ea336)}
 .app-sidebar .brand-mark img{transition:transform .3s cubic-bezier(.19,1,.22,1)}
 .app-sidebar .brand:hover .brand-mark img{transform:rotate(-7deg) scale(1.06)}
 .app-sidebar .sidebar-account{transition:border-color .2s,background-color .2s,box-shadow .2s}
 .app-sidebar .sidebar-account:hover{box-shadow:0 6px 20px #0c234015}
 .mobile-dock a{transition:color .2s,background-color .2s,transform .2s}
 .mobile-dock a:hover{transform:translateY(-2px)}
}
@media(max-width:820px){
 .app-sidebar{animation:none!important;transition:transform .32s cubic-bezier(.22,1,.36,1),background-color .22s,border-color .22s!important;will-change:transform}
 .nav-shade{animation:creditNavShadeIn .22s ease both}
 .mobile-dock{transition:background-color .22s,border-color .22s}
}
@media(prefers-reduced-motion:reduce){
 .app-sidebar,.app-topbar,.page-view > :first-child,.nav-shade,.first-paint-bar,
 .page-view :is(.skeleton,.skeleton-card,.skeleton-line,.skeleton-item,.skeleton-table-row,.loading-skeleton){
  animation:none!important;transition:none!important
 }
 .app-sidebar .side-link,.app-sidebar .side-link .side-icon img,.mobile-dock a{transition:none!important}
}

/* v3.4.2: audited WCAG-readable text tokens across both themes.
   Keep geometry untouched; do not override badges, primary button lettering or status chips. */
html[data-theme="light"]{
 --ui-muted:#53647b;
 --ui-primary:#205dc4;
 --ui-highlight-text:#144ca5;
 --ui-danger:#a9233b;
}
html[data-theme="dark"]{
 --ui-muted:#bacce3;
 --ui-primary:#8ab9ff;
 --ui-danger:#ffacb6;
}
.breadcrumb-sep,.app-sidebar .sidebar-account small{color:var(--ui-muted)!important}
html[data-theme] .page-view .back-row h2,
html[data-theme] .page-view .permission-bar .label,
html[data-theme] .page-view .permission-bar>span:not(.permission-badge),
html[data-theme] .page-view :is(.form-title,.section-title,.panel-title){color:var(--ui-text)!important}
html[data-theme] .page-view :is(.upload-hint,.file-info,.file-hint,.form-hint,.hint-text,.field-hint,.form-note,.help-text,.secondary-text,.description-text,.progress-text,.application-progress-number,.application-progress-detail,.upload-files-list,.text-muted){color:var(--ui-muted)!important}
html[data-theme] .page-view :is(.required,.validation-error,.field-error,.error-text){color:var(--ui-danger)!important}
html[data-theme] .page-view :is(.file-item,.upload-files-list){background:var(--ui-soft)!important;color:var(--ui-text)!important;border-color:var(--ui-stroke)!important}
html[data-theme] .page-view :is(.application-progress-dialog,.upload-modal-card,.admin-progress-dialog){background:var(--ui-card)!important;color:var(--ui-text)!important;border:1px solid var(--ui-stroke)!important}
html[data-theme] .page-view :is(.application-progress-dialog,.upload-modal-card,.admin-progress-dialog) :is(h2,h3,strong){color:var(--ui-text)!important}
html[data-theme] .page-view :is(.application-progress-dialog,.upload-modal-card,.admin-progress-dialog) :is(p,small,.progress-text){color:var(--ui-muted)!important}
html[data-theme] .page-view :is(.form-control:disabled,.form-control[readonly]){background:var(--ui-soft)!important;color:var(--ui-muted)!important}
html[data-theme] .page-view :is(.login-prompt p,.about-public-heading p,.music-manager-head p){color:var(--ui-muted)!important}
html[data-theme] .page-view :is(.app-card,.card,.form-section) small{color:var(--ui-muted)}
/* High-contrast link affordances; reserve blue for actions, not quiet descriptions. */
html[data-theme] .page-view a:not(.btn):not(.app-card):not(.tab-btn):not(.settings-primary):not(.settings-secondary){text-underline-offset:2px}

/* v3.4.2: formerly inline upload notes now respond to selected theme. */
html[data-theme] .page-view .form-note{font-size:13px;margin-top:5px;color:var(--ui-muted)!important}
html[data-theme] .page-view .form-validation-hint{font-size:13px;margin-top:5px;color:var(--ui-danger)!important}
/* Service-unavailable page used to retain fixed light-theme text on a dark card. */
html[data-theme] .page-close .is-auth .page-view .service-notice #noticeTitle{color:var(--ui-text)!important}
html[data-theme] .page-close .is-auth .page-view .service-notice #messageText{color:var(--ui-text)!important}
html[data-theme] .page-close .is-auth .page-view .service-notice .notice-help{color:var(--ui-muted)!important}
html[data-theme="light"] .page-close .is-auth .page-view .notice-symbol{background:#fff1e8;color:#94500c}
html[data-theme="light"] .page-close .is-auth .page-view .notice-label{color:#94500c}
html[data-theme="dark"] .page-close .is-auth .page-view .notice-symbol{background:#403324;color:#ffce9d}
html[data-theme="dark"] .page-close .is-auth .page-view .notice-label{color:#ffce9d}

/* v3.4.3 · State surfaces audit. Login/setup/unauthed panels once inherited
   light-only backgrounds/lettering, even when the surrounding card was dark. */
html[data-theme] .page-login .page-view .create-system{
 background:var(--ui-soft)!important;color:var(--ui-text)!important;
 border:1px solid var(--ui-stroke)!important;box-shadow:none!important;
}
html[data-theme] .page-login .page-view .create-system strong,
html[data-theme] .page-login .page-view .create-system h2{color:var(--ui-text)!important}
html[data-theme] .page-login .page-view .create-system p{color:var(--ui-muted)!important}
html[data-theme] .page-login .page-view .setup-checking{color:var(--ui-muted)!important}
html[data-theme] .page-login .page-view .setup-status-error{
 background:color-mix(in srgb,var(--ui-danger) 9%,var(--ui-card))!important;
 color:var(--ui-text)!important;border:1px solid var(--ui-stroke)!important;
}
html[data-theme] .page-login .page-view .setup-status-error p{color:var(--ui-text)!important}
html[data-theme] .page-login .page-view .setup-status-error button{
 background:var(--ui-soft)!important;color:var(--ui-text)!important;border:1px solid var(--ui-stroke)!important;
}
html[data-theme] .page-index .page-view .login-prompt{
 background:var(--ui-card)!important;color:var(--ui-text)!important;
 border:1px solid var(--ui-stroke)!important;border-radius:18px;
 max-width:900px;margin:0 auto;padding:clamp(27px,5vw,56px) clamp(16px,4vw,36px);
}
html[data-theme] .page-index .page-view .login-prompt h3{color:var(--ui-text)!important}
html[data-theme] .page-index .page-view .login-prompt p{color:var(--ui-muted)!important}
html[data-theme] .page-index .page-view .login-prompt .login-btn{background:#286de0!important;color:#fff!important;border:1px solid #286de0!important}
html[data-theme] .page-index .page-view .message-toast{
 background:var(--ui-card)!important;color:var(--ui-text)!important;
 border-top:1px solid var(--ui-stroke)!important;border-right:1px solid var(--ui-stroke)!important;
 border-bottom:1px solid var(--ui-stroke)!important;
}
html[data-theme] .page-index .page-view .message-toast .toast-title{color:var(--ui-text)!important}
html[data-theme] .page-index .page-view .message-toast :is(.toast-time,.toast-content){color:var(--ui-muted)!important}
/* Explicit auth card palette: shared by admin, student and system initialization. */
html[data-theme] .page-create-system .page-view #formContainer,
html[data-theme] .page-login .page-view .login-card,
html[data-theme] .page-student-login .page-view .login-card{
 background:var(--ui-card)!important;color:var(--ui-text)!important;
 border:1px solid var(--ui-stroke)!important;
}
html[data-theme] .page-create-system .page-view #formContainer h2,
html[data-theme] .page-create-system .page-view #formContainer label,
html[data-theme] .page-login .page-view .login-card :is(h2,label),
html[data-theme] .page-student-login .page-view .login-card :is(h2,label){color:var(--ui-text)!important}
html[data-theme] .page-create-system .page-view #formContainer :is(input,textarea),
html[data-theme] .page-login .page-view .login-card :is(input:not([type=checkbox]),textarea),
html[data-theme] .page-student-login .page-view .login-card :is(input:not([type=checkbox]),textarea){
 background:var(--ui-control)!important;color:var(--ui-text)!important;border:1px solid var(--ui-stroke)!important;
}
html[data-theme] .page-create-system .page-view #formContainer :is(.alert-error,.alert-success),
html[data-theme] .page-login .page-view .login-card .error,
html[data-theme] .page-student-login .page-view .login-card .error-box{
 background:var(--ui-soft)!important;color:var(--ui-text)!important;border:1px solid var(--ui-stroke)!important;
}
html[data-theme] .page-create-system .page-view #formContainer .auth-role-icon{
 margin:0 auto 16px;width:58px;height:58px;object-fit:contain;
}
/* Harmonize non-list data/empty/error surfaces with the selected theme. */
html[data-theme] .page-view :is(.no-data,.no-results,.no-records,.not-logged-in,.login-required,.auth-required,.access-denied,.status-empty,.list-empty,.empty-message,.empty-notice,.permission-notice){
 background:var(--ui-soft)!important;color:var(--ui-text)!important;
 border-color:var(--ui-stroke)!important;
}
html[data-theme] .page-view :is(.no-data,.no-results,.no-records,.not-logged-in,.login-required,.auth-required,.access-denied,.status-empty,.list-empty,.empty-message,.empty-notice,.permission-notice) :is(h2,h3,h4,b,strong){color:var(--ui-text)!important}
html[data-theme] .page-view :is(.no-data,.no-results,.no-records,.not-logged-in,.login-required,.auth-required,.access-denied,.status-empty,.list-empty,.empty-message,.empty-notice,.permission-notice) :is(p,small){color:var(--ui-muted)!important}
/* v3.4.4: A disabled destructive action must remain legible (no opacity washout).
 * The state is conveyed by muted paint plus a not-allowed cursor, not by fading text. */
:root,html[data-theme="light"]{
 --ui-danger-disabled-bg:#f1dce1;
 --ui-danger-disabled-text:#78273b;
 --ui-danger-disabled-border:#d2a6b1;
}
html[data-theme="dark"]{
 --ui-danger-disabled-bg:#42313e;
 --ui-danger-disabled-text:#ffd9df;
 --ui-danger-disabled-border:#735263;
}
html[data-theme] .page-view :is(button.btn-danger,button.btn-logout,button.music-danger-btn,button.music-delete-confirm):disabled{
 background:var(--ui-danger-disabled-bg)!important;
 color:var(--ui-danger-disabled-text)!important;
 -webkit-text-fill-color:var(--ui-danger-disabled-text)!important;
 border:1px solid var(--ui-danger-disabled-border)!important;
 opacity:1!important;
 filter:none!important;
 box-shadow:none!important;
 transform:none!important;
 cursor:not-allowed!important;
}
html[data-theme] .page-music .page-view button:disabled{cursor:not-allowed!important;transform:none!important;filter:none!important}

@media(prefers-reduced-motion:reduce){html[data-theme] .page-index .page-view .message-toast{animation:none!important}}
