/* 喇叭花 · 教师端「我的班级」仪表盘外壳（侧边栏 + 顶栏 + 横幅 + 班级卡片） */
/* 双栏独立滚动：外壳锁死一屏高度，左侧菜单自己滚、右侧内容自己滚，互不带跑 */
.dash-shell { height: 100vh; overflow: hidden; display: flex; background: var(--bg); }
.dash-side { width: 232px; flex-shrink: 0; height: 100vh; overflow-y: auto; overscroll-behavior: contain;
             background: var(--card); display: flex; flex-direction: column; border-right: 1px solid var(--line); }
.dash-brand { padding: 18px 20px; display: flex; align-items: center; gap: 8px;
              font-size: 19px; font-weight: 700; color: var(--ink); }
.dash-nav { padding: 6px 12px; display: flex; flex-direction: column; gap: 2px; }
.dash-nav-item { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: 10px;
                 font-size: 14px; font-weight: 500; color: var(--ink2); cursor: pointer; border: none;
                 background: transparent; text-align: left; min-height: 42px; width: 100%; }
.dash-nav-item:hover { background: #f3f6fb; color: var(--ink); }
.dash-nav-item.active { background: var(--primary-soft, #eff6ff); color: var(--b1); font-weight: 600; }
.dash-spacer { flex: 1; }
.dash-user { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-top: 1px solid var(--line); }
.dash-avatar { width: 34px; height: 34px; border-radius: 50%; flex-shrink: 0; display: flex; align-items: center;
               justify-content: center; color: #fff; font-size: 13px; font-weight: 600;
               background: linear-gradient(120deg, var(--b1), var(--b2)); }
.dash-user-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.dash-user-info b { font-size: 13px; color: var(--ink); }
.dash-user-info span { font-size: 11px; color: var(--ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 账号区的套餐标识（体验版 / 多班版…）：与权益卡同源同配色，只是尺寸更小。
   用 div 而非 span：躲开上面那条 .dash-user-info span 的 11px/ink2/省略号 */
.dash-user-info .du-plan { align-self: flex-start; margin-top: 3px; padding: 1px 8px;
                           border-radius: 999px; font-size: 10px; font-weight: 700; line-height: 1.7; }
.dash-logout { border: none; background: transparent; cursor: pointer; color: var(--ink2); padding: 6px; font-size: 15px; }

.dash-main { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.dash-mtop { display: none; }
/* 移动端 ☰ 与抽屉遮罩：桌面端一律关掉，样式主体在下面的 ≤900px 里 */
.mtop-menu { display: none; align-items: center; justify-content: center; width: 36px; height: 36px;
             flex-shrink: 0; padding: 0; border: none; border-radius: 10px; background: var(--bg);
             cursor: pointer; }
/* 三条线用伪元素 + box-shadow 画，不用 ☰ 字符：那个码点在部分中文字体里会缺字/粗细不一 */
.mtop-menu::before { content: ''; width: 16px; height: 2px; border-radius: 2px; background: var(--ink);
                     box-shadow: 0 -5px 0 var(--ink), 0 5px 0 var(--ink); }
.mtop-menu:active { background: var(--primary-soft, #eff6ff); }
.dash-mask { display: none; }
.dash-top { height: 70px; padding: 0 28px; display: flex; align-items: center; gap: 12px;
            background: var(--card); border-bottom: 1px solid var(--line); }
.dash-title { display: flex; flex-direction: column; gap: 2px; }
.dash-title b { font-size: 18px; color: var(--ink); }
.dash-title span { font-size: 12px; color: var(--ink2); }
.dash-top .sp { flex: 1; }
.btn-gradient { display: inline-flex; align-items: center; gap: 6px; padding: 10px 18px; border: none;
                border-radius: 10px; background: linear-gradient(120deg, var(--b1), var(--b2));
                color: #fff; font-size: 14px; font-weight: 600; cursor: pointer; }
.btn-gradient:hover { filter: brightness(1.08); }

.dash-content { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
                padding: 28px; display: flex; flex-direction: column; gap: 18px; align-items: flex-start; }
/* 五个内嵌视图共用此容器。父级是 align-items:flex-start，子项不会自动拉伸，
   不显式给 width:100% 就会收缩到内容宽度（班级卡片宽度会随最长文案漂移）。 */
.dash-view { width: 100%; min-width: 0; }

/* 体验/买断横幅 */
.dash-banner { width: 100%; padding: 16px 22px; border-radius: 14px; display: flex; align-items: center;
               gap: 14px; color: #fff; background: linear-gradient(90deg, var(--b1), var(--b2)); }
.dash-banner .bicon { width: 40px; height: 40px; border-radius: 12px; background: #ffffff2b; flex-shrink: 0;
                      display: flex; align-items: center; justify-content: center; font-size: 19px; }
.dash-banner .btext { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.dash-banner .btext b { font-size: 15px; }
.dash-banner .btext span { font-size: 12px; color: #ffffffb3; }
.btn-white { padding: 9px 16px; border: none; border-radius: 9px; background: #fff; color: var(--b1);
             font-size: 13px; font-weight: 700; cursor: pointer; flex-shrink: 0; }

/* 区块标题 */
.dash-sec { width: 100%; display: flex; align-items: center; gap: 8px; }
.dash-sec b { font-size: 15px; color: var(--ink); }
.dash-sec .chip { padding: 2px 9px; border-radius: 999px; background: var(--primary-soft, #eff6ff);
                  color: var(--b1); font-size: 12px; font-weight: 700; }

/* 班级卡片 */
.dash-cards { width: 100%; display: flex; flex-direction: column; gap: 16px; }
/* 班级列表改网格：桌面自动多列，≤900px 由 media query 降单列。
   之所以不给 minmax 套 min(330px,100%)：宁可用显式 media query 切 1fr，
   320px 的老机器也不会横向溢出，且不依赖浏览器对 min() 的支持。 */
.room-grid { width: 100%; display: grid; grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
             gap: 16px; align-items: start; }
/* 只有 1 个班时给列宽封顶：否则单卡横跨整行，看着像另一页 */
.room-grid.single { grid-template-columns: minmax(330px, 520px); }
.room-grid .room-card { gap: 12px; }
.room-card { width: 100%; background: var(--card); border: 1px solid var(--line); border-radius: 16px;
             padding: 20px; display: flex; flex-direction: column; gap: 14px; position: relative;
             box-shadow: 0 6px 18px rgba(11, 42, 74, 0.08); }
.room-card .rc-head { display: flex; align-items: center; gap: 10px; }
.room-card .rc-head b { font-size: 16px; color: var(--ink); }
.badge { padding: 3px 9px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.badge-trial { background: #fef3c7; color: #b45309; }
.badge-lifetime { background: #d1fae5; color: #047857; }
.badge-active { background: #dbeafe; color: #1d4ed8; }
/* 试用到期后仍是「权益」的一种状态，得有个说得清的颜色，别复用上面三种 */
.badge-expired { background: #fee2e2; color: #b91c1c; }
/* 一条开通记录都没有（未开通）：中性灰，别用红色吓人 */
.badge-none { background: #eef2f9; color: #5a7ba6; }
.room-card .rc-more { margin-left: auto; border: none; background: transparent; cursor: pointer;
                      color: var(--ink2); font-size: 16px; padding: 4px 8px; border-radius: 8px; position: relative; }
.room-card .rc-more:hover { background: var(--bg); }
.room-card .rc-menu { position: absolute; right: 12px; top: 44px; background: #fff; border: 1px solid var(--line);
                      border-radius: 10px; box-shadow: 0 10px 26px rgba(11,42,74,.16); z-index: 5;
                      display: flex; flex-direction: column; overflow: hidden; }
.room-card .rc-menu button { border: none; background: transparent; padding: 9px 18px; font-size: 13px;
                             cursor: pointer; text-align: left; color: var(--ink); }
.room-card .rc-menu button:hover { background: var(--bg); }
.room-card .rc-menu button.danger { color: var(--danger, #ef4444); }
.room-card .rc-meta { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.room-card .rc-meta .m { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink2); }
.room-card .rc-meta .m b { font-size: 12px; color: var(--ink); }
/* 两个码：整块就是复制按钮。原来只有末尾一个 📋 小图标可点，手机上很难按准 */
.room-card .rc-codes { display: flex; gap: 8px; flex-wrap: wrap; }
/* min-width 是两个码并肩的底线：容不下就自动换行堆叠，比把码缩成省略号好——码是要照着抄的 */
.code-btn { flex: 1 1 calc(50% - 4px); min-width: 132px; display: flex; align-items: center; gap: 8px; padding: 9px 12px;
            border: 1px solid var(--line); border-radius: 10px; background: var(--bg);
            font-family: inherit; text-align: left; cursor: pointer; }
.code-btn:hover { border-color: var(--b1); }
.code-btn:hover i { color: var(--b1); }
.code-btn span { flex-shrink: 0; font-size: 11px; color: var(--ink2); }
.code-btn b { flex: 1; min-width: 0; font-size: 14px; color: var(--ink); font-family: Consolas, Monaco, monospace;
              letter-spacing: .5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.code-btn i { flex-shrink: 0; font-style: normal; font-size: 13px; color: var(--ink2); }
/* 绑定提示：整行独占，不再和「进入工作台」抢同一行的空间 */
.room-card .rc-note { margin: 0; font-size: 12px; color: var(--ink2); line-height: 1.7;
                      display: flex; align-items: flex-start; gap: 6px; }
.room-card .rc-note > span { min-width: 0; }
/* 主行动按钮：每天都要点，给它渐变实心 + 整行宽度 */
.room-card .btn-enter { width: 100%; justify-content: center; }
.room-card .rc-foot { display: flex; align-items: center; gap: 10px; }

/* 我的班级：纵向撑满可用高度，让空状态居中而不是吊在顶部、下面拖一大片留白 */
#viewRooms { display: flex; flex-direction: column; gap: 16px; flex: 1; min-height: 0; }
#viewRooms .dash-cards { flex: 1; }

/* 空状态（无班级 / 无设备等场景通用）：占满可用区并居中，自带主行动按钮 */
.dash-empty { width: 100%; padding: 46px 24px; background: var(--card); border: 1px solid var(--line);
              border-radius: 16px; display: flex; flex-direction: column; align-items: center;
              justify-content: center; gap: 8px; text-align: center; }
#viewRooms .dash-empty { flex: 1; }
.dash-empty .de-icon { width: 54px; height: 54px; border-radius: 16px; margin-bottom: 4px; font-size: 24px;
                       background: var(--primary-soft, #eff6ff); display: flex; align-items: center;
                       justify-content: center; }
.dash-empty .de-title { font-size: 15px; color: var(--ink); }
.dash-empty .de-sub { margin: 0; max-width: 430px; font-size: 12px; color: var(--ink2); line-height: 1.8; }
.dash-empty .de-cta { margin-top: 10px; }
.dash-empty .de-alt { margin: 4px 0 0; font-size: 12px; color: var(--ink2); }
/* 额度用尽：主按钮置灰，别让用户点了才被告知 */
.btn-gradient:disabled { filter: grayscale(1); opacity: .5; cursor: not-allowed; }
.btn-gradient:disabled:hover { filter: grayscale(1); }

/* 移动端适配 */
@media (max-width: 900px) {
  /* 手机上侧边栏改抽屉：原来是 `display:none`，导航 / 账号卡 / 退出登录全失联
     （2026-09-17 修）。这里不复制导航 DOM —— 同一条 .dash-side 变成从左侧滑出的
     fixed 抽屉，靠 body.mnav-open 切换，事件在 lib/navdrawer.js。 */
  .dash-side { display: flex; position: fixed; top: 0; bottom: 0; left: 0; width: 258px; max-width: 84vw;
               height: 100vh; z-index: 60; overflow-y: auto;
               transform: translateX(-100%); transition: transform .24s ease;
               box-shadow: 0 0 30px rgba(11, 42, 74, .16); }
  body.mnav-open .dash-side { transform: none; }
  /* 抽屉铺满屏时锁住背景滚动，否则手指在遮罩上一划会滚到底下的班级列表 */
  body.mnav-open { overflow: hidden; }
  .mtop-menu { display: flex; }
  .dash-mask { display: block; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 55;
               background: rgba(11, 42, 74, .45); opacity: 0; pointer-events: none;
               transition: opacity .24s ease; }
  body.mnav-open .dash-mask { opacity: 1; pointer-events: auto; }
  .dash-mtop { display: flex; align-items: center; gap: 10px; height: 58px; padding: 0 18px;
               background: var(--card); border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 4; }
  .dash-mtop b { flex: 1; font-size: 16px; color: var(--ink); }
  .dash-top { padding: 0 18px; }
  .dash-content { padding: 16px; gap: 14px; }
  .dash-empty { padding: 32px 16px; }
  .dash-banner { flex-wrap: wrap; padding: 14px 16px; }
  .dash-banner .btn-white { width: 100%; }
  .room-card { padding: 16px; }
  .room-card .rc-meta { flex-direction: column; align-items: flex-start; gap: 7px; }
  .room-card .rc-foot { flex-wrap: wrap; }
  /* 窄屏一律单列（两条选择器都写，否则 .room-grid.single 的特异性会盖掉这条） */
  .room-grid, .room-grid.single { grid-template-columns: 1fr; }
  /* 通讯页：输入+按钮堆叠，Broker 黄底节左右不再外扩 */
  .conn-card { padding: 16px; }
  .conn-main { padding: 0 16px; }
  .conn-fieldrow { flex-direction: column; align-items: stretch; }
  .conn-fieldrow .btn { width: 100%; justify-content: center; }
  .conn-sec-warn { margin: 0 -16px; padding: 16px; }
}

/* ================= 内嵌视图（设备/兑换/公告/设置） ================= */
.dash-hint { font-size: 12px; color: var(--ink2); margin: 0; }

/* ================= 我的套餐页（/plan：权益卡 / 档位网格 / 兑换卡密 / 开通记录） =================
   2026-09-16：从教师端内嵌视图迁出为独立页，样式在 dashboard.css 里集中维护
   （独立页与教师端共用同一套 .dash-shell/.dash-sec 外壳，拆成两个文件会立刻漂移）。
   原「开通买断」弹窗那套 .lb-upg-* 已随弹窗一起删除。 */

/* 权益卡：badge 与标题同一行（设计稿），右侧三个统计数 */
.ent-card { width: 100%; background: var(--card); border: 1px solid var(--line); border-radius: 16px;
            padding: 20px; display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
            box-shadow: 0 6px 18px rgba(11, 42, 74, 0.08); }
.ent-main { flex: 1; min-width: 240px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.ent-main .ent-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ent-main .ent-head { font-size: 18px; color: var(--ink); }
.ent-main .ent-sub { margin: 0; font-size: 12px; color: var(--ink2); line-height: 1.75; }
.ent-stats { display: flex; gap: 26px; flex-shrink: 0; }
.ent-stat { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.ent-stat b { font-size: 20px; color: var(--ink); }
.ent-stat span { font-size: 11px; color: var(--ink2); }

/* 档位网格：必须用 auto-fit（不是 auto-fill）——auto-fill 会保留空轨道，
   1400 宽时 3 张卡挤成 258px 还在右边留个洞；auto-fit 把空轨道收起、卡吃满一行。
   卡片另加 max-width，防"只剩一个档位时被拉成整条横幅"。 */
.plan-grid { width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
             gap: 16px; align-items: start; }
.plan-card { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 18px;
             max-width: 460px; display: flex; flex-direction: column; gap: 10px; }
/* 主推档（fa_lbh_sku.is_hot）：整卡蓝框 + 名称后的「主推」角标 */
.plan-card.hot { border: 1.5px solid var(--b1); }
.plan-head { display: flex; align-items: center; gap: 8px; }
.plan-head b { font-size: 15px; color: var(--ink); }
.plan-hot { padding: 1px 8px; border-radius: 999px; background: var(--primary-soft, #eff6ff);
            color: var(--b1); font-size: 11px; font-weight: 600; }
.plan-price { margin-left: auto; font-size: 20px; font-weight: 800; color: var(--b1); }
/* 卖点：设计稿用绿色对勾，不用默认圆点 —— 圆点在 12px 灰字下几乎看不见 */
.plan-feats { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px;
              font-size: 12px; color: var(--ink2); line-height: 1.75; }
.plan-feats li { display: flex; align-items: flex-start; gap: 6px; }
.plan-feats li::before { content: '✓'; flex-shrink: 0; font-weight: 700; color: var(--ok, #10b981); }
.plan-desc { margin: 0; padding-top: 10px; border-top: 1px solid var(--line);
             font-size: 12px; color: var(--ink2); line-height: 1.7; }
/* 「还没有卡密？」那行：有卖家联系方式就直接给，没有时只说事实，不留空 */
.plan-note { margin: 10px 0 0; font-size: 12px; color: var(--ink2); line-height: 1.7; }

/* 兑换卡密：左边图标+说明，右边输入+按钮（设计稿为横排卡片，不是竖排表单） */
.redeem-card { width: 100%; background: var(--card); border: 1px solid var(--line); border-radius: 16px;
               padding: 16px 20px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
               box-shadow: 0 6px 18px rgba(11, 42, 74, 0.08); }
.rd-main { flex: 1; min-width: 220px; display: flex; align-items: center; gap: 12px; }
.rd-icon { width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0; font-size: 18px;
           background: var(--primary-soft, #eff6ff); display: flex; align-items: center; justify-content: center; }
.rd-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rd-text b { font-size: 14px; color: var(--ink); }
.rd-text span { font-size: 12px; color: var(--ink2); }
.rd-form { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.rd-form input { width: 240px; }
.rd-err { width: 100%; margin: 0; font-size: 12px; color: var(--danger, #ef4444); }

/* 开通记录：四列表格（时间/来源/套餐/名额）。用 grid 而不是 <table>，
   是为了窄屏能整体换成 flex 换行，不用改 DOM。 */
.order-table { width: 100%; background: var(--card); border: 1px solid var(--line); border-radius: 16px;
               overflow: hidden; box-shadow: 0 6px 18px rgba(11, 42, 74, 0.08); }
.ot-head, .ot-row { display: grid; grid-template-columns: 200px 1fr 220px 100px;
                    align-items: center; gap: 12px; padding: 11px 20px; }
.ot-head { background: #f6f9fd; font-size: 12px; color: var(--ink2); }
.ot-row { font-size: 12px; color: var(--ink2); border-top: 1px solid var(--line); }
.ot-row .ot-c3 b { font-size: 13px; color: var(--ink); }
.ot-src { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 11px; font-weight: 600;
          background: #fef3c7; color: #b45309; }                 /* 注册赠送 */
.ot-src.src-card { background: #dbeafe; color: #1d4ed8; }         /* 卡密兑换 */
.ot-src.src-epay { background: #d1fae5; color: #047857; }         /* 在线支付 */
.ot-src.src-admin { background: #eef2f9; color: #48709f; }        /* 后台开通 */
.ot-empty { margin: 0; padding: 18px 20px; font-size: 12px; color: var(--ink2); }

.dash-sec .sp { flex: 1; }
.sec-hint { font-size: 12px; color: var(--ink2); }

/* ⚠️ 这段必须留在本节末尾（即基础规则之后）：上面那份 900px 媒体查询在文件更前面，
   把覆盖写进那里会被后定义的 .plan-grid / .ent-card 基础规则按"同权重后胜"盖掉。
   实测过：那样写 760px 下档位仍是 2 列。 */
@media (max-width: 900px) {
  /* 250px 的下限在手机上一行放不下，别留半格 */
  .plan-grid { grid-template-columns: 1fr; }
  .ent-card { padding: 16px; gap: 16px; }
  .ent-stats { width: 100%; justify-content: space-between; gap: 0; }
  .redeem-card { padding: 16px; }
  .rd-form { width: 100%; }
  .rd-form input { flex: 1; width: auto; }
  /* 表格换行堆叠：表头没有意义了，时间独占一行，其余三项自动折行 */
  .ot-head { display: none; }
  .ot-row { display: flex; flex-wrap: wrap; gap: 6px 12px; }
  .ot-row .ot-c1 { width: 100%; }
  .sec-hint { display: none; }
}

.dev-list { display: flex; flex-direction: column; }
.dev-row { display: flex; align-items: center; gap: 12px; padding: 11px 2px; border-bottom: 1px solid var(--bg); }
.dev-row:last-child { border-bottom: none; }
.dev-row .dev-ic { font-size: 14px; }
.dev-row .dev-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.dev-row .dev-info b { font-size: 13px; color: var(--ink); }
.dev-row .dev-info span { font-size: 11px; color: var(--ink2); }
.dev-row .btn-unbind { padding: 6px 14px; font-size: 12px; }

.order-card .rc-foot { gap: 12px; }
.order-card .osku { font-size: 13px; color: var(--ink); }
.order-card .ono { font-family: Consolas, Monaco, monospace; font-size: 11px; color: var(--ink2); }
.order-card .oamt { font-size: 14px; color: var(--ink); }

.notice-card .nc-title { font-size: 14px; font-weight: 700; color: var(--ink); }
.notice-card .nc-body { margin-top: 8px; font-size: 13px; color: var(--ink2); line-height: 1.8; white-space: pre-wrap; }

#viewSettings .join-form input { width: 100%; text-align: left; }
#viewSettings .join-form label { margin-top: 10px; }
