diff --git a/web/.eleventy.js b/web/.eleventy.js index 9e7f194..4dbb12b 100644 --- a/web/.eleventy.js +++ b/web/.eleventy.js @@ -4,7 +4,7 @@ module.exports = function(cfg) { // scan.html 面向消费者,独立维护,直接复制不经模板 cfg.addPassthroughCopy("scan.html"); - cfg.addPassthroughCopy("features"); + // features/ 已改为 .njk 模板,不再需要 passthrough return { dir: { diff --git a/web/assets/features-approval.css b/web/assets/features-approval.css new file mode 100644 index 0000000..b37da45 --- /dev/null +++ b/web/assets/features-approval.css @@ -0,0 +1,915 @@ +* { box-sizing: border-box; } +html, body { + margin: 0; padding: 0; + font-family: var(--font-sans); color: var(--fg-default); + background: var(--bg-surface); + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-feature-settings: "tnum" 1; +} +img, svg { display: block; max-width: 100%; } +a { color: inherit; text-decoration: none; } +button { font-family: inherit; cursor: pointer; } + +.btn { + display: inline-flex; align-items: center; gap: 8px; + height: 40px; padding: 0 18px; + border-radius: var(--radius-md); + font-size: var(--text-md); font-weight: 500; + border: 1px solid transparent; + transition: background var(--duration-fast) var(--ease-standard); + white-space: nowrap; +} +.btn-primary { background: var(--brand-500); color: #fff; } +.btn-primary:hover { background: var(--brand-600); } +.btn-secondary { background: var(--gray-0); color: var(--brand-900); border-color: var(--border-default); } +.btn-secondary:hover { background: var(--gray-50); border-color: var(--border-strong); } +.btn-ghost { background: transparent; color: var(--fg-default); } +.btn-ghost:hover { background: var(--gray-100); } +.btn-lg { height: 48px; padding: 0 24px; font-size: var(--text-lg); } +.btn .icon { width: 18px; height: 18px; } + +.container { max-width: 1280px; margin: 0 auto; padding: 0 32px; } +.section { padding: 96px 0; } +.eyebrow { + font-size: var(--text-xs); font-weight: 600; + letter-spacing: 0.12em; text-transform: uppercase; + color: var(--brand-500); margin: 0 0 12px; +} + +/* Top Nav */ +.topnav { position: sticky; top: 0; z-index: 50; background: rgba(255,255,255,0.85); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid var(--border-subtle); } +.topnav-inner { height: 64px; display: flex; align-items: center; justify-content: space-between; max-width: 1440px; margin: 0 auto; padding: 0 32px; } +.topnav-brand { display: flex; align-items: center; gap: 10px; } +.topnav-brand img { height: 32px; } +.topnav-links { display: flex; align-items: center; gap: 4px; font-size: var(--text-md); color: var(--gray-700); } +.topnav-links a { padding: 8px 14px; border-radius: var(--radius-md); transition: background var(--duration-fast) var(--ease-standard); } +.topnav-links a:hover { background: var(--gray-100); color: var(--brand-900); } +.topnav-links a.active { color: var(--brand-500); background: var(--brand-50); } +.topnav-cta { display: flex; gap: 10px; align-items: center; } + +/* Nav user dropdown */ +.nav-user { position: relative; } +.nav-user-btn { + display: flex; align-items: center; gap: 8px; + height: 36px; padding: 0 12px 0 8px; + border-radius: var(--radius-md); + border: 1px solid var(--border-default); + background: var(--gray-0); + font-size: var(--text-sm); color: var(--gray-800); + cursor: pointer; + transition: background var(--duration-fast) var(--ease-standard); +} +.nav-user-btn:hover { background: var(--gray-50); } +.nav-avatar { + width: 22px; height: 22px; border-radius: 50%; + background: var(--brand-500); color: #fff; + font-size: 11px; font-weight: 700; + display: flex; align-items: center; justify-content: center; + flex-shrink: 0; +} +.nav-user-btn .icon { width: 14px; height: 14px; color: var(--fg-muted); } +.nav-dropdown { + display: none; position: absolute; top: calc(100% + 8px); right: 0; + min-width: 200px; + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + padding: 6px; + z-index: 100; +} +.nav-dropdown.open { display: block; } +.nav-dropdown-info { + padding: 8px 10px 10px; + border-bottom: 1px solid var(--border-subtle); + margin-bottom: 6px; +} +.nav-dropdown-name { font-size: var(--text-sm); font-weight: 600; color: var(--brand-900); } +.nav-dropdown-role { font-size: 11px; color: var(--fg-muted); margin-top: 2px; } +.nav-dropdown a, .nav-dropdown button { + display: flex; align-items: center; gap: 8px; + width: 100%; padding: 8px 10px; + border-radius: var(--radius-md); + font-size: var(--text-sm); color: var(--gray-700); + background: none; border: none; text-align: left; cursor: pointer; + transition: background var(--duration-fast) var(--ease-standard); +} +.nav-dropdown a:hover, .nav-dropdown button:hover { background: var(--gray-50); color: var(--brand-900); } +.nav-dropdown .icon { width: 15px; height: 15px; color: var(--fg-muted); } +.nav-dropdown .logout { color: var(--danger-600); } +.nav-dropdown .logout .icon { color: var(--danger-400); } + +/* ==================================================================== + HERO + ==================================================================== */ +.feat-hero { + position: relative; overflow: hidden; + padding: 80px 0 72px; + background: + radial-gradient(900px 480px at 10% 30%, rgba(37, 99, 172, 0.06), transparent 60%), + radial-gradient(900px 480px at 90% 90%, rgba(139, 35, 49, 0.04), transparent 60%), + linear-gradient(180deg, #FBFCFD 0%, #FFFFFF 80%); + border-bottom: 1px solid var(--border-subtle); +} +.feat-hero-inner { + display: grid; + grid-template-columns: 1fr 1.2fr; + gap: 64px; + align-items: center; +} +.feat-breadcrumb { + display: flex; align-items: center; gap: 8px; + font-size: var(--text-sm); color: var(--fg-muted); + margin-bottom: 20px; +} +.feat-breadcrumb a { color: var(--fg-muted); } +.feat-breadcrumb a:hover { color: var(--brand-500); } +.feat-breadcrumb .icon { width: 14px; height: 14px; color: var(--gray-300); } +.feat-hero h1 { + font-size: 48px; line-height: 1.15; + letter-spacing: var(--tracking-cn-display); + color: var(--brand-900); margin: 0 0 18px; + font-weight: 700; +} +.feat-hero h1 em { + font-style: normal; color: var(--accent-500); +} +.feat-hero p.lead { + font-size: var(--text-xl); line-height: 1.6; + color: var(--gray-600); margin: 0 0 28px; +} +.feat-hero .actions { display: flex; gap: 12px; margin-bottom: 28px; } +.feat-hero .quick-stats { + display: grid; grid-template-columns: repeat(3, 1fr); + border-top: 1px solid var(--border-subtle); + padding-top: 20px; +} +.feat-hero .quick-stat-label { font-size: 11px; color: var(--fg-subtle); letter-spacing: 0.04em; } +.feat-hero .quick-stat-val { font-size: var(--text-xl); font-weight: 600; color: var(--brand-900); font-variant-numeric: tabular-nums; margin-top: 4px; } + +/* ==================================================================== + HERO STAMP / DOCUMENT VISUAL + ==================================================================== */ +.hero-doc-stack { + position: relative; + height: 520px; +} +.hero-doc { + position: absolute; + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + padding: 24px; + transform-origin: center; +} +.hero-doc-back-2 { + top: 36px; left: 24px; right: 64px; bottom: 64px; + transform: rotate(-2deg); + opacity: 0.6; + background: var(--gray-50); +} +.hero-doc-back-1 { + top: 18px; left: 12px; right: 80px; bottom: 80px; + transform: rotate(2deg); + opacity: 0.85; + background: var(--gray-25); +} +.hero-doc-main { + top: 0; left: 60px; right: 0; bottom: 60px; + box-shadow: var(--shadow-xl); +} +.hero-doc-head { + display: flex; justify-content: space-between; align-items: flex-start; + padding-bottom: 16px; + border-bottom: 1px solid var(--border-subtle); + margin-bottom: 16px; +} +.hero-doc-id { + font-family: var(--font-mono); font-size: var(--text-md); + color: var(--brand-500); font-weight: 600; +} +.hero-doc-meta { font-size: 11px; color: var(--fg-muted); margin-top: 4px; font-family: var(--font-mono); } +.hero-doc-status { + background: var(--success-50); color: var(--success-700); + font-size: 12px; font-weight: 600; + padding: 4px 12px; border-radius: var(--radius-pill); + display: inline-flex; align-items: center; gap: 4px; +} +.hero-doc-status .icon { width: 14px; height: 14px; } + +.hero-doc-row { + display: grid; grid-template-columns: 1fr 60px 80px; + padding: 8px 0; + border-bottom: 1px dashed var(--border-subtle); + font-size: var(--text-sm); + color: var(--gray-700); + font-variant-numeric: tabular-nums; +} +.hero-doc-row:last-of-type { border-bottom: 1px solid var(--border-default); } +.hero-doc-foot { + display: grid; grid-template-columns: 1fr 60px 80px; + padding-top: 10px; + font-weight: 600; + color: var(--brand-900); + font-size: var(--text-md); +} + +/* Stamp visual on hero */ +.hero-stamp { + position: absolute; + right: -10px; bottom: 20px; + width: 130px; height: 130px; + border-radius: 50%; + border: 3px solid var(--accent-500); + background: rgba(139, 35, 49, 0.04); + transform: rotate(-12deg); + display: grid; place-items: center; + z-index: 10; + box-shadow: 0 6px 18px rgba(139, 35, 49, 0.15); +} +.hero-stamp::before { + content: ''; + position: absolute; inset: 8px; + border-radius: 50%; + border: 1px solid var(--accent-500); +} +.hero-stamp svg.ring { position: absolute; inset: 0; width: 100%; height: 100%; } +.hero-stamp-core { + font-family: var(--font-sans); + color: var(--accent-500); + text-align: center; + font-weight: 700; + z-index: 1; +} +.hero-stamp-core .big { font-size: 22px; letter-spacing: 0.06em; } +.hero-stamp-core .sub { font-size: 9px; letter-spacing: 0.16em; margin-top: 2px; font-weight: 600; } +.hero-stamp-core .date { font-family: var(--font-mono); font-size: 10px; margin-top: 4px; color: var(--accent-700); font-weight: 500; } + +/* ==================================================================== + FEATURE BLOCKS — alternating + ==================================================================== */ +.feat-block { + padding: 96px 0; + border-bottom: 1px solid var(--border-subtle); +} +.feat-block:nth-child(even) { background: var(--gray-25); } +.feat-block-inner { + display: grid; + grid-template-columns: 5fr 7fr; + gap: 64px; + align-items: center; +} +.feat-block.reverse .feat-block-inner { grid-template-columns: 7fr 5fr; } +.feat-block.reverse .feat-text { order: 2; } +.feat-block.reverse .feat-visual { order: 1; } + +.feat-tag { + display: inline-flex; align-items: center; gap: 6px; + background: var(--brand-50); + color: var(--brand-700); + padding: 4px 10px; + border-radius: var(--radius-pill); + font-size: var(--text-xs); + font-weight: 600; + letter-spacing: 0.04em; + margin-bottom: 16px; +} +.feat-tag.danger { background: var(--danger-50); color: var(--danger-700); } +.feat-tag.success { background: var(--success-50); color: var(--success-700); } +.feat-tag .icon { width: 14px; height: 14px; } + +.feat-text h2 { + font-size: 36px; font-weight: 600; + line-height: 1.18; letter-spacing: var(--tracking-cn-display); + color: var(--brand-900); margin: 0 0 16px; +} +.feat-text p.lead { + font-size: var(--text-lg); line-height: 1.7; + color: var(--gray-600); margin: 0 0 24px; +} +.feat-bullets { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 14px; } +.feat-bullets li { + display: grid; grid-template-columns: 22px 1fr; + gap: 12px; + font-size: var(--text-md); color: var(--gray-700); + line-height: 1.6; align-items: start; +} +.feat-bullets li .icon { width: 18px; height: 18px; color: var(--brand-500); margin-top: 2px; } +.feat-bullets li strong { color: var(--brand-900); font-weight: 600; display: block; margin-bottom: 2px; } + +/* ==================================================================== + BLOCK 1: STATE MACHINE + ==================================================================== */ +.state-machine { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + padding: 48px 36px 40px; + position: relative; + overflow: hidden; +} +.state-machine-tabs { + position: absolute; top: 16px; left: 16px; + display: flex; gap: 2px; + background: var(--gray-50); + padding: 3px; + border-radius: var(--radius-md); + border: 1px solid var(--border-default); +} +.state-tab { + padding: 4px 12px; + font-size: 11px; + font-weight: 500; + color: var(--fg-muted); + border-radius: var(--radius-sm); + letter-spacing: 0.04em; +} +.state-tab.active { + background: var(--brand-500); color: #fff; +} +.state-machine-meta { + position: absolute; top: 24px; right: 20px; + font-size: 11px; color: var(--fg-subtle); + font-family: var(--font-mono); letter-spacing: 0.04em; +} + +/* Diagram */ +.sm-diagram { + display: grid; + grid-template-columns: 1fr 50px 1fr 50px 1fr; + gap: 0; + align-items: center; + margin-top: 24px; +} +.sm-node { + display: flex; flex-direction: column; + align-items: center; gap: 8px; +} +.sm-bubble { + padding: 12px 18px; + border-radius: var(--radius-pill); + font-size: var(--text-md); + font-weight: 600; + letter-spacing: 0.04em; + border: 2px solid; + display: inline-flex; align-items: center; gap: 6px; + background: var(--gray-0); +} +.sm-bubble .icon { width: 14px; height: 14px; } +.sm-node.draft .sm-bubble { border-color: var(--gray-300); color: var(--gray-700); background: var(--gray-50); } +.sm-node.pending .sm-bubble { border-color: var(--info-500); color: var(--info-700); background: var(--info-50); } +.sm-node.approved .sm-bubble { + border-color: var(--success-500); color: var(--success-700); + background: var(--success-50); + box-shadow: 0 0 0 4px rgba(46, 139, 87, 0.10); +} +.sm-node.rejected .sm-bubble { border-color: var(--danger-500); color: var(--danger-700); background: var(--danger-50); } +.sm-node small { font-size: 11px; color: var(--fg-muted); font-family: var(--font-mono); } + +.sm-arrow { + display: flex; align-items: center; justify-content: center; + color: var(--gray-400); + position: relative; +} +.sm-arrow svg { width: 36px; height: 14px; } +.sm-arrow-label { + position: absolute; top: -22px; + font-size: 10px; color: var(--fg-subtle); + font-family: var(--font-mono); letter-spacing: 0.04em; + white-space: nowrap; +} + +.sm-fork { + display: flex; flex-direction: column; gap: 20px; + position: relative; +} +.sm-fork::before { + content: ''; + position: absolute; + left: -28px; top: 50%; transform: translateY(-50%); + width: 1px; height: 60%; + background: var(--gray-300); +} + +/* applies-to legend */ +.sm-applies { + margin-top: 32px; + padding-top: 20px; + border-top: 1px dashed var(--border-default); + display: flex; gap: 10px; align-items: center; + flex-wrap: wrap; + font-size: var(--text-xs); + color: var(--fg-muted); + letter-spacing: 0.02em; +} +.sm-applies-pill { + display: inline-flex; align-items: center; gap: 6px; + padding: 4px 10px; + background: var(--gray-50); + border: 1px solid var(--border-default); + border-radius: var(--radius-md); + font-size: 11px; + color: var(--gray-700); + font-weight: 500; +} +.sm-applies-pill .icon { width: 12px; height: 12px; color: var(--brand-500); } + +/* ==================================================================== + BLOCK 2: AUTO-LINKING — Before/After + ==================================================================== */ +.linking-visual { + display: flex; flex-direction: column; gap: 0; +} +.linking-doc { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + padding: 20px 24px; + position: relative; +} +.linking-doc-head { + display: flex; justify-content: space-between; align-items: center; + margin-bottom: 12px; +} +.linking-doc-id { + font-family: var(--font-mono); font-size: var(--text-md); + color: var(--brand-700); font-weight: 600; +} +.linking-doc-action { + display: inline-flex; align-items: center; gap: 6px; + padding: 6px 14px; + background: var(--success-500); color: #fff; + border-radius: var(--radius-md); + font-size: 12px; font-weight: 600; + letter-spacing: 0.04em; +} +.linking-doc-action .icon { width: 14px; height: 14px; } + +.linking-arrow { + width: 100%; + display: flex; align-items: center; justify-content: center; + padding: 16px 0; + position: relative; +} +.linking-arrow::before, .linking-arrow::after { + content: ''; height: 1px; flex: 1; + background: var(--gray-200); +} +.linking-arrow-label { + margin: 0 14px; + padding: 4px 14px; + background: var(--success-50); + color: var(--success-700); + border-radius: var(--radius-pill); + font-size: var(--text-xs); + font-weight: 600; + letter-spacing: 0.04em; + display: inline-flex; align-items: center; gap: 6px; +} +.linking-arrow-label .icon { width: 13px; height: 13px; } + +.linking-effects { + display: grid; grid-template-columns: 1fr 1fr; + gap: 12px; +} +.linking-effect { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + padding: 20px; + position: relative; +} +.linking-effect-label { + font-size: 11px; color: var(--fg-muted); + font-weight: 600; letter-spacing: 0.06em; + text-transform: uppercase; + margin-bottom: 12px; + display: flex; align-items: center; gap: 6px; +} +.linking-effect-label .icon { width: 14px; height: 14px; color: var(--brand-500); } +.linking-effect-num { + font-size: 28px; font-weight: 700; + color: var(--brand-900); + font-variant-numeric: tabular-nums; + font-family: var(--font-mono); +} +.linking-effect-from { + font-size: 12px; color: var(--fg-subtle); + font-family: var(--font-mono); + margin-top: 4px; + font-variant-numeric: tabular-nums; +} +.linking-effect-from .delta { color: var(--success-700); font-weight: 600; } + +/* ==================================================================== + BLOCK 3: STOCK VALIDATION — Error visual + ==================================================================== */ +.validation-card { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + overflow: hidden; +} +.validation-head { + padding: 16px 20px; + background: var(--gray-50); + border-bottom: 1px solid var(--border-subtle); + display: flex; justify-content: space-between; align-items: center; +} +.validation-title { font-size: var(--text-sm); font-weight: 600; color: var(--brand-900); } +.validation-meta { font-size: 11px; color: var(--fg-muted); font-family: var(--font-mono); } + +.validation-body { padding: 20px; } +.validation-row { + display: grid; + grid-template-columns: 1fr 60px 60px 80px; + gap: 12px; + padding: 10px 0; + border-bottom: 1px solid var(--border-subtle); + font-size: var(--text-sm); + align-items: center; + font-variant-numeric: tabular-nums; +} +.validation-row.head { font-size: 11px; color: var(--fg-muted); font-weight: 500; padding-top: 0; } +.validation-row .qty-req { font-weight: 600; color: var(--gray-900); } +.validation-row .qty-stock { color: var(--gray-700); } +.validation-row .qty-shortage { + background: var(--danger-50); + color: var(--danger-700); + font-weight: 600; + padding: 2px 8px; + border-radius: var(--radius-pill); + font-size: 11px; + text-align: center; + display: inline-block; +} +.validation-row.invalid .qty-req { color: var(--danger-700); } + +.error-toast { + margin: 16px 0 0; + padding: 14px 16px; + background: var(--danger-50); + border: 1px solid #F8B4B4; + border-left: 3px solid var(--danger-500); + border-radius: var(--radius-md); + display: grid; grid-template-columns: 22px 1fr; + gap: 12px; +} +.error-toast .icon { width: 18px; height: 18px; color: var(--danger-700); margin-top: 1px; } +.error-toast-title { + font-size: var(--text-sm); font-weight: 600; + color: var(--danger-700); + margin-bottom: 2px; +} +.error-toast-body { font-size: 12px; color: var(--gray-700); line-height: 1.55; } + +.api-response { + background: var(--gray-900); + color: #DCE2EB; + font-family: var(--font-mono); + font-size: 12px; + padding: 16px 18px; + border-radius: var(--radius-md); + margin-top: 16px; + line-height: 1.7; + overflow-x: auto; +} +.api-response .key { color: #ADC9EA; } +.api-response .str { color: #C97B86; } +.api-response .num { color: #FFD9A6; } +.api-response .bool { color: #C97B86; font-weight: 500; } + +/* ==================================================================== + BLOCK 4: AUDIT LOG TIMELINE + ==================================================================== */ +.audit-timeline { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + overflow: hidden; +} +.audit-head { + padding: 14px 18px; + background: var(--gray-50); + border-bottom: 1px solid var(--border-subtle); + display: flex; justify-content: space-between; align-items: center; +} +.audit-doc-id { font-family: var(--font-mono); color: var(--brand-700); font-size: var(--text-sm); font-weight: 600; } +.audit-doc-status { + padding: 3px 10px; border-radius: var(--radius-pill); + background: var(--success-50); color: var(--success-700); + font-size: 11px; font-weight: 600; +} + +.audit-events { padding: 4px 18px 18px; } +.audit-event { + display: grid; + grid-template-columns: 32px 1fr; + gap: 14px; + padding: 14px 0; + border-bottom: 1px solid var(--border-subtle); + position: relative; +} +.audit-event:last-child { border-bottom: none; } + +.audit-event-marker { + width: 32px; height: 32px; + border-radius: 50%; + display: grid; place-items: center; + position: relative; + z-index: 1; +} +.audit-event-marker .icon { width: 16px; height: 16px; } +.audit-event.create .audit-event-marker { background: var(--gray-100); color: var(--gray-700); } +.audit-event.submit .audit-event-marker { background: var(--info-50); color: var(--info-700); border: 1px solid var(--info-500); } +.audit-event.approve .audit-event-marker { background: var(--success-50); color: var(--success-700); border: 1px solid var(--success-500); } +.audit-event.reject .audit-event-marker { background: var(--danger-50); color: var(--danger-700); border: 1px solid var(--danger-500); } +.audit-event.settle .audit-event-marker { background: var(--brand-50); color: var(--brand-700); border: 1px solid var(--brand-500); } + +.audit-event::before { + content: ''; + position: absolute; + left: 15px; top: 32px; bottom: -14px; + width: 1px; + background: var(--gray-200); +} +.audit-event:last-child::before { display: none; } + +.audit-event-body { padding-top: 5px; } +.audit-event-action { + font-size: var(--text-sm); + font-weight: 600; + color: var(--brand-900); + margin-bottom: 2px; +} +.audit-event-meta { + font-size: 12px; color: var(--fg-muted); + display: flex; gap: 12px; + flex-wrap: wrap; + font-variant-numeric: tabular-nums; + letter-spacing: 0.02em; +} +.audit-event-meta strong { color: var(--gray-800); font-weight: 500; } +.audit-event-meta .time { font-family: var(--font-mono); font-size: 11px; } +.audit-event-comment { + margin-top: 6px; + padding: 8px 12px; + background: var(--gray-25); + border-radius: var(--radius-sm); + font-size: 12px; + color: var(--gray-700); + line-height: 1.55; + font-style: italic; + border-left: 2px solid var(--gray-300); +} + +/* ==================================================================== + REVERSAL STYLES (unused, kept for possible future use) + ==================================================================== */ +.reversal-pair { + display: grid; + grid-template-columns: 1fr 60px 1fr; + gap: 0; + align-items: center; +} +.reversal-doc { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + padding: 18px; + position: relative; +} +.reversal-doc.original .reversal-stamp-mini { color: var(--success-500); border-color: var(--success-500); } +.reversal-doc.reversal { + background: linear-gradient(135deg, #FDFAFA 0%, #FFF 100%); + border-color: #F1D2D7; +} +.reversal-stamp-mini { + position: absolute; + top: 14px; right: 14px; + font-size: 10px; + border: 1.5px solid var(--accent-500); + color: var(--accent-500); + padding: 2px 8px; + border-radius: var(--radius-sm); + font-weight: 700; + letter-spacing: 0.08em; + transform: rotate(-4deg); +} +.reversal-doc-id { + font-family: var(--font-mono); font-size: 13px; + color: var(--brand-700); font-weight: 600; + margin-bottom: 4px; +} +.reversal-doc-meta { + font-size: 11px; color: var(--fg-muted); + font-family: var(--font-mono); + margin-bottom: 12px; + padding-bottom: 12px; + border-bottom: 1px solid var(--border-subtle); +} +.reversal-doc-row { + display: grid; grid-template-columns: 1fr 60px; + font-size: 12px; + padding: 5px 0; + color: var(--gray-700); + font-variant-numeric: tabular-nums; +} +.reversal-doc.reversal .reversal-doc-row { color: var(--accent-700); } +.reversal-doc-foot { + margin-top: 12px; padding-top: 10px; + border-top: 1px solid var(--border-default); + font-size: var(--text-sm); font-weight: 700; + color: var(--brand-900); + display: grid; grid-template-columns: 1fr 70px; + font-variant-numeric: tabular-nums; +} +.reversal-doc.reversal .reversal-doc-foot { color: var(--accent-500); } +.reversal-arrow { + display: flex; flex-direction: column; + align-items: center; gap: 6px; + color: var(--accent-500); + font-size: 10px; + font-family: var(--font-mono); + letter-spacing: 0.06em; +} +.reversal-arrow svg { width: 24px; height: 24px; } +.reversal-arrow-label { + background: var(--accent-50); + color: var(--accent-700); + padding: 3px 10px; + border-radius: var(--radius-pill); + font-size: 10px; + font-weight: 600; + letter-spacing: 0.04em; +} + +.reversal-net { + margin-top: 24px; + padding: 16px 20px; + background: var(--brand-900); + color: #fff; + border-radius: var(--radius-md); + display: grid; + grid-template-columns: 1fr 1fr 1fr; + gap: 16px; +} +.reversal-net-item { text-align: center; } +.reversal-net-label { + font-size: 11px; color: #ADC9EA; + letter-spacing: 0.06em; margin-bottom: 4px; +} +.reversal-net-val { + font-size: var(--text-xl); font-weight: 700; + font-variant-numeric: tabular-nums; + font-family: var(--font-mono); +} + +/* ==================================================================== + BLOCK 6: PERMISSION MATRIX + ==================================================================== */ +.perm-matrix { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: var(--shadow-md); +} +.perm-row { + display: grid; + grid-template-columns: 200px repeat(4, 1fr); + align-items: center; + border-bottom: 1px solid var(--border-subtle); + font-size: var(--text-sm); +} +.perm-row.head { + background: var(--brand-900); color: #fff; + font-size: 12px; font-weight: 500; + letter-spacing: 0.04em; +} +.perm-row.head > div { padding: 14px 16px; } +.perm-row.head > div:not(:first-child) { text-align: center; border-left: 1px solid rgba(255,255,255,0.08); } +.perm-row:last-child { border-bottom: none; } +.perm-role { + padding: 16px 20px; + background: var(--gray-25); + font-weight: 600; + color: var(--brand-900); +} +.perm-role small { + display: block; font-weight: 400; + color: var(--fg-muted); + font-size: 11px; + margin-top: 2px; + letter-spacing: 0.02em; +} +.perm-cell { + padding: 16px; + text-align: center; + border-left: 1px solid var(--border-subtle); +} +.perm-cell .icon { width: 18px; height: 18px; display: inline-block; } +.perm-cell.yes .icon { color: var(--success-500); } +.perm-cell.no .icon { color: var(--gray-300); } +.perm-cell.partial { color: var(--warning-500); font-size: 11px; font-weight: 500; } + +/* ==================================================================== + USE CASES + ==================================================================== */ +.usecases-grid { + display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; + margin-top: 48px; +} +.usecase-card { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + padding: 28px; +} +.usecase-card .icon { width: 36px; height: 36px; color: var(--brand-500); margin-bottom: 16px; } +.usecase-card h4 { margin: 0 0 8px; font-size: var(--text-lg); font-weight: 600; color: var(--brand-900); } +.usecase-card p { margin: 0; font-size: var(--text-sm); color: var(--gray-700); line-height: 1.65; } +.usecase-card .quote { + margin-top: 14px; + font-size: 12px; + color: var(--fg-muted); + font-style: italic; + border-left: 2px solid var(--brand-300); + padding-left: 12px; +} + +/* Final CTA */ +.cta-strip { + background: + radial-gradient(800px 360px at 20% 30%, rgba(139, 35, 49, 0.20), transparent 60%), + linear-gradient(135deg, #0A1F3B 0%, #15407D 100%); + color: #fff; + border-radius: var(--radius-xl); + padding: 56px 48px; + display: grid; + grid-template-columns: 1.4fr 1fr; + gap: 32px; + align-items: center; + margin: 0 0 96px; +} +.cta-strip h2 { font-size: 32px; font-weight: 600; letter-spacing: var(--tracking-cn-display); color: #fff; margin: 0 0 12px; line-height: 1.25; } +.cta-strip p { font-size: var(--text-md); color: #ADC9EA; margin: 0; line-height: 1.6; } +.cta-strip-actions { display: flex; flex-direction: column; gap: 10px; align-items: flex-end; } +.cta-strip .btn-primary { background: #fff; color: var(--brand-700); } +.cta-strip .btn-primary:hover { background: #DCE2EB; } +.cta-strip .btn-secondary { background: transparent; color: #fff; border-color: rgba(255,255,255,0.30); } +.cta-strip .btn-secondary:hover { background: rgba(255,255,255,0.10); } + +/* Footer */ +footer { background: var(--gray-25); border-top: 1px solid var(--border-subtle); padding: 64px 0 32px; color: var(--fg-muted); font-size: var(--text-sm); } +.footer-grid { display: grid; grid-template-columns: 1.5fr repeat(4, 1fr); gap: 48px; margin-bottom: 48px; } +.footer-brand img { height: 32px; margin-bottom: 16px; } +.footer-brand p { margin: 0 0 16px; max-width: 320px; line-height: 1.6; color: var(--fg-muted); } +.footer-contact { font-size: var(--text-sm); color: var(--gray-700); line-height: 1.8; } +.footer-col h5 { font-size: var(--text-xs); font-weight: 600; color: var(--brand-900); letter-spacing: 0.06em; margin: 0 0 16px; text-transform: uppercase; } +.footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; } +.footer-col li a { color: var(--gray-600); } +.footer-col li a:hover { color: var(--brand-500); } +.footer-bottom { border-top: 1px solid var(--border-subtle); padding-top: 24px; display: flex; justify-content: space-between; font-size: var(--text-xs); color: var(--fg-subtle); } + +@media (max-width: 1024px) { + .feat-hero-inner, .feat-block-inner, .feat-block.reverse .feat-block-inner, .cta-strip, .linking-effects, .reversal-pair { grid-template-columns: 1fr; gap: 24px; } + .feat-block.reverse .feat-text, .feat-block.reverse .feat-visual { order: initial; } + .usecases-grid { grid-template-columns: 1fr 1fr; } + .footer-grid { grid-template-columns: 1fr 1fr; } + .feat-hero h1 { font-size: 36px; } + .sm-diagram { grid-template-columns: 1fr; gap: 16px; } + .sm-arrow { transform: rotate(90deg); } + .perm-row { grid-template-columns: 130px repeat(4, 1fr); } + .reversal-arrow { transform: rotate(90deg); padding: 16px 0; } +} +/* Hamburger */ +.nav-hamburger { display: none; flex-direction: column; justify-content: center; gap: 5px; width: 40px; height: 40px; padding: 8px; background: none; border: none; cursor: pointer; border-radius: 8px; } +.nav-hamburger span { display: block; height: 2px; width: 22px; background: var(--gray-700); border-radius: 2px; } +.nav-mobile-menu { display: none; flex-direction: column; background: var(--gray-0); border-top: 1px solid var(--border-subtle); padding: 8px 0 16px; } +.nav-mobile-menu.open { display: flex; } +.nav-mobile-menu a { padding: 12px 24px; font-size: var(--text-md); color: var(--gray-700); font-weight: 500; } +.nav-mobile-menu a:hover { background: var(--gray-50); color: var(--brand-900); } +.nav-mobile-cta { display: flex; flex-direction: column; gap: 8px; padding: 12px 24px 0; border-top: 1px solid var(--border-subtle); margin-top: 8px; } +@media (max-width: 768px) { + .nav-hamburger { display: flex; } + .topnav-links, .topnav-cta { display: none; } + .feat-hero-inner { grid-template-columns: 1fr; } +} +@media (max-width: 600px) { + .topnav-inner { padding: 0 16px; } + .feat-hero h1 { font-size: 28px; } + .footer-grid { grid-template-columns: 1fr; gap: 32px; } + .footer-bottom { flex-direction: column; gap: 8px; text-align: center; } + .usecases-grid { grid-template-columns: 1fr; } + .perm-row { overflow-x: auto; } + .container { padding: 0 16px; } +} + diff --git a/web/assets/features-inventory.css b/web/assets/features-inventory.css new file mode 100644 index 0000000..eb15564 --- /dev/null +++ b/web/assets/features-inventory.css @@ -0,0 +1,657 @@ +* { box-sizing: border-box; } +html, body { + margin: 0; padding: 0; + font-family: var(--font-sans); color: var(--fg-default); + background: var(--bg-surface); + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-feature-settings: "tnum" 1; +} +img, svg { display: block; max-width: 100%; } +a { color: inherit; text-decoration: none; } +button { font-family: inherit; cursor: pointer; } + +.btn { + display: inline-flex; align-items: center; gap: 8px; + height: 40px; padding: 0 18px; + border-radius: var(--radius-md); + font-size: var(--text-md); font-weight: 500; + border: 1px solid transparent; + transition: background var(--duration-fast) var(--ease-standard); + white-space: nowrap; +} +.btn-primary { background: var(--brand-500); color: #fff; } +.btn-primary:hover { background: var(--brand-600); } +.btn-secondary { background: var(--gray-0); color: var(--brand-900); border-color: var(--border-default); } +.btn-secondary:hover { background: var(--gray-50); border-color: var(--border-strong); } +.btn-ghost { background: transparent; color: var(--fg-default); } +.btn-ghost:hover { background: var(--gray-100); } +.btn-lg { height: 48px; padding: 0 24px; font-size: var(--text-lg); } +.btn .icon { width: 18px; height: 18px; } + +.container { max-width: 1280px; margin: 0 auto; padding: 0 32px; } +.section { padding: 96px 0; } +.eyebrow { + font-size: var(--text-xs); font-weight: 600; + letter-spacing: 0.12em; text-transform: uppercase; + color: var(--brand-500); margin: 0 0 12px; +} + +/* Top Nav */ +.topnav { position: sticky; top: 0; z-index: 50; background: rgba(255,255,255,0.85); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid var(--border-subtle); } +.topnav-inner { height: 64px; display: flex; align-items: center; justify-content: space-between; max-width: 1440px; margin: 0 auto; padding: 0 32px; } +.topnav-brand { display: flex; align-items: center; gap: 10px; } +.topnav-brand img { height: 32px; } +.topnav-links { display: flex; align-items: center; gap: 4px; font-size: var(--text-md); color: var(--gray-700); } +.topnav-links a { padding: 8px 14px; border-radius: var(--radius-md); transition: background var(--duration-fast) var(--ease-standard); } +.topnav-links a:hover { background: var(--gray-100); color: var(--brand-900); } +.topnav-links a.active { color: var(--brand-500); background: var(--brand-50); } +.topnav-cta { display: flex; gap: 10px; align-items: center; } + +/* Nav user dropdown */ +.nav-user { position: relative; } +.nav-user-btn { + display: flex; align-items: center; gap: 8px; + height: 36px; padding: 0 12px 0 8px; + border-radius: var(--radius-md); + border: 1px solid var(--border-default); + background: var(--gray-0); + font-size: var(--text-sm); color: var(--gray-800); + cursor: pointer; + transition: background var(--duration-fast) var(--ease-standard); +} +.nav-user-btn:hover { background: var(--gray-50); } +.nav-avatar { + width: 22px; height: 22px; border-radius: 50%; + background: var(--brand-500); color: #fff; + font-size: 11px; font-weight: 700; + display: flex; align-items: center; justify-content: center; + flex-shrink: 0; +} +.nav-user-btn .icon { width: 14px; height: 14px; color: var(--fg-muted); } +.nav-dropdown { + display: none; position: absolute; top: calc(100% + 8px); right: 0; + min-width: 200px; + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + padding: 6px; + z-index: 100; +} +.nav-dropdown.open { display: block; } +.nav-dropdown-info { + padding: 8px 10px 10px; + border-bottom: 1px solid var(--border-subtle); + margin-bottom: 6px; +} +.nav-dropdown-name { font-size: var(--text-sm); font-weight: 600; color: var(--brand-900); } +.nav-dropdown-role { font-size: 11px; color: var(--fg-muted); margin-top: 2px; } +.nav-dropdown a, .nav-dropdown button { + display: flex; align-items: center; gap: 8px; + width: 100%; padding: 8px 10px; + border-radius: var(--radius-md); + font-size: var(--text-sm); color: var(--gray-700); + background: none; border: none; text-align: left; cursor: pointer; + transition: background var(--duration-fast) var(--ease-standard); +} +.nav-dropdown a:hover, .nav-dropdown button:hover { background: var(--gray-50); color: var(--brand-900); } +.nav-dropdown .icon { width: 15px; height: 15px; color: var(--fg-muted); } +.nav-dropdown .logout { color: var(--danger-600); } +.nav-dropdown .logout .icon { color: var(--danger-400); } + +/* ==================================================================== + HERO + ==================================================================== */ +.feat-hero { + position: relative; overflow: hidden; + padding: 80px 0 72px; + background: + radial-gradient(1000px 480px at 88% 8%, rgba(37, 99, 172, 0.08), transparent 60%), + linear-gradient(180deg, #FBFCFD 0%, #FFFFFF 80%); + border-bottom: 1px solid var(--border-subtle); +} +.feat-hero-inner { + display: grid; + grid-template-columns: 1fr 1.15fr; + gap: 56px; + align-items: center; +} +.feat-breadcrumb { + display: flex; align-items: center; gap: 8px; + font-size: var(--text-sm); color: var(--fg-muted); + margin-bottom: 20px; +} +.feat-breadcrumb a { color: var(--fg-muted); } +.feat-breadcrumb a:hover { color: var(--brand-500); } +.feat-breadcrumb .icon { width: 14px; height: 14px; color: var(--gray-300); } +.feat-hero h1 { + font-size: 48px; line-height: 1.15; + letter-spacing: var(--tracking-cn-display); + color: var(--brand-900); margin: 0 0 18px; + font-weight: 700; +} +.feat-hero p.lead { + font-size: var(--text-xl); line-height: 1.6; + color: var(--gray-600); margin: 0 0 28px; +} +.feat-hero .actions { display: flex; gap: 12px; margin-bottom: 28px; } +.feat-hero .quick-stats { + display: grid; grid-template-columns: repeat(3, 1fr); + gap: 0; border-top: 1px solid var(--border-subtle); + padding-top: 20px; +} +.feat-hero .quick-stat-label { font-size: 11px; color: var(--fg-subtle); letter-spacing: 0.04em; } +.feat-hero .quick-stat-val { font-size: var(--text-xl); font-weight: 600; color: var(--brand-900); font-variant-numeric: tabular-nums; margin-top: 4px; } + +/* Hero composite: stacked cards */ +.composite { position: relative; height: 540px; } +.composite-card { + position: absolute; + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + overflow: hidden; +} +.composite-main { top: 0; left: 0; right: 60px; bottom: 60px; box-shadow: var(--shadow-xl); } +.composite-secondary { right: 0; top: 70px; width: 240px; padding: 16px; box-shadow: var(--shadow-lg); } +.composite-tertiary { left: 80px; bottom: 0; right: 0; padding: 14px; box-shadow: var(--shadow-md); } + +.mc-head { + padding: 12px 16px; + background: var(--gray-50); + border-bottom: 1px solid var(--border-subtle); + display: flex; justify-content: space-between; align-items: center; +} +.mc-title { font-size: 13px; font-weight: 600; color: var(--brand-900); } +.mc-tabs { display: flex; gap: 4px; } +.mc-tab { padding: 3px 10px; font-size: 11px; color: var(--fg-muted); border-radius: var(--radius-sm); } +.mc-tab.active { background: var(--gray-0); color: var(--brand-700); border: 1px solid var(--brand-200); } + +.mc-stats { display: grid; grid-template-columns: repeat(3, 1fr); padding: 14px 16px; gap: 10px; border-bottom: 1px solid var(--border-subtle); background: var(--gray-25); } +.mc-stat-label { font-size: 10px; color: var(--fg-subtle); margin-bottom: 2px; } +.mc-stat-val { font-size: 16px; font-weight: 600; color: var(--brand-900); font-variant-numeric: tabular-nums; } +.mc-stat-val .delta { font-size: 10px; color: var(--success-500); margin-left: 4px; font-weight: 500; } + +.mc-table { font-size: 11px; } +.mc-thead, .mc-trow { + display: grid; + grid-template-columns: 88px 1fr 50px 60px 60px 70px; + padding: 8px 16px; + gap: 8px; + align-items: center; + font-variant-numeric: tabular-nums; +} +.mc-thead { background: var(--gray-50); font-size: 10px; font-weight: 500; color: var(--fg-muted); border-bottom: 1px solid var(--border-subtle); } +.mc-trow { border-bottom: 1px solid var(--border-subtle); color: var(--gray-800); } +.mc-trow:last-child { border-bottom: none; } +.mc-trow .sku { font-family: var(--font-mono); color: var(--brand-500); font-size: 10px; } +.mc-pill { display: inline-block; padding: 1px 7px; border-radius: var(--radius-pill); font-size: 9px; font-weight: 500; } +.mc-pill.ok { background: var(--success-50); color: var(--success-700); } +.mc-pill.warn { background: var(--warning-50); color: var(--warning-700); } +.mc-pill.low { background: var(--danger-50); color: var(--danger-700); } + +/* Alert card secondary */ +.alert-card-title { font-size: 11px; color: var(--fg-muted); margin-bottom: 8px; letter-spacing: 0.04em; } +.alert-row { + display: flex; justify-content: space-between; align-items: center; + padding: 8px 10px; + background: var(--warning-50); + border-left: 2px solid var(--warning-500); + border-radius: 3px; + margin-bottom: 6px; + font-size: 12px; +} +.alert-row.danger { background: var(--danger-50); border-color: var(--danger-500); } +.alert-row .name { color: var(--gray-900); font-weight: 500; flex: 1; } +.alert-row .qty { color: var(--gray-700); font-variant-numeric: tabular-nums; font-family: var(--font-mono); font-size: 11px; } + +/* Batch card (tertiary) */ +.batch-title { font-size: 11px; color: var(--fg-muted); margin-bottom: 6px; letter-spacing: 0.04em; display: flex; align-items: center; gap: 6px; } +.batch-title .icon { width: 12px; height: 12px; color: var(--brand-500); } +.batch-row { + display: grid; + grid-template-columns: 90px 1fr 60px 50px; + font-size: 11px; + padding: 6px 0; + border-bottom: 1px dashed var(--border-subtle); + align-items: center; + font-variant-numeric: tabular-nums; +} +.batch-row:last-child { border-bottom: none; } +.batch-row .lot { font-family: var(--font-mono); color: var(--brand-600); font-size: 10px; } +.batch-row .meta { color: var(--fg-muted); font-size: 10px; } + +/* ==================================================================== + FEATURE BLOCKS + ==================================================================== */ +.feat-block { + padding: 96px 0; + border-bottom: 1px solid var(--border-subtle); +} +.feat-block:nth-child(even) { background: var(--gray-25); } +.feat-block-inner { + display: grid; + grid-template-columns: 5fr 7fr; + gap: 64px; + align-items: center; +} +.feat-block.reverse .feat-block-inner { grid-template-columns: 7fr 5fr; } +.feat-block.reverse .feat-text { order: 2; } +.feat-block.reverse .feat-visual { order: 1; } + +.feat-tag { + display: inline-flex; align-items: center; gap: 6px; + background: var(--brand-50); + color: var(--brand-700); + padding: 4px 10px; + border-radius: var(--radius-pill); + font-size: var(--text-xs); + font-weight: 600; + letter-spacing: 0.04em; + margin-bottom: 16px; +} +.feat-tag .icon { width: 14px; height: 14px; } + +.feat-text h2 { + font-size: 36px; + font-weight: 600; + line-height: 1.18; + letter-spacing: var(--tracking-cn-display); + color: var(--brand-900); + margin: 0 0 16px; +} +.feat-text p.lead { + font-size: var(--text-lg); + line-height: 1.7; + color: var(--gray-600); + margin: 0 0 24px; +} +.feat-bullets { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 14px; } +.feat-bullets li { + display: grid; + grid-template-columns: 22px 1fr; + gap: 12px; + font-size: var(--text-md); + color: var(--gray-700); + line-height: 1.6; + align-items: start; +} +.feat-bullets li .icon { width: 18px; height: 18px; color: var(--brand-500); margin-top: 2px; } +.feat-bullets li strong { color: var(--brand-900); font-weight: 600; display: block; margin-bottom: 2px; } + +/* Visual primitives */ +.visual-card { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + overflow: hidden; +} +.visual-card-head { + padding: 14px 18px; + background: var(--gray-50); + border-bottom: 1px solid var(--border-subtle); + display: flex; justify-content: space-between; align-items: center; +} +.visual-card-title { font-size: var(--text-sm); font-weight: 600; color: var(--brand-900); } +.visual-card-meta { font-size: 11px; color: var(--fg-muted); } + +/* Inventory table visual */ +.inv-table { font-size: var(--text-sm); } +.inv-table-row { + display: grid; + grid-template-columns: 110px 1fr 70px 80px 80px 110px; + padding: 12px 18px; + gap: 12px; + border-bottom: 1px solid var(--border-subtle); + align-items: center; + font-variant-numeric: tabular-nums; +} +.inv-table-row.head { + background: var(--gray-50); + font-size: 11px; font-weight: 500; + color: var(--fg-muted); + letter-spacing: 0.02em; + padding: 10px 18px; +} +.inv-table-row:last-child { border-bottom: none; } +.inv-table-row:hover:not(.head) { background: var(--gray-25); } +.inv-table-row .sku { font-family: var(--font-mono); color: var(--brand-500); font-size: 12px; } +.inv-table-row .name { color: var(--gray-900); font-weight: 500; } +.inv-table-row .name small { display: block; color: var(--fg-muted); font-weight: 400; font-size: 11px; margin-top: 1px; } + +/* Batch tracking visual — journey */ +.batch-journey { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + padding: 28px; +} +.batch-journey-head { + display: flex; justify-content: space-between; align-items: flex-start; + margin-bottom: 24px; + padding-bottom: 18px; + border-bottom: 1px solid var(--border-subtle); +} +.bj-meta-main { font-size: var(--text-sm); } +.bj-lot { font-family: var(--font-mono); font-size: var(--text-xl); font-weight: 600; color: var(--brand-700); margin-bottom: 4px; } +.bj-product { font-size: var(--text-md); color: var(--gray-900); font-weight: 500; } +.bj-product small { color: var(--fg-muted); font-weight: 400; margin-left: 8px; } +.bj-totals { text-align: right; } +.bj-total-row { font-size: var(--text-xs); color: var(--fg-muted); display: flex; gap: 8px; justify-content: flex-end; margin-bottom: 4px; } +.bj-total-row strong { color: var(--gray-900); font-weight: 600; font-variant-numeric: tabular-nums; } + +.bj-progress { + background: var(--gray-100); + height: 8px; + border-radius: var(--radius-pill); + margin-bottom: 24px; + position: relative; + overflow: hidden; +} +.bj-progress-bar { + height: 100%; + background: linear-gradient(90deg, var(--brand-500), var(--brand-400)); + width: 67%; + border-radius: var(--radius-pill); +} +.bj-progress-labels { display: flex; justify-content: space-between; margin-top: -16px; } +.bj-progress-labels span { font-size: 11px; color: var(--fg-muted); font-variant-numeric: tabular-nums; } + +.bj-timeline { display: flex; flex-direction: column; gap: 0; } +.bj-event { + display: grid; + grid-template-columns: 16px 110px 1fr 80px 90px; + gap: 16px; + padding: 12px 0; + align-items: center; + border-bottom: 1px solid var(--border-subtle); + position: relative; +} +.bj-event:last-child { border-bottom: none; } +.bj-event-dot { + width: 10px; height: 10px; + border-radius: 50%; + background: var(--gray-300); + margin: 0 auto; +} +.bj-event.stockin .bj-event-dot { background: var(--brand-500); box-shadow: 0 0 0 4px var(--brand-50); } +.bj-event.stockout .bj-event-dot { background: var(--accent-500); } +.bj-event.adjust .bj-event-dot { background: var(--warning-500); } +.bj-event-date { font-size: 11px; color: var(--fg-muted); font-family: var(--font-mono); font-variant-numeric: tabular-nums; } +.bj-event-desc { font-size: var(--text-sm); color: var(--gray-800); } +.bj-event-desc small { display: block; color: var(--fg-muted); font-size: 11px; margin-top: 2px; } +.bj-event-qty { font-size: var(--text-md); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; } +.bj-event.stockin .bj-event-qty { color: var(--success-700); } +.bj-event.stockout .bj-event-qty { color: var(--accent-500); } +.bj-event-doc { font-size: 11px; color: var(--brand-500); font-family: var(--font-mono); text-align: right; } + +/* Stocktake comparison */ +.stocktake-table { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: var(--shadow-md); +} +.st-summary { + display: grid; grid-template-columns: repeat(4, 1fr); + padding: 18px 20px; + background: var(--brand-900); + color: #fff; + gap: 16px; +} +.st-summary-item .label { font-size: 11px; color: #ADC9EA; margin-bottom: 4px; letter-spacing: 0.04em; } +.st-summary-item .val { font-size: var(--text-xl); font-weight: 600; font-variant-numeric: tabular-nums; } +.st-summary-item .val.neg { color: var(--danger-500); } + +.st-row { + display: grid; + grid-template-columns: 1fr 70px 70px 80px 90px; + padding: 12px 20px; + gap: 12px; + border-bottom: 1px solid var(--border-subtle); + font-size: var(--text-sm); + align-items: center; + font-variant-numeric: tabular-nums; +} +.st-row:last-child { border-bottom: none; } +.st-row.head { background: var(--gray-50); font-size: 11px; color: var(--fg-muted); font-weight: 500; } +.st-row.head > div { text-align: right; } +.st-row.head > div:first-child { text-align: left; } +.st-row .diff-pill { + display: inline-block; + padding: 2px 8px; + border-radius: var(--radius-pill); + font-size: 11px; + font-weight: 600; +} +.st-row .diff-pill.zero { background: var(--gray-100); color: var(--gray-700); } +.st-row .diff-pill.neg { background: var(--danger-50); color: var(--danger-700); } +.st-row .diff-pill.pos { background: var(--success-50); color: var(--success-700); } +.st-row > div:not(:first-child) { text-align: right; } + +/* Log timeline */ +.log-card { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + overflow: hidden; +} +.log-toolbar { + display: flex; gap: 8px; padding: 12px 18px; + background: var(--gray-50); + border-bottom: 1px solid var(--border-subtle); + align-items: center; + font-size: var(--text-xs); + color: var(--fg-muted); +} +.log-filter-pill { + display: inline-flex; align-items: center; gap: 4px; + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-pill); + padding: 3px 10px; + font-size: 11px; + color: var(--gray-700); +} +.log-filter-pill.active { background: var(--brand-50); border-color: var(--brand-300); color: var(--brand-700); } +.log-filter-pill .icon { width: 12px; height: 12px; } +.log-row { + display: grid; + grid-template-columns: 100px 60px 1fr 60px 80px; + padding: 12px 18px; + gap: 14px; + border-bottom: 1px solid var(--border-subtle); + font-size: var(--text-sm); + align-items: center; + font-variant-numeric: tabular-nums; +} +.log-row:last-child { border-bottom: none; } +.log-time { font-family: var(--font-mono); font-size: 11px; color: var(--fg-muted); } +.log-type-pill { + display: inline-block; + padding: 1px 8px; + border-radius: var(--radius-pill); + font-size: 10px; + font-weight: 500; +} +.log-type-pill.in { background: var(--success-50); color: var(--success-700); } +.log-type-pill.out { background: var(--accent-50); color: var(--accent-700); } +.log-type-pill.check { background: var(--info-50); color: var(--info-700); } +.log-desc { color: var(--gray-800); font-size: 13px; } +.log-desc small { color: var(--fg-muted); display: block; font-size: 11px; margin-top: 1px; } +.log-qty { text-align: right; font-weight: 600; } +.log-qty.in { color: var(--success-700); } +.log-qty.out { color: var(--accent-500); } +.log-op { text-align: right; font-size: 12px; color: var(--gray-700); } + +/* Alert config */ +.alert-config-card { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); + padding: 24px; +} +.alert-config-card h4 { + margin: 0 0 4px; + font-size: var(--text-md); + font-weight: 600; + color: var(--brand-900); +} +.alert-config-card p.sub { margin: 0 0 20px; font-size: var(--text-sm); color: var(--fg-muted); } + +.threshold-bar { + position: relative; + height: 56px; + margin: 28px 0 12px; +} +.threshold-track { + position: absolute; top: 24px; left: 0; right: 0; + height: 8px; + background: linear-gradient(90deg, var(--danger-100, #FBC9C9) 0%, var(--danger-100, #FBC9C9) 18%, var(--warning-50) 18%, var(--warning-50) 42%, var(--success-50) 42%, var(--success-50) 100%); + border-radius: var(--radius-pill); +} +.threshold-marker { + position: absolute; top: 18px; + width: 20px; height: 20px; + border-radius: 50%; + background: var(--gray-0); + border: 3px solid var(--brand-500); + transform: translateX(-50%); + box-shadow: 0 2px 6px rgba(20,24,33,0.10); +} +.threshold-tick { + position: absolute; + top: 38px; + transform: translateX(-50%); + font-size: 10px; + color: var(--fg-muted); + font-family: var(--font-mono); + font-variant-numeric: tabular-nums; + white-space: nowrap; +} +.threshold-label { + position: absolute; + bottom: 8px; + transform: translateX(-50%); + font-size: 10px; + color: var(--fg-muted); + letter-spacing: 0.04em; + white-space: nowrap; +} +.alert-rules { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; } +.alert-rule { + display: flex; justify-content: space-between; align-items: center; + padding: 10px 14px; + background: var(--gray-25); + border-radius: var(--radius-md); + font-size: 13px; + color: var(--gray-700); +} +.alert-rule strong { color: var(--brand-900); font-weight: 600; } +.alert-rule .switch { + width: 32px; height: 18px; + background: var(--brand-500); + border-radius: var(--radius-pill); + position: relative; +} +.alert-rule .switch::after { + content: ''; + position: absolute; + top: 2px; right: 2px; + width: 14px; height: 14px; + background: #fff; + border-radius: 50%; +} +.alert-rule .switch.off { background: var(--gray-300); } +.alert-rule .switch.off::after { right: auto; left: 2px; } + +/* Use cases */ +.usecases-grid { + display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; + margin-top: 48px; +} +.usecase-card { + background: var(--gray-0); + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + padding: 28px; +} +.usecase-card .icon { + width: 36px; height: 36px; color: var(--brand-500); margin-bottom: 16px; +} +.usecase-card h4 { margin: 0 0 8px; font-size: var(--text-lg); font-weight: 600; color: var(--brand-900); } +.usecase-card p { margin: 0; font-size: var(--text-sm); color: var(--gray-700); line-height: 1.65; } + +/* Final CTA */ +.cta-strip { + background: linear-gradient(135deg, #0A1F3B 0%, #15407D 100%); + color: #fff; + border-radius: var(--radius-xl); + padding: 56px 48px; + display: grid; + grid-template-columns: 1.4fr 1fr; + gap: 32px; + align-items: center; + margin: 0 0 96px; +} +.cta-strip h2 { + font-size: 32px; font-weight: 600; + letter-spacing: var(--tracking-cn-display); + color: #fff; margin: 0 0 12px; line-height: 1.25; +} +.cta-strip p { font-size: var(--text-md); color: #ADC9EA; margin: 0; line-height: 1.6; } +.cta-strip-actions { display: flex; flex-direction: column; gap: 10px; align-items: flex-end; } +.cta-strip .btn-primary { background: #fff; color: var(--brand-700); } +.cta-strip .btn-primary:hover { background: #DCE2EB; } +.cta-strip .btn-secondary { background: transparent; color: #fff; border-color: rgba(255,255,255,0.30); } +.cta-strip .btn-secondary:hover { background: rgba(255,255,255,0.10); } + +/* Footer */ +footer { background: var(--gray-25); border-top: 1px solid var(--border-subtle); padding: 64px 0 32px; color: var(--fg-muted); font-size: var(--text-sm); } +.footer-grid { display: grid; grid-template-columns: 1.5fr repeat(4, 1fr); gap: 48px; margin-bottom: 48px; } +.footer-brand img { height: 32px; margin-bottom: 16px; } +.footer-brand p { margin: 0 0 16px; max-width: 320px; line-height: 1.6; color: var(--fg-muted); } +.footer-contact { font-size: var(--text-sm); color: var(--gray-700); line-height: 1.8; } +.footer-col h5 { font-size: var(--text-xs); font-weight: 600; color: var(--brand-900); letter-spacing: 0.06em; margin: 0 0 16px; text-transform: uppercase; } +.footer-col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; } +.footer-col li a { color: var(--gray-600); } +.footer-col li a:hover { color: var(--brand-500); } +.footer-bottom { border-top: 1px solid var(--border-subtle); padding-top: 24px; display: flex; justify-content: space-between; font-size: var(--text-xs); color: var(--fg-subtle); } + +@media (max-width: 1024px) { + .feat-hero-inner, .feat-block-inner, .feat-block.reverse .feat-block-inner, .cta-strip { grid-template-columns: 1fr; gap: 32px; } + .feat-block.reverse .feat-text, .feat-block.reverse .feat-visual { order: initial; } + .usecases-grid { grid-template-columns: 1fr 1fr; } + .footer-grid { grid-template-columns: 1fr 1fr; } + .feat-hero h1 { font-size: 36px; } + .composite { height: 480px; } +} +/* Hamburger */ +.nav-hamburger { display: none; flex-direction: column; justify-content: center; gap: 5px; width: 40px; height: 40px; padding: 8px; background: none; border: none; cursor: pointer; border-radius: 8px; } +.nav-hamburger span { display: block; height: 2px; width: 22px; background: var(--gray-700); border-radius: 2px; } +.nav-mobile-menu { display: none; flex-direction: column; background: var(--gray-0); border-top: 1px solid var(--border-subtle); padding: 8px 0 16px; } +.nav-mobile-menu.open { display: flex; } +.nav-mobile-menu a { padding: 12px 24px; font-size: var(--text-md); color: var(--gray-700); font-weight: 500; } +.nav-mobile-menu a:hover { background: var(--gray-50); color: var(--brand-900); } +.nav-mobile-cta { display: flex; flex-direction: column; gap: 8px; padding: 12px 24px 0; border-top: 1px solid var(--border-subtle); margin-top: 8px; } +@media (max-width: 768px) { + .nav-hamburger { display: flex; } + .topnav-links, .topnav-cta { display: none; } + .composite { display: none; } +} +@media (max-width: 600px) { + .topnav-inner { padding: 0 16px; } + .feat-hero h1 { font-size: 28px; } + .footer-grid { grid-template-columns: 1fr; gap: 32px; } + .footer-bottom { flex-direction: column; gap: 8px; text-align: center; } + .usecases-grid { grid-template-columns: 1fr; } + .container { padding: 0 16px; } +} + diff --git a/web/features/approval.html b/web/features/approval.html deleted file mode 100644 index 7eaab90..0000000 --- a/web/features/approval.html +++ /dev/null @@ -1,1701 +0,0 @@ - - -
- - -功能详情 · 审核驱动业务流
-- 入库、出库、盘点 —— 统一状态机,统一审批界面。审批不仅是一个按钮,是一笔事务:库存动了,账款也跟着动,全程留痕。 -
- -- 入库、出库、盘点 —— 全部走同一套状态:草稿 → 待审核 → 已审批 / 已拒绝。员工学一次,全员通用。 -
-- 审批通过不是一个"标记",而是一组真实的数据库写入。库存增减、应付应收、批次创建 —— 在同一事务内完成。 -
-FOR UPDATE 锁住库存行,杜绝并发超卖。
- - 出库单审批前,系统按 SKU 实时核对库存。任一行不足,整单审批失败、库存与账款均不变。永远不会超卖。 -
-- 从录入到结清,每一次状态变更都记录经办人、时间、决策、备注。是单据的完整生命周期,也是合规审计的完整证据。 -
-- 系统内置四个角色,按岗位职责拆分审批权。最小权限原则 —— 不该看的看不到,不该签的签不了。 -
-shop_id),跨店访问数据天然隔离。
- 典型场景
-- 三个常见门店场景,看审核流如何把日常工作中的失误拦在事前。 -
- -大客户来订 24 瓶飞天,操作员录了出库单。审批时系统提示某 SKU 库存只剩 12 瓶 —— 提前发现,先补货后出库。
-财务问"这批拉菲是哪个供应商进的,谁审的",打开单据点击「审计链」,从草稿、提交、审批到结清的每一步都列得清清楚楚。
-审批通过的单据不可撤销,但可补录一张方向相反的修正单提交审核,两笔记录都完整保留在审计链中,库存与账款同步修正。
-30 天免费试用,无需绑定支付方式。所有审批与审计数据可随时导出。
-功能详情 · 审核驱动业务流
++ 入库、出库、盘点 —— 统一状态机,统一审批界面。审批不仅是一个按钮,是一笔事务:库存动了,账款也跟着动,全程留痕。 +
+ ++ 入库、出库、盘点 —— 全部走同一套状态:草稿 → 待审核 → 已审批 / 已拒绝。员工学一次,全员通用。 +
++ 审批通过不是一个"标记",而是一组真实的数据库写入。库存增减、应付应收、批次创建 —— 在同一事务内完成。 +
+FOR UPDATE 锁住库存行,杜绝并发超卖。
+ + 出库单审批前,系统按 SKU 实时核对库存。任一行不足,整单审批失败、库存与账款均不变。永远不会超卖。 +
++ 从录入到结清,每一次状态变更都记录经办人、时间、决策、备注。是单据的完整生命周期,也是合规审计的完整证据。 +
++ 系统内置四个角色,按岗位职责拆分审批权。最小权限原则 —— 不该看的看不到,不该签的签不了。 +
+shop_id),跨店访问数据天然隔离。
+ 典型场景
++ 三个常见门店场景,看审核流如何把日常工作中的失误拦在事前。 +
+ +大客户来订 24 瓶飞天,操作员录了出库单。审批时系统提示某 SKU 库存只剩 12 瓶 —— 提前发现,先补货后出库。
+财务问"这批拉菲是哪个供应商进的,谁审的",打开单据点击「审计链」,从草稿、提交、审批到结清的每一步都列得清清楚楚。
+审批通过的单据不可撤销,但可补录一张方向相反的修正单提交审核,两笔记录都完整保留在审计链中,库存与账款同步修正。
+30 天免费试用,无需绑定支付方式。所有审批与审计数据可随时导出。
+功能详情 · 库存管理
-- 从入库到售出,每一次库存变动都有记录、可追溯、可回放。多仓库统一管理、批次级追踪、账实差异自动核算 — 不止是库存表。 -
- -- 库存数据自动跟随入库、出库、盘点变动 — 每一次写入都是一次事务,不存在「待同步」状态。 -
-- 每张审批通过的入库单都会自动形成一个独立批次,可追踪其后续被谁出库、剩余多少、还在哪个仓库。 -
-- 逐 SKU 录入实盘数量,系统自动核算账实差异、损耗金额,并一键转为盘亏调整单。 -
-- 所有库存变动都会自动写入流水表,包括入库、出库、盘点调整,附带时间戳与经办人。 -
-- 为每件商品设置最低库存量,系统根据当前库存自动标记「充足 / 偏低 / 告急」,无需手工比对。 -
-基于最低库存量 (min_stock) 自动标记状态。
-典型场景
-- 三个常见门店场景,看库存管理如何省下你每天的时间。 -
- -客户要 12 瓶飞天,先在批次追踪里看哪一批快到期;优先发出旧批次,新批次留着。
-用移动端扫码逐瓶录入,系统对比账面 → 实时显示差异。损耗自动转入应付,不用再算。
-打开库存流水,按 SKU 筛选,全部入库、出库、盘点变动一目了然,每条都关联到原始单据。
-30 天免费试用,无需绑定支付。所有数据云端实时备份,可随时导出。
-功能详情 · 库存管理
++ 从入库到售出,每一次库存变动都有记录、可追溯、可回放。多仓库统一管理、批次级追踪、账实差异自动核算 — 不止是库存表。 +
+ ++ 库存数据自动跟随入库、出库、盘点变动 — 每一次写入都是一次事务,不存在「待同步」状态。 +
++ 每张审批通过的入库单都会自动形成一个独立批次,可追踪其后续被谁出库、剩余多少、还在哪个仓库。 +
++ 逐 SKU 录入实盘数量,系统自动核算账实差异、损耗金额,并一键转为盘亏调整单。 +
++ 所有库存变动都会自动写入流水表,包括入库、出库、盘点调整,附带时间戳与经办人。 +
++ 为每件商品设置最低库存量,系统根据当前库存自动标记「充足 / 偏低 / 告急」,无需手工比对。 +
+基于最低库存量 (min_stock) 自动标记状态。
+典型场景
++ 三个常见门店场景,看库存管理如何省下你每天的时间。 +
+ +客户要 12 瓶飞天,先在批次追踪里看哪一批快到期;优先发出旧批次,新批次留着。
+用移动端扫码逐瓶录入,系统对比账面 → 实时显示差异。损耗自动转入应付,不用再算。
+打开库存流水,按 SKU 筛选,全部入库、出库、盘点变动一目了然,每条都关联到原始单据。
+30 天免费试用,无需绑定支付。所有数据云端实时备份,可随时导出。
+