/* ============================================================================
   pages-login.css —— 原 pages.css 的第 1/6 段（2026-09-19 拆分）

   原文件 3,696 行，把六种板块的样式装在了一起（《模型档位与代码质量_操作准则》
   §5 点名的技术债）。现按文件自己的 ===== 横幅拆成六段，index.html 按
   原顺序引入 —— 层叠顺序与拆分前完全一致（拆分脚本做过逐行相等校验）：

     1 pages-login.css → 2 pages-store.css → 3 pages-practice.css
     → 4 pages-identity.css → 5 pages-practice-fx.css → 6 pages-learn.css

   本段：登录页 + 登录仪式 + 全局小件（页脚 / 打印 / 启动遮罩…）
   ============================================================================ */

/* pages.css —— 各页面专属样式 */

/* ---------- 登录页 ---------- */
.login-page {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
  overflow: hidden;
  background:
    radial-gradient(1100px 480px at 50% -10%, #24405c 0%, transparent 62%),
    var(--c-bg);
}

/* 卡片背后那团缓慢呼吸的蓝雾。纯装饰，不参与布局，也不接事件。 */
.login-glow {
  position: absolute;
  top: -12%;
  left: 50%;
  width: min(760px, 130vw);
  height: 420px;
  transform: translateX(-50%);
  background: radial-gradient(closest-side, rgba(102, 192, 244, 0.16), transparent 70%);
  pointer-events: none;
}

.login-card {
  position: relative;
  width: 100%;
  max-width: 380px;
  background: var(--c-card);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  padding: 28px 26px 24px;
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.5);
  animation: login-in 0.32s ease both;
}

@keyframes login-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.login-head {
  text-align: center;
  margin-bottom: 22px;
}

.login-mark {
  position: relative;
  width: 52px;
  height: 52px;
  margin: 0 auto 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.login-mark .mark {
  width: 34px;
  height: 34px;
  color: var(--c-accent);
}

/* 一圈常驻的淡弧。过渡层的字母动画转的也是「一圈」的东西，
   登录页和过渡页要像同一个东西 —— 但这里慢得多（6s），
   因为登录页是**静止等人输入**的，转太快会抢注意力。 */
.login-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  border-top-color: rgba(117, 176, 34, 0.75);
  border-right-color: rgba(102, 192, 244, 0.45);
  transform: rotate(0deg);
  animation: login-spin 6s linear infinite;
}

@keyframes login-spin {
  to { transform: rotate(360deg); }
}

.login-head h1 {
  font-size: var(--fs-xl);
  letter-spacing: 0.5px;
}

/* 主 logo 文字：**SPRINT**（一个短促的固定词，不带后缀）。
   拆出来单独设字距，是因为它是一个品牌固定词，
   比普通标题更需要"被当成图形看"——大写字距撑开一点才有 mark 的分量。
   完整品牌名在下面那行 <p> 里（文字场合用全名）。 */
.login-head h1.login-wordmark {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: 6px;
  /* letter-spacing 会在最后一个字母右边多出一格，把整词往左推半格回来，
     这样视觉中心才和上面的圆标、下面的副标题对齐 */
  text-indent: 6px;
}

.login-head p {
  margin-top: 5px;
  font-size: var(--fs-sm);
  color: var(--t-dim);
}

/* ---------- 带右侧动作按钮的输入框 ---------- */
.input-wrap {
  position: relative;
  display: block;
}

.input-wrap .input.has-action {
  padding-right: 44px;
}

.input-action {
  position: absolute;
  top: 50%;
  right: 4px;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--t-dim);
  cursor: pointer;
}

.input-action:hover {
  color: var(--c-accent);
  background: rgba(102, 192, 244, 0.1);
}

.input-action.is-on { color: var(--c-accent); }

.input-action .icon {
  width: 18px;
  height: 18px;
}

/* 提交中：给按钮一条走马灯，免得学生以为没点上 */
.btn.is-loading { position: relative; overflow: hidden; }

.btn.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.22), transparent);
  animation: btn-sheen 1.1s linear infinite;
}

@keyframes btn-sheen {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}

.login-aside {
  margin-top: 18px;
  padding-top: 15px;
  border-top: 1px solid var(--c-line-soft);
  font-size: var(--fs-xs);
  color: var(--t-dim);
  line-height: 1.75;
}

.login-aside code {
  color: var(--c-accent);
  font-family: Consolas, "Courier New", monospace;
}

.login-foot {
  margin-top: 16px;
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--t-dim);
}

