/* ================================================
   租房管理系统 - 响应式样式
   PC + 平板 + 移动端 自适应
   ================================================ */

* { margin: 0; padding: 0; box-sizing: border-box; }
html, body, #app { height: 100%; font-family: 'Helvetica Neue', 'PingFang SC', 'Microsoft YaHei', sans-serif; }
body { background: #f0f2f5; }
/* 移动端菜单打开时锁定背景滚动（配合 JS 切换 body.menu-open 类 + touchmove 拦截） */
body.menu-open { overflow: hidden; }
/* 真正滚动的是 .page-body，必须锁它；遮罩层也禁止滚动 */
body.menu-open .page-body { overflow: hidden; touch-action: none; }
body.menu-open .mobile-overlay { touch-action: none; }

/* ==================== 登录页 ==================== */
.login-container {
    display: flex; justify-content: center; align-items: center; height: 100vh; height: calc(var(--vh, 1vh) * 100); height: 100dvh;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    padding: 20px;
}
.login-box {
    width: 420px; padding: 40px; background: #fff; border-radius: 12px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}
.login-box h2 { text-align: center; margin-bottom: 30px; color: #333; font-size: 24px; }
.login-box .el-button { width: 100%; height: 44px; font-size: 16px; }
.login-version { text-align: center; margin-top: 18px; font-size: 12px; color: #b0b0b0; }

/* ==================== 主布局 ==================== */
.main-layout { display: flex; height: 100vh; height: calc(var(--vh, 1vh) * 100); height: 100dvh; position: relative; }

/* 侧边栏 - PC */
.sidebar {
    width: 220px; background: #304156; color: #fff; overflow-y: auto;
    transition: transform 0.3s, width 0.3s; flex-shrink: 0; z-index: 999;
    display: flex; flex-direction: column;
    overscroll-behavior: contain; /* 阻止侧边栏滚动链到背景页面 */
}
.sidebar.collapsed { width: 64px; }
.sidebar-logo {
    height: 60px; display: flex; align-items: center; justify-content: center;
    font-size: 18px; font-weight: bold; color: #fff; border-bottom: 1px solid rgba(255,255,255,0.1);
    white-space: nowrap; overflow: hidden; flex-shrink: 0;
}
.sidebar-menu { padding: 8px 0; flex: 1; overflow-y: auto; scrollbar-width: thin; scrollbar-color: transparent transparent; }
/* 侧边栏滚动条：默认隐藏，鼠标悬停侧边栏时显示（Chrome/Edge/Safari） */
.sidebar-menu::-webkit-scrollbar { width: 6px; }
.sidebar-menu::-webkit-scrollbar-track { background: transparent; }
.sidebar-menu::-webkit-scrollbar-thumb { background: transparent; border-radius: 3px; }
.sidebar:hover .sidebar-menu { scrollbar-color: rgba(255,255,255,0.25) transparent; }
.sidebar:hover .sidebar-menu::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.25); }
.sidebar-menu::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.45); }
.menu-item {
    display: flex; align-items: center; padding: 14px 20px; cursor: pointer;
    color: #bfcbd9; transition: all 0.3s; font-size: 14px; white-space: nowrap;
}
.menu-item:hover { color: #fff; background: rgba(255,255,255,0.05); }
.menu-item.active { color: #409EFF; background: rgba(64,158,255,0.1); }
.menu-item .menu-icon { margin-right: 10px; font-size: 18px; width: 20px; text-align: center; flex-shrink: 0; }
.menu-item .menu-title { overflow: hidden; }

/* 侧边栏底部信息 */
.sidebar-footer {
    padding: 12px 20px; padding-bottom: calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid rgba(255,255,255,0.08);
    font-size: 12px; color: #8a9bb5; display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.sidebar-version { font-size: 11px; color: #6b7a96; flex-shrink: 0; }

.main-content { flex: 1; display: flex; flex-direction: column; overflow: hidden; min-width: 0; }
.header {
    height: 50px; background: #fff; display: flex; align-items: center; justify-content: space-between;
    padding: 0 20px; box-shadow: 0 1px 4px rgba(0,0,0,0.08); z-index: 10; flex-shrink: 0;
}
.header-left { display: flex; align-items: center; gap: 10px; }
.header-right { display: flex; align-items: center; gap: 15px; }
.header-collapse-btn { font-size: 20px; cursor: pointer; color: #666; padding: 4px; border-radius: 4px; }
.header-collapse-btn:hover { background: #f0f0f0; }
/* padding-bottom 为全局「快速抄表」悬浮按钮（v1.1.177）留出避让空间：
   FAB 是 position:fixed，会浮在滚动内容之上，不留白会永久遮挡列表最后一行（尤其是分页控件） */
.page-body { flex: 1; padding: 20px; padding-bottom: 76px; overflow-y: auto; overscroll-behavior: contain; }
/* v1.1.179 报修页内联提示（如"在租租客"） */
.hint { font-size: 12px; color: #909399; line-height: 1.6; margin-top: 4px; }

/* ==================== 搜索栏 ==================== */
.search-bar { background: #fff; padding: 18px 20px; border-radius: 8px; margin-bottom: 16px; }
.search-bar .el-form--inline .el-form-item { margin-right: 16px; margin-bottom: 8px; align-items: center; }
.search-bar .el-form-item:last-child { margin-bottom: 0; }

/* ==================== 表格容器 ==================== */
.table-card { background: #fff; padding: 20px; border-radius: 8px; }
.table-card .el-table { width: 100%; }
/* 表格横向滚动容器（移动端自动出现滚动条） */
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ==================== 仪表盘 ==================== */
.dashboard-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 20px; }
.stat-card {
    background: #fff; border-radius: 8px; padding: 20px; display: flex;
    align-items: center; gap: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.stat-icon { width: 56px; height: 56px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 28px; }
.stat-icon.blue { background: #e6f4ff; color: #409EFF; }
.stat-icon.green { background: #e6f9ee; color: #67C23A; }
.stat-icon.orange { background: #fef0e6; color: #E6A23C; }
.stat-icon.red { background: #fde8e8; color: #F56C6C; }
.stat-info h3 { font-size: 28px; font-weight: bold; color: #333; }
.stat-info p { font-size: 13px; color: #999; margin-top: 4px; }

.dashboard-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.dashboard-panel { background: #fff; border-radius: 8px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
.panel-title { font-size: 16px; font-weight: bold; color: #333; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid #f0f0f0; }

/* ==================== 移动端遮罩 ==================== */
.mobile-overlay {
    position: fixed; top: 0; left: 0; width: 100%; height: 100%;
    background: rgba(0,0,0,0.5); z-index: 998;
    display: none;
}
.mobile-overlay.visible { display: block; }

/* ==================== 平板端 (768px - 1024px) ==================== */
@media (max-width: 1024px) {
    .sidebar { width: 64px; }
    .sidebar:not(.mobile-open) .menu-title,
    .sidebar:not(.mobile-open) .sidebar-footer { display: none; }
    .sidebar:not(.mobile-open) .menu-item { justify-content: center; padding: 14px 0; }
    .sidebar:not(.mobile-open) .menu-icon { margin-right: 0; }
    .sidebar:not(.mobile-open) .sidebar-logo { font-size: 14px; }

    .dashboard-cards { grid-template-columns: repeat(2, 1fr); }
    .dashboard-grid { grid-template-columns: 1fr; }
}

/* ==================== 移动端 (<768px) ==================== */
@media (max-width: 768px) {
    /* 登录页 */
    .login-container { padding: 15px; }
    .login-box { width: 100%; max-width: 400px; padding: 30px 24px; border-radius: 10px; }
    .login-box h2 { font-size: 20px; margin-bottom: 24px; }

    /* 侧边栏 → 抽屉 */
    .sidebar {
        position: fixed; top: 0; left: 0;
        /* 优先级：100dvh(动态可视区，最准) > --vh(JS 实测 innerHeight) > 100vh(兜底) */
        height: 100vh; height: calc(var(--vh, 1vh) * 100); height: 100dvh;
        width: 260px; transform: translateX(-100%); z-index: 999;
        overscroll-behavior: contain;
        padding-top: env(safe-area-inset-top);
        padding-bottom: env(safe-area-inset-bottom);
    }
    .sidebar.mobile-open { transform: translateX(0); box-shadow: 2px 0 12px rgba(0,0,0,0.3); }

    /* 主内容区 */
    .header { padding: 0 12px; height: 48px; }
    .header-left { gap: 6px; }
    .header-collapse-btn { font-size: 22px; padding: 6px; }
    .header .page-title { font-size: 14px; }
    .header-right { gap: 8px; }
    .header-right .user-name { display: none; }
    .header-right .el-button { padding: 5px 10px; font-size: 12px; }

    .page-body { padding: 12px; }

    /* 仪表盘 */
    .dashboard-cards { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .stat-card { padding: 14px; gap: 10px; }
    .stat-icon { width: 42px; height: 42px; border-radius: 8px; font-size: 20px; }
    .stat-info h3 { font-size: 22px; }
    .stat-info p { font-size: 11px; }
    .dashboard-grid { grid-template-columns: 1fr; gap: 10px; }
    .dashboard-panel { padding: 14px; }

    /* 搜索栏 - 纵向排列 */
    .search-bar { padding: 12px; margin-bottom: 10px; border-radius: 6px; }
    .search-bar .el-form--inline { display: flex; flex-wrap: wrap; }
    .search-bar .el-form--inline .el-form-item {
        display: flex !important; margin-right: 0 !important; margin-bottom: 8px;
        width: 100%; align-items: center;
    }
    .search-bar .el-form--inline .el-form-item .el-form-item__content {
        flex: 1; margin-left: 0 !important;
    }
    .search-bar .el-form--inline .el-form-item .el-input,
    .search-bar .el-form--inline .el-form-item .el-select {
        width: 100% !important;
    }
    .search-bar .el-form--inline .el-form-item .el-button { margin-top: 4px; }
    .search-bar .el-form-item:has(.el-button) { width: auto; margin-right: 8px !important; }

    /* 表格容器 */
    .table-card { padding: 10px; border-radius: 6px; overflow-x: auto; -webkit-overflow-scrolling: touch; }

    /* 表格 - 紧凑+水平滚动 */
    .table-card .el-table { font-size: 13px; min-width: 600px; }
    .table-card .el-table .cell { padding: 0 6px; white-space: nowrap; }
    .table-card .el-table th .cell, .table-card .el-table td .cell { padding: 0 4px; }
    .table-card .el-table th, .table-card .el-table td { padding: 8px 0; }
    .table-card .el-button--small { padding: 5px 8px; font-size: 12px; }
    .table-card .el-tag--small { padding: 0 6px; font-size: 11px; }

    /* 移动端：操作列（预览/编辑/删除等）固定右列，2x2 网格按钮，保证始终可见、不被裁剪 */
    .el-table__fixed-right { box-shadow: -3px 0 8px rgba(0,0,0,0.06); }
    .el-table__fixed-right,
    .el-table__fixed-right .el-table__cell { width: 92px !important; }
    .el-table__fixed-right .el-table__fixed-header-wrapper,
    .el-table__fixed-right .el-table__fixed-body-wrapper { width: 92px !important; }
    .table-card .el-table td .cell,
    .table-card .el-table th .cell { min-height: 54px; line-height: 54px; }
    .el-table__fixed-right .cell {
        display: grid !important; grid-template-columns: 1fr 1fr; gap: 4px;
        align-content: center; line-height: normal !important; min-height: 54px;
    }
    .el-table__fixed-right .el-button--small { width: 100%; margin: 0 !important; padding: 4px 0; }
    /* 保证数据列可横向滑动以查看完整信息 */
    .table-card .el-table__body-wrapper { -webkit-overflow-scrolling: touch; }
    .table-card .el-table .el-scrollbar__bar.is-horizontal { height: 8px; }
    .table-card .el-table .el-scrollbar__bar.is-horizontal > div { background: #c0c4cc; }

    /* 弹窗 */
    .el-dialog { width: 95% !important; margin-top: 10vh !important; }
    .el-dialog__body { padding: 15px; }

    /* 表单：移动端改为「label 顶部左对齐 + 控件整行占满」，避免右对齐 label 挤压控件导致内容看不全 */
    /* 覆盖 Element Plus 默认 label-position="right" 的右对齐行为：用 grid 让 label 占满整行并左对齐 */
    .el-form:not(.el-form--inline) .el-form-item,
    .el-form--label-top .el-form-item {
        display: grid !important;
        grid-template-columns: 1fr;
        align-items: stretch !important;
    }
    /* label 整行显示、左对齐、清除固定宽度（覆盖行内 label-width=220px 等写死值） */
    .el-form:not(.el-form--inline) .el-form-item__label,
    .el-form--label-top .el-form-item__label {
        width: auto !important;
        max-width: 100% !important;
        text-align: left !important;
        justify-content: flex-start !important;
        margin-bottom: 4px;
        line-height: 1.4 !important;
        padding: 0 !important;
    }
    /* 内容区占满整行，控件 100% 宽，不再被右侧 label 挤压 */
    .el-form:not(.el-form--inline) .el-form-item__content,
    .el-form--label-top .el-form-item__content {
        width: 100% !important;
        margin-left: 0 !important;
    }
    .el-form:not(.el-form--inline) .el-form-item__content .el-input,
    .el-form:not(.el-form--inline) .el-form-item__content .el-select,
    .el-form:not(.el-form--inline) .el-form-item__content .el-input-number,
    .el-form:not(.el-form--inline) .el-form-item__content .el-date-editor,
    .el-form:not(.el-form--inline) .el-form-item__content .el-textarea,
    .el-form:not(.el-form--inline) .el-form-item__content > .el-cascader {
        width: 100% !important;
    }
    /* 搜索栏/工具栏（inline 表单）保持横向换行，但每个表单项整行占满，控件 100% 宽（已在上方 .search-bar 处理，这里兜底） */
    .search-bar .el-form--inline .el-form-item .el-form-item__label { text-align: left !important; }

    /* 分页 */
    .el-pagination { font-size: 12px; flex-wrap: wrap; justify-content: center; }
    .el-pagination button, .el-pager li { min-width: 28px; height: 28px; line-height: 28px; }

    /* 描述列表 */
    .el-descriptions { --el-descriptions-item-bordered-label-background: #fafafa; }
    .el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell {
        font-size: 12px; padding: 8px 6px;
    }
}

/* ==================== 超小屏 (<400px) ==================== */
@media (max-width: 400px) {
    .dashboard-cards { grid-template-columns: 1fr; }
    .stat-icon { width: 38px; height: 38px; font-size: 18px; }
    .stat-info h3 { font-size: 20px; }
}

/* ==================== 平板横屏优化 ==================== */
@media (min-width: 769px) and (max-width: 1024px) and (orientation: landscape) {
    .sidebar { width: 200px; }
    .sidebar .menu-title, .sidebar .sidebar-footer { display: block !important; }
    .sidebar .menu-item { justify-content: flex-start; padding: 12px 16px; }
    .sidebar .menu-icon { margin-right: 8px; }
}

/* ==================== 照片上传（租客证件照/人像） ==================== */
.photo-uploader { display: flex; flex-direction: column; gap: 6px; }
.photo-preview {
    position: relative; width: 160px; max-width: 100%; height: 100px; border-radius: 8px;
    overflow: hidden; border: 1px solid #ebeef5; background: #f5f7fa;
}
.photo-preview img { width: 100%; height: 100%; object-fit: cover; cursor: pointer; display: block; }
.photo-preview .photo-remove { position: absolute; top: 4px; right: 4px; }
.photo-placeholder {
    width: 160px; max-width: 100%; height: 150px; border: 1px dashed #c0c4cc; border-radius: 8px;
    background: #fafafa; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 4px; color: #909399; cursor: pointer; transition: all .2s; padding: 8px;
}
.photo-placeholder:hover { border-color: #409EFF; color: #409EFF; }
.frame-svg { width: 86px; height: auto; max-height: 72px; opacity: .85; }
.frame-svg--portrait { width: 66px; }
.photo-frame-label { font-size: 13px; font-weight: 500; color: #606266; }
.photo-frame-hint { font-size: 11px; color: #c0c4cc; }
.photo-tip { font-size: 12px; color: #a8abb2; }
@media (max-width: 768px) {
    .photo-preview, .photo-placeholder { width: 100%; height: 150px; }
}

/* ============ 合同签署面板 ============ */
.sign-panel { padding: 4px 2px; }
.sign-row { display: flex; gap: 16px; flex-wrap: wrap; }
.sign-box { flex: 1; min-width: 260px; }
.sign-title { font-size: 13px; color: #606266; margin-bottom: 6px; font-weight: 600; display: flex; align-items: center; justify-content: space-between; }
.sign-title-ops { display: inline-flex; gap: 10px; font-weight: 400; font-size: 13px; }
.sign-tag { font-size: 11px; color: #909399; font-weight: 400; background: #f0f2f5; border-radius: 4px; padding: 1px 6px; margin-left: 6px; }
.sign-canvas { width: 100%; height: 160px; border: 1px dashed #c0c4cc; border-radius: 6px; background: #fff; touch-action: none; cursor: crosshair; }
.sign-canvas.readonly { cursor: default; border-style: solid; border-color: #e4e7ed; background: #fafafa; }
.sign-actions { margin-top: 8px; display: flex; align-items: center; gap: 8px; }
.sign-done { color: #67c23a; font-size: 13px; }
.gen-bar { margin: 16px 0 8px; text-align: center; }
.gen-bar.center, .pdf-links.center, .qr-zone.center { text-align: center; }
.pdf-links { text-align: center; padding-top: 12px; border-top: 1px solid #ebeef5; display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 24px; }
.pdf-links .pdf-link { display: inline-block; padding: 6px 4px; }
.qr-zone { background: #f7f8fa; border-radius: 8px; padding: 12px; margin-bottom: 6px; }
.qr-box { margin-top: 12px; text-align: center; }
.qr-img { width: 140px; height: 140px; background: #fff; border: 1px solid #ebeef5; border-radius: 6px; }
.qr-tip { font-size: 12px; color: #909399; margin-top: 6px; }
.qr-links { margin-top: 6px; display: inline-flex; gap: 16px; }
.sign-state { font-size: 13px; color: #606266; margin: 4px 0 8px; }
.sign-state b { margin-left: 4px; }
.sign-state b.st-none { color: #c0c4cc; }
.sign-state b.st-wait { color: #e6a23c; }
.sign-state b.st-signed { color: #409eff; }
.sign-state b.st-done { color: #67c23a; }
/* 房东端：待租客签/待确认时持续旋转等待图标 */
.st-spin { display:inline-block; width:14px; height:14px; margin-right:6px; vertical-align:-2px;
    border:2px solid #e3e7ee; border-top-color:#e6a23c; border-radius:50%; animation:stspin 0.9s linear infinite; }
@keyframes stspin { to { transform:rotate(360deg); } }

/* ============ 数据库结构检测与修复 ============ */
.schema-card { border: 1px solid #ebeef5; box-shadow: 0 2px 12px rgba(64,158,255,0.06); }
/* 环境自检：部署规则片段代码块 */
.code-block {
    background: #1e1e1e; color: #d4d4d4; padding: 14px 16px; border-radius: 8px; margin: 0;
    font-family: "Consolas", "Courier New", monospace; font-size: 12.5px; line-height: 1.6;
    white-space: pre-wrap; word-break: break-all; max-height: 360px; overflow: auto;
}
/* 环境自检：片段上方说明卡（与代码块分离，护眼醒目） */
.snippet-guide {
    background: linear-gradient(180deg, #eaf6ec 0%, #e3f1e8 100%);
    border: 1px solid #b9dcbf;
    border-left: 4px solid #2e9e5b;
    border-radius: 8px;
    box-shadow: 0 2px 10px rgba(46,158,91,0.10);
    padding: 12px 16px;
    margin: 0 0 12px;
}
.snippet-guide-text {
    margin: 0; padding: 0; border: 0; background: transparent;
    font-family: -apple-system, "Microsoft YaHei", "PingFang SC", sans-serif;
    font-size: 12.5px; line-height: 1.75; color: #1f5132;
    white-space: pre-wrap; word-break: break-word;
}
/* 环境自检：三个设置项说明卡仍用护眼样式（见下方 .snippet-guide） */
/* 注：设置项区块/分割线已改为 js/app.js 内联样式，避免 CSS 缓存导致不可见 */
.schema-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap; }
.schema-title { display: flex; gap: 14px; align-items: center; }
.schema-ico {
    width: 52px; height: 52px; border-radius: 12px; background: linear-gradient(135deg, #409EFF, #66b1ff);
    color: #fff; font-size: 26px; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
    box-shadow: 0 4px 12px rgba(64,158,255,0.3);
}
.schema-title h3 { font-size: 18px; color: #303133; }
.schema-sub { margin: 4px 0 0; font-size: 13px; color: #909399; }
.schema-actions { display: flex; gap: 10px; flex-shrink: 0; }
.schema-body { margin-top: 18px; }
.schema-stat { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
.stat-item {
    background: #f7f8fa; border: 1px solid #ebeef5; border-radius: 10px; padding: 16px 12px; text-align: center;
    transition: all .2s;
}
.stat-item.ok { background: #f0f9eb; border-color: #c2e7b0; }
.stat-item.bad { background: #fef0f0; border-color: #fbc4c4; }
.stat-num { font-size: 26px; font-weight: 700; color: #303133; line-height: 1.1; }
.stat-item.ok .stat-num { color: #67c23a; }
.stat-item.bad .stat-num { color: #f56c6c; }
.stat-label { font-size: 12px; color: #909399; margin-top: 6px; }
.tb-name { font-weight: 600; color: #303133; font-family: 'Consolas','Menlo',monospace; font-size: 13px; }
.tb-comment { font-size: 11px; color: #a8abb2; margin-top: 2px; }
.miss-tag { margin: 3px 4px 0 0; font-family: 'Consolas','Menlo',monospace; }
.miss-tag .miss-type { color: #909399; font-weight: 400; font-size: 11px; }
.all-ok { color: #67c23a; font-size: 13px; }
.err-txt { color: #f56c6c; font-size: 13px; }
.schema-empty { margin-top: 18px; padding: 30px; text-align: center; color: #909399; background: #f7f8fa; border-radius: 10px; border: 1px dashed #dcdfe6; }
@media (max-width: 768px) {
    .schema-stat { grid-template-columns: repeat(2, 1fr); }
    .schema-head { flex-direction: column; }
    .schema-actions { width: 100%; }
    .schema-actions .el-button { flex: 1; }
}

/* ============ 设置页横向分页 ============ */
.settings-tabs { background: #fff; padding: 8px 20px 20px; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.04); }
.settings-tabs .el-tabs__header { margin: 0 0 18px; }
.settings-tabs .el-tabs__nav-wrap::after { height: 1px; background: #ebeef5; }
.settings-tabs .el-tabs__item { height: 48px; line-height: 48px; font-size: 15px; font-weight: 500; }
.settings-tabs .el-tabs__item.is-active { font-weight: 600; }
.settings-tabs .tab-label { display: inline-flex; align-items: center; gap: 6px; }
.settings-tabs .tab-label .el-icon { font-size: 16px; }
.settings-tabs .el-tabs__content { padding-top: 4px; }
@media (max-width: 768px) {
    .settings-tabs { padding: 6px 12px 14px; }
    .settings-tabs .el-tabs__item { height: 42px; line-height: 42px; font-size: 14px; }
}

/* 默认房东签名预览（设置页） */
.sign-prev { max-width: 160px; max-height: 60px; border: 1px solid #dcdfe6; border-radius: 4px; background: #fff; object-fit: contain; vertical-align: middle; }
.avatar-uploader .el-upload { border: 1px dashed #c0c4cc; border-radius: 6px; cursor: pointer; width: 160px; height: 60px; display: flex; align-items: center; justify-content: center; background: #fafafa; }
.avatar-uploader .el-upload:hover { border-color: #409eff; }
.avatar-uploader-icon { font-size: 22px; color: #8c939d; }

/* 默认房东手写签名板（与签署页一致） */
.sign-pad-wrap { display: flex; flex-direction: column; }
.sign-pad-box { width: 300px; height: 140px; border: 1px solid #c0c4cc; border-radius: 6px; background: #fff; position: relative; overflow: hidden; }
.sign-pad { display: block; width: 300px; height: 140px; touch-action: none; cursor: crosshair; }
.sign-pad-ph { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #b0b4bb; font-size: 13px; pointer-events: none; }
.sign-pad-ops { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

/* ============ 手写签名板 ============ */
/* 签字操作按钮：图标化（✗重签 / ✓完成），简化首屏，避免租客滚动 */
.icon-btn { min-width: 96px; font-size: 16px; font-weight: 700; padding: 10px 16px; }
.char-ops { display: flex; gap: 12px; margin-top: 14px; flex-wrap: wrap; }
.btn { padding: 11px 20px; font-size: 15px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; touch-action: manipulation; -webkit-appearance: none; }
.btn.primary { background: #16324f; color: #fff; }
.btn.primary:disabled { background: #c0c4cc; }
.btn.ghost { background: #eef0f3; color: #555; }

/* ============ 逐字签名网格（v1.1.126）+ 字帖描红式（v1.1.127） ============
 * 需求：房东/租客姓名按字拆分逐字签名，每字一个格子，保存自动合并成行。
 *      v1.1.127 升级为「字帖描红式」：格内印半透明背景字，照描，描到约55%自动跳下一格。
 * 兼容性：租客端 sign.html 与 SPA(index.html) 共用本样式表，故统一在此定义。
 */
.char-host { width: 100%; }
.char-host .muted { margin: 4px 0 8px; color: #909399; font-size: 13px; }
.char-grid { display: flex; flex-wrap: nowrap; gap: 14px; align-items: flex-start; overflow-x: auto; padding-bottom: 6px; }
.char-cell { display: flex; flex-direction: column; align-items: center; width: 220px; position: relative; flex: 0 0 auto; }
.char-label { font-size: 13px; color: #909399; margin-bottom: 6px; z-index: 2; }
/* canvas 包裹层：相对定位，背景字层与 canvas 都在其内，背景字绝对定位铺满、canvas 透明叠上层 */
.char-canvas-wrap { position: relative; width: 300px; height: 320px; max-width: 92vw; }
.char-canvas { width: 300px; height: 320px; max-width: 92vw; height: auto; aspect-ratio: 300 / 320; border: 1px dashed #c0c4cc; border-radius: 8px; background: transparent; touch-action: none; cursor: crosshair; position: relative; z-index: 2; }
/* 描红背景字层：绝对定位铺满 canvas-wrap，半透明；必须位于 canvas 之上（z-index 高于 canvas），
   且 canvas 保持透明，这样背景字可见、用户描红笔迹（画在透明 canvas 上）盖在字上方 —— 即描红效果。
   落库合成时 canvas 透明只含笔迹，背景字层不参与，故导出图片无背景字（符合要求）。 */
.char-trace {
    position: absolute; left: 0; top: 0; width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: center;
    font-family: "Microsoft YaHei","PingFang SC","Heiti SC",sans-serif;
    font-weight: 700;
    font-size: 280px; /* 仅兜底：实际由 JS syncTraceSize 按画布尺寸动态设置，撑满方框 */
    line-height: 1;
    color: rgba(22,50,79,0.18); pointer-events: none; user-select: none; z-index: 3;
    border: 1px solid #bcd; border-radius: 8px; background: transparent;
    overflow: hidden;
}
.char-hint { margin-top: 6px; font-size: 15px; color: #303133; font-weight: 600; z-index: 2; }
/* 设置页默认房东签名：逐字网格容器需撑开固定高度，避免被 .sign-pad-box 裁切 */
.sign-pad-box:has(.char-host) { width: 100%; height: auto; min-height: 140px; overflow: visible; }

/* 字帖描红式（v1.1.127）：背景字由 JS 以半透明绘制在 canvas 上的 DOM 层（.char-trace，z-index 高于 canvas），
   这里仅强化格子视觉（实线框 + 居中提示）；canvas 必须保持透明，否则不透明底会挡住下层/上层背景字 */
.char-grid.tracing .char-canvas { border-style: solid; border-color: #bcd; background: transparent; }
/* 移动端横屏：让逐字格横向铺满，获得最大书写区域 */
@media (max-width: 820px) and (orientation: landscape) {
    .char-grid.tracing { gap: 8px; justify-content: center; }
    .char-cell { width: 26vw; max-width: 220px; }
    .char-canvas { width: 26vw; max-width: 220px; height: 30vw; max-height: 250px; }
    .char-grid.tracing .char-label { font-size: 12px; }
}
/* PC 端悬浮框：描红网格在弹框内横向排布、可内部滚动，保证单格足够大 */
.char-grid.tracing { max-width: 100%; overflow-x: auto; padding-bottom: 4px; }

/* 合同预览（step3）：打印版 PDF 原版（iframe 滚动到底才显示下一步） */
/* 标题行内横屏提示（不占独立行，把高度让给预览区） */
.step-panel[data-step="3"] .card h3 { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
.doc-tip-inline { font-size: 11px; font-weight: 400; color: #b8860b; background: #fffbe6; border: 1px solid #f0e6b6; border-radius: 6px; padding: 2px 6px; white-space: nowrap; }
.step-panel[data-step="3"] .card .sub { margin-bottom: 8px; font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.doc-tabs { display: flex; flex: none; flex-wrap: nowrap; align-items: center; gap: 4px; margin: 0; border-bottom: 1px solid #e6e9ee; padding-bottom: 5px; }
.doc-tab { padding: 5px 7px; font-size: 12px; border: 1px solid #d6dbe2; border-radius: 7px; background: #f6f8fa; color: #555; font-weight: 600; cursor: pointer; white-space: nowrap; }
.doc-tab.active { background: #16324f; color: #fff; border-color: #16324f; }
.doc-read-progress { margin-left: auto; font-size: 11px; color: #16324f; font-weight: 600; white-space: nowrap; padding: 3px 6px; background: #eef4fb; border-radius: 6px; }
/* 预览区域撑满外层宽度：去除多余 padding/边距 */
/* step3 合同预览（sign.html）：预览区自身定高 + 内部滚动，保证 tabs/提示/按钮固定不动、
   页面整体不滚动（单屏）。不依赖 :has()（部分移动浏览器不支持）与 flex 链
   （doc-panel 内联 display:block 会打断 flex 继承），calc 定高最稳。 */
.step-panel[data-step="3"] .card { padding: 12px 12px 0; flex: 1; min-height: 0; display: flex; flex-direction: column; }
.contract-view { width: 100%; margin: 0; flex: 1; min-height: 0; display: flex; flex-direction: column; }
.doc-panel { width: 100%; margin: 6px 0 0; padding: 0; flex: 1; min-height: 0; display: flex; flex-direction: column; }
.doc-tip { display: none; } /* 提示已并入标题行（.doc-tip-inline），此元素不再生成 */
/* 预览区：flex 撑满剩余可用高度（flex 链：body→#app→step-panel→card→contract-view→doc-panel），
   只在自身内部滚动；不再用 calc 猜预留高度，无上下空白 */
.doc-canvas-host {
    width: 100%; margin: 0 auto;
    flex: 1; min-height: 160px;
    box-sizing: border-box;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    background: #fff; border: 1px solid #e6e9ee; border-radius: 8px; padding: 8px;
    display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.doc-canvas-host .pdf-page { width: 100%; height: auto; box-shadow: 0 1px 3px rgba(0,0,0,.12); background: #fff; }
.doc-canvas-host .pdf-loading { padding: 40px 12px; color: #888; font-size: 14px; text-align: center; }
/* 下一步按钮位于预览区上方；容器固定预留高度，解锁显示前后布局不跳动 */
.contract-next-wrap { min-height: 50px; flex: none; display: flex; align-items: center; justify-content: center; margin: 4px 0 0; }
.contract-next-wrap .btn { width: 100%; max-width: 360px; }
/* 横屏矮屏：隐藏说明文字（提示已在标题行内，不占高度），预览区由 flex 自动撑满 */
@media (orientation: landscape) and (max-height: 520px) {
    .step-panel[data-step="3"] .card h3 { margin-bottom: 2px; font-size: 15px; }
    .step-panel[data-step="3"] .card .sub { display: none; }
    .contract-next-wrap { min-height: 42px; margin: 4px 0 2px; }
    .doc-canvas-host { min-height: 120px; }
}

/* ============ 悬浮弹框高度约束（v1.1.86） ============
 * 需求语义：弹框高度不得超过父框（视口/overlay），内容超出时在【弹框内部】滚动，
 *            即内容在弹框内下移，而非整个弹框在父框内下移或溢出。
 * 实现：.el-dialog 用 flex 纵向布局 + max-height 锁死总高；
 *       header/footer 固定不缩，body 占满剩余空间并 overflow-y:auto 出内部滚动条。
 */
.el-dialog {
    display: flex;
    flex-direction: column;
    max-height: 90vh;          /* 不超过父框高度，桌面端留上下安全边距 */
    margin: 5vh auto !important; /* 顶部留白 + 水平居中；被 overlay flex 居中时顶部留白仍生效 */
}
.el-dialog__header { flex-shrink: 0; }
.el-dialog__body {
    flex: 1 1 auto;
    min-height: 0;             /* 关键：允许 flex 子项收缩，overflow 才能生效出滚动条 */
    overflow-y: auto;
    overscroll-behavior: contain; /* 内部滚到顶/底不再链动背景 */
    -webkit-overflow-scrolling: touch;
}
.el-dialog__footer { flex-shrink: 0; }
/* 全屏模式（移动端 isMobileDialog）不约束高度，由 Element 自适应铺满 */
.el-dialog.is-fullscreen { max-height: none; display: flex; }
.el-dialog.is-fullscreen .el-dialog__body { overflow-y: auto; }
/* 移动端在窄屏内同样锁高，避免撑破视口；width 已在媒体查询设为 95% */
@media (max-width: 768px) {
    .el-dialog { max-height: 92vh; margin-top: 4vh !important; }
}

/* ============ 表单行内元素垂直居中（v1.1.87） ============
 * 需求：同一行内的 label / 文本框 / 按钮等控件，高度不一致时一律垂直居中对齐，避免高低参差。
 * 关键：Element 默认 .el-form-item 为 align-items:flex-start（顶部对齐）且部分布局用更高
 *       优先级覆盖，故此处用 !important 强制压过；同时覆盖【未包在 form-item 内的裸按钮/文本】。
 */
/* 1) 所有表单项：自身改为 flex 容器，label+content 严格居中；同时作为外层 flex 子项时行为可预测
 *    （探针实测：form-item 默认 display:block，作为 flex item 时 align-self:center 无法拉正最右按钮，
 *      改为 display:flex 后 flex item 定位精确，center 偏差消除） */
.el-form-item { display: flex !important; align-items: center !important; }
/* 2) 内容区（老 Element UI 默认为 block，align-items 不生效）→ 必须显式 display:flex 才能让内部控件垂直居中 */
.el-form-item__content { display: flex !important; align-items: center !important; flex-wrap: wrap; }
/* 3) label 文字自身垂直居中，避免多行 label 偏上 */
.el-form-item__label { display: inline-flex !important; align-items: center !important; }
/* 4) 内联表单（搜索栏/工具栏等）整行强制对齐：
 *    让 .el-form--inline 本身成为 flex 容器并 align-items:center，所有子 form-item
 *    （无论含输入框还是纯按钮）在父容器中一律纵向居中 → 同一行水平排列时上下中线对齐。
 *    Element Plus 默认 form-item 是 inline-flex，但父级若不是 flex+align-items:center，
 *    inline 子项之间靠 vertical-align 对齐，纯按钮与含输入框的 form-item 仍会差几像素。
 *    ⚠️ 必须 !important 压过 Element 默认 .el-form--inline 的 display:inline 行为。 */
.el-form--inline { display: flex !important; flex-wrap: wrap; align-items: center !important; }
/* 探针定位(v1.1.93)：Element Plus 默认 .el-form-item:last-child{margin-bottom:0}，
   导致最后一个纯按钮 form-item 的 margin-bottom=0，而前一个有 8px。
   在 flex align-items:center 按 margin-box 中心对齐时，二者中线差 4px（最右按钮偏低）。
   强制统一 margin-bottom:8px!important 并压过 :last-child，消除该偏差。 */
.el-form--inline .el-form-item,
.el-form--inline .el-form-item:last-child { align-items: center !important; align-self: center !important; margin-bottom: 8px !important; }
.search-bar .el-form .el-form-item,
.el-form .el-form-item { align-self: center !important; }
/* 消除按钮在 block/flex 混合下的 valign 残留偏移 */
.el-form-item .el-button { vertical-align: middle !important; margin-top: 0 !important; }
/* 5) 兜底：未包在 form-item 内的裸按钮（如直接并排的 el-button、按钮旁文本）——
 *    强制按钮与相邻内联元素中线对齐，解决"el-button--success/--default 高低不一"。 */
.el-button { vertical-align: middle !important; }
.el-button + span, span + .el-button,
.el-button + label, label + .el-button,
.el-button + .el-input, .el-input + .el-button,
.el-button + .el-select, .el-select + .el-button,
.el-button + b, b + .el-button,
.el-button + i, i + .el-button,
.el-button + a, a + .el-button { vertical-align: middle !important; }
/* 6) 任意内联文本/控件混排行，统一中线对齐（不依赖 form-item 结构） */
span, label, b, i, a, .el-input__inner, input, select, textarea { vertical-align: middle; }

/* 7) 裸按钮行工具类：直接包裹并排按钮/控件，整行 flex 垂直居中（根治高低不一） */
.btn-row { display: flex !important; align-items: center !important; gap: 8px; flex-wrap: wrap; }
/* header 左右区兜底居中（用户名文本 + 退出按钮等混排） */
.header-right, .header-left { align-items: center; }

/* ==================== 仪表防重复确认框（customClass: meter-dup-confirm） ====================
 * 产品约定：默认走「否」，只有特殊情况才走「是」，避免习惯性点右侧主按钮导致误添加。
 *   右侧 大号绿色按钮 = 「否」（cancelButton，安全默认项；回车/ESC/点关闭均落在此）
 *   左侧 小号白底按钮 = 「是」（confirmButton，需用户主动去找并点击）
 * Element Plus 的 DOM 顺序固定为 [cancelButton][confirmButton]，此处用 order 对调视觉位置。
 */
.meter-dup-confirm .el-message-box__btns{
    display:flex !important;
    justify-content:flex-end !important;
    align-items:center !important;
    gap:10px;
}
.meter-dup-confirm .el-message-box__btns .mb-btn-yes{ order:1 !important; }  /* 「是」→ 左侧 */
.meter-dup-confirm .el-message-box__btns .mb-btn-no { order:2 !important; }  /* 「否」→ 右侧 */
/* 「否」：安全默认项 —— 大号绿色主按钮 */
.meter-dup-confirm .el-message-box__btns .mb-btn-no{
    min-width:120px !important;
    font-size:15px !important;
    padding:10px 22px !important;
}
/* 「是」：需主动选择的次要项 —— 小号白底按钮 */
.meter-dup-confirm .el-message-box__btns .mb-btn-yes{
    min-width:96px !important;
    font-size:13px !important;
    padding:8px 16px !important;
    background:#fff !important;
    border-color:#DCDFE6 !important;
    color:#606266 !important;
}

/* ==================== 快速抄表悬浮按钮（v1.1.177） ====================
 * 层级取值依据（避免与既有组件打架）：
 *   .mobile-overlay 遮罩 = 998 ／ .sidebar 侧边栏与移动端抽屉 = 999 ／ Element Plus 弹窗 = 2000+
 *   → FAB 取 1000：高于侧边栏与遮罩，低于弹窗（弹窗打开时按钮被遮住，不会穿透点击）。
 */
.qr-fab {
    position: fixed;
    right: 24px;
    bottom: calc(24px + env(safe-area-inset-bottom));
    z-index: 1000;
    display: flex;
    align-items: center;
    gap: 6px;
    height: 48px;
    padding: 0 18px;
    border: none;
    border-radius: 24px;
    background: linear-gradient(135deg, #409eff, #2f7de1);
    color: #fff;
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 6px 16px rgba(64, 158, 255, .4);
    transition: transform .15s, box-shadow .15s;
    -webkit-tap-highlight-color: transparent;
}
.qr-fab:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(64, 158, 255, .5); }
.qr-fab:active { transform: translateY(0); }
.qr-fab-icon { font-size: 18px; line-height: 1; }
.qr-fab-text { white-space: nowrap; }

/* —— 弹窗：步骤1 房间列表 —— */
.qr-search { margin-bottom: 10px; }
.qr-filter { margin-bottom: 10px; }
.qr-room-list { max-height: 46vh; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.qr-room-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
    margin-bottom: 8px;
    background: #f7f9fc;
    border: 1px solid #ebeef5;
    border-radius: 8px;
    cursor: pointer;
}
.qr-room-item:active { background: #ecf5ff; }
.qr-room-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.qr-room-name { font-size: 15px; font-weight: 600; color: #303133; }
.qr-room-tenant { font-size: 12px; color: #909399; }
.qr-room-side { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
.qr-room-meters { font-size: 12px; color: #67c23a; }
.qr-room-arrow { font-size: 18px; color: #c0c4cc; }
.qr-empty { padding: 24px 8px; text-align: center; color: #909399; font-size: 13px; }

/* —— 弹窗：步骤2 读数录入 —— */
.qr-back { padding-left: 0 !important; margin-bottom: 8px; }
.qr-alert { margin-bottom: 10px; }
.qr-meter-row { padding: 12px 0; border-bottom: 1px dashed #ebeef5; }
.qr-meter-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.qr-meter-title { font-size: 15px; font-weight: 600; color: #303133; }
.qr-meter-title small { margin-left: 8px; font-weight: 400; font-size: 12px; color: #909399; }
.qr-meter-prev { font-size: 12px; color: #909399; white-space: nowrap; }
.qr-meter-body { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.qr-input { width: 190px; flex: 1 1 190px; }
.qr-calc { display: flex; gap: 14px; font-size: 13px; color: #606266; white-space: nowrap; }
.qr-calc b { color: #e6a23c; }
.qr-form { margin-top: 14px; display: flex; flex-direction: column; gap: 10px; }
.qr-form-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.qr-label { width: 64px; flex-shrink: 0; font-size: 13px; color: #606266; }
.qr-tip { font-size: 12px; color: #c0c4cc; }

/* ==================== 顶部通知铃铛（v1.1.185） ==================== */
.notify-popover { padding: 0 !important; }
.notify-title { padding: 12px 16px 8px; font-weight: 600; font-size: 14px; color: #303133; border-bottom: 1px solid #ebeef5; }
.notify-item { display: flex; justify-content: space-between; align-items: center; padding: 11px 16px; cursor: pointer; font-size: 13px; color: #606266; border-bottom: 1px solid #f2f3f5; }
.notify-item:last-child { border-bottom: none; }
.notify-item:hover { background: #f5f7fa; color: #16324f; }
.notify-empty { padding: 24px 16px; text-align: center; color: #909399; font-size: 13px; }

/* —— 提交回执（逐表用量/金额 + 账单原因） —— */
.qr-receipt { margin-top: 12px; background: #f7f9fc; border-radius: 8px; padding: 10px 12px; }
.qr-receipt-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: baseline; font-size: 12px; padding: 3px 0; color: #606266; }
.qr-receipt-name { font-weight: 600; color: #303133; min-width: 130px; }
.qr-receipt-note { color: #909399; }

@media (max-width: 768px) {
    /* 手机上放大触控区并避开底部安全区（iPhone 手势条） */
    .qr-fab { right: 16px; bottom: calc(16px + env(safe-area-inset-bottom)); height: 52px; padding: 0 16px; }
    .qr-room-list { max-height: 52vh; }
    .qr-input { width: 100%; flex: 1 1 100%; }
    .qr-meter-body { gap: 8px; }
    .qr-receipt-name { min-width: 100%; }
}

/* 报表导出页（v1.1.181） */
.page-title { font-size: 18px; font-weight: 600; margin: 0 0 16px; color: #16324f; }
.form-row { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.form-row .lbl { width: 72px; color: #606266; font-size: 14px; flex: none; }
.form-row .sep { color: #909399; }
.room-stat { margin-top: 14px; font-size: 14px; color: #1f2d3d; line-height: 1.8; }
.room-stat b { color: #16324f; }

