/* 网页端设计系统：token、基础元素、页面骨架、组件。
 *
 * 为什么是一个文件而不是四份内联样式：五个页面原本各自内联一套，同名规则一直在
 * 漂移 —— :root 有两种、button 有三种互不相干的定义、圆角凑齐了 5/6/8/9/10/12/
 * 13/14/16/20 十档。真正的麻烦不在重复，而在于各页用的是裸元素选择器
 * （button {} / input {} / p {}），于是每加一个新控件都要再写一条更"specific"的
 * 规则去压住前一条，样式因此每隔几次改动就会崩一次。
 *
 * 三条约定，坏掉的地方基本都是违反了其中之一：
 *
 * 1. 分层（@layer）。层的顺序就是覆盖顺序，和选择器权重、书写先后都无关。
 *    页面自己 <style> 里的规则不属于任何层，天然赢过这里的一切 —— 想覆盖直接写，
 *    不需要 !important，也不需要把选择器写长。
 * 2. 组件用类，不用元素。这里没有一条裸 button/input/p 规则（.prose 里的除外，
 *    那是成篇的正文，本来就该按元素排版）。
 * 3. 变体用自定义属性（--btn-bg 之类），不用更高权重的选择器。所以
 *    `.btn.armed { --btn-bg: var(--danger) }` 一定生效，无论它写在哪儿。
 *
 * 颜色变量名与 src/styles.css 保持一致，桌面端和网页端的紫色是同一个紫。
 */

@layer tokens, base, layout, components, utilities;

/* ========================================================================
   tokens
   ======================================================================== */
@layer tokens {
  :root {
    color-scheme: light dark;

    --bg: #f6f6f8;
    --fg: #1c1c22;
    --muted: #71717a;
    --card: #ffffff;
    --border: #e4e4e9;
    --accent: #6366f1;
    --accent-2: #7c3aed;
    --danger: #dc2626;
    --ok: #16a34a;
    --warn: #d97706;

    /* 由上面派生。四个页面原本各写各的 color-mix()，同一个意思配了 10%/14%/
       16%/18%/20% 五种比例；写在这里之后"淡一层的强调色"只有一个定义。 */
    --accent-soft: color-mix(in srgb, var(--accent) 14%, transparent);
    --accent-ring: color-mix(in srgb, var(--accent) 18%, transparent);
    --accent-line: color-mix(in srgb, var(--accent) 40%, transparent);
    --danger-soft: color-mix(in srgb, var(--danger) 12%, transparent);
    --neutral-soft: color-mix(in srgb, var(--fg) 8%, transparent);
    --hover-bg: color-mix(in srgb, var(--fg) 4%, transparent);
    --grad-accent: linear-gradient(
      135deg,
      var(--accent),
      color-mix(in srgb, var(--accent) 60%, var(--accent-2))
    );
    --glow-accent: 0 4px 14px color-mix(in srgb, var(--accent) 35%, transparent);

    /* 圆角。原本十档，肉眼分不出差别，但改一处就对不齐一处。收成五档。 */
    --r-xs: 6px;
    --r-sm: 8px;
    --r-md: 10px;
    --r-lg: 14px;
    --r-xl: 20px;
    --r-pill: 999px;

    /* 间距，一律 4 的倍数。 */
    --s-1: 4px;
    --s-2: 8px;
    --s-3: 12px;
    --s-4: 16px;
    --s-5: 20px;
    --s-6: 24px;
    --s-8: 32px;
    --s-10: 40px;
    --s-12: 48px;
    --s-16: 64px;

    --fs-xs: 11px;
    --fs-sm: 12px;
    --fs-md: 13px;
    --fs-base: 14px;
    --fs-lg: 15px;
    --fs-xl: 17px;
    --fs-title: 22px;
    --fs-section: 24px;
    --fs-hero: 40px;

    --font: -apple-system, "PingFang SC", "Microsoft YaHei", "Helvetica Neue",
      Arial, sans-serif;
    --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;

    /* 页宽和左右留白。--gutter 两边共用，导航和正文的左右边界才对得齐 ——
       分开写过一次，结果导航比内容宽 28px，肉眼刚好看得出来。

       导航另有自己的宽度，且不跟着 .narrow 收窄：它是站点外壳，五个链接加一枚
       会话胶囊需要将近 900px，跟着正文缩到 720px 就会折成两行 —— 而外壳在各页
       之间跳来跳去，比它和正文不同宽更难看。 */
    --page-w: 960px;
    --nav-w: 960px;
    --gutter: 28px;

    /* 导航行高。会话胶囊比一行纯链接高 11px，而它要等 /api/me 回来才出现 ——
       不把这个高度提前占住，页面就会在请求落地的那一刻整体往下跳一下。
       .nav-inner 和 .session-chip 都读它，两者不会各自漂移。 */
    --nav-row-h: 32px;

    --tap: 0.15s ease;
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --bg: #161619;
      --fg: #ececf1;
      --muted: #9c9ca6;
      --card: #212127;
      --border: #333339;
      --accent: #818cf8;
      --accent-2: #a78bfa;
      --danger: #f87171;
      --ok: #4ade80;
      --warn: #fbbf24;
    }
  }

  /* 窄页面（登录、帮助、隐私政策）只需要在 <body> 上加一个 narrow ——
     以前要同时改 body.narrow 和 .page.narrow 两处，漏一处就一边宽一边窄。 */
  body.narrow {
    --page-w: 720px;
  }

  @media (max-width: 560px) {
    :root {
      --gutter: 16px;
    }
  }
}

