Current section

Files

Jump to
arcana lib arcana_web assets.ex
Raw

lib/arcana_web/assets.ex

defmodule ArcanaWeb.Assets do
@moduledoc false
@behaviour Plug
# Bundle Phoenix LiveView JavaScript at compile time
@external_resource phoenix_js = Application.app_dir(:phoenix, "priv/static/phoenix.min.js")
@external_resource phoenix_html_js =
Application.app_dir(:phoenix_html, "priv/static/phoenix_html.js")
@external_resource live_view_js =
Application.app_dir(
:phoenix_live_view,
"priv/static/phoenix_live_view.min.js"
)
@phoenix_js File.read!(phoenix_js)
@phoenix_html_js File.read!(phoenix_html_js)
@live_view_js File.read!(live_view_js)
@app_js """
// CmdEnterSubmit: when the user presses Cmd+Enter (or Ctrl+Enter on
// non-mac) inside the bound element (typically a textarea), find the
// closest form and submit it. Used by the Ask page so the user can
// submit a question without reaching for the mouse.
let Hooks = {
CmdEnterSubmit: {
mounted() {
this.handler = (e) => {
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
e.preventDefault()
const form = this.el.closest("form")
if (form) {
form.dispatchEvent(new Event("submit", {bubbles: true, cancelable: true}))
}
}
}
this.el.addEventListener("keydown", this.handler)
},
destroyed() {
this.el.removeEventListener("keydown", this.handler)
}
}
}
let liveSocket = new window.LiveView.LiveSocket("/live", window.Phoenix.Socket, {hooks: Hooks})
liveSocket.connect()
window.liveSocket = liveSocket
"""
@js [@phoenix_js, @phoenix_html_js, @live_view_js, @app_js] |> Enum.join("\n")
@js_hash :crypto.hash(:md5, @js) |> Base.encode16(case: :lower) |> binary_part(0, 8)
@css """
.arcana-dashboard {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 1.5rem;
color: #1f2937;
}
.arcana-tabs {
display: flex;
gap: 0.5rem;
border-bottom: 2px solid #e5e7eb;
margin-bottom: 1.5rem;
}
.arcana-tab {
padding: 0.75rem 1.5rem;
border: none;
background: transparent;
font-size: 1rem;
font-weight: 500;
color: #6b7280;
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -2px;
transition: all 0.15s ease;
text-decoration: none;
}
.arcana-tab:hover {
color: #7c3aed;
}
.arcana-tab.active {
color: #7c3aed;
border-bottom-color: #7c3aed;
}
.arcana-dashboard h2 {
font-size: 1.5rem;
font-weight: 600;
color: #111827;
margin: 0 0 1rem 0;
}
.arcana-ingest-form,
.arcana-search-form {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1rem;
margin-bottom: 1.5rem;
}
.arcana-ingest-form textarea,
.arcana-search-form input[type="text"] {
width: 100%;
padding: 0.75rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
margin-bottom: 0.75rem;
box-sizing: border-box;
}
.arcana-ingest-form textarea:focus,
.arcana-search-form input:focus,
.arcana-search-form select:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
.arcana-search-options {
display: flex;
gap: 1rem;
flex-wrap: wrap;
margin-bottom: 0.75rem;
}
.arcana-search-options label {
display: flex;
flex-direction: column;
gap: 0.25rem;
font-size: 0.75rem;
font-weight: 500;
color: #6b7280;
}
.arcana-search-options select,
.arcana-search-options input[type="number"] {
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
min-width: 100px;
}
.arcana-ingest-form button,
.arcana-search-form button {
background: #7c3aed;
color: white;
padding: 0.625rem 1.25rem;
border: none;
border-radius: 0.375rem;
font-size: 0.875rem;
font-weight: 500;
cursor: pointer;
transition: background-color 0.15s ease;
}
.arcana-ingest-form button:hover,
.arcana-search-form button:hover {
background: #6d28d9;
}
.arcana-ingest-options {
display: flex;
gap: 1rem;
margin-bottom: 0.75rem;
}
.arcana-ingest-options label {
display: flex;
flex-direction: column;
gap: 0.25rem;
font-size: 0.75rem;
font-weight: 500;
color: #6b7280;
}
.arcana-ingest-options select {
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
min-width: 120px;
}
.arcana-ingest-options select:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
.arcana-empty {
color: #6b7280;
font-style: italic;
padding: 2rem;
text-align: center;
background: #f9fafb;
border-radius: 0.5rem;
}
.arcana-documents-table,
.arcana-results-table,
.arcana-table {
width: 100%;
border-collapse: collapse;
font-size: 0.875rem;
}
.arcana-documents-table th,
.arcana-results-table th,
.arcana-table th {
text-align: left;
padding: 0.75rem;
background: #f3f4f6;
border-bottom: 2px solid #e5e7eb;
font-weight: 600;
color: #374151;
}
.arcana-documents-table td,
.arcana-results-table td,
.arcana-table td {
padding: 0.75rem;
border-bottom: 1px solid #e5e7eb;
vertical-align: middle;
}
.arcana-documents-table td:nth-child(1) {
max-width: 120px;
word-break: break-all;
}
.arcana-documents-table td:nth-child(2) {
max-width: 300px;
}
.arcana-documents-table td:nth-child(5),
.arcana-documents-table td:nth-child(6),
.arcana-documents-table td:nth-child(7) {
white-space: nowrap;
}
.arcana-documents-table tr:hover,
.arcana-results-table tr:hover,
.arcana-table tr:hover {
background: #f9fafb;
}
.arcana-documents-table code,
.arcana-results-table code,
.arcana-table code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
font-size: 0.75rem;
background: #ede9fe;
color: #6d28d9;
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
}
.arcana-metadata {
font-size: 0.75rem;
color: #6b7280;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.arcana-stats {
display: flex;
gap: 1.5rem;
margin-bottom: 1.5rem;
padding: 1rem;
background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%);
border-radius: 0.5rem;
color: white;
align-items: center;
}
.arcana-brand {
font-size: 1.5rem;
font-weight: 700;
letter-spacing: -0.025em;
padding-right: 1.5rem;
border-right: 1px solid rgba(255, 255, 255, 0.3);
margin-right: 0.5rem;
display: flex;
align-items: center;
align-self: center;
}
.arcana-stat {
text-align: center;
}
.arcana-stat-value {
font-size: 1.5rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
letter-spacing: -0.01em;
}
.arcana-stat-label {
font-size: 0.75rem;
opacity: 0.9;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.arcana-stat-divider {
width: 1px;
height: 2rem;
background: rgba(255, 255, 255, 0.3);
margin: 0 0.5rem;
}
.arcana-pagination {
display: flex;
gap: 0.375rem;
justify-content: center;
align-items: center;
flex-wrap: wrap;
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
}
.arcana-page-btn {
padding: 0.5rem 0.75rem;
min-width: 2.5rem;
border: 1px solid #d1d5db;
background: white;
border-radius: 0.375rem;
font-size: 0.875rem;
font-variant-numeric: tabular-nums;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-page-btn:hover:not(:disabled) {
border-color: #7c3aed;
color: #7c3aed;
}
.arcana-page-btn.active {
background: #7c3aed;
border-color: #7c3aed;
color: white;
}
.arcana-page-btn:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.arcana-page-ellipsis {
padding: 0.5rem 0.25rem;
color: #9ca3af;
font-size: 0.875rem;
user-select: none;
}
.arcana-view-btn {
background: transparent;
color: #7c3aed;
border: 1px solid #7c3aed;
}
.arcana-view-btn:hover {
background: #7c3aed;
color: white;
}
.arcana-filter-bar {
display: flex;
align-items: center;
gap: 0.5rem;
flex-wrap: wrap;
padding: 0.75rem 1rem;
background: #f3f4f6;
border-radius: 0.5rem;
margin-bottom: 1rem;
}
.arcana-filter-label {
font-size: 0.875rem;
font-weight: 500;
color: #6b7280;
margin-right: 0.5rem;
}
.arcana-filter-btn {
padding: 0.375rem 0.75rem;
font-size: 0.875rem;
border: 1px solid #d1d5db;
border-radius: 9999px;
background: white;
color: #374151;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-filter-btn:hover {
border-color: #7c3aed;
color: #7c3aed;
}
.arcana-filter-btn.active {
background: #7c3aed;
border-color: #7c3aed;
color: white;
}
.arcana-filter-clear {
background: #fef2f2;
border-color: #fecaca;
color: #dc2626;
}
.arcana-filter-clear:hover {
background: #fee2e2;
border-color: #dc2626;
}
.arcana-doc-detail {
/* No background - inherits from page */
}
.arcana-doc-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
}
.arcana-doc-header h2 {
margin: 0;
}
.arcana-close-btn {
background: transparent;
color: #6b7280;
border: 1px solid #d1d5db;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
font-size: 0.875rem;
cursor: pointer;
transition: all 0.15s ease;
text-decoration: none;
}
.arcana-close-btn:hover {
border-color: #7c3aed;
color: #7c3aed;
}
.arcana-doc-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
background: #f9fafb;
border: 1px solid #e5e7eb;
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1.5rem;
}
.arcana-doc-field label {
display: block;
font-size: 0.75rem;
font-weight: 500;
color: #6b7280;
margin-bottom: 0.25rem;
}
.arcana-doc-section {
margin-bottom: 1.5rem;
}
.arcana-doc-section h3 {
font-size: 1rem;
font-weight: 600;
color: #374151;
margin: 0 0 0.75rem 0;
}
.arcana-doc-content {
background: #f9fafb;
border: 1px solid #e5e7eb;
padding: 1rem;
border-radius: 0.5rem;
font-size: 0.875rem;
white-space: pre-wrap;
word-wrap: break-word;
margin: 0;
max-height: 300px;
overflow-y: auto;
}
/* Info page grid layout */
.arcana-info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
margin-bottom: 1.5rem;
}
.arcana-info-section {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1rem;
}
.arcana-info-section h3 {
font-size: 0.875rem;
font-weight: 600;
color: #7c3aed;
margin: 0 0 0.75rem 0;
padding-bottom: 0.5rem;
border-bottom: 1px solid #f3e8ff;
}
.arcana-info-section .arcana-doc-info {
margin-bottom: 0;
background: transparent;
border: none;
padding: 0;
}
.arcana-info-full {
grid-column: 1 / -1;
}
.arcana-not-configured {
color: #9ca3af;
}
.arcana-status-badge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
.arcana-status-badge.enabled {
background: #d1fae5;
color: #065f46;
}
.arcana-status-badge.disabled {
background: #f3f4f6;
color: #6b7280;
}
/* Maintenance page styles */
.arcana-maintenance-section {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1.25rem;
margin-bottom: 2rem;
}
.arcana-maintenance-section h3 {
font-size: 0.875rem;
font-weight: 600;
color: #7c3aed;
margin: 0 0 0.75rem 0;
padding-bottom: 0.5rem;
border-bottom: 1px solid #f3e8ff;
}
.arcana-maintenance-section .arcana-doc-info {
margin-bottom: 0;
background: transparent;
border: none;
padding: 0;
}
.arcana-orphan-section {
background: #fef3c7;
border-color: #f59e0b;
}
.arcana-orphan-section h3 {
color: #b45309;
border-bottom-color: #fcd34d;
}
.arcana-orphan-count {
font-weight: 600;
color: #b45309;
}
.arcana-chunks-list {
display: flex;
flex-direction: column;
gap: 1rem;
}
.arcana-chunk {
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
}
.arcana-chunk-header {
display: flex;
justify-content: space-between;
padding: 0.5rem 1rem;
background: #f3f4f6;
font-size: 0.75rem;
font-weight: 500;
}
.arcana-chunk-index {
color: #7c3aed;
}
.arcana-chunk-tokens {
color: #6b7280;
}
.arcana-chunk-text {
padding: 1rem;
margin: 0;
font-size: 0.875rem;
white-space: pre-wrap;
word-wrap: break-word;
background: #f9fafb;
}
.arcana-btn {
background: transparent;
color: #374151;
border: 1px solid #d1d5db;
padding: 0.375rem 0.75rem;
border-radius: 0.25rem;
font-size: 0.75rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-btn:hover {
border-color: #7c3aed;
color: #7c3aed;
}
.arcana-btn-primary {
background: #7c3aed;
color: white;
border-color: #7c3aed;
}
.arcana-btn-primary:hover {
background: #6d28d9;
border-color: #6d28d9;
color: white;
}
.arcana-btn-danger {
background: transparent;
color: #dc2626;
border-color: #dc2626;
}
.arcana-btn-danger:hover {
background: #dc2626;
color: white;
}
.arcana-form-row {
display: flex;
gap: 0.5rem;
align-items: center;
}
.arcana-input {
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
}
.arcana-input:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
.arcana-confirm-delete {
display: flex;
gap: 0.5rem;
align-items: center;
}
.arcana-confirm-delete span {
font-size: 0.75rem;
color: #dc2626;
font-weight: 500;
}
/* Evaluation styles */
.arcana-eval-nav {
display: flex;
gap: 1.5rem;
margin-bottom: 1.5rem;
border-bottom: 1px solid #e5e7eb;
}
.arcana-eval-nav-btn {
position: relative;
padding: 0.625rem 0;
border: none;
background: transparent;
font-size: 0.9375rem;
font-weight: 500;
color: #6b7280;
cursor: pointer;
transition: color 0.15s ease;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
}
.arcana-eval-nav-btn:hover {
color: #7c3aed;
}
.arcana-eval-nav-btn.active {
color: #7c3aed;
border-bottom-color: #7c3aed;
font-weight: 600;
}
.arcana-eval-message {
padding: 0.75rem 1rem;
border-radius: 0.375rem;
margin-bottom: 1rem;
font-size: 0.875rem;
}
.arcana-eval-message.success {
background: #d1fae5;
color: #065f46;
border: 1px solid #a7f3d0;
}
.arcana-eval-message.error {
background: #fee2e2;
color: #991b1b;
border: 1px solid #fecaca;
}
/* Evaluation run form: vertical stack of sections, radio cards for
retriever, options row for mode + evaluate_answers toggle, a
prominent Run Evaluation button bottom-right. Replaces the old
flex-end one-liner that smushed inputs of different heights next
to each other. */
.arcana-eval-run-intro {
margin: 0 0 1.25rem;
color: #4b5563;
font-size: 0.9375rem;
}
.arcana-eval-run-intro strong {
color: #111827;
font-weight: 600;
}
.arcana-eval-run-form {
display: flex;
flex-direction: column;
gap: 1.5rem;
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.75rem;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
.arcana-eval-field {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.arcana-eval-field-label {
font-size: 0.75rem;
font-weight: 600;
color: #374151;
text-transform: uppercase;
letter-spacing: 0.05em;
margin: 0;
}
.arcana-eval-hint {
font-size: 0.75rem;
color: #6b7280;
line-height: 1.4;
}
.arcana-eval-option-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.75rem;
}
.arcana-eval-option-card {
position: relative;
display: flex;
flex-direction: column;
gap: 0.375rem;
padding: 1rem 1rem 1rem 1rem;
background: #fafafa;
border: 2px solid #e5e7eb;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-eval-option-card input[type="radio"] {
position: absolute;
opacity: 0;
pointer-events: none;
}
.arcana-eval-option-card:hover {
border-color: #c4b5fd;
background: #faf5ff;
}
.arcana-eval-option-card:has(input:checked) {
border-color: #7c3aed;
background: #ede9fe;
}
.arcana-eval-option-card:has(input:checked) .arcana-eval-option-title {
color: #6d28d9;
}
.arcana-eval-option-title {
font-size: 0.9375rem;
font-weight: 600;
color: #111827;
}
.arcana-eval-option-desc {
font-size: 0.8125rem;
color: #6b7280;
line-height: 1.4;
}
.arcana-eval-option-desc code {
font-size: 0.75rem;
padding: 0.0625rem 0.25rem;
background: #f3f4f6;
border-radius: 0.1875rem;
color: #374151;
}
.arcana-eval-options-row {
display: grid;
grid-template-columns: minmax(0, 240px) minmax(0, 1fr);
gap: 1.5rem;
align-items: start;
}
.arcana-eval-select {
padding: 0.5rem 0.75rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
background: white;
color: #111827;
}
.arcana-eval-toggle {
position: relative;
display: flex;
align-items: flex-start;
gap: 0.625rem;
padding: 0.75rem 1rem;
background: #fafafa;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-eval-toggle input[type="checkbox"] {
position: absolute;
opacity: 0;
pointer-events: none;
}
.arcana-eval-toggle-indicator {
flex-shrink: 0;
width: 1rem;
height: 1rem;
margin-top: 0.125rem;
border: 2px solid #9ca3af;
border-radius: 0.25rem;
background: white;
transition: all 0.15s ease;
position: relative;
}
.arcana-eval-toggle:has(input:checked) {
border-color: #7c3aed;
background: #ede9fe;
}
.arcana-eval-toggle:has(input:checked) .arcana-eval-toggle-indicator {
border-color: #7c3aed;
background: #7c3aed;
}
.arcana-eval-toggle:has(input:checked) .arcana-eval-toggle-indicator::after {
content: "";
position: absolute;
left: 3px;
top: 0px;
width: 4px;
height: 8px;
border: solid white;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.arcana-eval-toggle-content {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.arcana-eval-toggle-title {
font-size: 0.875rem;
font-weight: 600;
color: #111827;
}
.arcana-eval-actions {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
border-top: 1px solid #f3f4f6;
padding-top: 1.25rem;
margin-top: 0.25rem;
}
.arcana-eval-progress {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.375rem;
min-width: 0;
}
.arcana-eval-progress-label {
display: flex;
justify-content: space-between;
font-size: 0.8125rem;
color: #4b5563;
}
.arcana-eval-progress-elapsed {
color: #6b7280;
font-variant-numeric: tabular-nums;
}
.arcana-eval-progress-bar {
height: 6px;
background: #ede9fe;
border-radius: 3px;
overflow: hidden;
}
.arcana-eval-progress-fill {
height: 100%;
background: linear-gradient(90deg, #8b5cf6, #7c3aed);
border-radius: 3px;
transition: width 0.3s ease;
}
.arcana-eval-progress-current {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.8125rem;
color: #6d28d9;
margin-top: 0.125rem;
}
.arcana-eval-progress-current-label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
}
.arcana-eval-progress-spinner {
display: inline-block;
width: 0.75rem;
height: 0.75rem;
border: 2px solid #ede9fe;
border-top-color: #7c3aed;
border-radius: 50%;
flex-shrink: 0;
animation: arcana-eval-spin 0.8s linear infinite;
}
@keyframes arcana-eval-spin {
to { transform: rotate(360deg); }
}
.arcana-eval-run-btn {
background: #7c3aed;
color: white;
padding: 0.625rem 1.5rem;
border: none;
border-radius: 0.5rem;
font-size: 0.9375rem;
font-weight: 600;
cursor: pointer;
transition: background-color 0.15s ease;
}
.arcana-eval-run-btn:hover:not(:disabled) {
background: #6d28d9;
}
.arcana-eval-run-btn:disabled {
background: #9ca3af;
cursor: not-allowed;
opacity: 0.7;
}
@media (max-width: 640px) {
.arcana-eval-option-grid,
.arcana-eval-options-row {
grid-template-columns: 1fr;
}
}
.arcana-metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.arcana-metric-card {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1rem;
text-align: center;
}
.arcana-metric-value {
font-size: 1.5rem;
font-weight: 700;
color: #7c3aed;
}
.arcana-metric-label {
font-size: 0.75rem;
color: #6b7280;
margin-top: 0.25rem;
}
/* Empty state for the test cases view when no test cases exist. */
.arcana-eval-empty-state {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
padding: 3rem 1rem;
background: #fafafa;
border: 1px dashed #d1d5db;
border-radius: 0.75rem;
text-align: center;
color: #6b7280;
}
.arcana-eval-empty-state h4 {
margin: 0;
font-size: 1rem;
font-weight: 600;
color: #374151;
}
.arcana-eval-empty-state p {
margin: 0;
font-size: 0.875rem;
}
.arcana-eval-empty-state code {
background: #f3f4f6;
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
font-size: 0.8125rem;
}
.arcana-eval-empty-icon {
font-size: 2.5rem;
color: #d1d5db;
line-height: 1;
}
/* Test case list: compact rows that expand on click to show the
reference answer (when present) and the relevant chunks. */
.arcana-test-case-list {
display: flex;
flex-direction: column;
gap: 0.375rem;
margin-top: 1.5rem;
}
.arcana-test-case {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
transition: border-color 0.15s ease;
}
.arcana-test-case.expanded {
border-color: #c4b5fd;
}
.arcana-test-case-row {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.625rem 0.875rem;
}
.arcana-test-case-row-main {
display: grid;
grid-template-columns: auto 1fr auto auto auto;
align-items: center;
gap: 0.75rem;
flex: 1;
min-width: 0;
cursor: pointer;
padding: 0.125rem 0;
border-radius: 0.25rem;
transition: background-color 0.15s ease;
}
.arcana-test-case-row-main:hover {
background: #fafafa;
}
.arcana-test-case.expanded .arcana-test-case-row {
background: #faf5ff;
border-bottom: 1px solid #ede9fe;
}
.arcana-test-case-chevron {
color: #9ca3af;
font-size: 0.75rem;
width: 0.75rem;
text-align: center;
}
.arcana-test-case-question {
font-size: 0.875rem;
color: #111827;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
}
.arcana-test-case-badge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.6875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.02em;
}
.arcana-test-case-badge--generated {
background: #ede9fe;
color: #6d28d9;
}
.arcana-test-case-badge--synthetic {
background: #ede9fe;
color: #6d28d9;
}
.arcana-test-case-badge--manual {
background: #dbeafe;
color: #1d4ed8;
}
.arcana-test-case-chunks {
font-size: 0.75rem;
color: #6b7280;
white-space: nowrap;
font-variant-numeric: tabular-nums;
}
.arcana-test-case-time {
font-size: 0.75rem;
color: #9ca3af;
white-space: nowrap;
cursor: help;
}
.arcana-test-case-detail {
padding: 1rem 1rem 1.25rem 2rem;
background: #fafafa;
}
.arcana-test-case-detail-section {
margin-top: 0.75rem;
}
.arcana-test-case-detail-section:first-child {
margin-top: 0;
}
.arcana-test-case-detail-section h5 {
font-size: 0.6875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #6d28d9;
margin: 0 0 0.375rem;
}
.arcana-test-case-detail-section p {
margin: 0;
font-size: 0.875rem;
color: #374151;
line-height: 1.5;
}
.arcana-test-case-chunk-list {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.375rem;
}
.arcana-test-case-chunk-list li {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.625rem;
align-items: baseline;
padding: 0.375rem 0.5rem;
background: white;
border-radius: 0.25rem;
border: 1px solid #f3f4f6;
}
.arcana-test-case-chunk-id {
font-family: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace;
font-size: 0.75rem;
color: #7c3aed;
padding: 0.0625rem 0.25rem;
background: #faf5ff;
border-radius: 0.1875rem;
}
.arcana-test-case-chunk-text {
font-size: 0.8125rem;
color: #4b5563;
line-height: 1.5;
}
.arcana-test-case-empty {
font-size: 0.875rem;
color: #9ca3af;
font-style: italic;
}
.arcana-actions-cell {
text-align: center;
white-space: nowrap;
}
.arcana-icon-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.375rem;
background: transparent;
color: #9ca3af;
border: none;
border-radius: 0.25rem;
cursor: pointer;
}
.arcana-icon-btn:hover {
color: #7c3aed;
background: #f3f4f6;
}
.arcana-delete-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.375rem;
background: transparent;
color: #9ca3af;
border: none;
border-radius: 0.25rem;
cursor: pointer;
}
.arcana-delete-btn:hover {
color: #dc2626;
background: #fef2f2;
}
.arcana-run-card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
margin-bottom: 1rem;
overflow: hidden;
}
.arcana-run-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 1rem;
background: #f3f4f6;
border-bottom: 1px solid #e5e7eb;
}
.arcana-run-header-left {
display: flex;
align-items: center;
gap: 0.75rem;
}
.arcana-run-status {
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
.arcana-run-status.completed {
background: #d1fae5;
color: #065f46;
}
.arcana-run-status.running {
background: #fef3c7;
color: #92400e;
}
.arcana-run-status.failed {
background: #fee2e2;
color: #991b1b;
}
.arcana-run-body {
padding: 1rem;
}
.arcana-run-config {
font-size: 0.75rem;
color: #6b7280;
margin-bottom: 0.75rem;
}
/* Upload styles */
.arcana-dropzone {
position: relative;
border: 2px dashed #d1d5db;
border-radius: 0.5rem;
padding: 2rem;
text-align: center;
cursor: pointer;
transition: all 0.15s ease;
margin-bottom: 1rem;
}
.arcana-dropzone:hover {
border-color: #7c3aed;
background: #f5f3ff;
}
.arcana-dropzone p {
margin: 0 0 0.5rem 0;
color: #374151;
}
.arcana-upload-hint {
font-size: 0.75rem;
color: #6b7280;
}
.arcana-file-input {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
}
.arcana-upload-entry {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.5rem;
background: #f9fafb;
border-radius: 0.375rem;
margin-bottom: 0.5rem;
}
.arcana-upload-entry progress {
flex: 1;
height: 0.5rem;
}
.arcana-upload-entry button {
background: transparent;
border: none;
color: #dc2626;
cursor: pointer;
font-size: 1.25rem;
}
.arcana-upload-error {
color: #dc2626;
font-size: 0.75rem;
}
.arcana-upload-btn {
background: #7c3aed;
color: white;
padding: 0.625rem 1.25rem;
border: none;
border-radius: 0.375rem;
font-size: 0.875rem;
font-weight: 500;
cursor: pointer;
}
.arcana-upload-btn:hover {
background: #6d28d9;
}
.arcana-divider {
text-align: center;
color: #6b7280;
font-size: 0.875rem;
margin: 1.5rem 0;
position: relative;
}
.arcana-divider::before,
.arcana-divider::after {
content: "";
position: absolute;
top: 50%;
width: 40%;
height: 1px;
background: #e5e7eb;
}
.arcana-divider::before {
left: 0;
}
.arcana-divider::after {
right: 0;
}
/* Search Results Styles */
.arcana-search-results {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.arcana-search-result {
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
background: white;
}
.arcana-result-header {
display: flex;
align-items: center;
gap: 1rem;
padding: 0.75rem 1rem;
background: #f9fafb;
border-bottom: 1px solid #e5e7eb;
}
.arcana-result-score {
min-width: 60px;
}
.arcana-result-score .score-value {
font-weight: 600;
color: #7c3aed;
font-size: 0.875rem;
}
.arcana-result-meta {
display: flex;
align-items: center;
gap: 0.5rem;
flex: 1;
}
.arcana-result-meta code {
font-size: 0.7rem;
}
.arcana-chunk-badge {
background: #ede9fe;
color: #6d28d9;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
.arcana-result-actions {
display: flex;
gap: 0.5rem;
}
.arcana-result-btn {
padding: 0.375rem 0.75rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
background: white;
font-size: 0.75rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-result-btn:hover {
border-color: #7c3aed;
color: #7c3aed;
}
.arcana-result-btn-primary {
background: #7c3aed;
border-color: #7c3aed;
color: white;
}
.arcana-result-btn-primary:hover {
background: #6d28d9;
border-color: #6d28d9;
color: white;
}
.arcana-result-text {
padding: 1rem;
font-size: 0.875rem;
white-space: pre-wrap;
word-wrap: break-word;
color: #374151;
max-height: 100px;
overflow: hidden;
position: relative;
}
.arcana-result-text.expanded {
max-height: none;
overflow: visible;
}
/* ChunkResultsComponent: grouped chunks with expandable details. */
.arcana-chunk-results {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.arcana-chunk-doc {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
}
.arcana-chunk-doc--has-source {
border-color: #a7f3d0;
box-shadow: 0 0 0 1px #a7f3d0 inset;
}
.arcana-chunk-doc-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
padding: 0.625rem 0.875rem;
background: #f9fafb;
border-bottom: 1px solid #e5e7eb;
}
.arcana-chunk-doc--has-source .arcana-chunk-doc-header {
background: #ecfdf5;
border-bottom-color: #a7f3d0;
}
.arcana-chunk-doc-title {
margin: 0;
font-size: 0.875rem;
font-weight: 600;
color: #111827;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
min-width: 0;
}
.arcana-chunk-doc-link {
color: inherit;
text-decoration: none;
transition: color 0.15s ease;
}
.arcana-chunk-doc-link:hover {
color: #6d28d9;
text-decoration: underline;
}
.arcana-chunk-doc-meta {
display: inline-flex;
align-items: center;
gap: 0.375rem;
font-size: 0.75rem;
color: #6b7280;
flex-shrink: 0;
}
.arcana-chunk-source-dot {
display: inline-block;
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
background: #10b981;
}
.arcana-chunk-list {
list-style: none;
margin: 0;
padding: 0;
}
.arcana-chunk-item {
border-top: 1px solid #f3f4f6;
}
.arcana-chunk-item:first-child {
border-top: none;
}
.arcana-chunk-item--source {
background: #f0fdf4;
}
.arcana-chunk-details {
width: 100%;
}
.arcana-chunk-summary {
display: flex;
align-items: center;
gap: 0.625rem;
padding: 0.5rem 0.875rem;
cursor: pointer;
list-style: none;
font-size: 0.8125rem;
line-height: 1.4;
user-select: none;
}
.arcana-chunk-summary::-webkit-details-marker {
display: none;
}
.arcana-chunk-summary::before {
content: 'ā–ø';
color: #9ca3af;
font-size: 0.6875rem;
flex-shrink: 0;
transition: transform 0.15s ease;
display: inline-block;
}
.arcana-chunk-details[open] > .arcana-chunk-summary::before {
transform: rotate(90deg);
}
.arcana-chunk-summary:hover {
background: #f9fafb;
}
.arcana-chunk-item--source .arcana-chunk-summary:hover {
background: #dcfce7;
}
.arcana-chunk-score {
font-family: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace;
font-size: 0.6875rem;
font-weight: 600;
color: #6d28d9;
flex-shrink: 0;
}
.arcana-chunk-index {
font-family: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace;
font-size: 0.6875rem;
color: #9ca3af;
flex-shrink: 0;
}
.arcana-chunk-supports {
font-size: 0.6875rem;
font-weight: 600;
color: #047857;
background: #d1fae5;
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
flex-shrink: 0;
}
.arcana-chunk-via {
font-size: 0.6875rem;
color: #7c3aed;
background: #ede9fe;
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
flex-shrink: 0;
max-width: 12rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.arcana-chunk-preview {
flex: 1;
min-width: 0;
color: #4b5563;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.arcana-chunk-full {
padding: 0.75rem 1rem 1rem 2.25rem;
font-size: 0.8125rem;
line-height: 1.55;
color: #1f2937;
white-space: pre-line;
border-top: 1px dashed #e5e7eb;
}
/* Collection checkboxes - shared between Search and Ask tabs */
.arcana-ask-collections {
margin: 1rem 0;
}
.arcana-ask-collections > label {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: #374151;
margin-bottom: 0.5rem;
}
.arcana-llm-select-toggle {
margin-bottom: 0.75rem;
padding: 0.75rem;
background: #f5f3ff;
border: 1px solid #ddd6fe;
border-radius: 0.5rem;
}
.arcana-llm-select-toggle .arcana-checkbox-label {
margin: 0;
}
.arcana-collection-checkboxes {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.arcana-collection-check {
display: inline-flex;
align-items: center;
gap: 0.375rem;
padding: 0.375rem 0.75rem;
background: white;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.8125rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-collection-check:hover {
border-color: #7c3aed;
background: #faf5ff;
}
.arcana-collection-check:has(input:checked) {
border-color: #7c3aed;
background: #ede9fe;
color: #5b21b6;
}
.arcana-collection-check input {
accent-color: #7c3aed;
}
.arcana-collection-hint {
display: block;
margin-top: 0.375rem;
font-size: 0.75rem;
color: #6b7280;
}
/* Tab description */
.arcana-tab-description {
color: #6b7280;
margin-bottom: 1rem;
font-size: 0.875rem;
}
/* Ask tab styles */
.arcana-ask-mode-nav {
display: inline-flex;
background: #f3f4f6;
border-radius: 0.5rem;
padding: 0.25rem;
margin-bottom: 0.75rem;
}
.arcana-mode-btn {
padding: 0.5rem 1rem;
border: none;
background: transparent;
color: #6b7280;
font-size: 0.875rem;
font-weight: 500;
border-radius: 0.375rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-mode-btn:hover {
color: #374151;
}
.arcana-mode-btn.active {
background: white;
color: #7c3aed;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.arcana-mode-description {
color: #9ca3af;
font-size: 0.8125rem;
margin-bottom: 1rem;
font-style: italic;
}
.arcana-ask-form {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1rem;
margin-bottom: 1.5rem;
}
.arcana-ask-input textarea {
width: 100%;
padding: 0.75rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
resize: vertical;
box-sizing: border-box;
}
.arcana-ask-input textarea:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
.arcana-ask-options {
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid #e5e7eb;
}
.arcana-ask-options h4 {
font-size: 0.875rem;
font-weight: 600;
color: #374151;
margin: 0 0 0.75rem 0;
}
.arcana-pipeline {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
}
.arcana-pipeline > li {
display: flex;
flex-direction: column;
align-items: center;
}
.arcana-pipeline > li:not(:last-child)::after {
content: '';
display: block;
width: 2px;
height: 1.25rem;
background: #c4b5fd;
}
.arcana-pipeline > li:has(> .arcana-pipeline-step:not(:has(input:checked)):not(.fixed)):not(:last-child)::after {
background: none;
border-left: 2px dashed #d1d5db;
}
.arcana-pipeline-step {
display: flex;
flex-direction: column;
align-items: center;
width: 240px;
padding: 0.625rem 1rem;
background: #fafafa;
border: 2px dashed #d1d5db;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.15s ease;
text-align: center;
}
.arcana-pipeline-step:has(input:checked) {
background: #ede9fe;
border: 2px solid #7c3aed;
}
.arcana-pipeline-step:has(input:checked) .arcana-step-label {
color: #6d28d9;
}
.arcana-pipeline-step:not(.fixed):hover {
border-color: #a78bfa;
}
.arcana-pipeline-step.fixed {
background: #f0fdf4;
border: 2px solid #86efac;
cursor: default;
}
.arcana-pipeline-step.fixed .arcana-step-label {
color: #15803d;
}
.arcana-pipeline-step input[type="checkbox"],
.arcana-pipeline-step input[type="radio"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.arcana-step-label {
font-size: 0.875rem;
font-weight: 600;
color: #374151;
}
.arcana-pipeline-step small {
font-size: 0.75rem;
color: #6b7280;
margin-top: 0.125rem;
}
.arcana-pipeline-fork {
display: flex;
align-items: center;
gap: 0.75rem;
}
.arcana-pipeline-fork .arcana-pipeline-step {
width: 160px;
}
.arcana-fork-or {
font-size: 0.75rem;
font-weight: 500;
color: #9ca3af;
text-transform: uppercase;
}
.arcana-pipeline-step:has(input:disabled) {
opacity: 0.5;
cursor: not-allowed;
}
/* Phase grouping: wraps the flat pipeline into three labeled sections
(Query preparation, Retrieval, Answer) with a thin divider line
between them. Each phase keeps its own vertical flow; the dividers
make the three stages visible without losing the single-column shape. */
.arcana-pipeline-phases {
display: flex;
flex-direction: column;
align-items: stretch;
gap: 1rem;
}
.arcana-pipeline-phase {
display: flex;
flex-direction: column;
align-items: center;
padding: 1rem 0.75rem 1.25rem;
background: #faf5ff;
border: 1px solid #ede9fe;
border-radius: 0.625rem;
}
.arcana-pipeline-phase-header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
max-width: 280px;
margin: 0 auto 0.75rem;
}
.arcana-pipeline-phase-header h5 {
margin: 0;
font-size: 0.6875rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: #7c3aed;
}
.arcana-pipeline-phase-toggle {
font-size: 0.6875rem;
font-weight: 400;
color: #9ca3af;
letter-spacing: 0;
text-transform: none;
}
/* Substep: a conditional loop on the previous step (Multi-hop reasoning
loops search, Self-correction loops answer). The ↻ glyph on the label
signals the loop relationship. Keeps the same width + center axis as
the primary steps so the vertical connector stays straight. */
.arcana-loop-glyph {
display: inline-block;
margin-right: 0.25rem;
color: #a78bfa;
font-weight: 700;
}
.arcana-pipeline-step:has(input:checked) .arcana-loop-glyph {
color: #7c3aed;
}
/* Ask page sub-tabs: segmented pill control. Distinct from the
top-level .arcana-tab nav (which uses underlines) so the two
navigation levels don't visually compete. */
.arcana-ask-sub-tab-nav {
display: inline-flex;
align-items: center;
background: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 0.25rem;
gap: 0.125rem;
margin: 1rem 0 0.75rem;
}
.arcana-ask-sub-tab {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 36px;
padding: 0.5rem 1.25rem;
border: none;
background: transparent;
font-size: 0.875rem;
font-weight: 500;
color: #6b7280;
cursor: pointer;
border-radius: 0.375rem;
transition: all 0.15s ease;
}
.arcana-ask-sub-tab:hover:not(.active) {
color: #4b5563;
background: rgba(255, 255, 255, 0.6);
}
.arcana-ask-sub-tab.active {
background: #ffffff;
color: #6d28d9;
font-weight: 600;
box-shadow:
0 1px 2px rgba(15, 23, 42, 0.06),
0 1px 3px rgba(15, 23, 42, 0.04);
}
.arcana-sub-tab-description {
color: #6b7280;
font-size: 0.875rem;
margin: 0 0 1.25rem 0;
line-height: 1.5;
}
/* Loop settings: card grid that mirrors the .arcana-pipeline-step
visual language so the Loop sub-tab feels like part of the same
surface as the Pipeline sub-tab. */
.arcana-loop-settings {
margin-top: 0.75rem;
}
.arcana-loop-settings h4 {
font-size: 0.6875rem;
font-weight: 600;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.06em;
margin: 0 0 0.5rem 0;
}
/* Two-row layout: info cards (4-col) row, then number+toggle (2-col)
row. Both rows live inside the same grid so column widths align.
Info cards are horizontally compact; number inputs and the toggle
get their own tighter row beneath them. */
.arcana-loop-settings-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.5rem;
}
.arcana-loop-setting {
display: flex;
flex-direction: column;
padding: 0.625rem 0.75rem;
background: #fafafa;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
gap: 0.125rem;
transition: border-color 0.15s ease;
min-width: 0;
}
.arcana-loop-setting:hover {
border-color: #d1d5db;
}
.arcana-loop-setting label {
font-size: 0.75rem;
font-weight: 600;
color: #374151;
}
.arcana-loop-setting > small {
font-size: 0.6875rem;
color: #6b7280;
line-height: 1.35;
}
.arcana-loop-setting code {
font-size: 0.625rem;
background: #ede9fe;
color: #6d28d9;
padding: 0.0625rem 0.3125rem;
border-radius: 0.1875rem;
}
.arcana-loop-setting--info {
background: #f5f3ff;
border-color: #ddd6fe;
}
.arcana-loop-setting--info:hover {
border-color: #c4b5fd;
}
.arcana-loop-setting-value {
margin-top: 0.25rem;
font-size: 0.6875rem;
color: #6d28d9;
font-family:
ui-monospace, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Inline temperature row inside an LLM info card. The temperature is
visually attached to the LLM it controls so users can see at a
glance which model each setting affects. */
.arcana-loop-setting-temp {
display: flex;
align-items: center;
gap: 0.375rem;
margin-top: 0.5rem;
padding-top: 0.5rem;
border-top: 1px dashed #ddd6fe;
}
.arcana-loop-setting-temp label {
font-size: 0.625rem;
font-weight: 600;
color: #9ca3af;
text-transform: uppercase;
letter-spacing: 0.04em;
margin: 0;
}
.arcana-loop-setting-temp input[type="number"] {
width: 2.75rem;
margin: 0;
padding: 0.125rem 0.3125rem;
border: 1px solid #ddd6fe;
border-radius: 0.25rem;
font-size: 0.6875rem;
background: white;
color: #6d28d9;
box-sizing: border-box;
/* Hide the spin buttons in WebKit since the field is too narrow
for them to be useful and they consume horizontal space. */
appearance: textfield;
-moz-appearance: textfield;
}
.arcana-loop-setting-temp input[type="number"]::-webkit-inner-spin-button,
.arcana-loop-setting-temp input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.arcana-loop-setting-temp input[type="number"]:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.15);
}
.arcana-loop-setting-temp input[type="number"]:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* Number-input cards (max_iterations, chunk_cap) sit in two
compact columns beneath the four LLM info cards. The remaining
two columns of the row are visually balanced by the full-width
toggle below. */
.arcana-loop-setting--number {
grid-column: span 1;
}
.arcana-loop-setting input[type="number"] {
margin-top: 0.25rem;
width: 100%;
padding: 0.375rem 0.625rem;
border: 1px solid #d1d5db;
border-radius: 0.3125rem;
font-size: 0.8125rem;
background: white;
color: #111827;
box-sizing: border-box;
transition:
border-color 0.15s ease,
box-shadow 0.15s ease;
}
.arcana-loop-setting input[type="number"]:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
.arcana-loop-setting input[type="number"]:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.arcana-loop-setting--toggle {
grid-column: 1 / -1;
flex-direction: row;
align-items: center;
gap: 0.625rem;
padding: 0.5rem 0.75rem;
cursor: pointer;
}
.arcana-loop-setting--toggle:has(input:checked) {
background: #ede9fe;
border-color: #7c3aed;
}
.arcana-loop-setting--toggle:has(input:checked) .arcana-loop-toggle-label {
color: #6d28d9;
}
.arcana-loop-setting--toggle input[type="checkbox"] {
margin: 0;
width: 15px;
height: 15px;
accent-color: #7c3aed;
cursor: pointer;
flex-shrink: 0;
}
.arcana-loop-toggle-content {
display: flex;
flex-direction: row;
align-items: baseline;
gap: 0.5rem;
flex-wrap: wrap;
min-width: 0;
}
.arcana-loop-toggle-label {
font-size: 0.75rem;
font-weight: 600;
color: #374151;
}
.arcana-loop-toggle-content small {
font-size: 0.6875rem;
color: #6b7280;
line-height: 1.3;
}
/* Loop trace: shared visual language for both the live (during run)
and the static (post run) tool history. The live variant adds a
pulsing header and a slide-in animation on each new entry. */
.arcana-loop-trace,
.arcana-loop-live-trace {
margin-top: 1rem;
background: #fafafa;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1rem 1.25rem;
}
.arcana-loop-live-trace {
background: linear-gradient(180deg, #faf5ff 0%, #fafafa 100%);
border-color: #ddd6fe;
}
.arcana-loop-trace h4 {
font-size: 0.75rem;
font-weight: 600;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.06em;
margin: 0 0 0.875rem 0;
display: flex;
align-items: center;
gap: 0.625rem;
}
.arcana-loop-meta {
font-size: 0.6875rem;
font-weight: 500;
color: #9ca3af;
text-transform: none;
letter-spacing: 0;
}
.arcana-loop-meta code {
font-size: 0.6875rem;
background: #ede9fe;
color: #6d28d9;
padding: 0.0625rem 0.375rem;
border-radius: 0.25rem;
}
.arcana-loop-live-header {
display: flex;
align-items: center;
gap: 0.625rem;
font-size: 0.75rem;
font-weight: 600;
color: #6d28d9;
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 0.875rem;
}
.arcana-loop-live-pulse {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background: #7c3aed;
box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.6);
animation: arcana-loop-pulse 1.6s ease-out infinite;
}
@keyframes arcana-loop-pulse {
0% {
box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.6);
}
70% {
box-shadow: 0 0 0 8px rgba(124, 58, 237, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(124, 58, 237, 0);
}
}
.arcana-loop-live-title {
flex: 1;
}
.arcana-loop-live-count {
font-size: 0.6875rem;
font-weight: 500;
color: #9ca3af;
text-transform: none;
letter-spacing: 0;
}
.arcana-loop-live-empty {
font-size: 0.8125rem;
color: #9ca3af;
font-style: italic;
padding: 0.5rem 0 0.25rem;
}
.arcana-loop-iterations {
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
/* Vertical timeline rail running down the left side of the iteration
list. Anchored to the iter-num badge so the rail aligns with the
center of each badge. */
.arcana-loop-iterations::before {
content: '';
position: absolute;
left: 0.875rem;
top: 0.75rem;
bottom: 0.75rem;
width: 2px;
background: #e5e7eb;
border-radius: 1px;
}
.arcana-loop-iterations--live::before {
background: linear-gradient(180deg, #c4b5fd 0%, #ddd6fe 100%);
}
.arcana-loop-iteration {
position: relative;
padding: 0.375rem 0 0.375rem 2.25rem;
min-height: 2.5rem;
display: flex;
align-items: center;
animation: arcana-loop-fade-in 0.35s ease-out both;
}
@keyframes arcana-loop-fade-in {
from {
opacity: 0;
transform: translateY(-4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.arcana-loop-iter-header {
display: flex;
align-items: center;
gap: 0.625rem;
flex-wrap: wrap;
min-height: 1.75rem;
}
.arcana-loop-iter-num {
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 1.75rem;
height: 1.75rem;
display: inline-flex;
align-items: center;
justify-content: center;
background: white;
border: 2px solid #e5e7eb;
border-radius: 50%;
font-size: 0.6875rem;
font-weight: 700;
color: #6b7280;
z-index: 1;
}
.arcana-loop-iterations--live .arcana-loop-iter-num {
border-color: #c4b5fd;
color: #6d28d9;
}
/* Per-tool color coding so search vs answer vs give_up is scannable */
.arcana-tool-search .arcana-loop-iter-num {
border-color: #93c5fd;
color: #1d4ed8;
background: #eff6ff;
}
.arcana-tool-answer .arcana-loop-iter-num {
border-color: #86efac;
color: #15803d;
background: #f0fdf4;
}
.arcana-tool-give_up .arcana-loop-iter-num {
border-color: #fca5a5;
color: #b91c1c;
background: #fef2f2;
}
.arcana-tool-synthesis .arcana-loop-iter-num {
border-color: #fcd34d;
color: #b45309;
background: #fffbeb;
}
.arcana-loop-tool {
font-size: 0.8125rem;
font-weight: 600;
font-family:
ui-monospace, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace;
padding: 0.125rem 0.5rem;
border-radius: 0.25rem;
background: #f3f4f6;
color: #374151;
}
.arcana-tool-search .arcana-loop-tool {
background: #dbeafe;
color: #1d4ed8;
}
.arcana-tool-answer .arcana-loop-tool {
background: #dcfce7;
color: #15803d;
}
.arcana-tool-give_up .arcana-loop-tool {
background: #fee2e2;
color: #b91c1c;
}
.arcana-tool-synthesis .arcana-loop-tool {
background: #fef3c7;
color: #b45309;
}
/* Pipeline step trace: same visual language as the loop trace, but
each entry is a "step" with a running/done state instead of a
completed tool call. The number badge contains a tiny spinner
while running, then becomes a step number when done. */
.arcana-pipeline-iterations::before {
background: linear-gradient(180deg, #c4b5fd 0%, #ddd6fe 100%);
}
.arcana-pipeline-step-trace--running .arcana-loop-iter-num {
background: #f5f3ff;
border-color: #c4b5fd;
color: #6d28d9;
}
.arcana-pipeline-step-trace--running .arcana-loop-tool {
background: #ede9fe;
color: #6d28d9;
}
.arcana-pipeline-step-trace--done .arcana-loop-iter-num {
background: #f0fdf4;
border-color: #86efac;
color: #15803d;
}
.arcana-pipeline-step-trace--done .arcana-loop-tool {
background: #dcfce7;
color: #15803d;
}
.arcana-pipeline-step-spinner {
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
border: 2px solid rgba(124, 58, 237, 0.25);
border-top-color: #7c3aed;
animation: arcana-pipeline-spin 0.8s linear infinite;
}
@keyframes arcana-pipeline-spin {
to {
transform: rotate(360deg);
}
}
.arcana-loop-args {
font-size: 0.8125rem;
color: #4b5563;
font-family:
ui-monospace, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace;
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.arcana-loop-chunk-count {
font-size: 0.6875rem;
font-weight: 600;
color: #6d28d9;
background: #ede9fe;
padding: 0.125rem 0.5rem;
border-radius: 999px;
flex-shrink: 0;
}
.arcana-checkbox-label {
display: flex;
flex-direction: column;
padding: 0.75rem;
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-checkbox-label:hover {
border-color: #7c3aed;
}
.arcana-checkbox-label input[type="checkbox"] {
position: absolute;
opacity: 0;
width: 0;
height: 0;
}
.arcana-checkbox-label span {
font-size: 0.875rem;
font-weight: 500;
color: #374151;
}
.arcana-checkbox-label small {
font-size: 0.75rem;
color: #6b7280;
margin-top: 0.25rem;
}
.arcana-checkbox-label:has(input:checked) {
background: #ede9fe;
border-color: #7c3aed;
}
.arcana-checkbox-label:has(input:checked) span {
color: #6d28d9;
}
.arcana-checkbox-label:has(input:disabled) {
opacity: 0.5;
cursor: not-allowed;
}
.arcana-ask-actions {
display: flex;
gap: 0.5rem;
margin-top: 1rem;
}
.arcana-ask-actions button {
background: #7c3aed;
color: white;
padding: 0.625rem 1.25rem;
border: none;
border-radius: 0.375rem;
font-size: 0.875rem;
font-weight: 500;
cursor: pointer;
transition: background-color 0.15s ease;
}
.arcana-ask-actions button:hover {
background: #6d28d9;
}
.arcana-ask-actions button:disabled {
background: #9ca3af;
cursor: not-allowed;
}
.arcana-ask-actions button[type="button"] {
background: transparent;
color: #6b7280;
border: 1px solid #d1d5db;
}
.arcana-ask-actions button[type="button"]:hover {
border-color: #7c3aed;
color: #7c3aed;
background: transparent;
}
.arcana-ask-loading {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 1.5rem;
background: #f9fafb;
border-radius: 0.5rem;
color: #6b7280;
}
.arcana-spinner {
width: 1.25rem;
height: 1.25rem;
border: 2px solid #e5e7eb;
border-top-color: #7c3aed;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.arcana-ask-results {
margin-top: 1.5rem;
}
.arcana-ask-answer {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
overflow: hidden;
margin-bottom: 1rem;
}
.arcana-ask-answer h3 {
margin: 0;
padding: 0.75rem 1rem;
background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%);
color: white;
font-size: 0.875rem;
font-weight: 600;
}
.arcana-answer-content {
padding: 1rem 1.25rem;
font-size: 0.875rem;
line-height: 1.6;
color: #1f2937;
}
/* Markdown elements inside a rendered answer. Earmark produces
standard HTML, so we style a minimal set: paragraphs, lists,
inline emphasis, inline code, and a few headers. */
.arcana-answer-content > :first-child {
margin-top: 0;
}
.arcana-answer-content > :last-child {
margin-bottom: 0;
}
.arcana-answer-content p {
margin: 0 0 0.75rem 0;
}
.arcana-answer-content ul,
.arcana-answer-content ol {
margin: 0 0 0.75rem 0;
padding-left: 1.5rem;
}
.arcana-answer-content li {
margin-bottom: 0.25rem;
}
.arcana-answer-content li > ul,
.arcana-answer-content li > ol {
margin-top: 0.25rem;
margin-bottom: 0.25rem;
}
.arcana-answer-content strong {
font-weight: 600;
color: #111827;
}
.arcana-answer-content em {
font-style: italic;
}
.arcana-answer-content code {
background: #f3f4f6;
color: #7c3aed;
padding: 0.0625rem 0.375rem;
border-radius: 0.25rem;
font-size: 0.8125rem;
font-family:
ui-monospace, "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono", monospace;
}
.arcana-answer-content pre {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
padding: 0.75rem;
overflow-x: auto;
margin: 0 0 0.75rem 0;
}
.arcana-answer-content pre code {
background: transparent;
color: inherit;
padding: 0;
}
.arcana-answer-content h1,
.arcana-answer-content h2,
.arcana-answer-content h3,
.arcana-answer-content h4,
.arcana-answer-content h5,
.arcana-answer-content h6 {
font-weight: 700;
color: #1f2937;
margin: 1.5rem 0 0.5rem 0;
line-height: 1.3;
}
/* First heading shouldn't push down — there's already padding above. */
.arcana-answer-content > :first-child:is(h1, h2, h3, h4, h5, h6) {
margin-top: 0;
}
.arcana-answer-content h1 {
font-size: 1.25rem;
color: #111827;
padding-bottom: 0.375rem;
border-bottom: 2px solid #ede9fe;
}
/* h2 is the most common section heading the LLM emits. Distinctive
but not loud: a left accent bar + a slightly bigger size + a touch
of color. */
.arcana-answer-content h2 {
font-size: 1.0625rem;
color: #6d28d9;
padding-left: 0.75rem;
border-left: 3px solid #7c3aed;
}
.arcana-answer-content h3 {
font-size: 0.9375rem;
color: #4b5563;
text-transform: uppercase;
letter-spacing: 0.04em;
font-weight: 600;
}
.arcana-answer-content h4,
.arcana-answer-content h5,
.arcana-answer-content h6 {
font-size: 0.875rem;
color: #4b5563;
font-weight: 600;
}
.arcana-answer-content blockquote {
border-left: 3px solid #c4b5fd;
padding-left: 0.875rem;
color: #4b5563;
margin: 0 0 0.75rem 0;
}
.arcana-answer-content a {
color: #7c3aed;
text-decoration: underline;
}
.arcana-answer-content a:hover {
color: #6d28d9;
}
.arcana-ask-section {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 1rem;
margin-bottom: 1rem;
}
.arcana-ask-section h4 {
margin: 0 0 0.75rem 0;
font-size: 0.875rem;
font-weight: 600;
color: #374151;
}
.arcana-query-list {
margin: 0;
padding-left: 1.5rem;
font-size: 0.875rem;
color: #374151;
}
.arcana-query-list li {
margin-bottom: 0.25rem;
}
/* Pipeline internals: one block below the answer that shows what each
pipeline step produced (rewritten query, gate decision, sub-questions,
etc). Renders as a <dl> with each step's label + value on one line. */
.arcana-pipeline-internals-list {
display: grid;
grid-template-columns: max-content 1fr;
gap: 0.5rem 1rem;
margin: 0;
font-size: 0.875rem;
}
.arcana-pipeline-internals-list dt {
font-weight: 600;
color: #6d28d9;
white-space: nowrap;
}
.arcana-pipeline-internals-list dd {
margin: 0;
color: #374151;
min-width: 0;
}
.arcana-pipeline-internals-quote {
font-family: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace;
font-size: 0.8125rem;
color: #4b5563;
background: #f9fafb;
padding: 0.125rem 0.5rem;
border-radius: 0.25rem;
display: inline-block;
}
.arcana-pipeline-internals-badge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.75rem;
font-weight: 600;
}
.arcana-pipeline-internals-badge.skip {
background: #fef3c7;
color: #b45309;
}
.arcana-pipeline-internals-badge.retrieve {
background: #dbeafe;
color: #1d4ed8;
}
.arcana-pipeline-internals-badge.neutral {
background: #f3f4f6;
color: #6b7280;
}
.arcana-pipeline-internals-reasoning {
display: block;
margin-top: 0.25rem;
font-size: 0.8125rem;
color: #6b7280;
font-style: italic;
}
.arcana-pipeline-internals-feedback {
font-size: 0.8125rem;
color: #6b7280;
font-style: italic;
margin-bottom: 0.25rem;
}
.arcana-collection-badges {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.arcana-collection-badge {
background: #ede9fe;
color: #6d28d9;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
/* Grounding Styles */
.arcana-grounding-score {
font-weight: 500;
font-size: 0.75rem;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
margin-left: 0.5rem;
}
.arcana-grounding-score.good { background: #d1fae5; color: #065f46; }
.arcana-grounding-score.warn { background: #fef3c7; color: #92400e; }
.arcana-grounding-score.bad { background: #fee2e2; color: #991b1b; }
.arcana-grounding-spans h5 {
font-size: 0.8rem;
font-weight: 600;
color: #6b7280;
margin: 0.75rem 0 0.5rem 0;
}
.arcana-span {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem;
padding: 0.375rem 0.5rem;
border-radius: 0.375rem;
margin-bottom: 0.25rem;
font-size: 0.8rem;
}
.arcana-span.hallucinated {
background: #fef2f2;
border-left: 3px solid #ef4444;
}
.arcana-span.faithful {
background: #f0fdf4;
border-left: 3px solid #22c55e;
}
.arcana-span-text {
font-family: ui-monospace, monospace;
font-size: 0.8rem;
}
.arcana-span-score {
font-size: 0.7rem;
color: #9ca3af;
}
.arcana-span-sources {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
width: 100%;
}
.arcana-source-badge {
font-size: 0.65rem;
background: #f3f4f6;
color: #6b7280;
padding: 0.125rem 0.375rem;
border-radius: 0.25rem;
}
.arcana-source-badge.clickable {
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 0.25rem;
list-style: none;
}
.arcana-source-badge.clickable:hover {
background: #e5e7eb;
}
.arcana-source-badge.clickable::-webkit-details-marker {
display: none;
}
.arcana-source-label {
font-weight: 600;
color: #4b5563;
}
.arcana-source-overlap {
color: #9ca3af;
}
.arcana-source-detail {
display: inline;
}
.arcana-source-preview {
font-size: 0.7rem;
color: #4b5563;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.25rem;
padding: 0.5rem;
margin-top: 0.375rem;
margin-bottom: 0.25rem;
line-height: 1.5;
width: 100%;
}
/* Answer highlighting */
.arcana-hl-hallucinated {
background: #fecaca;
border-bottom: 2px solid #ef4444;
border-radius: 2px;
padding: 0 1px;
}
.arcana-hl-faithful {
background: #bbf7d0;
border-bottom: 2px solid #22c55e;
border-radius: 2px;
padding: 0 1px;
}
/* Graph Tab Styles */
.arcana-graph-subtabs {
display: flex;
gap: 0.5rem;
margin-bottom: 1.5rem;
}
.arcana-subtab-btn {
padding: 0.5rem 1rem;
border: 1px solid #d1d5db;
background: white;
border-radius: 0.375rem;
font-size: 0.875rem;
cursor: pointer;
transition: all 0.15s ease;
}
.arcana-subtab-btn:hover {
border-color: #7c3aed;
color: #7c3aed;
}
.arcana-subtab-btn.active {
background: #7c3aed;
border-color: #7c3aed;
color: white;
}
.arcana-graph-table {
margin-top: 1rem;
}
/* Entity type badges */
.arcana-entity-type-badge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
text-transform: lowercase;
}
.arcana-entity-type-badge.person {
background: #dbeafe;
color: #1e40af;
}
.arcana-entity-type-badge.organization {
background: #dcfce7;
color: #166534;
}
.arcana-entity-type-badge.technology {
background: #fce7f3;
color: #9d174d;
}
.arcana-entity-type-badge.concept {
background: #fef3c7;
color: #92400e;
}
.arcana-entity-type-badge.location {
background: #e0e7ff;
color: #3730a3;
}
.arcana-entity-type-badge.event {
background: #f3e8ff;
color: #6b21a8;
}
/* Relationship strength meter */
.arcana-strength-meter {
display: inline-flex;
gap: 2px;
align-items: center;
}
.arcana-strength-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: #e5e7eb;
}
.arcana-strength-dot.filled {
background: #7c3aed;
}
/* Community status indicators */
.arcana-status-ready {
color: #16a34a;
}
.arcana-status-pending {
color: #d97706;
}
.arcana-status-empty {
color: #9ca3af;
}
.arcana-no-summary {
color: #9ca3af;
font-style: italic;
}
/* Graph empty state */
.arcana-empty-state {
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
padding: 2rem;
text-align: center;
}
.arcana-empty-state h3 {
margin: 0 0 1rem 0;
color: #374151;
}
.arcana-empty-state p {
color: #6b7280;
margin: 0.5rem 0;
}
.arcana-empty-state pre {
background: #1f2937;
color: #e5e7eb;
padding: 0.75rem 1rem;
border-radius: 0.375rem;
display: inline-block;
margin: 1rem 0;
font-size: 0.875rem;
}
.arcana-empty-state code {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
}
/* Entity detail panel */
.arcana-entity-row {
cursor: pointer;
transition: background-color 0.15s;
}
.arcana-entity-row.selected {
background: #ede9fe;
}
.arcana-entity-detail {
margin-top: 1.5rem;
padding: 1.5rem;
background: #faf5ff;
border: 1px solid #e9d5ff;
border-radius: 0.5rem;
}
.arcana-entity-detail-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1rem;
}
.arcana-entity-detail-header h3 {
margin: 0;
font-size: 1.125rem;
color: #1f2937;
}
.arcana-entity-detail-close {
margin-left: auto;
background: transparent;
border: none;
font-size: 1.5rem;
color: #6b7280;
cursor: pointer;
padding: 0;
line-height: 1;
}
.arcana-entity-detail-close:hover {
color: #374151;
}
.arcana-entity-description {
color: #4b5563;
margin: 0 0 1rem 0;
}
.arcana-entity-relationships h4,
.arcana-entity-mentions h4 {
margin: 0 0 0.5rem 0;
font-size: 0.875rem;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.arcana-rel-cards {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.arcana-rel-card {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
font-size: 0.875rem;
}
.arcana-rel-type {
font-family: monospace;
background: #ede9fe;
color: #5b21b6;
padding: 0.125rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
}
.arcana-rel-arrow {
color: #9ca3af;
font-weight: bold;
}
.arcana-rel-target,
.arcana-rel-source {
font-weight: 500;
color: #1f2937;
}
.arcana-rel-self {
color: #6b7280;
font-style: italic;
font-size: 0.75rem;
}
.arcana-mention-preview {
background: white;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
padding: 0.75rem;
margin-bottom: 0.5rem;
}
.arcana-mention-preview p {
margin: 0 0 0.5rem 0;
font-size: 0.875rem;
color: #374151;
}
.arcana-view-in-docs {
font-size: 0.75rem;
color: #7c3aed;
text-decoration: none;
}
.arcana-view-in-docs:hover {
text-decoration: underline;
}
/* Relationship detail panel */
.arcana-relationship-row {
cursor: pointer;
transition: background-color 0.15s;
}
.arcana-relationship-row.selected {
background: #ede9fe;
}
.arcana-relationship-detail {
margin-top: 1.5rem;
padding: 1.5rem;
background: #faf5ff;
border: 1px solid #e9d5ff;
border-radius: 0.5rem;
}
.arcana-relationship-detail-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
}
.arcana-relationship-visual {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 1rem;
}
.arcana-relationship-source,
.arcana-relationship-target {
font-weight: 600;
color: #1f2937;
}
.arcana-relationship-arrow {
color: #9ca3af;
}
.arcana-relationship-type {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
font-size: 0.875rem;
background: #ede9fe;
color: #6d28d9;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
}
.arcana-relationship-detail-close {
background: transparent;
border: none;
font-size: 1.5rem;
color: #6b7280;
cursor: pointer;
padding: 0;
line-height: 1;
}
.arcana-relationship-detail-close:hover {
color: #374151;
}
.arcana-relationship-strength {
margin-bottom: 0.75rem;
color: #4b5563;
}
.arcana-relationship-description {
color: #4b5563;
margin: 0;
}
.arcana-empty-hint {
font-size: 0.8125rem;
}
/* Community detail panel */
.arcana-community-row {
cursor: pointer;
transition: background-color 0.15s;
}
.arcana-community-row.selected {
background: #ede9fe;
}
.arcana-community-detail {
margin-top: 1.5rem;
padding: 1.5rem;
background: #faf5ff;
border: 1px solid #e9d5ff;
border-radius: 0.5rem;
}
.arcana-community-detail-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1rem;
}
.arcana-community-detail-header h3 {
margin: 0;
font-size: 1.125rem;
color: #1f2937;
}
.arcana-community-level-badge {
display: inline-block;
padding: 0.125rem 0.5rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
background: #ddd6fe;
color: #5b21b6;
}
.arcana-community-detail-close {
margin-left: auto;
background: transparent;
border: none;
font-size: 1.5rem;
color: #6b7280;
cursor: pointer;
padding: 0;
line-height: 1;
}
.arcana-community-detail-close:hover {
color: #374151;
}
.arcana-community-summary,
.arcana-community-entities,
.arcana-community-relationships {
margin-bottom: 1rem;
}
.arcana-community-summary h4,
.arcana-community-entities h4,
.arcana-community-relationships h4 {
margin: 0 0 0.5rem 0;
font-size: 0.875rem;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.arcana-community-summary p {
margin: 0;
color: #374151;
line-height: 1.5;
}
.arcana-community-entities ul,
.arcana-community-relationships ul {
list-style: none;
padding: 0;
margin: 0;
}
.arcana-community-entities li,
.arcana-community-relationships li {
padding: 0.5rem 0;
border-bottom: 1px solid #e5e7eb;
display: flex;
align-items: center;
gap: 0.5rem;
}
.arcana-community-entities li:last-child,
.arcana-community-relationships li:last-child {
border-bottom: none;
}
.arcana-community-no-summary {
color: #9ca3af;
font-style: italic;
}
/* Collection selector */
.arcana-collection-selector {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1rem;
}
.arcana-collection-selector label {
font-size: 0.875rem;
font-weight: 500;
color: #374151;
}
.arcana-collection-selector select {
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
font-size: 0.875rem;
min-width: 200px;
}
.arcana-collection-selector select:focus {
outline: none;
border-color: #7c3aed;
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.1);
}
/* Entity/Relationship/Community views */
.arcana-entities-view,
.arcana-relationships-view,
.arcana-communities-view {
margin-top: 1rem;
}
/* Deep Search toggle (simple mode, below textarea) */
.arcana-deep-search-toggle {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
margin-top: 0.5rem;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.375rem;
cursor: pointer;
font-size: 0.8125rem;
}
.arcana-deep-search-toggle:hover {
background: #f3f4f6;
}
.arcana-deep-search-toggle input[type="checkbox"] {
accent-color: #7c3aed;
}
.arcana-deep-search-toggle span {
font-weight: 500;
color: #374151;
}
.arcana-deep-search-toggle small {
color: #6b7280;
font-size: 0.75rem;
}
/* Graph Context section */
.arcana-graph-context {
margin: 1.5rem 0;
padding: 1rem;
background: linear-gradient(to right, #faf5ff, #f3e8ff);
border: 1px solid #e9d5ff;
border-radius: 0.5rem;
}
.arcana-graph-context-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
}
.arcana-graph-context-header h4 {
margin: 0;
color: #7c3aed;
font-size: 1rem;
}
.arcana-toggle-btn {
background: transparent;
border: 1px solid #d8b4fe;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
cursor: pointer;
color: #7c3aed;
font-size: 0.75rem;
}
.arcana-toggle-btn:hover {
background: #f3e8ff;
}
.arcana-no-matches {
color: #9ca3af;
font-style: italic;
margin: 0.5rem 0;
}
.arcana-matched-entities,
.arcana-matched-relationships {
margin-top: 0.75rem;
}
.arcana-matched-entities h5,
.arcana-matched-relationships h5 {
margin: 0 0 0.5rem 0;
font-size: 0.875rem;
color: #6b21a8;
}
.arcana-matched-entities ul,
.arcana-matched-relationships ul {
list-style: none;
padding: 0;
margin: 0;
}
.arcana-matched-entities li,
.arcana-matched-relationships li {
padding: 0.375rem 0;
display: flex;
align-items: center;
gap: 0.5rem;
border-bottom: 1px solid #f3e8ff;
}
.arcana-matched-entities li:last-child,
.arcana-matched-relationships li:last-child {
border-bottom: none;
}
.arcana-entity-name {
font-weight: 500;
color: #1f2937;
}
.arcana-entity-type {
font-size: 0.75rem;
padding: 0.125rem 0.5rem;
background: #e9d5ff;
color: #7c3aed;
border-radius: 9999px;
}
.arcana-view-in-graph {
margin-left: auto;
font-size: 0.75rem;
color: #7c3aed;
text-decoration: none;
}
.arcana-view-in-graph:hover {
text-decoration: underline;
}
.arcana-rel-source,
.arcana-rel-target {
color: #1f2937;
}
.arcana-rel-type {
font-size: 0.75rem;
color: #7c3aed;
font-family: monospace;
}
/* Graph attribution in chunks */
.arcana-graph-attribution {
display: block;
font-size: 0.75rem;
color: #7c3aed;
margin-top: 0.25rem;
font-style: italic;
}
"""
@css_hash :crypto.hash(:md5, @css) |> Base.encode16(case: :lower) |> binary_part(0, 8)
@doc """
Returns the current hash for the given asset type.
"""
def current_hash(:js), do: @js_hash
def current_hash(:css), do: @css_hash
@impl Plug
def init(asset), do: asset
@impl Plug
def call(conn, asset) do
{content, content_type} =
case asset do
:js -> {@js, "text/javascript"}
:css -> {@css, "text/css"}
end
conn
|> Plug.Conn.put_resp_header("content-type", content_type)
|> Plug.Conn.put_resp_header("cache-control", "public, max-age=31536000, immutable")
|> Plug.Conn.delete_resp_header("x-frame-options")
|> Plug.Conn.put_private(:plug_skip_csrf_protection, true)
|> Plug.Conn.send_resp(200, content)
end
end