/* ============================================================================
 * HomeworkShower 网页端样式表（单一来源，不再追加补丁）
 *
 *   1. 基础与字体        7. 登录注册
 *   2. 顶栏与个人中心     8. 发布页
 *   3. 看板与分栏        9. 富文本编辑器
 *   4. 作业卡片         10. 弹窗与表单字段
 *   5. 状态/横幅/占位    11. 用户管理
 *   6. 右下角编辑按钮    12. 兜底页与手机适配
 * ========================================================================= */

/* ---------------------------------------------------------------- 1. 基础 */

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

html,
body {
  margin: 0;
  min-height: 100%;
  background: var(--md-sys-color-background, #f5fafc);
  color: var(--md-sys-color-on-background, #171d1e);
}

html,
body,
m3e-theme {
  font-family: "PingFang SC", "HarmonyOS Sans SC", "Microsoft YaHei", "MiSans",
    "Source Han Sans SC", "Noto Sans CJK SC", Inter, ui-sans-serif, system-ui,
    -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
  font-synthesis: none;
}

input,
textarea,
select,
button {
  font-family: inherit !important;
}

m3e-theme {
  display: block;
  min-height: 100dvh;
}

/* 组件升级前先藏起来，避免弹窗内容裸奔 */
m3e-dialog:not(:defined),
m3e-fab:not(:defined),
m3e-fab-menu:not(:defined),
m3e-datepicker:not(:defined),
m3e-snackbar:not(:defined) {
  display: none !important;
}

/* Snackbar（那个底部提示条）是用 popover 显示的，宿主元素自己没样式，
   不处理就会在圆角外露出一块白底（看着就是"提示条四个角发白"）。
   真正有背景的是它内部的 .base，把宿主刷成透明即可。 */
m3e-snackbar {
  background: transparent !important;
  border: 0 !important;
  padding: 0 !important;
  overflow: visible !important;
  max-width: min(560px, calc(100vw - 32px));
}

m3e-snackbar::backdrop {
  background: transparent !important;
}

/* 启动遮罩：组件就绪后由页面脚本撤掉 */
html.hs-booting body {
  visibility: hidden;
}

/* ------------------------------------------------- 2. 顶栏与个人中心 */

.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  background: var(--md-sys-color-background, #f5fafc);
  border-bottom: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
}

.topbar__title {
  margin-inline-end: auto;
}

.topbar__controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.account {
  position: relative;
}

.account__panel {
  position: absolute;
  inset-inline-end: 0;
  top: calc(100% + 8px);
  z-index: 25;
  /* 绝对定位 + inset-inline-end:0 的元素，宽度是 shrink-to-fit，可用宽度取自包含块
     （那个 116px 宽的「个人中心」按钮），所以必须靠 min-width 撑回设计宽度。
     但写死 320px 在窄屏上会把左半边顶出屏幕（邮箱整行看不见），
     所以用 min() 按视口钳制：放得下就 320px，放不下才收缩。
     ⚠ 别改成 min-width: 0 —— 面板会塌到内容宽（实测只剩 122px，邮箱被迫折行）。 */
  min-width: min(320px, calc(100vw - 28px));
  /* 兜底：面板锚在按钮右边缘，屏幕不够宽时它会往左溢出到屏幕外 */
  max-width: calc(100vw - 28px);
  display: grid;
  gap: 8px;
  padding: 22px 22px 18px;
  border: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
  border-radius: 16px;
  background: var(--md-sys-color-surface-container-high, #e3e9eb);
  box-shadow: 0 8px 24px rgb(0 0 0 / 18%);
}

.account__meta {
  display: grid;
  gap: 2px;
  font-size: 14px;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

.account__meta strong {
  font-size: 16px;
  font-weight: 500;
  color: var(--md-sys-color-on-surface, #171d1e);
  overflow-wrap: anywhere;
}

.role-chip {
  justify-self: start;
  padding: 2px 12px;
  border: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
  border-radius: 999px;
  font-size: 12px;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

/* 宽度要放得下完整日期「2026 年 9 月 23 日」（约 130px）+ 后缀日历按钮 */
#date-field {
  width: 260px;
  min-width: 260px;
  max-width: 260px;
}

/* ---------------------------------------------------- 3. 看板与分栏 */

.homework-board {
  padding: 24px 20px 96px;
}

/* 分栏前先量版面：量的时候把内容藏起来。
   用 visibility 而不是 display:none —— 后者量不到尺寸（全 0）；visibility 保留布局，
   元素照样有真实宽高，只是用户看不见。排好了再显示，用户就不会看到"跳一下"。 */
.homework-board--measuring {
  visibility: hidden;
}

/* 列由 JS 分配：先量出每个科目组的高度，再装箱（见 board.js 的 layoutColumns）。
   JS 分栏时会给容器加 .masonry-columns--js，把下面的多列兜底关掉。 */
.masonry-columns {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

.masonry-column {
  display: block;
  flex: 1 1 0;
  min-width: 0;
}

/* 兜底：万一 JS 没跑到（脚本出错等），用浏览器原生多列把内容排开，
   总比全部堆成一列好。 */
.masonry-columns:not(.masonry-columns--js) {
  display: block;
  column-count: 3;
  column-gap: 8px;
}

.masonry-columns:not(.masonry-columns--js) > .subject-group {
  break-inside: avoid;
  page-break-inside: avoid;
}

@media (max-width: 1100px) {
  .masonry-columns:not(.masonry-columns--js) {
    column-count: 2;
  }
}

@media (max-width: 700px) {
  .masonry-columns:not(.masonry-columns--js) {
    column-count: 1;
  }
}

@keyframes hs-rise {
  from {
    opacity: 0;
    transform: scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes hs-fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.subject-group {
  margin: 0 0 36px;
  /* backwards：动画播完交回普通样式，不永久覆盖后续状态 */
  animation: hs-rise 420ms cubic-bezier(0.25, 1, 0.5, 1) backwards;
  animation-delay: calc(var(--i, 0) * 60ms);
}

.subject-group > m3e-heading {
  display: block;
  margin: 0 0 0.65rem;
  color: var(--md-sys-color-on-surface, #171d1e);
}

.subject-homework-list {
  display: block;
  width: 100%;
  /* m3e-list 自己带着 overflow: auto，而卡片的阴影是画在 M3E 内部那层 surface 上的 ——
     宿主这一层的 overflow 会在自己的 padding box 上把它裁掉，表现就是
     "卡片四周的阴影被切平了，右边最明显"。
     这里放开裁切，让阴影能画到列表盒子外面去。 */
  overflow: visible;
  --m3e-segmented-list-segment-gap: 0.125rem;
  --m3e-segmented-list-container-shape: 0.75rem;
  --m3e-segmented-list-item-container-color: var(--md-sys-color-surface-container-low, #eff4f6);
  --m3e-segmented-list-item-container-shape: 0;
}

/* ------------------------------------------------------- 4. 作业卡片 */

.homework-item {
  position: relative;
  min-width: 0;
  width: 100%;
  animation: hs-rise 360ms cubic-bezier(0.25, 1, 0.5, 1) backwards;
  animation-delay: calc(var(--i, 0) * 40ms + 80ms);
  transition:
    background-color 200ms ease-out,
    transform 220ms cubic-bezier(0.5, 1, 0.89, 1),
    box-shadow 200ms ease-out;
  --m3e-list-item-container-color: var(--md-sys-color-surface-container-low, #eff4f6);
  --m3e-list-item-label-text-color: var(--md-sys-color-on-surface, #171d1e);
  --m3e-list-item-supporting-text-color: var(--md-sys-color-on-surface-variant, #3f484a);
  --m3e-list-item-leading-color: var(--md-sys-color-primary, #006877);
  --m3e-list-item-between-space: 0.75rem;
  --m3e-list-item-padding-block: 0.75rem;
  --m3e-list-item-padding-inline: 0.9rem;
}

.homework-item--clickable {
  cursor: pointer;
}

/* 点击卡片：只有卡片自己缩一下。
   两种情况让位：
     1. 卡片内的图标按钮（修改/删除）自己有点击反馈，别让整张卡片跟着动；
     2. 鼠标停在图片上时，反馈交给图片自己的伪 3D 上浮。 */
.homework-item--clickable:not(:has(m3e-icon-button:active)):not([data-hover-image="1"]):active {
  transform: scale(0.975);
}

/* 鼠标在图片上时，卡片的悬停反馈让位给图片本身的上浮 */
.homework-item--clickable:hover:not([data-hover-image="1"]) {
  box-shadow: 0 3px 12px rgb(0 0 0 / 10%);
}

.homework-item--selected {
  --m3e-list-item-container-color: var(--md-sys-color-secondary-container, #cde7ed);
  --m3e-list-item-label-text-color: var(--md-sys-color-on-secondary-container, #334a50);
  --m3e-list-item-leading-color: var(--md-sys-color-on-secondary-container, #334a50);
  box-shadow: 0 2px 10px rgb(0 0 0 / 12%);
}

.homework-item--expired {
  --m3e-list-item-label-text-color: var(--md-sys-color-error, #ba1a1a);
  --m3e-list-item-leading-color: var(--md-sys-color-error, #ba1a1a);
}

.homework-content {
  display: grid;
  grid-template-columns: 0.375rem minmax(0, 1fr);
  column-gap: 0.65rem;
  align-items: start;
  min-width: 0;
  max-width: 100%;
  font-size: 1.125rem;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow: hidden;
}

.homework-text {
  display: block;
  grid-column: 2;
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.homework-text :where(p, h1, h2, h3, h4, h5, h6, pre, blockquote) {
  margin: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
}

.homework-text :where(ul, ol) {
  margin: 0;
  padding-inline-start: 1.4em;
}

.homework-text img {
  max-width: 100%;
  height: auto;
  -webkit-touch-callout: none;
  -webkit-user-drag: none;
  user-select: none;
  border-radius: 8px;
  transform-origin: center bottom;
  /* 卡片 hover/按下时 M3E 会把状态层画在内容下面；把图片提到上层，
     这样卡片变暗时图片自己不变暗 */
  position: relative;
  z-index: 1;
  isolation: isolate;
  /* 用 transform 做抬升，避免和卡片自身的 hover 抢同一个属性 */
  transition:
    transform 260ms cubic-bezier(0.2, 0, 0, 1),
    box-shadow 260ms cubic-bezier(0.2, 0, 0, 1);
}

/**
 * 桌面端鼠标悬停在图片上：轻轻上浮一点点就好
 * （之前那版透视+仰角+投影太花哨）。
 * 只在真的有指针悬停的设备上启用，触摸设备看不到 hover 会一直"卡"在浮起状态。
 */
@media (hover: hover) and (pointer: fine) {
  .homework-text img:hover {
    transform: translateY(-3px);
    box-shadow: 0 8px 18px rgb(0 0 0 / 14%);
  }
}

.homework-text a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.homework-marker {
  display: block;
  grid-column: 1;
  grid-row: 1;
  width: 0.375rem;
  height: 0.375rem;
  margin-top: calc((1.55em - 0.375rem) / 2);
  border-radius: 50%;
  background: currentColor;
}

.homework-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding-block-start: 0.35rem;
}

/* 展开/收起：常驻文档流（display:none 无法参与过渡） */
.homework-actions {
  display: flex;
  justify-content: flex-end;
  gap: 2px;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  transition:
    max-height 240ms cubic-bezier(0.5, 1, 0.89, 1),
    opacity 180ms cubic-bezier(0.5, 1, 0.89, 1);
}

.homework-item--selected .homework-actions {
  max-height: 72px;
  opacity: 1;
  pointer-events: auto;
}

/* ------------------------------------------- 5. 状态 / 横幅 / 空状态 */

/* ------------------------------------------------- 3.5 公告栏 */

/* 公告栏：状态条上方一个框，每条一行。
   没有公告时由脚本加 hidden 属性，整块收起（不占位、不留边框）。 */
.announcement-bar {
  margin: 16px 20px 0;
  padding: 14px 16px 16px;
  border: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
  border-radius: 14px;
  background: var(--md-sys-color-surface-container-low, #eff4f6);
  animation: hs-fade 260ms cubic-bezier(0.25, 1, 0.5, 1) backwards;
}

.announcement-bar[hidden] {
  display: none;
}

.announcement-bar__head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

.announcement-bar__head m3e-heading {
  margin: 0;
}

.announcement-list {
  display: block;
  width: 100%;
  /* 同 .subject-homework-list：放开裁切，否则卡片的阴影会被列表边界切掉 */
  overflow: visible;
  --m3e-segmented-list-segment-gap: 0.375rem;
  --m3e-segmented-list-container-shape: 0.75rem;
  --m3e-segmented-list-item-container-color: var(--md-sys-color-surface, #ffffff);
}

.announcement-item {
  position: relative;
  width: 100%;
  /* 每条一行：内容过长就换行，不横向溢出 */
  overflow-wrap: anywhere;
}

.announcement-item__body {
  display: block;
  min-width: 0;
}

.announcement-item__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 12px;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

/* 公告是"一行一条"，正文排版比作业略小 */
.announcement-item .homework-text {
  font-size: 14px;
  line-height: 1.7;
}

.announcement-item .homework-text img {
  max-width: min(320px, 100%);
}

/* 重要等级标签：颜色区分，文字一律中文 */
.announcement-tag {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
  font-size: 12px;
  line-height: 1.6;
  white-space: nowrap;
}

.announcement-tag--LOW,
.announcement-tag--NORMAL {
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

.announcement-tag--MODERATE {
  color: #7a5900;
  border-color: #e6c34a;
  background: #fff3cd;
}

.announcement-tag--IMPORTANT {
  color: #7f1d1d;
  border-color: #f3b4b4;
  background: #ffe4e6;
  font-weight: 600;
}

.announcement-tag--pinned {
  color: var(--md-sys-color-primary, #006877);
  border-color: var(--md-sys-color-primary, #006877);
}

.announcement-tag--internal {
  color: #4338ca;
  border-color: #c7d2fe;
  background: #eef2ff;
}

/* 左侧色条：等级越高越醒目（置顶用主色） */
.announcement-item--IMPORTANT { border-inline-start: 3px solid #ef4444; }
.announcement-item--MODERATE { border-inline-start: 3px solid #e6b800; }
.announcement-item--pinned { border-inline-start: 3px solid var(--md-sys-color-primary, #006877); }

/* 编辑公告对话框里的可点击选项。
   M3E 只注册了 10 个组件，没有 switch / checkbox / select，
   所以等级与开关用自绘 chip 实现（带按压反馈、键盘可聚焦）。 */
/* 公告选项：开关。
   M3E 只注册了 10 个组件、其中没有 switch，所以这里用原生 checkbox +
   appearance:none 做 M3 外观 —— 语义与键盘操作都还是浏览器原生的，
   只是把绘制交给了 CSS，不是自己画控件。 */
/* 公告详情（只读）。
   未登录或无编辑权限的人点公告进这里：内容给足阅读宽度，图片可点开放大。 */
.announcement-view {
  max-height: min(58vh, 520px);
  overflow-y: auto;
  padding: 2px 2px 4px;
  font-size: 15px;
  line-height: 1.8;
  color: var(--md-sys-color-on-surface, #171d1e);
  overflow-wrap: anywhere;
}

.announcement-view :where(p, ul, ol, h1, h2, h3, h4) {
  margin: 0 0 0.7em;
}

.announcement-view :where(ul, ol) {
  padding-inline-start: 1.4em;
}

.announcement-view a {
  color: var(--md-sys-color-primary, #006877);
}

.announcement-view img {
  max-width: 100%;
  height: auto;
  border-radius: 10px;
  cursor: zoom-in;
}

.announcement-view__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  margin: 0 0 12px;
  font-size: 12px;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

.switch-list {
  display: grid;
  gap: 12px;
}

.switch-item {
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  user-select: none;
  font-size: 14px;
  color: var(--md-sys-color-on-surface, #171d1e);
}

.switch-item[hidden] {
  display: none;
}

.switch-item__text {
  min-width: 0;
}

/* 轨道。
   选择器写成 .switch-item input.switch 是为了压过通用规则 .form-row input
   （它是 0,1,1；只用 .switch 是 0,1,0，会被套上 width:100% / min-height:44px /
   圆角 10px —— 开关就会被撑成一条 348×44 的长条）。 */
.switch-item input.switch {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  position: relative;
  width: 52px;
  min-width: 52px;
  max-width: 52px;
  height: 32px;
  min-height: 32px;
  margin: 0;
  padding: 0;
  border: 2px solid var(--md-sys-color-outline, #6f7a7d);
  border-radius: 999px;
  background: var(--md-sys-color-surface-container-highest, #e0e5e7);
  cursor: pointer;
  transition:
    background-color 200ms cubic-bezier(0.2, 0, 0, 1),
    border-color 200ms cubic-bezier(0.2, 0, 0, 1);
}

/* 拇指：M3 未选中 16dp，选中放大到 24dp */
.switch-item input.switch::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 6px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--md-sys-color-outline, #6f7a7d);
  transform: translateY(-50%);
  transition:
    left 240ms cubic-bezier(0.2, 0, 0, 1),
    width 240ms cubic-bezier(0.2, 0, 0, 1),
    height 240ms cubic-bezier(0.2, 0, 0, 1),
    background-color 200ms cubic-bezier(0.2, 0, 0, 1);
}

.switch-item input.switch:checked {
  border-color: var(--md-sys-color-primary, #006877);
  background: var(--md-sys-color-primary, #006877);
}

.switch-item input.switch:checked::before {
  left: 22px;
  width: 24px;
  height: 24px;
  background: var(--md-sys-color-on-primary, #ffffff);
}

.switch-item input.switch:focus-visible {
  outline: 2px solid var(--md-sys-color-primary, #006877);
  outline-offset: 3px;
}

.switch-item input.switch:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* 截止日期的折叠槽位。
   hidden / display:none 是没法过渡的，所以换成 max-height + opacity + 位移：
   勾上「永不过期」时向上收起，取消勾选时展开。
   内层 overflow:hidden 负责裁切，日期字段自己的浮动标签在展开态不受影响。 */
.ann-expiry-slot {
  overflow: hidden;
  max-height: 96px;
  opacity: 1;
  transform: translateY(0);
  margin-block-end: 10px;
  transition:
    max-height 280ms cubic-bezier(0.2, 0, 0, 1),
    opacity 200ms cubic-bezier(0.2, 0, 0, 1),
    transform 280ms cubic-bezier(0.2, 0, 0, 1),
    margin-block-end 280ms cubic-bezier(0.2, 0, 0, 1);
}

.ann-expiry-slot.is-collapsed {
  max-height: 0;
  opacity: 0;
  transform: translateY(-8px);
  margin-block-end: 0;
  pointer-events: none;
}

/* 对话框刚打开时按当前状态定位，不要播一次动画 */
.ann-expiry-slot.no-anim {
  transition: none;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chip-toggle {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  padding: 6px 14px;
  border: 1px solid var(--md-sys-color-outline, #6f7a7d);
  border-radius: 999px;
  background: transparent;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
  font: inherit;
  font-size: 13px;
  line-height: 1.5;
  cursor: pointer;
  transition:
    background-color 160ms ease-out,
    border-color 160ms ease-out,
    color 160ms ease-out,
    transform 120ms cubic-bezier(0.5, 1, 0.89, 1);
}

.chip-toggle:hover {
  background: rgb(0 0 0 / 4%);
}

.chip-toggle:active {
  transform: scale(0.96);
}

.chip-toggle[aria-checked="true"] {
  border-color: var(--md-sys-color-primary, #006877);
  background: var(--md-sys-color-secondary-container, #cde7ed);
  color: var(--md-sys-color-on-secondary-container, #00363d);
  font-weight: 600;
}

/* 被禁用的选项（如管理员看不到「重要」）：保留说明性，不给点 */
.chip-toggle:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.chip-toggle:focus-visible {
  outline: 2px solid var(--md-sys-color-primary, #006877);
  outline-offset: 2px;
}

.status {
  margin: 16px 20px 0;
  padding: 12px 16px;
  border: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
  border-radius: 12px;
  background: var(--md-sys-color-surface-container-low, #eff4f6);
  color: var(--md-sys-color-on-surface-variant, #3f484a);
  font-size: 14px;
  animation: hs-fade 260ms cubic-bezier(0.25, 1, 0.5, 1) backwards;
}

.status--error {
  border-color: var(--md-sys-color-error, #ba1a1a);
  color: var(--md-sys-color-error, #ba1a1a);
}

.banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 12px 20px;
  background: var(--md-sys-color-error-container, #ffdad6);
  color: var(--md-sys-color-on-error-container, #410002);
  border-bottom: 1px solid var(--md-sys-color-error, #ba1a1a);
  animation: hs-fade 260ms cubic-bezier(0.25, 1, 0.5, 1) backwards;
}

.banner__text {
  margin-inline-end: auto;
  font-size: 14px;
  line-height: 1.6;
}

.banner--fatal {
  position: sticky;
  top: 0;
  z-index: 999;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 13px;
  word-break: break-all;
}

.homework-empty-state {
  display: grid;
  min-height: 14rem;
  place-content: center;
  justify-items: center;
  gap: 0.75rem;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
  text-align: center;
  animation: hs-fade 260ms cubic-bezier(0.25, 1, 0.5, 1) backwards;
}

.homework-empty-state > m3e-icon {
  font-size: 3rem;
}

.homework-board--prompt {
  display: grid;
  place-items: center;
  min-height: calc(100dvh - 11rem);
}

.homework-empty-state--prompt m3e-icon {
  --m3e-icon-size: 3rem;
  color: var(--md-sys-color-primary, #006877);
}

/* 图片被清理后的原位占位块 */
/* 图片两种失败状态：过期（灰底，说明按容量清理）与加载失败（可点重试，强调色边框） */
.image-expired,
.image-failed {
  display: grid;
  place-items: center;
  gap: 6px;
  width: 100%;
  min-height: 140px;
  margin: 6px 0;
  padding: 16px;
  border: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
  border-radius: 12px;
  background: var(--md-sys-color-surface-container-high, #e3e9eb);
  color: var(--md-sys-color-on-surface-variant, #3f484a);
  text-align: center;
  font-size: 13px;
}

.image-expired m3e-icon,
.image-failed m3e-icon {
  --m3e-icon-size: 2.5rem;
  color: var(--md-sys-color-outline, #6f797b);
}

/* 加载失败是"还能救"的状态：可点击，给个明确的边框与指针 */
.image-failed {
  cursor: pointer;
  border-color: var(--md-sys-color-primary, #006877);
  color: var(--md-sys-color-primary, #006877);
}

.image-failed m3e-icon {
  color: var(--md-sys-color-primary, #006877);
}

.image-failed:hover {
  background: var(--md-sys-color-surface-container-highest, #dde3e5);
}

/* ------------------------------------------------ 6. 右下角编辑按钮 */

#fab-host {
  position: fixed;
  right: 2rem;
  bottom: 2rem;
  left: auto;
  top: auto;
  z-index: 30;
}

#fab-menu {
  z-index: 40;
}

/* 手机上点卡片会出现浏览器自带的蓝色高亮方框 / 焦点框，去掉它。
   m3e-list-action 自己有涟漪反馈，够用了。 */
html body,
html body * {
  -webkit-tap-highlight-color: transparent;
}

html body m3e-list-action,
html body m3e-list-item,
html body m3e-fab,
html body m3e-button,
html body button {
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}


/* --------------------------------------------- 6.1 图片放大查看（灯箱） */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  /* 左右内边距做成变量：下面要拿它算"图片最大宽度"，好给阴影留出余量 */
  --lightbox-pad-x: 32px;
  /* 阴影模糊半径 30px，图片外面至少要留这么多，否则阴影会一直铺到屏幕边缘，
     看上去就像被切了一刀（手机上最明显）。 */
  --lightbox-shadow-room: 26px;
  padding: 36px var(--lightbox-pad-x);
  background: rgb(12 18 20 / 88%);
  backdrop-filter: blur(2px);
  /* 让放大后的图片能做"电子收藏卡"那种跟随鼠标的轻微立体倾斜 */
  perspective: 1200px;
}

.lightbox[hidden] {
  display: none;
}

.lightbox img {
  /* 宽度上限 = 视口 - 两侧内边距 - 两侧阴影余量。
     以前写 90vw：390px 的手机上只剩 19px 边距，而阴影要 30px，
     于是右边（倾斜时翘得更高的一侧）最先被屏幕边缘吃掉。 */
  max-width: min(
    1100px,
    calc(100vw - 2 * (var(--lightbox-pad-x) + var(--lightbox-shadow-room)))
  );
  /* 给下面的按钮留出位置，同时给阴影留出余量 */
  max-height: min(64vh, 780px);
  object-fit: contain;
  border-radius: 12px;
  background: #fff;
  transform-style: preserve-3d;
  backface-visibility: hidden;
  box-shadow: 0 10px 30px rgb(0 0 0 / 35%);
}

.lightbox__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
}

/* 自绘的下载图标：尺寸与 M3E 按钮里的 icon 槽保持一致 */
.lightbox__icon {
  width: 1.15rem;
  height: 1.15rem;
  display: block;
}

@media (max-width: 700px) {
  .lightbox {
    /* 手机上也要给阴影与倾斜留余量，别把 padding 压得太狠 */
    --lightbox-pad-x: 18px;
    --lightbox-shadow-room: 24px;
    padding: 22px var(--lightbox-pad-x);
    gap: 14px;
  }

  .lightbox img {
    max-height: 60vh;
  }
}

/* --------------------------------------------------------- 7. 登录注册 */

.auth {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px;
}

.auth__card {
  width: min(430px, 100%);
  display: grid;
  gap: 18px;
  padding: 30px 28px;
  border: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
  border-radius: 24px;
  background: var(--md-sys-color-surface-container-low, #eff4f6);
}

/* 登录/注册卡片左上角的返回按钮（用负外边距抵掉卡片的留白，视觉上贴左上角） */
.auth__back {
  display: flex;
  margin: -14px 0 -8px -12px;
}

.auth__back m3e-button {
  --m3e-button-container-height: 36px;
}

.auth__card h1 {
  margin: 0;
}

.auth__tabs {
  display: flex;
  gap: 8px;
}

/* M3E 按钮是自定义元素，选择器要命中元素本身 */
.auth__tabs > * {
  flex: 1;
}

.auth__panes {
  position: relative;
  display: block;
  overflow: hidden;
  transition: height 280ms cubic-bezier(0.25, 1, 0.5, 1);
}

.auth__pane {
  display: grid;
  gap: 16px;
  /* 给浮动标签留空间，避免被内容区裁掉 */
  padding-block-start: 12px;
  transition:
    opacity 280ms cubic-bezier(0.25, 1, 0.5, 1),
    transform 280ms cubic-bezier(0.25, 1, 0.5, 1);
}

.auth__pane.is-active {
  opacity: 1;
  transform: none;
}

.auth__pane:not(.is-active) {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
}

.auth__actions {
  display: grid;
  gap: 10px;
  width: 100%;
}

.hint {
  margin: 0;
  font-size: 14px;
  line-height: 1.7;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

.auth__card m3e-form-field {
  width: 100%;
}

/* ----------------------------------------------------------- 8. 发布页 */

.publish {
  max-width: 900px;
  margin: 0 auto;
  padding: 24px 20px 72px;
  display: grid;
  gap: 16px;
}

.publish__row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px;
}

.publish__row > * {
  flex: 1 1 240px;
}

.publish m3e-form-field {
  min-width: 0;
  /* 浮动标签需要上方空间 */
  padding-block-start: 10px;
}

.publish__actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

/* --------------------------------------------------- 9. 富文本编辑器 */

.edit-form {
  display: grid;
  gap: 14px;
  /* 对话框内容区会裁掉首个浮动标签，留足空间 */
  padding-block-start: 22px;
}

.rich-editor {
  border: 1px solid var(--md-sys-color-outline, #6f797b);
  border-radius: 12px;
  background: var(--md-sys-color-surface-container-low, #eff4f6);
  overflow: hidden;
}

.rich-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  padding: 4px 6px;
  border-bottom: 1px solid var(--md-sys-color-outline-variant, #bfc8cb);
}

.rich-surface {
  min-height: 110px;
  max-height: 40vh;
  overflow: auto;
  padding: 10px 12px;
  font-size: 16px;
  line-height: 1.55;
  color: var(--md-sys-color-on-surface, #171d1e);
  overflow-wrap: anywhere;
}

.rich-surface :where(p, h1, h2, h3, h4, h5, h6) {
  margin: 0 0 0.4em;
}

.rich-surface :where(ul, ol) {
  margin: 0 0 0.4em;
  padding-inline-start: 1.5em;
}

.rich-surface a {
  color: var(--md-sys-color-primary, #006877);
}

.rich-surface img {
  max-width: 100%;
  height: auto;
  border-radius: 8px;
}

.rich-image-input {
  display: none;
}

/* --------------------------------------------- 10. 弹窗与表单字段 */

.form-row {
  display: grid;
  gap: 6px;
}

.form-row > span {
  font-size: 13px;
  color: var(--md-sys-color-on-surface-variant, #3f484a);
}

.form-row input,
.form-row textarea {
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  border: 1px solid var(--md-sys-color-outline, #6f797b);
  border-radius: 10px;
  background: var(--md-sys-color-surface-container-low, #eff4f6);
  color: var(--md-sys-color-on-surface, #171d1e);
  font: inherit;
}

.form-row textarea {
  min-height: 96px;
  resize: vertical;
}

/* 日期框文字不允许被选中 */
#date-input,
#edit-due-input,
#publish-date,
.form-row input[readonly] {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

/* --------------------------------------------------------- 11. 用户管理 */

.users-list {
  display: grid;
  gap: 4px;
  min-width: 0;
  max-height: 60vh;
  overflow-x: hidden;
  overflow-y: auto;
}

.user-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 10px 12px;
  border-radius: 12px;
  background: var(--md-sys-color-surface-container-low, #eff4f6);
}

.user-row__info {
  flex: 1 1 180px;
  display: grid;
  gap: 4px;
  min-width: 0;
}

.user-row__info strong {
  font-size: 15px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.user-row__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
}

/* ------------------------------------------------- 12. 兜底页与适配 */

.not-found {
  justify-items: center;
  text-align: center;
  gap: 14px;
}

.not-found m3e-heading:first-of-type {
  line-height: 1;
  color: var(--md-sys-color-primary, #006877);
}

@media (max-width: 600px) {
  .topbar {
    padding: 10px 14px;
    padding-top: max(10px, env(safe-area-inset-top));
  }

  .homework-board {
    padding: 16px 14px calc(96px + env(safe-area-inset-bottom));
  }

  #fab-host {
    right: 1.25rem;
    bottom: max(1.25rem, env(safe-area-inset-bottom));
  }

  /* 手机：单列 */
  .masonry-columns,
  .masonry-column {
    display: block;
  }
}

/* 兜底页里自绘 SVG 图标的作用域（这两个页面是内联样式，这里只为 <svg> 兜底） */
svg.icon {
  display: inline-block;
  vertical-align: middle;
  flex: 0 0 auto;
}

/* 表单字段统一占满一行。
   重写样式表时漏掉了这条，导致发布页/弹窗里的输入框缩成内容大小。 */
m3e-form-field {
  width: 100%;
  min-width: 0;
  display: block;
}

m3e-form-field input,
m3e-form-field textarea {
  width: 100%;
}

/* ---------- 安全中心：居中的窄栏布局（此前误用了发布页的 900px 布局） ---------- */
.security {
  max-width: 430px;
  margin: 0 auto;
  padding: 24px 20px 72px;
  display: grid;
  gap: 16px;
}

.security > .status {
  margin: 0;
}

.security .auth__card {
  width: 100%;
}

/* 弹窗内容里第一个表单字段：留出浮动标签的空间（否则标签上沿被内容区裁掉）。
   用 margin 而不是 padding —— 标签是跟着字段一起移动的。 */
m3e-dialog > m3e-form-field:first-of-type,
m3e-dialog .edit-form > m3e-form-field:first-child {
  margin-block-start: 18px;
}

/* 顶栏控件在桌面端保持一排：日期框在左，两个按钮在右 */
.topbar__title {
  min-width: 0;
}

/* 顶栏控件的排布交给 client.js 的 fitTopbar() 统一处理：
   单行放不下就先换行（按钮保持自然大小），
   两行还放不下才等比缩到 75% 以内。
   所以这里必须是 wrap —— 之前的 nowrap 会挡住"换行"这一步，
   导致单行放不下时直接溢出顶栏右边界。 */
.topbar__controls {
  flex-wrap: wrap;
}

#date-field {
  flex: 0 0 auto;
  width: 260px;
  min-width: 260px;
}

/* 手机上窄，改成固定两行两列（见文件末尾的移动端规则） */

/* 右下角按钮：脱离可能建立包含块的祖先，避免点击时随页面"飞" */
#fab-host {
  position: fixed;
  right: 2rem;
  bottom: 2rem;
  left: auto;
  top: auto;
  z-index: 30;
  /* 只保留 layout：容器与按钮同尺寸（80×80），一旦加上 paint，
     M3E 按钮自身的投影（内部 elevation 层）就会被裁掉，边缘看着像被切平 */
  contain: layout;
  transform: none;
}

#fab-host m3e-fab {
  transform: none;
}

/* 顶栏里的日期字段：不要吃掉整行（全局 m3e-form-field 是 width:100%，
   在 nowrap 的控件区里会被撑开） */
.topbar__controls m3e-form-field,
#date-field {
  flex: 0 0 auto;
  width: 260px;
  min-width: 260px;
  max-width: 260px;
}

.topbar__controls m3e-form-field input {
  width: 100%;
}

/* 顶栏日期字段：回到 M3E 原生外形（outlined + 浮动标签 + 后缀日历按钮）。
   这个外形必须留着 —— m3e-datepicker-toggle 打开日历时，浮层的锚点是
   this.closest("m3e-form-field")，拆掉它日历会失去锚点、飘到窗口顶上。
   高度用 M3E 自己的密度变量压：它的内容是
   min-height: calc(3.5rem + max(-3, --md-sys-density-scale) * 0.25rem)，
   密度 -2 正好把 56px 压到 48px。直接砍 height 会让内部 56px 的标签/轮廓
   溢到边框外面（标签浮在边框线上、看着"格外高"）。 */
#date-field {
  --md-sys-density-scale: -2;
  height: 48px;
  block-size: 48px;
}

/* 辅助行（subscript）即使隐藏，也仍然占着高度，直接不参与布局 */
#date-field [slot="subscript"],
#date-field .subscript {
  display: none !important;
}

#date-field input {
  cursor: pointer;
  user-select: none;
  text-overflow: ellipsis;
}

/* 后缀的日历按钮收小一点，别把字段撑开 */
#date-field m3e-icon-button {
  --m3e-icon-button-size: 32px;
}

/* 手机端顶栏。
 *
 * 两种形态：
 *   首页（没有日期框）—— 标题 +「时光机 / 登录」本来一行就放得下，
 *     控件区就按内容宽度待着，靠 .topbar__title 的 margin-inline-end:auto 顶到右边，
 *     不额外占一行。
 *   时光机（有日期框）—— 日期框要独占整行，控件区这时才 flex:1 1 100% 单独成行，
 *     内部用 grid 的 1fr auto auto：第一列吃掉剩余空间，两个按钮各占内容宽、贴右边。
 * 用 :has() 区分这两种，而不是给两个页面各写一套类名。
 * （m3e-datepicker 是 position:fixed 的浮层，display:none 时不成为栅格项，
 *  打开时也已脱离文档流，不会来抢格子。） */
@media (max-width: 700px) {
  .topbar {
    padding: 8px 14px;
    gap: 8px;
  }

  /* 默认：只占内容宽，尽量和标题挤在同一行。
     margin-inline-start: auto 是为了"万一放不下而换行"时仍然靠右 ——
     不加的话第二行会按 flex-start 左对齐，右侧空出一条（实测空 53px）。 */
  .topbar__controls {
    display: flex;
    flex: 0 1 auto;
    align-items: center;
    gap: 8px;
    margin-inline-start: auto;
  }

  /* 带日期框的顶栏（时光机）：控件区独占一行 */
  .topbar__controls:has(> #date-field) {
    display: grid;
    flex: 1 1 100%;
    grid-template-columns: 1fr auto auto;
    gap: 8px;
  }

  .topbar__controls > #date-field {
    grid-column: 1 / -1;
    width: 100%;
    min-width: 0;
    max-width: none;
  }

  /* 首页的「时光机」、时光机的「回到今天」：第二列，靠右 */
  .topbar__controls > #timemachine-button,
  .topbar__controls > #back-button {
    grid-column: 2;
    width: auto;
    min-width: 0;
    justify-self: end;
  }

  /* 「登录」/「个人中心」：第三列（最右） */
  .topbar__controls > .account {
    grid-column: 3;
    width: auto;
    min-width: 0;
    justify-self: end;
  }

  .topbar__controls > .account > m3e-button {
    width: auto;
  }

  /* 个人中心面板：宽度已由基础规则的 min(320px, 100vw - 28px) 按视口钳制，
     这里**不能再写 min-width: 0** —— 那样面板会塌到内容宽（实测 122px，
     邮箱整行被迫折行）。手机上只收紧内边距。 */
  .account__panel {
    padding: 18px 16px 14px;
  }

  .account__panel m3e-button {
    width: 100%;
  }
}