/* ========================================================================
   base：元素默认值。只放"每个页面都一样"的东西。
   ======================================================================== */
@layer base {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  body {
    margin: 0;
    background: var(--bg);
    color: var(--fg);
    font-family: var(--font);
    font-size: var(--fs-base);
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
  }

  h1 {
    font-size: var(--fs-title);
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0 0 var(--s-1);
  }

  h2 {
    font-size: var(--fs-xl);
    font-weight: 600;
    margin: var(--s-8) 0 var(--s-2);
  }

  h3 {
    font-size: var(--fs-base);
    font-weight: 600;
    margin: var(--s-5) 0 var(--s-1);
  }

  a {
    color: var(--accent);
  }

  /* 键盘可见焦点。原来只有输入框有焦点样式，按钮和链接靠 Tab 走过去毫无反馈。
     :where() 让权重为 0，页面想换随便换。 */
  :where(a, button, input, textarea, select, summary, [tabindex]):focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }

  /* 组件里有 display:flex 的（.me-card、.session-chip），不加这条 hidden 属性
     压不住。 */
  [hidden] {
    display: none !important;
  }
}

/* ========================================================================
   layout：页面骨架 —— 页宽容器和顶部导航条。
   ======================================================================== */
@layer layout {
  .page {
    max-width: var(--page-w);
    margin: 0 auto;
    padding-inline: var(--gutter);
    padding-bottom: var(--s-12);
  }

  /* 导航条通栏、内层限宽：底边的那条线要贯穿整个视口，而限宽的是里面的内容。
     以前 sticky 和限宽是同一个元素，于是登录页想让卡片居中，就把整条导航压成了
     400px 宽 —— 五个链接挤成三行，会话胶囊撑满一整行。 */
  .site-nav {
    position: sticky;
    top: 0;
    z-index: 20;
    margin-bottom: var(--s-6);
    border-bottom: 1px solid var(--border);
    background: color-mix(in srgb, var(--bg) 85%, transparent);
    backdrop-filter: blur(8px);
  }

  .nav-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* 换行，而不是压缩。中文可以在任意两个字之间断行，被挤窄的链接不会变短，
       只会变成一列一个字宽的竖排。 */
    flex-wrap: wrap;
    gap: var(--s-3) var(--s-5);
    /* 见 --nav-row-h：先占住会话胶囊的高度，它异步出现时导航才不会长高。
       加上下 padding —— box-sizing 是 border-box，min-height 量的是外框。 */
    min-height: calc(var(--nav-row-h) + var(--s-3) * 2);
    max-width: var(--nav-w);
    margin: 0 auto;
    padding: var(--s-3) var(--gutter);
    font-size: var(--fs-md);
  }

  /* 内容在视口里垂直居中的页面（登录页）。导航条仍然是通栏的，
     居中的只是它下面那块。 */
  body.centered {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
  }

  body.centered .page {
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding-block: var(--s-6) var(--s-10);
  }
}

