<template>
  <div class="doc-page">
    <div class="doc-container">
      <!-- ====== 页头 ====== -->
      <header class="doc-hero">
        <div class="doc-hero-left">
          <svg class="doc-logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/>
          </svg>
          <div>
            <h1>{{ sys?.systemName || '系统' }} — 接入文档</h1>
            <p>Mokee Gateway 统一登录网关 · 系统对接完整指南</p>
          </div>
        </div>
        <div class="doc-hero-right">
          <el-tag size="large" type="primary" effect="dark" round>系统编码: {{ sys?.systemCode }}</el-tag>
        </div>
      </header>

      <!-- ====== 一、系统信息 ====== -->
      <section class="doc-section">
        <h2 class="section-h2"><span class="s-num">1</span>当前系统配置</h2>
        <el-descriptions :column="2" border size="large">
          <el-descriptions-item label="系统编码"><code class="inline-code">{{ sys?.systemCode }}</code></el-descriptions-item>
          <el-descriptions-item label="系统名称">{{ sys?.systemName }}</el-descriptions-item>
          <el-descriptions-item label="前端地址"><code class="inline-code">{{ sys?.frontUrl }}</code></el-descriptions-item>
          <el-descriptions-item label="后端地址"><code class="inline-code">{{ sys?.backendUrl }}</code></el-descriptions-item>
          <el-descriptions-item label="系统描述" :span="2">{{ sys?.description || '-' }}</el-descriptions-item>
        </el-descriptions>
      </section>

      <!-- ====== 二、架构概览 ====== -->
      <section class="doc-section">
        <h2 class="section-h2"><span class="s-num">2</span>架构概览</h2>
        <div class="arch-diagram">
          <pre class="arch-text">┌──────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  业务前端     │────▶│  Mokee Gateway   │────▶│  业务后端         │
│  (Vue/React)  │     │  gw.server.zgitm.com    │     │  (任意语言)       │
│               │     │                  │     │                  │
│  携带 Token   │     │  验证 Token      │     │  从请求头读取:    │
│  + SystemCode │     │  识别系统编码     │     │  X-User-Id       │
│               │     │  转发请求        │     │  X-User-Name     │
│               │     │  注入用户信息头   │     │  X-System-Code   │
└──────────────┘     └──────────────────┘     └──────────────────┘</pre>
        </div>
        <div class="flow-steps">
          <div class="flow-step"><b>①</b> 用户访问业务前端 → 无 Token → 跳转统一登录页</div>
          <div class="flow-step"><b>②</b> 登录成功 → 获得 JWT Token → 回跳到业务前端</div>
          <div class="flow-step"><b>③</b> 业务前端所有 API 请求 → 网关 (携带 Authorization + X-System-Code)</div>
          <div class="flow-step"><b>④</b> 网关验证 Token → 注入用户信息请求头 → 转发到业务后端</div>
          <div class="flow-step"><b>⑤</b> 业务后端从请求头读取用户信息 → 执行业务逻辑</div>
        </div>

        <div class="arch-warnings">
          <div class="warn-item">
            <b>🔴 关键规则一：前端只调网关</b>
            <p>业务前端的 <code>baseURL</code> 必须配置为 <b>网关地址</b>（如 <code>{{ gatewayUrl }}</code>），<b>绝对不能</b>直接调用业务后端。网关根据请求头 <code>X-System-Code</code> 自动识别并转发到对应后端。</p>
          </div>
          <div class="warn-item">
            <b>🔴 关键规则二：后端必须开跨域 (CORS)</b>
            <p>业务后端需要允许来自网关域名的跨域请求。网关转发请求时 origin 是浏览器地址，不是网关地址。</p>
            <p><b>Java Spring Boot 配置：</b></p>
            <div class="code-box"><pre><code>@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOriginPatterns("*")
            .allowedMethods("*")
            .allowedHeaders("*")
            .allowCredentials(true);
    }
}</code></pre></div>
          </div>
          <div class="warn-item">
            <b>🔴 关键规则三：业务后端不再做登录/鉴权</b>
            <p>Token 验证由网关完成。业务后端只需从请求头读取用户信息，不需要再验证 Token、不需要查询用户表。</p>
          </div>
        </div>
      </section>

      <!-- ====== 三、前端接入 ====== -->
      <section class="doc-section">
        <h2 class="section-h2"><span class="s-num">3</span>前端接入 (完整代码)</h2>

        <h3 class="section-h3">3.1 安装依赖</h3>
        <div class="code-box">
          <div class="code-label">Shell</div>
          <pre><code>npm install axios</code></pre>
        </div>

        <h3 class="section-h3">3.2 环境变量 (.env)</h3>
        <div class="code-box">
          <div class="code-label">.env</div>
          <pre><code>VITE_GATEWAY_URL = {{ gatewayUrl }}