/* ---------- 「记住用户名和密码」（登录页，2026-09-19 加） ----------
   ★ 全站唯一的复选框就在这里（web 端只有控制台有勾，那是另一套 CSS）。
     所以就地把样式写全，不往 components.css 里塞一条只被用一次的东西。

   为什么自己做一套而不是复用一个 chip 按钮：这是个**勾**，
   它要回答的问题是「你现在是不是在替我存密码」。chip 的高亮态
   表达的是「选中了哪个档位」，语义完全不同 —— 复用它，
   学生就分不清「我点的是选项还是开关」。 */
.login-remember {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  /* 上边距收一点：它紧跟在密码框后面，是那张表单的一部分 */
  margin: -4px 0 14px;
  /* 触控目标不小于 --tap —— 平板上的勾比鼠标上的勾难按得多 */
  min-height: var(--tap);
}

.login-remember .check-inline {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-sm);
  color: var(--t-primary);
  cursor: pointer;
  /* 双击标签不会选中文字，平板上不容易误选 */
  -webkit-user-select: none;
  user-select: none;
}

.login-remember input[type="checkbox"] {
  width: 18px;
  height: 18px;
  /* 浏览器默认给勾 3px 外边距，会把标签顶歪，清掉自己控间距 */
  margin: 0;
  flex: none;
  cursor: pointer;
  /* accent-color 让原生勾跟着主题走，不用自己画一个假勾 */
  accent-color: var(--c-accent);
}

.login-remember-note {
  font-size: var(--fs-xs);
  color: var(--t-dim);
  text-align: right;
}

.login-remember-note code {
  color: var(--c-accent);
  font-family: Consolas, "Courier New", monospace;
}

/* ---------- 登录过渡（仪式层） ----------
   见 core/ceremony.js。时长关系（老师 2026-09-18 定的）：
     · 窗口停留 = JS 里 10–15 秒随机，由 inline animation-duration 驱动进度条；
     · 动画节奏 = 2.6 秒一轮无限循环，见下面的 .wm-* 系列。
   两者**不是同一个数**，窗口里动画会转 4–6 圈。 */
.ceremony {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  padding: 24px;
  background:
    radial-gradient(900px 460px at 50% 42%, rgba(36, 64, 92, 0.9) 0%, transparent 68%),
    rgba(23, 26, 33, 0.97);
  opacity: 0;
  animation: cer-in 0.24s ease forwards;
  /* 不给 cursor:pointer —— 这一段不可点击跳过，指针不要暗示能点 */
}

@keyframes cer-in {
  to { opacity: 1; }
}

/* 收尾的渐隐由 ceremony.js 用 inline style 驱动，这里不再定义 .is-out。
   原因：.ceremony 基类的 animation: cer-in forwards 会**压过**普通 opacity 声明，
   写在 CSS 里的 .is-out { opacity: 0 } 不生效，必须由 JS 先把 animation 清掉。
   留这个空注释只是给「样式表里找不到 .is-out」一个说明，避免以后有人再补一遍。 */

/* ---------- 收尾：整块内容向中心收缩（老师 2026-09-18 要的） ----------
   学生看到的是「窗口被吸走」，而不是「画面突然没了」。
   为什么加在 .ceremony-core 而不是 .ceremony 上：
   .ceremony 自己是那层全屏底色，它得**最后**才淡掉（否则背景先没了，
   内容会浮在主页面上方收缩，像是两个图层错位）。
   所以：内核先缩 → 底色随后淡出 → 整层摘掉。 */
.ceremony-core {
  display: flex;
  flex-direction: column;
  align-items: center;
  transform-origin: center center;
}

.is-collapse .ceremony-core {
  animation: cer-collapse 520ms cubic-bezier(0.55, 0, 0.68, 1) forwards;
}

@keyframes cer-collapse {
  from { transform: scale(1) translateY(0); opacity: 1; }
  to { transform: scale(0.72) translateY(6px); opacity: 0; }
}

/* ---------- 主页面显现：淡入 + 轻微放大（老师选的方案） ----------
   收缩动画结束的那一刻，主页面从 98% 放大到 100% 淡入，
   接住前面「被吸走」的动势 —— 一收一放，眼睛就跟着走到内容上了。
   98% → 100% 幅度很小是刻意的：再大就成了「弹出来」，不像 Steam。 */
body.is-page-in .view {
  animation: page-in 420ms cubic-bezier(0.22, 0.9, 0.3, 1) both;
}

@keyframes page-in {
  from { opacity: 0; transform: scale(0.98); }
  to { opacity: 1; transform: scale(1); }
}

