:root { --bg: #0e0e14; --panel: #1a1a24; --panel-2: #22222e; --ink: #e8e8f0; --muted: #9a9ab0; --accent: #7c83ff; --accent-2: #b07cff; --good: #4ade80; --warn: #fbbf24; --bad: #f87171; --radius: 14px; --shadow: 0 10px 30px rgba(0, 0, 0, .45); } * { box-sizing: border-box; } html, body { margin: 0; padding: 0; } body { background: radial-gradient(1200px 600px at 80% -10%, #2a1f44 0%, transparent 60%), var(--bg); color: var(--ink); font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; min-height: 100vh; } /* Top bar */ .topbar { position: sticky; top: 0; z-index: 20; display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: space-between; padding: 14px 22px; background: rgba(14, 14, 20, .85); backdrop-filter: blur(10px); border-bottom: 1px solid rgba(255, 255, 255, .06); } .brand { display: flex; align-items: baseline; gap: 10px; } .brand .logo { font-size: 22px; } .brand h1 { font-size: 18px; margin: 0; letter-spacing: .3px; } .brand .tagline { color: var(--muted); font-size: 12px; } .controls { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; } .controls input[type=search], .controls select { background: var(--panel); color: var(--ink); border: 1px solid rgba(255, 255, 255, .08); border-radius: 8px; padding: 8px 10px; outline: none; min-width: 140px; } .controls input[type=search] { min-width: 220px; } .btn { background: var(--accent); color: white; border: 0; border-radius: 8px; padding: 8px 12px; cursor: pointer; font-weight: 600; } .btn.ghost { background: transparent; border: 1px solid rgba(255, 255, 255, .14); color: var(--ink); } .btn:hover { filter: brightness(1.1); } .btn.ghost.on { background: rgba(124, 131, 255, .18); border-color: var(--accent); } .llm-panel { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; padding: 12px 22px; border-bottom: 1px solid rgba(255, 255, 255, .06); background: rgba(124, 131, 255, .06); } .llm-panel label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); } .llm-panel input { background: var(--panel); color: var(--ink); border: 1px solid rgba(255, 255, 255, .08); border-radius: 8px; padding: 6px 8px; outline: none; min-width: 220px; } .hint { color: var(--muted); font-size: 12px; } /* Grid of tiles */ .grid { display: grid; gap: 18px; padding: 22px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); } .tile { background: linear-gradient(180deg, var(--panel) 0%, var(--panel-2) 100%); border: 1px solid rgba(255, 255, 255, .07); border-radius: var(--radius); overflow: hidden; cursor: pointer; display: flex; flex-direction: column; min-height: 220px; transition: transform .12s ease, box-shadow .12s ease, border-color .12s; } .tile:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: rgba(124, 131, 255, .4); } .tile-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; background: rgba(0, 0, 0, .25); border-bottom: 1px solid rgba(255, 255, 255, .06); } .traffic { display: flex; gap: 6px; } .traffic i { width: 10px; height: 10px; border-radius: 50%; display: block; } .traffic i:nth-child(1) { background: #ff5f57; } .traffic i:nth-child(2) { background: #febc2e; } .traffic i:nth-child(3) { background: #28c840; } .tile-source { font-size: 11px; color: var(--muted); margin-left: auto; text-transform: uppercase; letter-spacing: .5px; } .tile-title { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; } .tile-body { padding: 10px 12px; flex: 1; } .tile-snip { color: var(--muted); font-size: 12px; line-height: 1.45; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; } .tile-foot { padding: 10px 12px; border-top: 1px solid rgba(255, 255, 255, .06); display: flex; flex-wrap: wrap; gap: 6px; } .badge { font-size: 11px; padding: 3px 7px; border-radius: 999px; background: rgba(255, 255, 255, .06); color: var(--ink); display: inline-flex; gap: 4px; align-items: center; } .badge .k { color: var(--muted); } .badge.conv { background: rgba(124, 131, 255, .18); } .badge.sent-good { background: rgba(74, 222, 128, .18); color: #b6f3c8; } .badge.sent-bad { background: rgba(248, 113, 113, .18); color: #fcc8c8; } .badge.sent-mid { background: rgba(154, 154, 176, .18); } .dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; } .conv-bar { width: 100%; height: 6px; border-radius: 999px; background: rgba(255, 255, 255, .08); overflow: hidden; margin-top: 6px; } .conv-bar > i { display: block; height: 100%; background: linear-gradient(90deg, var(--accent), var(--accent-2)); } .llm-tag { font-size: 10px; color: var(--accent-2); margin-left: auto; } /* Empty */ .empty { text-align: center; color: var(--muted); padding: 60px; } /* Modal */ .modal { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; } .modal.hidden { display: none; } .modal-backdrop { position: absolute; inset: 0; background: rgba(0, 0, 0, .6); } .modal-card { position: relative; z-index: 1; width: min(820px, 92vw); max-height: 88vh; overflow: auto; background: var(--panel); border: 1px solid rgba(255, 255, 255, .1); border-radius: var(--radius); display: flex; flex-direction: column; } .modal-card.narrow { width: min(620px, 92vw); } .modal-head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid rgba(255, 255, 255, .07); position: sticky; top: 0; background: var(--panel); } .modal-title { font-weight: 700; flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .modal-x { background: transparent; border: 0; color: var(--muted); font-size: 16px; cursor: pointer; } .modal-x:hover { color: var(--ink); } .modal-kpis { display: flex; flex-wrap: wrap; gap: 10px; padding: 14px; border-bottom: 1px solid rgba(255, 255, 255, .07); } .kpi { background: var(--panel-2); border-radius: 10px; padding: 10px 12px; min-width: 130px; } .kpi .label { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; } .kpi .value { font-size: 18px; font-weight: 700; margin-top: 2px; } .modal-body { padding: 14px; overflow: auto; } .msg { margin-bottom: 12px; } .msg .who { font-size: 11px; color: var(--muted); text-transform: capitalize; margin-bottom: 2px; } .msg .bubble { background: var(--panel-2); border-radius: 10px; padding: 8px 12px; white-space: pre-wrap; word-wrap: break-word; } .msg.user .bubble, .msg.customer .bubble { background: rgba(124, 131, 255, .14); } .modal-foot { display: flex; gap: 10px; align-items: center; padding: 12px 14px; border-top: 1px solid rgba(255, 255, 255, .07); position: sticky; bottom: 0; background: var(--panel); } .schema { background: var(--panel-2); padding: 10px; border-radius: 8px; font-size: 11px; overflow: auto; color: var(--muted); } #fileInput { margin: 8px 0; } #jsonInput { width: 100%; background: var(--panel-2); color: var(--ink); border: 1px solid rgba(255, 255, 255, .08); border-radius: 8px; padding: 8px; font-family: ui-monospace, monospace; font-size: 12px; } @media (max-width: 600px) { .controls { width: 100%; } .controls input[type=search] { min-width: 0; flex: 1; } } /* ---------- Physics stage ---------- */ .stage { position: relative; width: 100%; height: calc(100vh - 60px); overflow: hidden; background: radial-gradient(circle at 30% 20%, rgba(124, 131, 255, .08), transparent 50%), radial-gradient(circle at 70% 80%, rgba(176, 124, 255, .08), transparent 50%); } .stage.hidden { display: none; } #links { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 1; } .bodies, .services { position: absolute; inset: 0; z-index: 2; pointer-events: none; } .bodies .tile, .services .service { pointer-events: auto; } /* floating chat body — reuse .tile but absolute-positioned, smaller, draggable feel */ .bodies .tile { position: absolute; top: 0; left: 0; margin: 0; width: 240px; min-height: 0; transform-origin: center; transition: box-shadow .15s, border-color .15s; will-change: transform; } .bodies .tile.attached { border-color: rgba(124, 131, 255, .55); box-shadow: 0 0 0 1px rgba(124, 131, 255, .25), 0 8px 24px rgba(0, 0, 0, .4); } .bodies .tile .tile-body { padding: 8px 10px; } .bodies .tile .tile-snip { -webkit-line-clamp: 3; } /* emergent service node */ .service { position: absolute; top: 0; left: 0; width: 200px; padding: 12px 14px; background: linear-gradient(135deg, rgba(124, 131, 255, .22), rgba(176, 124, 255, .22)); border: 1px solid rgba(176, 124, 255, .6); border-radius: 16px; box-shadow: 0 0 24px rgba(176, 124, 255, .35), 0 10px 30px rgba(0, 0, 0, .45); cursor: pointer; will-change: transform; backdrop-filter: blur(6px); animation: svc-pop .4s ease; } @keyframes svc-pop { from { transform: scale(.6); opacity: 0; } to { transform: scale(1); opacity: 1; } } .service .svc-spark { font-size: 16px; } .service .svc-name { font-weight: 700; font-size: 14px; margin: 4px 0 2px; line-height: 1.25; } .service .svc-desc { font-size: 11px; color: var(--muted); line-height: 1.4; } .service .svc-meta { margin-top: 8px; display: flex; gap: 6px; flex-wrap: wrap; } .service .svc-meta .badge { font-size: 10px; padding: 2px 6px; } .service .svc-new { position: absolute; top: -8px; right: -8px; background: var(--accent-2); color: #fff; font-size: 9px; font-weight: 700; padding: 2px 6px; border-radius: 999px; letter-spacing: .5px; } .stage-hint { position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%); z-index: 3; color: var(--muted); font-size: 12px; background: rgba(0, 0, 0, .3); padding: 6px 12px; border-radius: 999px; pointer-events: none; } /* ---------- Get real chats modal ---------- */ .modal-body h3 { font-size: 15px; margin: 18px 0 6px; } .modal-body h3:first-child { margin-top: 0; } .modal-body code { background: var(--panel-2); padding: 1px 5px; border-radius: 4px; font-size: 12px; } .bm-row { display: flex; gap: 10px; align-items: center; margin: 10px 0; } .bookmarklet { display: inline-block; padding: 10px 16px; background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: #fff; border-radius: 10px; text-decoration: none; font-weight: 700; cursor: grab; border: 1px solid rgba(255, 255, 255, .2); box-shadow: 0 4px 14px rgba(124, 131, 255, .4); } .bookmarklet:active { cursor: grabbing; }