VITE_LOGIN_URL   = {{ loginUrl }}
VITE_SYSTEM_CODE = {{ sys?.systemCode || 'YOUR_CODE' }}</code></pre>
        </div>

        <h3 class="section-h3">3.3 Axios 实例 (src/utils/request.ts)</h3>
        <div class="code-box">
          <div class="code-label">TypeScript</div>
          <pre><code>import axios from 'axios'
import { ElMessage } from 'element-plus'

const SYSTEM_CODE = import.meta.env.VITE_SYSTEM_CODE

const request = axios.create({
  baseURL: import.meta.env.VITE_GATEWAY_URL,
  timeout: 30000,
})

// 请求拦截器：携带 Token 和系统编码
request.interceptors.request.use(config => {
  const token = localStorage.getItem('token')
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  // 关键：网关根据此头识别业务系统
  config.headers['X-System-Code'] = SYSTEM_CODE
  return config
})

// 响应拦截器：401 自动跳转登录
request.interceptors.response.use(
  res => res.data.code === 200 ? res.data : Promise.reject(res.data),
  err => {
    if (err.response?.status === 401) {
      localStorage.removeItem('token')
      window.location.href = `${import.meta.env.VITE_LOGIN_URL}?systemCode=${SYSTEM_CODE}`
    }
    return Promise.reject(err)
  }
)

export default request</code></pre>
        </div>

        <h3 class="section-h3">3.4 路由守卫 (src/router/index.ts)</h3>
        <div class="code-box">
          <div class="code-label">TypeScript</div>
          <pre><code>import { createRouter, createWebHistory } from 'vue-router'

const SYSTEM_CODE = import.meta.env.VITE_SYSTEM_CODE
const LOGIN_URL  = import.meta.env.VITE_LOGIN_URL

const router = createRouter({
  history: createWebHistory(),
  routes: [ /* 你的路由 */ ],
})

router.beforeEach((to, _from, next) => {
  const token = localStorage.getItem('token')
  if (!token && to.path !== '/login') {
    // 无 Token → 跳统一登录页
    window.location.href = `${LOGIN_URL}?systemCode=${SYSTEM_CODE}`
    return
  }
  next()
})

export default router</code></pre>
        </div>

        <h3 class="section-h3">3.5 登录成功回调处理</h3>
        <p class="text-p">统一登录成功后，网关会将 Token 写入 localStorage 并跳回业务前端。业务前端无需处理登录请求，只需从 localStorage 读取 Token。</p>
        <div class="code-box">
          <div class="code-label">TypeScript</div>
          <pre><code>// main.ts 或 App.vue onMounted
const token = localStorage.getItem('token')
if (token) {
  // 用户已登录，正常渲染应用
  // 如需获取用户信息，调用网关 API：
  const res = await request.get('/zgapi/v1/auth/user/info')
  console.log('当前用户:', res.data)
}</code></pre>
        </div>
      </section>

      <!-- ====== 四、后端接入 ====== -->
      <section class="doc-section">
        <h2 class="section-h2"><span class="s-num">4</span>后端接入 (完整代码)</h2>

        <h3 class="section-h3">4.1 网关转发到后端时注入的请求头</h3>
        <el-table :data="headerTable" border stripe size="large" style="width:100%">
          <el-table-column prop="name" label="请求头名称" width="200" />
          <el-table-column prop="type" label="数据类型" width="120" />
          <el-table-column prop="desc" label="说明" />
        </el-table>
        <p class="text-p" style="margin-top:16px"><b>重要：</b>这些请求头由网关注入，业务后端可以信任这些值。不需要再验证 Token 或查询用户信息。</p>

        <h3 class="section-h3">4.2 Java — UserContext 工具类</h3>
        <p class="text-p">用 ThreadLocal 缓存请求头，业务代码零侵入获取用户信息。</p>
        <div class="code-box">
          <div class="code-label">Java</div>
          <pre><code>// ====== UserContext.java ======