/* ---------- 字母演化动画（登录仪式的主角） ----------
   见 core/wordmark.js。这是老师要的「单词演化 gif」的矢量版。
   一轮的时长由 `--wm-cycle` 决定（线上 = wordmark.js 的 CYCLE_MS 注入；
   下面的兜底值只为「JS 没跑起来」这种情况）—— 就是一个 GIF 的播法，但任意分辨率都锐利。

   **版式：单行，只有 SPRINT**（老师 2026-09-18 定稿）
     六个大写字母被吸进来、落位、点亮、扫光、光标闪 —— 全部叙事。
     曾经有过第二行小写尾巴 `lish`；老师明确去掉了，
     所以**这里不再有 .wm-tail 规则**，别再加回来
     （图形 logo 用短记 SPRINT，和 Steam 同一个记忆方式；
       完整品牌名 SPRINT Kingdom 只出现在文字场合，见 §9.1）。
   viewBox 640×200，字母居中在 x=320；6 个字母共宽 5×74 = 370（5 字母时是 296）。

   时间轴（占一轮的比例）：
     0–14%   字母从画面外被吸入，灰色待选
     14–34%  落位，颜色点亮
     34–52%  整排轻微回弹
     52–72%  保持（扫光前的静默拍）
     72–88%  扫光掠过
     88–100% 光标闪烁
   下面的百分比必须和 wordmark.js 的注释一致，改一处要改两处。 */
.wordmark {
  width: 100%;
  max-width: 560px;
  margin-bottom: 8px;
}

.wm-svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}

/* 底部字母带：低对比度，只在余光里可见，负责「这是英语」的气氛。
   一个 --wm-cycle 滚一轮，和主叙事同频。 */
.wm-ribbon {
  opacity: 0.14;
}

.wm-ribbon-text {
  font-family: var(--font);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 7px;
  fill: var(--c-accent);
  animation: wm-roll var(--wm-cycle, 3s) linear infinite;
}

@keyframes wm-roll {
  from { transform: translateX(0); }
  to { transform: translateX(-320px); }
}

/* 每个字母：被吸进来 → 落位点亮 → 轻微回弹。
   --i 是序号，用来做逐个延迟；把 delay 写成负值可以让动画「已经跑在前面」，
   所以整排看起来是依次就位而不是同时冒出来。 */
.wm-letter {
  font-family: var(--font);
  font-size: 84px;
  font-weight: 700;
  letter-spacing: 0;
  fill: var(--c-accent);
  transform-box: fill-box;
  transform-origin: center;
  animation: wm-in var(--wm-cycle, 3s) cubic-bezier(0.2, 0.9, 0.3, 1) infinite;
  /* 每个字母晚 0.09s 出发，6 个字母拉开 0.45s —— 短到不拖沓，
     又长到能看出「一个个来」。 */
  animation-delay: calc(var(--i) * 0.09s);
}

@keyframes wm-in {
  0% {
    opacity: 0;
    fill: #4a6076;
    transform: translateX(-120px) rotate(-14deg) scale(0.6);
  }
  14% {
    opacity: 1;
    fill: #4a6076;
    transform: translateX(0) rotate(0) scale(1);
  }
  30% { fill: var(--c-accent); }
  34% { transform: translateX(0) rotate(0) scale(1.12); }
  46% { transform: translateX(0) rotate(0) scale(1); }
  72% { transform: translateX(0) rotate(0) scale(1); }
  100% {
    opacity: 1;
    fill: var(--c-accent);
    transform: translateX(0) rotate(0) scale(1);
  }
}

/* 光标：每轮末尾闪两下，像刚打完一行字 */
.wm-caret {
  fill: var(--c-accent);
  opacity: 0;
  animation: wm-caret var(--wm-cycle, 3s) steps(1, end) infinite;
}

@keyframes wm-caret {
  0%, 80% { opacity: 0; }
  82% { opacity: 1; }
  88% { opacity: 0; }
  91% { opacity: 1; }
  97% { opacity: 0; }
  100% { opacity: 0; }
}

/* 扫光：一道斜向高光从左边掠过字母排 */
.wm-sweep {
  fill: rgba(255, 255, 255, 0.05);
  transform: skewX(-18deg);
  animation: wm-sweep var(--wm-cycle, 3s) ease-in-out infinite;
}

@keyframes wm-sweep {
  0%, 52% { transform: translateX(0) skewX(-18deg); opacity: 0; }
  56% { opacity: 1; }
  80% { transform: translateX(760px) skewX(-18deg); opacity: 0; }
  100% { transform: translateX(760px) skewX(-18deg); opacity: 0; }
}

/* 身份行：头像 + 姓名。头像做呼吸灯式若隐若现（老师指定的效果），
   周期 --wm-cycle 和动画同频，整块画面像一台在待机的机器。 */
