/* Hero Inspector Dashboard Styles */

:root {
    --status-ok: #198754;
    --status-warn: #ffc107;
    --status-error: #dc3545;
    --ui-scale: 1;
}

/* Resolution scaling — all rem values scale with --ui-scale */
html { font-size: calc(16px * var(--ui-scale)); height: 100%; }

/* Compact sizing */
/* The shell is a fixed-height column: navbar + tabs stay pinned at the top and
   never scroll; only the content area below scrolls. This keeps the whole UI
   within the window height instead of pushing the navbar off-screen. */
body {
    font-size: 0.85rem;
    height: 100vh;
    margin: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}
/* Navbar + tabs strip: natural height, never shrink, never scroll away. */
body > nav.navbar,
body > .container-fluid.border-bottom { flex: 0 0 auto; }
/* Main content wrapper: fills the remaining height and owns the scroll. */
body > .container-fluid.p-0 {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}
.form-control, .form-select { font-size: 0.85rem; }
.form-label { font-size: 0.85rem; margin-bottom: 0.25rem; }
.btn { font-size: 0.85rem; }
/* Outline-secondary buttons mirror Bootstrap's btn-outline-warning exactly —
   visible border + colored text, fills solid on hover — but in a clearly
   visible gray instead of yellow. Bootstrap's default secondary gray (#6c757d)
   is too dim against the dashboard chrome and reads as plain text; gray-500
   (#adb5bd) gives the same "obviously clickable" contrast warning has. */
.btn-outline-secondary {
    --bs-btn-color: #adb5bd;
    --bs-btn-border-color: #adb5bd;
    --bs-btn-hover-color: #000;
    --bs-btn-hover-bg: #adb5bd;
    --bs-btn-hover-border-color: #adb5bd;
    --bs-btn-active-color: #000;
    --bs-btn-active-bg: #adb5bd;
    --bs-btn-active-border-color: #adb5bd;
}
.tab-content { font-size: 0.85rem; }
.nav-tabs .nav-link { font-size: 0.85rem; padding: 0.4rem 0.75rem; }
textarea.form-control { font-size: 0.8rem; }