/* ========================================================================
   components
   ======================================================================== */
@layer components {
  /* ---- 顶部导航（DOM 由 nav.js 生成） ------------------------------- */

  .nav-brand {
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    gap: 7px;
    color: var(--fg);
    font-weight: 700;
    text-decoration: none;
  }

  .nav-dot {
    width: 18px;
    height: 18px;
    border-radius: 5px;
    background: url("/web/favicon.svg") center / contain no-repeat;
    box-shadow: 0 3px 10px color-mix(in srgb, var(--accent) 28%, transparent);
  }

  .nav-links {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: var(--s-3) var(--s-5);
    margin-left: auto;
    margin-right: 0;
  }

  .nav-link {
    color: var(--muted);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--tap);
  }

  .nav-link:hover {
    color: var(--accent);
  }

  .nav-link.current,
  .nav-brand.current {
    color: var(--fg);
    font-weight: 600;
    cursor: default;
    pointer-events: none;
  }

  .nav-link[href="/web/login.html"] {
    padding: 7px 13px;
    border: 1px solid color-mix(in srgb, var(--accent) 72%, white 8%);
    border-radius: var(--r-pill);
    background: var(--accent);
    color: #fff;
    font-weight: 650;
    line-height: 1;
    box-shadow: 0 5px 16px color-mix(in srgb, var(--accent) 24%, transparent);
  }

  .nav-link[href="/web/login.html"]:hover {
    background: color-mix(in srgb, var(--accent) 88%, white);
    color: #fff;
  }

  /* 长得像链接的按钮（退出登录）。 */
  .linkbtn {
    padding: 0;
    border: none;
    background: none;
    color: var(--muted);
    font: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: color var(--tap);
  }

  .linkbtn:hover {
    color: var(--accent);
  }

  .session-menu {
    position: relative;
    flex: 0 0 auto;
  }

  /* inline-flex 而不是 flex：块级的 flex 容器宽度是 auto，会把父元素撑满，
     于是这枚胶囊会横贯一整行。 */
  .session-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--nav-row-h);
    /* 和 .nav-inner 预留的高度是同一个值，不然预留多少就白留多少。 */
    height: var(--nav-row-h);
    padding: 3px;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    background: var(--card);
    cursor: pointer;
    list-style: none;
    transition: border-color var(--tap), background var(--tap);
  }
  .session-chip::-webkit-details-marker { display: none; }
  .session-chip:hover,
  .session-menu[open] .session-chip {
    border-color: color-mix(in srgb, var(--fg) 22%, transparent);
    background: color-mix(in srgb, var(--card) 88%, white 3%);
  }

  .session-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 30;
    min-width: 220px;
    padding: 6px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--card);
    box-shadow: 0 14px 34px rgba(0,0,0,.28);
  }
  .session-dropdown-account {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 8px 10px;
  }
  .session-dropdown-email {
    min-width: 0;
    overflow: hidden;
    color: var(--fg);
    font-weight: 550;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .session-dropdown-separator {
    display: block;
    height: 1px;
    margin: 4px 6px;
    background: var(--border);
  }
  .session-dropdown-item {
    display: block;
    width: 100%;
    padding: 9px 11px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: var(--muted);
    font: inherit;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
  }
  .session-dropdown-item:hover {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    color: var(--fg);
  }

  /* ---- 按钮 --------------------------------------------------------- */

  /* 变体通过改这三个变量实现，不通过提高选择器权重。所以在页面里写
     `.btn.armed { --btn-bg: var(--danger) }` 一定生效，不用管它排在哪儿。 */
  .btn {
    --btn-bg: transparent;
    --btn-fg: var(--fg);
    --btn-border: var(--border);

    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-1);
    padding: 9px 18px;
    border: 1px solid var(--btn-border);
    border-radius: var(--r-sm);
    background: var(--btn-bg);
    color: var(--btn-fg);
    font: inherit;
    font-size: var(--fs-base);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background var(--tap), border-color var(--tap),
      color var(--tap), opacity var(--tap), transform 0.1s ease;
  }

  .btn:hover {
    opacity: 0.92;
  }

  .btn:active {
    transform: scale(0.98);
  }

  .btn:disabled {
    opacity: 0.45;
    cursor: default;
    transform: none;
  }

  /* 禁用态不响应 hover —— 否则"变淡了但还会亮"，看着像还能点。 */
  .btn:disabled:hover {
    --btn-border: var(--border);
    --btn-fg: var(--fg);
    opacity: 0.45;
  }

  .btn-primary {
    --btn-bg: var(--accent);
    --btn-fg: #fff;
    --btn-border: var(--accent);
  }

  .btn-secondary:hover {
    --btn-border: var(--accent);
    --btn-fg: var(--accent);
    opacity: 1;
  }

  .btn-ghost {
    --btn-fg: var(--muted);
  }

  .btn-ghost:hover {
    --btn-border: var(--accent);
    --btn-fg: var(--accent);
    opacity: 1;
  }

  .btn-danger {
    --btn-fg: var(--danger);
  }

  .btn-danger:hover {
    --btn-bg: var(--danger-soft);
    --btn-border: var(--danger);
    opacity: 1;
  }

  .btn-sm {
    padding: 5px 12px;
    font-size: var(--fs-sm);
    font-weight: 500;
  }

  .btn-lg {
    padding: 11px 22px;
    border-radius: var(--r-md);
  }

  .btn-pill {
    border-radius: var(--r-pill);
  }

  .btn-block {
    width: 100%;
  }

  /* ---- 表单 --------------------------------------------------------- */

  .field {
    margin-bottom: var(--s-4);
  }

  .label {
    display: block;
    margin-bottom: 5px;
    color: var(--muted);
    font-size: var(--fs-sm);
  }

  .label-strong {
    color: var(--fg);
    font-size: var(--fs-md);
    font-weight: 600;
  }

  .input {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    background: var(--bg);
    color: var(--fg);
    font: inherit;
    font-size: var(--fs-base);
    line-height: 1.5;
    outline: none;
    transition: border-color var(--tap), box-shadow var(--tap);
  }

  .input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-ring);
  }

  /* 上面的边框 + 光环已经是焦点提示了，再叠一圈 outline 就是两个方框。 */
  .input:focus-visible {
    outline: none;
  }

  textarea.input {
    min-height: 140px;
    resize: vertical;
  }

  /* 无论说不说话都占住一行，提交时按钮不会往下窜到光标底下。 */
  .status {
    min-height: 1.4em;
    font-size: var(--fs-sm);
  }

  .status[data-kind="ok"] {
    color: var(--ok);
  }

  .status[data-kind="err"] {
    color: var(--danger);
  }

  /* ---- 容器 --------------------------------------------------------- */

  .card {
    padding: var(--s-5);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--card);
  }

  .card-lg {
    padding: var(--s-8);
    border-radius: var(--r-xl);
  }

  /* 内容自己贴边的卡片（表格、列表）：圆角要能裁掉里面的东西。 */
  .card-flush {
    padding: 0;
    overflow: hidden;
    border-radius: var(--r-md);
  }

  .callout {
    margin: 0 0 var(--s-5);
    padding: var(--s-4) var(--s-5);
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: var(--r-md);
    background: var(--card);
  }

  .callout > :last-child {
    margin-bottom: 0;
  }

  .empty {
    padding: var(--s-8) var(--s-4);
    color: var(--muted);
    font-size: var(--fs-md);
    text-align: center;
  }

  /* ---- 标记与徽章 --------------------------------------------------- */

  /* 应用图标。里面放的就是 favicon.svg 本身 —— 渐变圆角方块和话筒都在那个文件
     里，这里只负责尺寸和外面那圈辉光。

     圆角仍然要写：辉光是照着元素的形状投的，元素是方的话辉光就是方的。25% 对应
     favicon.svg 的 rx="16"（64 的四分之一），改那边的圆角要跟着改这里。 */
  .mark {
    --mark-size: 40px;

    display: inline-block;
    width: var(--mark-size);
    height: var(--mark-size);
    border-radius: 25%;
    box-shadow: var(--glow-accent);
  }

  .mark img {
    display: block;
    width: 100%;
    height: 100%;
  }

  .mark-lg {
    --mark-size: 64px;

    box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 35%, transparent);
  }

  /* 首字母头像。同上，只改 --avatar-size。 */
  .avatar {
    --avatar-size: 32px;

    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: var(--avatar-size);
    height: var(--avatar-size);
    border-radius: 50%;
    background: var(--grad-accent);
    color: #fff;
    font-size: calc(var(--avatar-size) * 0.44);
    font-weight: 700;
    line-height: 1;
  }

  .badge {
    flex-shrink: 0;
    padding: 2px 9px;
    border-radius: var(--r-pill);
    background: var(--accent-soft);
    color: var(--accent);
    font-size: var(--fs-xs);
    font-weight: 600;
  }

  .badge-neutral {
    background: var(--neutral-soft);
    color: var(--muted);
    font-weight: 400;
  }

  /* 药丸。静态的（平台支持情况）和可点的（反馈分类）是同一个形状，
     区别只在 button.chip 多了指针和 hover。 */
  .chip {
    display: inline-flex;
    align-items: center;
    padding: 6px 14px;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--muted);
    font: inherit;
    font-size: var(--fs-md);
  }

  button.chip {
    cursor: pointer;
    transition: background var(--tap), border-color var(--tap), color var(--tap);
  }

  button.chip:hover {
    border-color: color-mix(in srgb, var(--fg) 30%, transparent);
    color: var(--fg);
  }

  /* 实心而不是描边：五个里选中一个要一眼看出来，而上面的 hover 已经动过边框了。 */
  .chip.selected {
    border-color: var(--accent);
    background: var(--accent);
    color: #fff;
  }

  /* 只是"被强调"，不是"被选中"。 */
  .chip.on {
    border-color: var(--accent-line);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    color: var(--accent);
  }

  /* ---- 正文排版 ------------------------------------------------------ */

  /* 帮助页和隐私政策是成篇的文章，按元素排版是对的 —— 但只在 .prose 里面，
     免得波及到别处那些恰好也是 <p> 的东西。 */
  .prose h2 {
    margin: var(--s-8) 0 var(--s-2);
    padding-top: var(--s-5);
    border-top: 1px solid var(--border);
    font-size: var(--fs-lg);
    font-weight: 700;
  }

  .prose h2:first-of-type {
    padding-top: 0;
    border-top: none;
  }

  .prose h3 {
    margin: var(--s-5) 0 var(--s-1);
    font-size: var(--fs-base);
    font-weight: 600;
  }

  .prose p,
  .prose ul,
  .prose ol {
    margin: 0 0 var(--s-3);
    font-size: var(--fs-base);
  }

  .prose ul,
  .prose ol {
    padding-left: 22px;
  }

  .prose li {
    margin-bottom: var(--s-1);
  }

  .prose strong {
    font-weight: 600;
  }

  .prose code,
  .prose kbd {
    padding: 1px 6px;
    border: 1px solid var(--border);
    border-radius: var(--r-xs);
    background: var(--card);
    font-size: var(--fs-sm);
  }

  .prose code {
    font-family: var(--font-mono);
  }

  .prose kbd {
    border-bottom-width: 2px;
    font-family: inherit;
    font-weight: 600;
  }

  /* 标题下面那行灰字：正文导语、"最后更新"、"用户与配额管理"都是它。 */
  .subtitle {
    margin: 0 0 var(--s-6);
    color: var(--muted);
    font-size: var(--fs-md);
  }

  .note {
    margin: var(--s-3) 0 0;
    color: var(--muted);
    font-size: var(--fs-xs);
    line-height: 1.6;
  }

  .divider {
    height: 1px;
    margin: var(--s-5) 0 var(--s-1);
    background: var(--border);
  }
}

/* ========================================================================
   utilities
   ======================================================================== */
@layer utilities {
  .muted {
    color: var(--muted);
  }

  .center {
    text-align: center;
  }

  /* 数字对齐用。用量、配额、计数这些会原地刷新，等宽数字才不会跳。 */
  .tabular {
    font-variant-numeric: tabular-nums;
  }
}