.ceremony-id {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 4px 0 18px;
  animation: cer-rise 0.4s 0.1s ease both;
}

.ceremony-avatar {
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  overflow: hidden;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
  animation: cer-breathe var(--wm-cycle, 3s) ease-in-out infinite;
}

.ceremony-avatar .avatar {
  width: 34px;
  height: 34px;
  display: block;
}

@keyframes cer-breathe {
  0%, 100% { opacity: 0.34; transform: scale(0.94); }
  50% { opacity: 1; transform: scale(1.04); }
}

.ceremony-name {
  font-size: var(--fs-lg);
  color: var(--t-bright);
  letter-spacing: 0.4px;
}

.ceremony-track {
  width: 220px;
  height: 4px;
  border-radius: 2px;
  background: #223449;
  overflow: hidden;
}

/* 进度条走满 = 窗口到点。duration 由 JS inline 成本次随机时长，
   所以这里只写关键帧，不写 animation-duration。 */
.ceremony-bar {
  width: 0;
  height: 100%;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--c-accent-dim), var(--c-accent));
  animation: cer-fill linear forwards;
}

@keyframes cer-fill {
  from { width: 0; }
  to { width: 100%; }
}

/* 底部落款。和动画里长出来的 SPRINT 呼应：
   动画演的是「名字怎么来的」，这里给的是「名字」。 */
.ceremony-sign {
  margin-top: 14px;
  font-size: var(--fs-xs);
  letter-spacing: 2px;
  color: var(--t-dim);
  animation: cer-rise 0.4s 0.5s ease both;
}

@keyframes cer-rise {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* 过渡层铺满时把底层页面锁住，别让学生看见下面还在滚 */
body.is-ceremony {
  overflow: hidden;
}

/* 系统设了「减少动态效果」就把所有旋转 / 呼吸 / 位移全部停掉。
   过渡层本身还在（仪式感不靠动画撑），只是不再动。

   注意：主定时器照旧跑，所以该等的时间一分不少 —— 这是刻意的。
   关了动效 ≠ 关了仪式，两者是独立的。唯一的例外是把进度条也定住，
   否则会出现「画面完全静止但进度条在爬」这种更难受的组合。 */
@media (prefers-reduced-motion: reduce) {
  .login-card,
  .login-ring,
  .btn.is-loading::after,
  .ceremony,
  .ceremony-avatar,
  .ceremony-id,
  .ceremony-sign,
  .wm-letter,
  .wm-caret,
  .wm-sweep,
  .wm-ribbon-text {
    animation: none !important;
  }

  .ceremony { opacity: 1; }
  .ceremony-id,
  .ceremony-sign { opacity: 1; }

  /* 静态降级：字母排直接以终态呈现，别留半截动画的样子 */
  .wm-letter { opacity: 1; fill: var(--c-accent); }

  /* ★★ 2026-09-20 修掉一个**静默失效**的既有 bug：这里原本多了一个 `}`，
     把 media 块提前关掉了 —— 于是下面这两条掉到**顶层**，
     又因为它们在文件里比第 296 / 309 行那两条规则**更靠后**，
     同选择器同特异性 → 后面的赢：`.is-collapse .ceremony-core` 的
     `animation: none` 覆盖了 `cer-collapse`，`body.is-page-in .view` 的
     `animation: none` 覆盖了 `page-in`。
     结果就是**两拍收尾对所有人生效地被关掉了**（内核不再收缩、主页面不再淡入），
     而 JS 那边照旧等满 COLLAPSE_MS / PAGE_IN_MS —— 时间没少，画面没了。
     ⚠️ `_selftest.py` 那几条「CSS 定义了 cer-collapse / is-collapse 真的会驱动内核」
     只查**字符串在不在**，查不出层叠被覆盖 —— 所以它能一直绿着。
     ⚠️ 往这个 media 块里加规则时：**别在块里手写多余的 `}`**，
     这个块结束的标志是下面那句「商店页」注释之前的那个 `}`。 */
  .is-collapse .ceremony-core { animation: none; }
  body.is-page-in .view { animation: none; }
}

/* ---------- 商店页 ---------- */
.store-side-sticky {
  position: sticky;
  top: 112px;
}

.store-hero-note {
  font-size: var(--fs-xs);
  color: var(--t-dim);
  margin-top: 8px;
}

.tag-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tag-cloud .badge {
  cursor: default;
}

/* ---------- 教材详情页 ---------- */
.detail-hero {
  border-radius: var(--r-md);
  overflow: hidden;
  background: #0e1621;
  margin-bottom: 16px;
}

.detail-hero svg {
  width: 100%;
  aspect-ratio: 1200 / 420;
  display: block;
}

.detail-head {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  flex-wrap: wrap;
  margin-bottom: 14px;
}

.detail-head h1 {
  font-size: var(--fs-2xl);
  line-height: 1.25;
  flex: 1 1 300px;
  min-width: 0;
}

.detail-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 16px;
}