import java.util.*;

public class UserContext {
    private static final ThreadLocal&lt;Map&lt;String, String&gt;&gt; CTX = new ThreadLocal&lt;&gt;();

    public static void set(Map&lt;String, String&gt; user)  { CTX.set(user); }
    public static Map&lt;String, String&gt; get()            { return CTX.get(); }
    public static void clear()                          { CTX.remove(); }

    // 快捷方法
    public static String getUserId()     { return get().get("X-User-Id"); }
    public static String getUserName()   { return get().get("X-User-Name"); }
    public static String getUserAccount(){ return get().get("X-User-Account"); }
    public static String getSystemCode() { return get().get("X-System-Code"); }
    public static String getSystemId()   { return get().get("X-System-Id"); }
}

// ====== UserContextFilter.java ======
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.*;

@Component
public class UserContextFilter implements Filter {
    private static final String[] HEADERS = {
        "X-User-Id", "X-User-Name", "X-User-Account",
        "X-User-Email", "X-User-Post", "X-User-Roles",
        "X-System-Id", "X-System-Code", "X-System-Name"
    };

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        Map&lt;String, String&gt; user = new HashMap&lt;&gt;();
        for (String h : HEADERS) {
            String v = request.getHeader(h);
            if (v != null) user.put(h, v);
        }
        UserContext.set(user);
        try {
            chain.doFilter(req, res);
        } finally {
            UserContext.clear();
        }
    }
}

// ====== 业务代码中使用 ======
@RestController
public class OrderController {

    @GetMapping("/api/orders")
    public List&lt;Order&gt; list() {
        String userId     = UserContext.getUserId();      // "123"
        String userName   = UserContext.getUserName();    // "张三"
        String systemCode = UserContext.getSystemCode();  // "msg"
        return orderService.findByUser(userId, systemCode);
    }
}</code></pre>
        </div>

        <h3 class="section-h3">4.3 Python — Flask 中间件</h3>
        <div class="code-box">
          <div class="code-label">Python</div>
          <pre><code># ====== middleware.py ======
from flask import request, g

USER_HEADERS = [
    'X-User-Id', 'X-User-Name', 'X-User-Account',
    'X-User-Email', 'X-User-Post', 'X-User-Roles',
    'X-System-Id', 'X-System-Code', 'X-System-Name',
]

def user_context_middleware():
    """将网关注入的用户信息存到 Flask g 对象"""
    for h in USER_HEADERS:
        val = request.headers.get(h)
        if val:
            setattr(g, h.replace('-', '_').lower(), val)

# 注册到 app (Flask)
# app.before_request(user_context_middleware)

# ====== 业务代码中使用 ======
from flask import g

@app.route('/api/orders')
def list_orders():
    user_id     = g.x_user_id       # "123"
    user_name   = g.x_user_name     # "张三"
    system_code = g.x_system_code   # "msg"
    return order_service.query(user_id, system_code)</code></pre>
        </div>

        <h3 class="section-h3">4.4 Go — 中间件</h3>
        <div class="code-box">
          <div class="code-label">Go</div>
          <pre><code>// ====== middleware.go ======
package middleware

import (
    "context"
    "net/http"
)

type contextKey string