/* Status dots — service list (sidebar/service cards) */
.status-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.status-ok    { background: var(--status-ok); }
.status-warn  { background: var(--status-warn); }
.status-error { background: var(--status-error); }
.status-off   { background: #6c757d; animation: none; }

/* Connection status widget (navbar dot) — states set by connection-status.js.
   JS sets className='status-dot' for connected (no extra class), so target by ID. */
#status-dot                { background: var(--status-ok);    animation: pulse 2s infinite; }
#status-dot.backend-down   { background: var(--status-warn);  animation: pulse 3s infinite; }
#status-dot.disconnected   { background: var(--status-error); animation: none; }

/* Label next to dot — only visible in degraded states */
.status-label { font-size: 0.7rem; color: var(--bs-secondary-color, #6c757d); margin-left: 4px; display: none; vertical-align: middle; }
#status-dot.disconnected ~ .status-label,
#status-dot.backend-down  ~ .status-label { display: inline; }

@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }

/* Spinning refresh icon: rotate the existing glyph in place (transform only, no
   box/layout change) so loading state never reflows or stutters on hover. */
@keyframes hero-spin { to { transform: rotate(360deg); } }
.icon-spin { animation: hero-spin 0.8s linear infinite; display: inline-block; }

/* Loading buttons must not react to the pointer: kills hover styles/flicker
   while a refresh/scan/clean action is in flight. Covers both spinner styles
   (in-place icon spin and the swapped-in spinner-border) plus disabled. */
.btn:disabled,
.btn.disabled,
.btn:has(.icon-spin),
.btn:has(.spinner-border) {
    pointer-events: none;
    cursor: default;
}

/* Service-list loading state: dim the list and overlay a spinner while a
   header action (scan / clean) is in flight, so the reload is obvious. */
#sidebar-service-list { position: relative; transition: opacity 0.15s ease; }
#sidebar-service-list.list-loading { opacity: 0.4; pointer-events: none; }
#sidebar-service-list.list-loading::after {
    content: "";
    position: absolute;
    top: 1.25rem;
    left: 50%;
    width: 1.5rem;
    height: 1.5rem;
    margin-left: -0.75rem;
    border: 0.18rem solid var(--bs-secondary-color, #6c757d);
    border-right-color: transparent;
    border-radius: 50%;
    animation: hero-spin 0.7s linear infinite;
}

/* Pre / code blocks */
pre {
    background: var(--bs-tertiary-bg);
    padding: 1rem;
    border-radius: 0.5rem;
    overflow-x: auto;
    font-size: 0.8rem;
}
.code-block { white-space: pre-wrap; word-break: break-all; }

/* ─── Full-viewport layout ────────────────────────────────────────── */
/* Fill the scrollable content wrapper exactly (its height is already viewport
   minus navbar+tabs via the body flex column), so the sidebar/main columns
   scroll internally and the page itself never scrolls. */
.router-layout {
    height: 100%;
}

.sidebar-column {
    overflow-y: auto;
    height: 100%;
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
}

.sidebar-column > .card {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.sidebar-column > .card > .card-body {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
}

.main-column {
    overflow: hidden;
    height: 100%;
    padding: 0.75rem;
}

/* ─── Service detail flex column ──────────────────────────────────── */
.service-detail-layout {
    display: flex;
    flex-direction: column;
    height: 100%;
}

/* Single card: header + tabs + scrollable body */
.service-card-island {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.service-card-island > :not(.service-card-body) {
    flex-shrink: 0;
}

.service-card-body {
    overflow-y: auto;
    flex: 1 1 0;
    min-height: 0;
}

/* Sidebar section headers */
.sidebar-section-header {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bs-secondary-color);
    padding: 0.4rem 0.4rem 0.2rem;
    margin-top: 0.25rem;
}

/* Service list items */
.service-item {
    cursor: pointer;
    padding: 0.3rem 0.4rem;
    border-radius: 4px;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    text-decoration: none;
    color: inherit;
    position: relative;
}
.service-item:hover { background: var(--bs-secondary-bg); color: inherit; }
.service-item.active, .service-item[aria-current="true"] {
    background: var(--bs-primary-bg-subtle);
    color: var(--bs-primary-text-emphasis);
}
.service-item .method-count {
    margin-left: auto;
    font-size: 0.7rem;
    flex-shrink: 0;
}
.service-item .remove-btn {
    display: none;
    background: none;
    border: none;
    padding: 0 0.2rem;
    color: var(--bs-secondary-color);
    cursor: pointer;
    flex-shrink: 0;
    line-height: 1;
}
.service-item .remove-btn:hover { color: var(--bs-danger); }
.service-item:hover .remove-btn { display: inline-flex; }

/* Method accordion compact */
.method-accordion .accordion-button {
    padding: 0.4rem 0.75rem;
    font-size: 0.85rem;
}
.method-accordion .accordion-body {
    padding: 0.5rem 0.75rem;
}
.accordion-button { font-size: 0.85rem; }

/* OpenRPC JSON display */
.openrpc-json {
    background: var(--bs-tertiary-bg);
    padding: 1.25rem;
    padding-top: 2.5rem;
    border-radius: 0.5rem;
    overflow: auto;
    max-height: 70vh;
    font-size: 0.8rem;
    line-height: 1.5;
    font-family: 'SF Mono', 'Fira Code', 'JetBrains Mono', 'Cascadia Code', 'Consolas', monospace;
}

/* JSON syntax highlighting */
.json-key { color: #79c0ff; }
.json-string { color: #a5d6ff; }
.json-number { color: #f0883e; }
.json-boolean { color: #ff7b72; }
.json-null { color: #8b949e; font-style: italic; }

[data-bs-theme="light"] .json-key { color: #0550ae; }
[data-bs-theme="light"] .json-string { color: #0a3069; }
[data-bs-theme="light"] .json-number { color: #953800; }
[data-bs-theme="light"] .json-boolean { color: #cf222e; }
[data-bs-theme="light"] .json-null { color: #6e7781; }

/* Copy button overlay */
.copy-btn {
    opacity: 0.7;
    transition: opacity 0.15s;
}
.copy-btn:hover { opacity: 1; }

/* Markdown content in tabs */
.markdown-content {
    background: var(--bs-body-bg);
    padding: 1.5rem;
    padding-top: 2.5rem;
    border-radius: 0.5rem;
    border: 1px solid var(--bs-border-color);
    line-height: 1.7;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
    font-size: 0.9rem;
}

.markdown-content h1 {
    border-bottom: 2px solid var(--bs-border-color);
    padding-bottom: 0.5rem;
    margin-top: 1.5rem;
    margin-bottom: 0.75rem;
    font-size: 1.75rem;
}

.markdown-content h1:first-child {
    margin-top: 0;
}

.markdown-content h2 {
    border-left: 4px solid var(--bs-primary);
    padding-left: 0.75rem;
    margin-top: 1.25rem;
    margin-bottom: 0.5rem;
    font-size: 1.35rem;
}

.markdown-content h3 {
    margin-top: 1rem;
    margin-bottom: 0.5rem;
    color: var(--bs-secondary);
    font-size: 1.1rem;
}

.markdown-content code {
    background: var(--bs-tertiary-bg);
    padding: 0.2em 0.4em;
    border-radius: 0.25rem;
    color: var(--bs-success);
    font-size: 0.9em;
}

.markdown-content pre {
    background: var(--bs-tertiary-bg);
    padding: 1rem;
    border-radius: 0.5rem;
    border-left: 4px solid var(--bs-info);
    overflow-x: auto;
    margin-bottom: 1rem;
}

.markdown-content pre code {
    background: none;
    padding: 0;
    color: inherit;
}

.markdown-content blockquote {
    border-left: 4px solid var(--bs-warning);
    padding-left: 1rem;
    margin-left: 0;
    margin-bottom: 1rem;
    color: var(--bs-secondary);
}

.markdown-content table {
    width: 100%;
    border-collapse: collapse;
    margin: 1rem 0;
}

.markdown-content table thead {
    background: var(--bs-tertiary-bg);
}

.markdown-content table th,
.markdown-content table td {
    border: 1px solid var(--bs-border-color);
    padding: 0.75rem;
    text-align: left;
}

.markdown-content ul,
.markdown-content ol {
    margin-bottom: 1rem;
    padding-left: 2rem;
}

.markdown-content li {
    margin-bottom: 0.5rem;
}

/* Sidebar dual-status badges */
.sidebar-dual-status {
    font-size: 0.6rem;
    flex-shrink: 0;
}

/* ─── OpenRPC inner split layout ─────────────────────────────────── */
.openrpc-inner-layout {
    display: flex;
    gap: 0.5rem;
    height: 100%;
}

.openrpc-inner-sidebar {
    width: 180px;
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
}

.openrpc-inner-sidebar > .card {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.openrpc-inner-content {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.openrpc-inner-content > .card {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.openrpc-inner-content > .card > .card-body {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
}

/* Inner sidebar items */
.openrpc-nav-item {
    cursor: pointer;
    padding: 0.4rem 0.6rem;
    border-radius: 4px;
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.82rem;
    color: inherit;
}
.openrpc-nav-item:hover { background: var(--bs-secondary-bg); }
.openrpc-nav-item.active {
    background: var(--bs-primary-bg-subtle);
    color: var(--bs-primary-text-emphasis);
}

/* Embedded UI iframe */
.ui-iframe-container {
    display: flex;
    flex-direction: column;
    height: 100%;
}

.embedded-ui-iframe {
    width: 100%;
    flex: 1 1 0;
    min-height: 300px;
    border: none;
    background: var(--bs-body-bg);
}

/* Nested schema tables */
.accordion-body .table .table {
    font-size: 0.78rem;
    margin-top: 0.25rem;
    margin-bottom: 0.25rem;
    background: var(--bs-tertiary-bg);
}

.accordion-body .table .table td,
.accordion-body .table .table th {
    padding: 0.2rem 0.5rem;
}

/* Light mode overrides */
[data-bs-theme="light"] pre {
    background: var(--bs-tertiary-bg);
    color: var(--bs-body-color);
}
[data-bs-theme="light"] .service-item .method-count.bg-secondary {
    background-color: var(--bs-primary) !important;
    color: #fff !important;
}
[data-bs-theme="light"] .service-item .method-count.bg-body-secondary {
    background-color: var(--bs-secondary-bg) !important;
    color: var(--bs-body-color) !important;
}

/* Fix bootstrap-icons font path for local serving (relative to css/ dir) */
@font-face {
    font-family: "bootstrap-icons";
    src: url("../fonts/bootstrap-icons.woff2") format("woff2"),
         url("../fonts/bootstrap-icons.woff") format("woff");
}

/* Home page */
.home-service-card {
    transition: transform 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
}
.home-service-card:hover {
    transform: translateY(-2px);
    border-color: var(--bs-info);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
}

/* Sidebar service filter */
#sidebarSearchClear {
    z-index: 2;
    box-shadow: none;
    text-decoration: none;
}
#sidebar-empty {
    border-top: 1px solid var(--bs-border-color, #dee2e6);
    font-style: italic;
}