.detail-cols {
  display: grid;
  gap: var(--gap);
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
}

@media (max-width: 899px) {
  .detail-cols { grid-template-columns: minmax(0, 1fr); }
}

.detail-block {
  background: var(--c-card);
  border-radius: var(--r-md);
  padding: 16px 18px;
  margin-bottom: var(--gap);
}

.detail-block h3 {
  font-size: var(--fs-md);
  text-transform: uppercase;
  letter-spacing: 0.9px;
  color: var(--t-muted);
  margin-bottom: 10px;
}

.sample-text {
  background: var(--c-input);
  border-left: 3px solid var(--c-accent-deep);
  border-radius: var(--r-sm);
  padding: 14px 16px 14px 18px;
  color: var(--t-primary);
  font-size: var(--fs-md);
  line-height: 1.9;
  white-space: pre-wrap;
  word-break: break-word;
}

.kv {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--c-line-soft);
  font-size: var(--fs-md);
}

.kv:last-child { border-bottom: 0; }

.kv .k { color: var(--t-dim); flex: 0 0 auto; }
.kv .v { color: var(--t-primary); text-align: right; }

/* ---------- 占位页 ---------- */
.soon {
  max-width: 620px;
  margin: 34px auto;
  background: var(--c-card);
  border-radius: var(--r-md);
  padding: 30px 28px;
  text-align: center;
}

.soon .icon-wrap {
  width: 46px;
  height: 46px;
  margin: 0 auto 14px;
  color: var(--c-accent-dim);
}

.soon h2 {
  font-size: var(--fs-xl);
  margin-bottom: 8px;
}

.soon p {
  color: var(--t-muted);
  font-size: var(--fs-md);
  margin-bottom: 6px;
}

.soon .stage {
  display: inline-block;
  margin-top: 14px;
  padding: 3px 10px;
  border-radius: var(--r-sm);
  background: var(--c-input);
  color: var(--t-dim);
  font-size: var(--fs-xs);
}

/* ---------- 首次登录改密提示 ---------- */
.pwd-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  background: rgba(212, 175, 55, 0.1);
  border: 1px solid rgba(212, 175, 55, 0.42);
  border-radius: var(--r-md);
  padding: 9px 13px;
  margin-bottom: var(--gap);
  font-size: var(--fs-sm);
  color: #e8d79a;
}

.pwd-banner .grow { flex: 1 1 240px; }

/* ---------- 页脚 ---------- */
.foot {
  border-top: 1px solid var(--c-line-soft);
  padding: 16px 0 26px;
  font-size: var(--fs-xs);
  color: var(--t-dim);
}

.foot-inner {
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: space-between;
}

/* ---------- 打印 ---------- */
@media print {
  .topbar, .subbar, .toasts, .foot { display: none; }
  body { background: #fff; color: #000; }
}

/* ---------- 独立练习窗口（body.is-bare）----------
   Steam 的心智模型：点「开始」弹出一个游戏窗口，平台留在原地。
   这里只藏外壳，不改任何组件样式 —— 题目那套 UI 原样复用。 */
body.is-bare .topbar,
body.is-bare .subbar,
body.is-bare .foot,
body.is-bare #notice-slot,
body.is-bare .toasts { display: none; }

body.is-bare .wrap { max-width: 1080px; padding-top: 14px; }

/* 桌面端触控目标不再需要 44px 的下限，字号回到阅读优先 */
body.is-bare { --tap: 40px; }


/* ---------- 启动遮罩 ----------
   读登录态是一次网络往返，期间先把外壳藏起来，
   否则已登录的老师打开首页会先闪一下登录版式。 */
body.is-booting .topbar,
body.is-booting .subbar,
body.is-booting .foot {
  visibility: hidden;
}

body.is-booting .view {
  min-height: 60vh;
}

/* ---------- 登录版式 ----------
   登录页不需要顶栏 / 二级条 / 页脚，登录视图会给 body 加 is-auth。 */
body.is-auth .topbar,
body.is-auth .subbar,
body.is-auth .foot {
  display: none;
}

body.is-auth .view {
  padding: 0;
  min-height: 0;
}

body.is-auth .wrap {
  max-width: none;
  padding: 0;
}