func UserContext(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()
        for _, h := range []string{
            "X-User-Id", "X-User-Name", "X-User-Account",
            "X-User-Email", "X-User-Roles",
            "X-System-Id", "X-System-Code",
        } {
            if v := r.Header.Get(h); v != "" {
                ctx = context.WithValue(ctx, contextKey(h), v)
            }
        }
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

// 快捷函数
func GetUserID(ctx context.Context) string {
    return ctx.Value(contextKey("X-User-Id")).(string)
}
func GetSystemCode(ctx context.Context) string {
    return ctx.Value(contextKey("X-System-Code")).(string)
}

// ====== main.go: 注册中间件 ======
// http.Handle("/api/", middleware.UserContext(yourHandler))

// ====== 业务代码 ======
func listOrders(w http.ResponseWriter, r *http.Request) {
    userID     := middleware.GetUserID(r.Context())     // "123"
    systemCode := middleware.GetSystemCode(r.Context()) // "msg"
    // ...
}</code></pre>
        </div>
      </section>

      <!-- ====== 五、API 接口参考 ====== -->
      <section class="doc-section">
        <h2 class="section-h2"><span class="s-num">5</span>API 接口参考</h2>

        <h3 class="section-h3">5.1 获取当前用户信息</h3>
        <div class="api-card">
          <div class="api-method get">GET</div>
          <div class="api-path">/zgapi/v1/auth/user/info</div>
          <div class="api-headers">
            <b>请求头：</b>Authorization: Bearer {token}
          </div>
          <div class="api-response">
            <b>响应：</b>
            <div class="code-box"><pre><code>{
  "code": 200,
  "data": {
    "userId":   1,
    "username": "admin",
    "realName": "管理员",
    "email":    "admin@zgitm.com",
    "phone":    "13800000000",
    "avatar":   null,
    "post":     "管理员"
  }
}</code></pre></div>
          </div>
        </div>

        <h3 class="section-h3">5.2 获取系统菜单路由</h3>
        <div class="api-card">
          <div class="api-method get">GET</div>
          <div class="api-path">/zgapi/v1/auth/menu/router?systemCode={{ sys?.systemCode || 'YOUR_CODE' }}</div>
          <div class="api-headers">
            <b>请求头：</b>Authorization: Bearer {token}
          </div>
          <div class="api-response">
            <b>响应：</b>树形菜单结构，包含 path / name / component / children / meta(含 title, icon)
          </div>
        </div>

        <h3 class="section-h3">5.3 退出登录</h3>
        <div class="api-card">
          <div class="api-method post">POST</div>
          <div class="api-path">/zgapi/v1/auth/logout</div>
          <div class="api-headers">
            <b>请求头：</b>Authorization: Bearer {token}
          </div>
        </div>
      </section>

      <!-- ====== 六、数据库初始化 ====== -->
      <section class="doc-section">
        <h2 class="section-h2"><span class="s-num">6</span>数据库初始化</h2>
        <p class="text-p">在网关平台的数据库执行以下 SQL，为「{{ sys?.systemName }}」创建默认菜单和角色。</p>
        <div class="code-box">
          <div class="code-label">SQL</div>
          <pre><code>{{ menuSql }}</code></pre>
        </div>
      </section>

      <!-- ====== 七、测试清单 ====== -->
      <section class="doc-section">
        <h2 class="section-h2"><span class="s-num">7</span>对接测试清单</h2>
        <div class="checklist">
          <div v-for="(item, i) in testChecklist" :key="i" class="check-item">
            <el-icon :size="20" color="var(--color-primary)"><component :is="getIconComponent(item.done ? 'CircleCheckFilled' : 'CircleClose')" /></el-icon>
            <span>{{ item.text }}</span>
          </div>
        </div>
      </section>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { useRoute } from 'vue-router'
import { CircleCheckFilled, CircleClose } from '@element-plus/icons-vue'
import { getIconComponent } from '@/utils/icons'
import request from '@/utils/request'

const route = useRoute()
const sys = ref<any>(null)
const token = route.params.token as string

const gatewayUrl = computed(() => import.meta.env.VITE_GATEWAY_URL || 'https://gw.server.zgitm.com')
const loginUrl   = computed(() => import.meta.env.VITE_LOGIN_URL   || 'https://login.user.zgitm.com')

const headerTable = [
  { name: 'X-User-Id',       type: 'String',  desc: '当前登录用户的唯一ID' },
  { name: 'X-User-Name',     type: 'String',  desc: '用户真实姓名' },
  { name: 'X-User-Account',  type: 'String',  desc: '用户登录账号' },
  { name: 'X-User-Email',    type: 'String',  desc: '用户邮箱' },
  { name: 'X-User-Post',     type: 'String',  desc: '用户岗位' },
  { name: 'X-User-Roles',    type: 'JSON',    desc: '用户角色列表 [{roleId, roleName, roleCode}]' },
  { name: 'X-System-Id',     type: 'String',  desc: '当前业务系统的数据库ID' },
  { name: 'X-System-Code',   type: 'String',  desc: '当前业务系统的唯一编码' },
  { name: 'X-System-Name',   type: 'String',  desc: '当前业务系统的显示名称' },
]

const menuSql = computed(() => {
  const sc = sys.value?.systemCode || 'YOUR_SYSTEM_CODE'
  const sn = sys.value?.systemName || '系统'
  return `-- =============================================
-- ${sn} 菜单 & 角色初始化 SQL
-- 系统编码: ${sc}
-- 将 system_code 替换为你的编码后直接执行
-- =============================================

-- 1. 创建顶级菜单目录 (parent_id = 0)
INSERT INTO sys_menu (system_id, parent_id, menu_name, menu_path, component, icon, menu_type, sort_order, status)
SELECT s.id, 0, '系统管理', '/system', 'Layout', 'Setting', 1, 1, 1
FROM sys_system s WHERE s.system_code = '${sc}';

INSERT INTO sys_menu (system_id, parent_id, menu_name, menu_path, component, icon, menu_type, sort_order, status)
SELECT s.id, 0, '业务管理', '/biz', 'Layout', 'Document', 1, 2, 1
FROM sys_system s WHERE s.system_code = '${sc}';

-- 2. 创建子菜单 (parent_id = 对应父菜单ID)
INSERT INTO sys_menu (system_id, parent_id, menu_name, menu_path, component, icon, menu_type, sort_order, status)
SELECT s.id, m.id, '用户管理', '/system/user', 'system/user/index', 'User', 2, 1, 1
FROM sys_system s, sys_menu m
WHERE s.system_code = '${sc}' AND m.menu_name = '系统管理' AND m.system_id = s.id;

INSERT INTO sys_menu (system_id, parent_id, menu_name, menu_path, component, icon, menu_type, sort_order, status)
SELECT s.id, m.id, '角色管理', '/system/role', 'system/role/index', 'Avatar', 2, 2, 1
FROM sys_system s, sys_menu m
WHERE s.system_code = '${sc}' AND m.menu_name = '系统管理' AND m.system_id = s.id;

INSERT INTO sys_menu (system_id, parent_id, menu_name, menu_path, component, icon, menu_type, sort_order, status)
SELECT s.id, m.id, '订单管理', '/biz/order', 'biz/order/index', 'Tickets', 2, 1, 1
FROM sys_system s, sys_menu m
WHERE s.system_code = '${sc}' AND m.menu_name = '业务管理' AND m.system_id = s.id;

-- 3. 创建角色
INSERT INTO sys_role (system_id, role_name, role_code, description, status)
SELECT s.id, '管理员', 'admin', '拥有全部权限', 1
FROM sys_system s WHERE s.system_code = '${sc}';

INSERT INTO sys_role (system_id, role_name, role_code, description, status)
SELECT s.id, '普通用户', 'user', '拥有基本权限', 1
FROM sys_system s WHERE s.system_code = '${sc}';

-- 4. 将菜单分配给角色
INSERT INTO sys_role_menu (role_id, menu_id)
SELECT r.id, m.id
FROM sys_role r, sys_menu m, sys_system s
WHERE r.role_code = 'admin'
  AND r.system_id = s.id
  AND m.system_id = s.id
  AND s.system_code = '${sc}';`
})

const testChecklist = computed(() => [
  { text: '访问业务前端首页 → 自动跳转到统一登录页', done: false },
  { text: '使用测试账号登录 → 成功进入业务前端', done: false },
  { text: '调用 GET /zgapi/v1/auth/user/info → 返回用户信息', done: false },
  { text: '业务后端 Controller 中 UserContext.getUserId() 能获取到用户ID', done: false },
  { text: '未放行的 API 请求被网关返回 403', done: false },
  { text: '退出登录后访问业务页面 → 重新跳转登录页', done: false },
])

onMounted(async () => {
  try {
    const res = await request.get('/zgapi/v1/admin/system/doc/' + token)
    sys.value = res.data
  } catch { /* ignore */ }
})
</script>

<style scoped>
/* ===== 整体 ===== */
.doc-page { min-height:100vh; background:var(--bg-page); padding:20px; }
.doc-container { max-width:960px; margin:0 auto; }

/* ===== 页头 ===== */
.doc-hero {
  display:flex; align-items:center; justify-content:space-between;
  padding:28px 32px; background:var(--bg-surface);
  border-radius:var(--radius-xl); border:1px solid var(--border-color);
  margin-bottom:24px; box-shadow:var(--shadow-sm);
}
.doc-hero-left { display:flex; align-items:center; gap:14px; }
.doc-logo { width:36px; height:36px; color:var(--color-primary); flex-shrink:0; }
.doc-hero-left h1 { font-size:22px; font-weight:700; margin:0 0 4px; color:var(--text-primary); }
.doc-hero-left p { font-size:14px; color:var(--text-muted); margin:0; }

/* ===== 章节 ===== */
.doc-section {
  background:var(--bg-surface); border-radius:var(--radius-xl);
  border:1px solid var(--border-color); padding:28px 32px;
  margin-bottom:20px; box-shadow:var(--shadow-sm);
}
.section-h2 {
  display:flex; align-items:center; gap:12px;
  font-size:20px; font-weight:700; color:var(--text-primary);
  margin:0 0 20px; padding-bottom:16px;
  border-bottom:1px solid var(--border-light);
}
.s-num {
  display:inline-flex; align-items:center; justify-content:center;
  width:32px; height:32px; border-radius:var(--radius-md);
  background:var(--color-primary); color:#fff;
  font-size:15px; font-weight:700; flex-shrink:0;
}
.section-h3 {
  font-size:16px; font-weight:600; color:var(--text-primary);
  margin:24px 0 10px;
}
.section-h3:first-of-type { margin-top:0; }

/* ===== 文字 ===== */
.text-p { font-size:14px; color:var(--text-secondary); line-height:1.7; margin:0 0 12px; }
.inline-code {
  background:var(--color-primary-bg); color:var(--color-primary);
  padding:2px 8px; border-radius:4px; font-size:13px;
  font-family:'SF Mono','Consolas',monospace;
}

/* ===== 架构图 ===== */
.arch-text {
  background:#1e293b; color:#e2e8f0; padding:16px 20px;
  border-radius:var(--radius-md); font-size:13px;
  line-height:1.7; overflow-x:auto; white-space:pre;
  font-family:'SF Mono','Consolas',monospace;
}
.flow-steps { margin-top:16px; display:flex; flex-direction:column; gap:10px; }
.flow-step { font-size:14px; color:var(--text-secondary); display:flex; align-items:flex-start; gap:8px; line-height:1.6; }
.flow-step b { color:var(--color-primary); flex-shrink:0; }

/* ===== 代码块 ===== */
.code-box {
  position:relative; background:#1e293b; border-radius:var(--radius-md);
  margin-bottom:16px; overflow:hidden;
}
.code-label {
  position:absolute; top:8px; right:12px; z-index:1;
  font-size:11px; color:rgba(255,255,255,0.45); font-weight:600;
  letter-spacing:0.5px; text-transform:uppercase;
}
.code-box pre {
  margin:0; padding:20px; overflow-x:auto;
}
.code-box code {
  font-family:'SF Mono','Fira Code','Consolas',monospace;
  font-size:13px; line-height:1.75; color:#e2e8f0; white-space:pre;
}

/* ===== API 卡片 ===== */
.api-card {
  border:1px solid var(--border-color); border-radius:var(--radius-lg);
  padding:20px; margin-bottom:16px;
}
.api-method {
  display:inline-block; padding:2px 10px; border-radius:4px;
  font-size:12px; font-weight:700; color:#fff; margin-bottom:8px;
}
.api-method.get  { background:#10b981; }
.api-method.post { background:#6366f1; }
.api-method.put  { background:#f59e0b; }
.api-path {
  font-size:15px; font-weight:600; color:var(--text-primary);
  font-family:'SF Mono','Consolas',monospace; margin-bottom:8px;
}
.api-headers { font-size:14px; color:var(--text-secondary); margin-bottom:8px; }
.api-response { font-size:14px; color:var(--text-secondary); }

/* ===== 测试清单 ===== */
.checklist { display:flex; flex-direction:column; gap:14px; }
.check-item { display:flex; align-items:center; gap:10px; font-size:14px; color:var(--text-secondary); }

/* 架构警告 */
.arch-warnings { margin-top:16px; display:flex; flex-direction:column; gap:12px; }
.warn-item {
  background:#fef2f2; border:1px solid #fecaca; border-radius:var(--radius-md);
  padding:14px 18px;
}
.warn-item b { color:#dc2626; font-size:14px; display:block; margin-bottom:4px; }
.warn-item p { color:var(--text-secondary); font-size:14px; margin:0 0 8px; line-height:1.7; }

@media (max-width:768px) {
  .doc-hero { flex-direction:column; gap:12px; align-items:flex-start; }
  .doc-section { padding:20px; }
}
</style>
