/*********************************************************************
 *
 * Copyright (c) 2026 Prometheus Platform LLC — All Rights Reserved.
 *
 * UNAUTHORIZED COPYING, MODIFICATION, DISTRIBUTION, OR USE OF THIS
 * SOFTWARE IS STRICTLY PROHIBITED.
 *
 *********************************************************************/

:root {
    /* Token values aligned to the LIVE Sibyl dashboard palette (see
       src/public/index.html :root) so this styleguide renders exactly how
       the real app looks. The internal Prometheus-era names (--panel,
       --accent, --ok/--warn/--err) are KEPT so the 2k-line ported CSS keeps
       working; the live-named aliases below are what new catalog sections
       and the app actually use (--surface, --blue, --green, …). */
    --bg:        #0d1117;
    --panel:     #161b22;
    --border:    #30363d;
    --text:      #e6edf3;
    --muted:     #8b949e;
    --accent:    #58a6ff;  /* live Sibyl blue */
    --ok:        #3fb950;
    --warn:      #d29922;
    --err:       #f85149;

    /* Live-named aliases — the canonical vocabulary the catalog teaches and
       the dashboard uses. Map onto the values above so both name sets work. */
    --surface:   var(--panel);
    --blue:      var(--accent);
    --green:     var(--ok);
    --yellow:    var(--warn);
    --red:       var(--err);

    /* Derived tints — auto-update when --accent changes (color-mix is well-
       supported in 2026: Chrome 111+, Firefox 113+, Safari 16.2+). */
    --accent-faint:  color-mix(in srgb, var(--accent) 6%,  transparent);
    --accent-soft:   color-mix(in srgb, var(--accent) 12%, transparent);
    --accent-mid:    color-mix(in srgb, var(--accent) 35%, transparent);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font: 14px/1.5 -apple-system, "Segoe UI", system-ui, sans-serif;
    /* Layout shell: topbar across the top, sidebar pinned left, content fills
       the rest. Sidebar collapses on narrow viewports — see the @media block
       at the bottom of this file. */
    display: grid;
    grid-template-columns: 220px 1fr;
    grid-template-rows: 48px 1fr;
    grid-template-areas:
        "topbar  topbar"
        "sidebar content";
    min-height: 100vh;
}

/* Default link color — body text, no underline. Hover lights to accent +
   underline for affordance. Specific surfaces (.sidebar-nav, .sg-toc,
   .filter-chip) override this with their own rules. */
a { color: var(--text); text-decoration: none; }
a:hover { color: var(--accent); text-decoration: underline; }

/* ─── Topbar ─────────────────────────────────────────────────────── */

.topbar {
    grid-area: topbar;
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 0 16px;
    border-bottom: 1px solid var(--border);
    background: var(--panel);
}
.topbar-menu-toggle {
    /* Hidden on desktop — only surfaces on the mobile breakpoint. Local rules
       since global button is too padded for the topbar. */
    display: none;
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text);
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    font: inherit;
    font-size: 16px;
    line-height: 1;
}
.topbar-menu-toggle:hover { background: rgba(255,255,255,0.04); }

.brand {
    font-weight: 600;
    color: var(--accent);
}
.topbar-spacer { flex: 1; }
.topbar-meta {
    color: var(--muted);
    font-size: 12px;
}

/* ─── Sidebar ────────────────────────────────────────────────────── */

.sidebar {
    grid-area: sidebar;
    background: var(--panel);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    padding: 16px 0;
}
.sidebar-nav {
    display: flex;
    flex-direction: column;
    gap: 18px;
}
.sidebar-section {
    display: flex;
    flex-direction: column;
}
.sidebar-section-label {
    padding: 0 16px 4px;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--muted);
    opacity: 0.7;
}
.sidebar-nav a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 16px;
    color: var(--muted);
    font-size: 13px;
    text-decoration: none;
    border-left: 2px solid transparent;
}
.sidebar-nav a:hover {
    color: var(--text);
    background: rgba(255,255,255,0.03);
    text-decoration: none;
}
.sidebar-nav a.active {
    color: var(--text);
    border-left-color: var(--accent);
    background: var(--accent-faint);
}
.sidebar-nav a.active svg.icon { color: var(--accent); }

/* ─── Icons ──────────────────────────────────────────────────────── */

svg.icon {
    width: 16px;
    height: 16px;
    display: inline-block;
    vertical-align: middle;
    flex-shrink: 0;
    /* color flows from text color via stroke="currentColor" */
}
svg.icon.page-icon {
    width: 22px;
    height: 22px;
    color: var(--accent);
}

.sidebar-backdrop { display: none; }

/* ─── Content area ───────────────────────────────────────────────── */

.content {
    grid-area: content;
    padding: 24px;
    width: 100%;
    box-sizing: border-box;
    /* min-width: 0 lets the column shrink below its descendants' min-content
       size. Without it, any non-wrapping flex/grid descendant (e.g. the
       look-samples carousel) blows out the body grid column, pushing the
       whole page wider than the viewport. The column's intrinsic content
       is contained by its own children's overflow rules. */
    min-width: 0;
    /* No max-width — content fills the full grid column. Individual elements
       (forms, text blocks) constrain themselves only when they explicitly
       need to (narrow inputs, hero blocks, etc.). */
}

/* ─── Mobile breakpoint ──────────────────────────────────────────── */

@media (max-width: 768px) {
    body {
        grid-template-columns: 1fr;
        grid-template-areas:
            "topbar"
            "content";
    }
    .topbar-menu-toggle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
    .sidebar {
        position: fixed;
        top: 48px;
        left: 0;
        bottom: 0;
        width: 240px;
        transform: translateX(-100%);
        transition: transform 0.2s ease;
        z-index: 100;
    }
    body.sidebar-open .sidebar {
        transform: translateX(0);
        box-shadow: 4px 0 16px rgba(0,0,0,0.4);
    }
    .sidebar-backdrop {
        display: block;
        position: fixed;
        top: 48px;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0,0,0,0.5);
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.2s ease;
        z-index: 99;
    }
    body.sidebar-open .sidebar-backdrop {
        opacity: 1;
        pointer-events: auto;
    }
}

h1 { font-size: 20px; margin: 0 0 16px; }
h2 { font-size: 16px; margin: 24px 0 8px; }

table {
    width: 100%;
    /* `separate` (with zero spacing) lets border-radius render reliably on
       the outer table border. `collapse` mode breaks the corner radius in
       most browsers. */
    border-collapse: separate;
    border-spacing: 0;
    margin-top: 12px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
}

/* Table card — single outlined container that wraps a pager + table so they
   read as one unit. Use this whenever a table has a pager. The bare <table>
   styling above still works for tables that don't need pagination. */
.table-card {
    margin-top: 12px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
}
.table-card > table {
    margin-top: 0;
    border: none;
    border-radius: 0;
    background: transparent;
}
.table-card > .table-pager {
    border: none;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    margin: 0;
    background: transparent;
}
.table-card > .table-filter {
    border: none;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    margin: 0;
    background: transparent;
}
/* Filter bar — text input first, dropdowns next, reset right-aligned. */
.table-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    font-size: 12px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-top: 12px;
}
.table-filter-text {
    flex: 1 1 240px;
    min-width: 200px;
    max-width: 360px;
    padding: 4px 8px;
}
.table-filter-select {
    padding: 4px 8px;
}
.table-filter-reset {
    margin-left: auto;
    padding: 3px 10px;
    font-size: 12px;
}

/* Pager toolbar — three slots via grid: size left, nav centered, results right.
   Grid (not flex) so the center slot stays mathematically centered regardless of
   how wide the side slots are. */
.table-pager {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 16px;
    padding: 8px 12px;
    font-size: 12px;
    color: var(--muted);
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-top: 12px;
}
.table-pager-size {
    display: flex;
    align-items: center;
    gap: 6px;
    justify-self: start;
}
.table-pager-size select {
    /* Compact padding for the pager's small-control context — global
       select rule provides border / background / color / font. */
    padding: 3px 6px;
}
.table-pager-nav {
    display: flex;
    align-items: center;
    gap: 2px;
    justify-self: center;
}
/* Pager nav buttons — compact outlined buttons (border inherits from base
   button styling). Smaller font, tighter padding, but visually a proper
   button rather than a bare chevron glyph. */
.table-pager-nav button {
    padding: 2px 8px;
    min-width: 26px;
    color: var(--muted);
    font-weight: normal;
    font-size: 14px;
    line-height: 1;
}
.table-pager-nav button:hover { color: var(--text); background: rgba(255,255,255,0.04); }
.table-pager-nav button:disabled { opacity: 0.35; cursor: not-allowed; }
.table-pager-page {
    padding: 0 8px;
    color: var(--muted);
    user-select: none;
    white-space: nowrap;
}
.table-pager-results {
    justify-self: end;
    white-space: nowrap;
}

th, td {
    padding: 8px 12px;
    text-align: left;
    border-bottom: 1px solid var(--border);
    font-size: 13px;
}

th {
    color: var(--muted);
    font-weight: 500;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    background: rgba(255,255,255,0.02);
    white-space: nowrap;
}

tr:last-child td { border-bottom: none; }

/* Click-through rows — set data-href="<url>" on a <tr> and the whole row
   navigates on click (handled in lib/render.js's inline script). Hover
   highlights the row so the affordance is obvious. Inline interactive
   elements (<a>, <button>, .persona-thumbnail, etc.) take precedence. */
tr[data-href] { cursor: pointer; }
tr[data-href]:hover td { background: rgba(255,255,255,0.04); }

/* Sortable column headers — clickable + caret indicator on the active column. */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--text); }
th.sortable .sort-caret {
    display: inline-block;
    margin-left: 4px;
    opacity: 0.35;
    font-size: 10px;
}
th.sortable.sorted { color: var(--text); }
th.sortable.sorted .sort-caret { opacity: 1; }

/* Right-aligned numeric column (opt-in). */
th.num,     td.num     { text-align: right;  font-variant-numeric: tabular-nums; }
th.actions, td.actions { text-align: center; width: 1%; white-space: nowrap; }

/* Empty-state row inside a table — preserves the table chrome (header,
   borders, pager) so the page reads as the same table, just with a
   centered "no data" message in place of rows. */
td.table-empty {
    padding: 48px 24px;
    text-align: center;
    color: var(--muted);
    background: transparent;
}

/* Form grid — labels left, inputs right, all aligned via CSS grid.
   `max-content 1fr` makes the label column auto-size to the longest label;
   inputs stretch in the right column. align-items: start so labels align
   to the top of multi-line inputs (textareas). No max-width — forms fill
   their container; wrap in `.card` for chrome (see §5). Narrow fields
   (slugs, ages) cap themselves with inline `style="max-width:Npx"`. */
.form-grid {
    display: grid;
    grid-template-columns: max-content 1fr;
    column-gap: 16px;
    row-gap: 12px;
    align-items: start;
}
/* `.aligned` locks the label column to a fixed width so multiple sibling
   .form-grids (e.g. inside several fieldsets on one form) share an input
   start-line, instead of each grid auto-sizing to its own longest label. */
.form-grid.aligned,
.form-grid.aligned .form-grid { grid-template-columns: 180px 1fr; }
.form-grid > label {
    color: var(--muted);
    font-size: 13px;
    text-align: left;     /* labels line up at their start; CSS grid keeps inputs aligned at theirs */
    padding-top: 8px;     /* aligns label baseline with input's first text line */
}
/* Fieldsets span both columns; nest a .form-grid inside for inner alignment. */
.form-grid > fieldset {
    grid-column: 1 / -1;
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 12px 16px 14px;
    margin: 4px 0;
}
.form-grid > fieldset > legend {
    color: var(--muted);
    font-size: 12px;
    padding: 0 6px;
}
/* Actions row spans the full form width and right-aligns its buttons. */
.form-grid > .form-actions {
    grid-column: 1 / -1;
    margin-top: 8px;
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
/* Collapsible advanced sections span both columns. */
.form-grid > details {
    grid-column: 1 / -1;
    color: var(--muted);
}
.form-grid > details > summary { cursor: pointer; padding: 4px 0; }
.form-grid > details > textarea,
.form-grid > details > input { margin-top: 8px; }

.tag {
    display: inline-block;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    background: rgba(255,255,255,0.06);
    color: var(--muted);
}
.tag.ok    { background: rgba(63,185,80,0.15);  color: var(--ok); }
.tag.warn  { background: rgba(210,153,34,0.15); color: var(--warn); }
.tag.err   { background: rgba(248,81,73,0.15);  color: var(--err); }

.empty {
    padding: 32px;
    text-align: center;
    color: var(--muted);
    background: var(--panel);
    border: 1px dashed var(--border);
    border-radius: 6px;
}

.setup {
    max-width: 720px;
    margin: 64px auto;
    padding: 24px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
}
.setup pre {
    background: rgba(0,0,0,0.4);
    padding: 12px;
    border-radius: 4px;
    overflow-x: auto;
    font-size: 13px;
}

/* Buttons — outline-only. Transparent bg, colored border, matching colored
   text, medium-weight label, subtle tinted hover. Color = semantics:
     green = commit, blue = forward, red = stop. Roles:
     - default:               neutral border + body text — secondary actions
                              (Refresh, Re-render, Reset, Import)
     - [type=submit] / .success: ok-green border + text — commit actions
                              (Save, Submit, Create, Run, Dispatch)
     - .primary:              accent-blue border + text — forward / additive
                              actions that aren't commits (Add a look, + New X
                              navigation, Compose, Open in tab)
     - .danger:               err-red border + text — destructive or
                              progress-discarding (Delete, Drop, Cancel, Dismiss)
     - .ghost:                borderless muted text — reversible tertiary
                              (Archive)
   No solid fills anywhere. */
button {
    background: transparent;
    color: var(--text);
    border: 1px solid var(--border);
    padding: 4px 11px;
    border-radius: 5px;
    cursor: pointer;
    font: inherit;
    font-size: 12px;
    font-weight: 500;
    line-height: 1.4;
    /* Inline-flex so buttons can hold an icon + text with consistent spacing.
       Icons render via renderIcon() from lib/render.js; flat single-color
       Lucide icons that inherit the button's text color via currentColor. */
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
/* In-button icons — slightly smaller than the default 16px to balance with
   the 12px button text. */
button svg.icon { width: 14px; height: 14px; }
button:hover { background: rgba(255,255,255,0.04); }
button:disabled { opacity: 0.5; cursor: not-allowed; }

button[type=submit],
button.success {
    border-color: var(--ok);
    color: var(--ok);
}
button[type=submit]:hover,
button.success:hover { background: color-mix(in srgb, var(--ok) 12%, transparent); }

button.primary {
    border-color: var(--accent);
    color: var(--accent);
}
button.primary:hover { background: color-mix(in srgb, var(--accent) 12%, transparent); }

button.danger {
    border-color: var(--err);
    color: var(--err);
}
button.danger:hover { background: color-mix(in srgb, var(--err) 12%, transparent); }

button.ghost {
    border-color: transparent;
    color: var(--muted);
    font-weight: normal;
}
button.ghost:hover { color: var(--text); background: rgba(255,255,255,0.04); }
/* Ghost-submit overrides submit-styling — used for secondary form-POST cases (Cancel-shaped POSTs). */
button.ghost[type=submit] { border-color: transparent; color: var(--muted); font-weight: normal; }
button.ghost[type=submit]:hover { background: rgba(255,255,255,0.04); }

.muted, td.muted { color: var(--muted); }

textarea, input[type=text], input:not([type]) {
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 8px 10px;
    font: inherit;
    width: 100%;
}
textarea { resize: vertical; min-height: 64px; }
input[type=number] {
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 8px 10px;
    font: inherit;
}
/* Native <select> styled to match text inputs at the chrome level
   (border, background, color, padding) but keeps the OS-native dropdown
   indicator + popup. We previously stripped chrome via `appearance:
   none` and drew a custom chevron, but that interacted badly with
   parent `overflow: hidden` (the table-card pager) — clicks didn't
   open the dropdown reliably across browsers. Trade-off: each browser
   renders its own dropdown arrow, but selects now Just Work in every
   context (forms, table pagers, anywhere). Width is content-fit by
   default; the .form-grid override stretches selects to fill their
   grid cell (matching textarea/input behavior in forms). */
select {
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 8px 10px;
    font: inherit;
    cursor: pointer;
}
.form-grid select { width: 100%; }
select:focus,
textarea:focus,
input[type=text]:focus,
input:not([type]):focus,
input[type=number]:focus {
    outline: none;
    border-color: var(--accent);
}

/* ─── Lightbox ────────────────────────────────────────────────────── */

img.persona-portrait,
img.advisor-face,
img.persona-thumbnail,
video.persona-portrait { cursor: zoom-in; transition: filter 0.15s; }
img.persona-portrait:hover,
img.advisor-face:hover,
img.persona-thumbnail:hover,
video.persona-portrait:hover { filter: brightness(1.1); }

video.persona-portrait {
    width: 200px;
    height: 200px;
    object-fit: cover;
    border-radius: 12px;
    border: 1px solid var(--border);
    display: block;
    background: #000;
}

.lightbox video {
    max-width: 95vw;
    max-height: 95vh;
    border-radius: 6px;
    box-shadow: 0 8px 40px rgba(0,0,0,0.6);
    background: #000;
}

.persona-thumbnail {
    width: 48px;
    height: 48px;
    object-fit: cover;
    border-radius: 6px;
    border: 1px solid var(--border);
    display: block;
}
.persona-thumbnail.placeholder {
    background: rgba(255,255,255,0.04);
    border-style: dashed;
    cursor: default;
}

.lightbox {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    padding: 20px;
    cursor: zoom-out;
    animation: lightbox-fade 0.12s ease;
}
.lightbox-stage {
    display: flex;
    align-items: center;
    justify-content: center;
    max-width: 95vw;
    max-height: 95vh;
    cursor: default;
}
.lightbox img {
    max-width: 95vw;
    max-height: 95vh;
    border-radius: 6px;
    box-shadow: 0 8px 40px rgba(0,0,0,0.6);
    object-fit: contain;
}
.lightbox-nav {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    background: rgba(0,0,0,0.55);
    color: #fff;
    border: 1px solid rgba(255,255,255,0.25);
    border-radius: 50%;
    width: 56px;
    height: 56px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.15s;
    padding: 0;
    z-index: 1001;
}
.lightbox-nav:hover {
    background: rgba(0,0,0,0.8);
    border-color: rgba(255,255,255,0.6);
}
.lightbox-nav:active { transform: translateY(-50%) scale(0.95); }
.lightbox-nav-prev { left: 24px; }
.lightbox-nav-next { right: 24px; }
.lightbox-nav[hidden] { display: none; }
.lightbox-caption {
    position: fixed;
    top: 24px;
    left: 50%;
    transform: translateX(-50%);
    color: #fff;
    font-size: 18px;
    font-weight: 500;
    letter-spacing: 0.02em;
    text-align: center;
    padding: 8px 18px;
    background: rgba(0,0,0,0.55);
    border: 1px solid rgba(255,255,255,0.18);
    border-radius: 999px;
    text-shadow: 0 1px 2px rgba(0,0,0,0.6);
    cursor: default;
    z-index: 1001;
    max-width: 80vw;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lightbox-caption[hidden] { display: none; }
body.lightbox-open { overflow: hidden; }
@keyframes lightbox-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* ─── Persona profile ─────────────────────────────────────────────── */

.persona-profile {
    display: flex;
    gap: 24px;
    align-items: flex-start;
    padding: 20px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-bottom: 16px;
}
.persona-portrait-col,
.persona-media-col {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.persona-portrait {
    width: 200px;
    height: 200px;
    object-fit: cover;
    border-radius: 12px;
    border: 1px solid var(--border);
    display: block;
}
.persona-portrait.placeholder {
    width: 200px;
    height: 200px;
    border-radius: 12px;
    border: 2px dashed var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: var(--muted);
    font-size: 11px;
    padding: 12px;
}
.persona-portrait.placeholder.small {
    font-size: 10px;
    line-height: 1.4;
}
.persona-profile-meta { flex: 1; min-width: 0; }
.persona-profile-meta .identity-table { margin-top: 0; }
.persona-voice {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
}
.persona-voice-sample {
    width: 100%;
    height: 32px;
    max-width: 420px;
}

/* ─── Page tabs ────────────────────────────────────────────────────── */

.page-tabs {
    display: flex;
    gap: 8px;
    margin: 20px 0 12px;
    border-bottom: 1px solid var(--border);
}
.page-tab {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    color: var(--muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    font-weight: 500;
    font-size: 14px;
    background: none;
    transition: color 0.12s, border-color 0.12s;
    cursor: pointer;
}
.page-tab .icon {
    width: 16px;
    height: 16px;
}
.page-tab:hover {
    color: var(--text);
}
.page-tab.active {
    color: var(--text);
    border-bottom-color: var(--accent);
}
.tab-panel { display: none; }
.tab-panel.active { display: block; }

/* ─── Generic sub-tab family ─────────────────────────────────────────
   Shared visual language for any section that needs nested sub-tabs.
   Currently used by:
     • the Archive tab (Images / Photos / Videos / Audio / Looks)
     • the Samples section at the top of embodiment detail (Looks /
       Audio / Video)
   Mirrors .page-tab (underline-on-active) but slightly smaller so the
   nesting is visually clear. .archive-subtab and .samples-subtab are
   convenience aliases for selector targeting in JS — the visual styles
   live on the .subtab base class. */
.subtabs,
.archive-subtabs,
.samples-subtabs {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: 0 0 16px;
    border-bottom: 1px solid var(--border);
}
.subtab,
.archive-subtab,
.samples-subtab {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    color: var(--muted);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
    font-size: 13px;
    font-weight: 500;
    background: none;
    cursor: pointer;
    transition: color 0.12s, border-color 0.12s;
}
.subtab .icon,
.archive-subtab .icon,
.samples-subtab .icon {
    width: 14px;
    height: 14px;
}
.subtab:hover,
.archive-subtab:hover,
.samples-subtab:hover {
    color: var(--text);
}
.subtab.active,
.archive-subtab.active,
.samples-subtab.active {
    color: var(--text);
    border-bottom-color: var(--accent);
}
.subtab[aria-disabled="true"],
.archive-subtab[aria-disabled="true"],
.samples-subtab[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
}
.subtab[aria-disabled="true"]:hover,
.archive-subtab[aria-disabled="true"]:hover,
.samples-subtab[aria-disabled="true"]:hover {
    color: var(--muted);
}
.subtab-pane,
.archive-pane,
.samples-pane {
    display: none;
}
.subtab-pane.active,
.archive-pane.active,
.samples-pane.active {
    display: block;
}

/* Archive Images sub-tab — filter bar above the grid */
.archive-images-filter {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    padding: 8px 12px;
    margin: 0 0 14px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
}
.archive-images-filter select {
    background: var(--bg);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 13px;
}

/* Samples section gets a subtle card frame so it's visually grouped
   apart from the page-level tabs below it. */
.samples-section {
    margin: 16px 0 24px;
    padding: 12px 16px 16px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
}
.samples-section-title {
    margin: 0 0 12px;
    font-size: 16px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.samples-section-title .icon {
    width: 18px;
    height: 18px;
}

/* ─── Render status panel (live render-job feed) ──────────────────── */

.render-status-panel {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 14px 18px;
    margin: 12px 0;
}
.render-status-header {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}
.render-status-header h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
.render-status-header h3 .icon { width: 14px; height: 14px; }
.render-status-summary {
    font-size: 12px;
}
.render-status-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.render-status-item {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 12px;
    align-items: center;
    padding: 8px 12px;
    background: rgba(255,255,255,0.02);
    border: 1px solid var(--border);
    border-radius: 6px;
}
.render-status-item[data-status="running"]   { border-color: color-mix(in srgb, var(--ok) 35%, var(--border)); }
.render-status-item[data-status="completed"] { opacity: 0.85; }
.render-status-item[data-status="failed"]    { border-color: color-mix(in srgb, var(--err) 35%, var(--border)); }

.render-status-icon {
    font-size: 14px;
    width: 18px;
    text-align: center;
    color: var(--muted);
}
.render-status-item[data-status="running"]   .render-status-icon { color: var(--ok);  animation: pulse 1.4s ease-in-out infinite; }
.render-status-item[data-status="completed"] .render-status-icon { color: var(--ok); }
.render-status-item[data-status="failed"]    .render-status-icon { color: var(--err); }
@keyframes pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

.render-status-body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.render-status-target {
    font-size: 13px;
    font-weight: 500;
}
.render-status-message {
    font-size: 12px;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.render-status-bar {
    margin-top: 4px;
    height: 4px;
    background: rgba(255,255,255,0.06);
    border-radius: 2px;
    overflow: hidden;
}
.render-status-bar-fill {
    height: 100%;
    background: var(--ok);
    transition: width 0.3s ease-out;
}
.render-status-elapsed {
    font-size: 11px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ─── Embodiment preview carousel (5 standard looks + operator-added,
     280×280 cells, horizontal scroll with prev/next nav) ─────────────── */

.embodiment-preview-grid {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 20px;
    margin: 12px 0 16px;
}
.embodiment-preview-heading {
    margin: 0 0 12px;
    font-size: 14px;
    display: flex;
    align-items: center;
    gap: 6px;
}
.embodiment-preview-heading .icon { width: 14px; height: 14px; }
.embodiment-preview-carousel {
    display: flex;
    align-items: center;
    gap: 12px;
}
.embodiment-preview-track {
    display: flex;
    gap: 16px;
    overflow-x: auto;
    scroll-behavior: smooth;
    scrollbar-width: thin;
    flex: 1 1 auto;
    min-width: 0;
}
.embodiment-preview-nav {
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: rgba(255,255,255,0.04);
    color: var(--text);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: background 0.15s;
}
.embodiment-preview-nav:hover { background: rgba(255,255,255,0.10); }
.embodiment-preview-nav .icon { width: 18px; height: 18px; }
.embodiment-preview-cell {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 0 0 auto;
}
.embodiment-preview-image {
    width: 280px;
    height: 280px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--border);
    display: block;
    cursor: zoom-in;
    transition: filter 0.15s;
}
img.embodiment-preview-image:hover { filter: brightness(1.1); }
.embodiment-preview-image.placeholder {
    background: rgba(255,255,255,0.04);
    border-style: dashed;
    cursor: default;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    font-size: 12px;
    text-align: center;
    padding: 12px;
}
.embodiment-preview-cell figcaption {
    color: var(--muted);
    font-size: 12px;
    text-align: center;
}
.embodiment-preview-cell-name {
    color: var(--fg);
    font-size: 13px;
    font-weight: 600;
    text-align: center;
    /* Override the muted figcaption default — when name sits ABOVE the
       image as a label, it should read as the cell's title, not a caption. */
}
.embodiment-preview-cell-actions {
    margin: 0;
    text-align: center;
}
.embodiment-preview-cell-actions button {
    width: 100%;
}

/* ─── Video tab: source-look thumbnail picker ──────────────────────── */
/* Radio inputs styled as 140×140 tiles with a selected ring. The native
   radio is hidden (sr-only) — the surrounding label is the click target,
   :has(:checked) and the script-applied .selected class both flip the
   visual state so progressive enhancement still works without JS. */

.video-look-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0;
}
.video-look-cell {
    position: relative;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 140px;
    cursor: pointer;
    border: 2px solid transparent;
    border-radius: 8px;
    padding: 4px;
    transition: border-color 0.12s, background 0.12s;
    background: rgba(255,255,255,0.02);
}
.video-look-cell:hover {
    background: rgba(255,255,255,0.05);
}
.video-look-cell.selected,
.video-look-cell:has(input[type="radio"]:checked) {
    border-color: var(--accent);
    background: var(--accent-faint);
}
.video-look-cell input[type="radio"] {
    position: absolute;
    opacity: 0;
    pointer-events: none;
    width: 0;
    height: 0;
}
.video-look-image {
    width: 132px;
    height: 132px;
    object-fit: cover;
    border-radius: 6px;
    display: block;
}
.video-look-cell figcaption {
    color: var(--muted);
    font-size: 11px;
    text-align: center;
    line-height: 1.2;
}
.video-look-cell.selected figcaption,
.video-look-cell:has(input[type="radio"]:checked) figcaption {
    color: var(--text);
}

/* ─── Embodiment audio sample card ─────────────────────────────────── */

.embodiment-audio-card,
.embodiment-video-card {
    margin: 0 0 16px;
}

/* Base-model drag-drop section on the Appearance tab. Side-by-side
   columns: the dropzone (or rendered base model) on the left, and
   the candidate Look 1 slot on the right. Both 280px wide to match
   .embodiment-preview-image. */
.base-model-card {
    margin: 0 0 16px;
}
.base-model-row {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
    align-items: flex-start;
}
.base-model-col {
    flex: 0 0 280px;
    display: flex;
    flex-direction: column;
}
.base-model-image {
    width: 280px;
    height: 280px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--border);
    display: block;
}
.base-model-dropzone {
    width: 280px;
    height: 280px;
    border-radius: 8px;
    border: 2px dashed var(--border);
    background: rgba(255, 255, 255, 0.03);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: border-color 0.15s ease, background-color 0.15s ease;
    overflow: hidden;
}
.base-model-dropzone.dragover {
    border-color: var(--accent);
    background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.base-model-dropzone.uploading {
    opacity: 0.6;
    pointer-events: none;
}
.base-model-dropzone.base-model-dropzone-error {
    border-color: var(--err);
}
.base-model-dropzone:hover { border-color: var(--accent-mid); }
.base-model-dropzone-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.base-model-dropzone img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 6px;
}
.base-model-candidate-wrap {
    display: flex;
    flex-direction: column;
}

/* Collapsible card pattern (built on native <details>/<summary>): the
   summary acts as a clickable heading; the body shows when [open] is
   set. Server-side renderer auto-opens when content is present;
   polling JS opens on new audio renders.
   Styled to feel like a regular card heading — no default disclosure
   triangle, hover affordance, custom caret on the right. */
.collapsible-card-summary {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    padding: 4px 0;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.collapsible-card-summary::-webkit-details-marker { display: none; }
.collapsible-card-summary::after {
    content: '▸';
    margin-left: auto;
    font-size: 11px;
    color: var(--muted);
    transition: transform 0.12s ease;
}
.collapsible-card[open] > .collapsible-card-summary::after {
    transform: rotate(90deg);
}
.collapsible-card-summary:hover { color: var(--accent); }
.collapsible-card-summary .icon { width: 14px; height: 14px; }
.collapsible-card-body {
    margin-top: 12px;
}
.embodiment-audio-sample {
    width: 100%;               /* span the full card width — no max cap */
    display: block;
}

/* ─── Embodiment video sample card ─────────────────────────────────── */

.embodiment-video-card h2 .icon { width: 14px; height: 14px; }
.embodiment-video-sample {
    width: 280px;
    height: 280px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--border);
    display: block;
    cursor: zoom-in;
    transition: filter 0.15s;
}
video.embodiment-video-sample:hover { filter: brightness(1.1); }

/* Multi-tile gallery for the Video sample card. Each render is a
   tile with its own player + trash button. auto-fill keeps the row
   left-aligned on wide screens. */
.embodiment-video-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, 280px);
    gap: 16px;
    justify-content: flex-start;
}
.embodiment-video-tile {
    margin: 0;
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 280px;
}
.embodiment-video-tile-player {
    width: 280px;
    height: 280px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--border);
    background: rgba(0,0,0,0.4);
    display: block;
    cursor: zoom-in;
    transition: filter 0.15s;
}
.embodiment-video-tile-player:hover { filter: brightness(1.1); }
/* Trash sits in the lower-right of the player — operator-requested
   location. Matches the source-photo tile's overlay-on-corner pattern
   so the eye finds it consistently across cards. */
.embodiment-video-tile-trash {
    position: absolute;
    right: 8px;
    /* 2px below the player bottom + caption gap (6px) so the trash
       overlay sits inside the video area, lower-right corner. */
    top: calc(280px - 36px - 4px);
    margin: 0;
    z-index: 1;
}
.embodiment-video-tile-trash button {
    padding: 4px 8px;
    font-size: 11px;
    background: rgba(0,0,0,0.65);
    border-color: rgba(255,255,255,0.2);
}
.embodiment-video-tile-trash button:hover {
    background: rgba(0,0,0,0.85);
}
.embodiment-video-tile-trash button .icon { width: 14px; height: 14px; }
.embodiment-video-tile-caption {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 0 2px;
}

/* ─── Looks form (single card, dynamic rows) ──────────────────────── */

.looks-card { padding: 20px 24px; }

/* Each look-row is a fieldset, matching the outline-box treatment of
   the Appearance / Voice / Face fieldsets on the Appearance tab. */
.looks-form .look-row {
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 12px 16px 16px;
    margin: 0 0 14px;
    position: relative;
}
.looks-form .look-row > legend {
    color: var(--muted);
    font-size: 12px;
    padding: 0 6px;
}

.look-row-body {
    display: flex;
    gap: 20px;
    align-items: flex-start;
    padding-top: 4px;
}

.look-row-image-col {
    flex-shrink: 0;
    width: 200px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.look-row-image {
    width: 200px;
    height: 200px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--border);
    display: block;
    cursor: zoom-in;
    transition: filter 0.15s;
}
img.look-row-image:hover {
    filter: brightness(1.1);
}
.look-row-image.placeholder {
    background: rgba(255,255,255,0.04);
    border-style: dashed;
    cursor: default;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    font-size: 12px;
    text-align: center;
}
.look-row-render-btn {
    width: 100%;
    justify-content: center;
}
.look-row-meta {
    font-size: 11px;
    margin: 0;
}

.look-row-fields {
    flex: 1;
    min-width: 0;
}

.look-row-delete-btn {
    position: absolute;
    top: 8px;
    right: 12px;
    padding: 4px 8px;
}

/* Prior-renders carousel (per look-row). Mirrors the embodiment-preview
   carousel pattern (flex container with prev/next chevrons + a min-width:0
   scroll track) — the min-width:0 is load-bearing: without it the track's
   intrinsic content width would push the fieldset / card / tab off the
   page when there are many history entries. */
.look-row-history {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
    min-width: 0;
}
.look-row-history-carousel {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}
.look-row-history-track {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scroll-behavior: smooth;
    scrollbar-width: thin;
    flex: 1 1 auto;
    min-width: 0;
    padding-bottom: 4px;
}
.look-row-history-nav {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid var(--border);
    background: rgba(255,255,255,0.04);
    color: var(--text);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    transition: background 0.15s;
}
.look-row-history-nav:hover { background: rgba(255,255,255,0.10); }
.look-row-history-nav .icon { width: 14px; height: 14px; }
.look-row-history-cell {
    margin: 0;
    flex: 0 0 auto;
    width: 96px;
}
.look-row-history-cell img {
    width: 96px;
    height: 96px;
    object-fit: cover;
    border-radius: 4px;
    border: 1px solid var(--border);
    cursor: zoom-in;
    display: block;
}

@media (max-width: 768px) {
    .look-row-body { flex-direction: column; }
    .look-row-image-col { width: 100%; }
    .look-row-image,
    .look-row-image.placeholder {
        width: 100%;
        height: auto;
        aspect-ratio: 1 / 1;
    }
}

/* ─── Intake chat ─────────────────────────────────────────────────── */

.intake-chat { max-width: 760px; margin: 0 auto; }

.intake-hero {
    display: flex;
    align-items: center;
    gap: 20px;
    padding: 16px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    margin-bottom: 16px;
}
.advisor-face {
    width: 120px;
    height: 120px;
    object-fit: cover;
    border-radius: 999px;
    border: 2px solid var(--accent);
    flex-shrink: 0;
}
.advisor-face.placeholder {
    width: 120px;
    height: 120px;
    border-radius: 999px;
    border: 2px dashed var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    color: var(--muted);
    font-size: 11px;
    padding: 8px;
}
.intake-hero-meta h1 { margin: 0; }
.intake-hero-meta .muted { font-size: 12px; }

.transcript {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-bottom: 16px;
    max-height: 60vh;
    overflow-y: auto;
    padding: 4px;
}

.turn {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-width: 75%;
    padding: 10px 14px;
    border-radius: 12px;
    background: var(--panel);
    border: 1px solid var(--border);
    line-height: 1.45;
    word-wrap: break-word;
}
.turn.advisor {
    align-self: flex-start;
    border-bottom-left-radius: 4px;
}
.turn.operator {
    align-self: flex-end;
    background: var(--accent-soft);
    border-color: var(--accent-mid);
    border-bottom-right-radius: 4px;
}
.turn-content { white-space: pre-wrap; }
.turn audio { width: 100%; height: 28px; }

.turn.typing {
    color: var(--muted);
    font-style: italic;
}

.intake-input {
    display: flex;
    gap: 8px;
    align-items: flex-end;
    padding: 12px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
}
.intake-input textarea { flex: 1; }

.finalize-section {
    margin-top: 24px;
    padding: 12px 16px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
}
.finalize-section summary { cursor: pointer; color: var(--muted); }
.finalize-form {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 12px;
    flex-wrap: wrap;
}
.finalize-form label { flex: 1; min-width: 220px; display: flex; flex-direction: column; gap: 4px; color: var(--muted); font-size: 12px; }

/* ─── Phase 1.9: Component vocabulary ─────────────────────────────── */
/* See /styleguide for live examples and component CLAUDE.md §14 for rules. */

/* Card — general-purpose panel container. */
.card {
    padding: 16px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
}
.card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: -4px 0 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
}
.card-footer {
    display: flex;
    gap: 8px;
    justify-content: flex-end;
    margin: 12px -4px -4px;
    padding-top: 8px;
    border-top: 1px solid var(--border);
}

/* Toolbar — page-title + action group at the top of a list page. */
.toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}
.toolbar-title h1 {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Button row — group related actions inline. */
.button-row {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.button-row.spread { justify-content: space-between; }
.button-row.right  { justify-content: flex-end; }

/* Button toolbar — a richer button-row with panel chrome + optional
   vertical dividers between sub-groups. Use for detail-page action
   bars combining nav + primary + secondary + tertiary actions. */
.button-toolbar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 12px;
    margin: 0 0 16px;
    background: rgba(255,255,255,0.02);
    border: 1px solid var(--border);
    border-radius: 8px;
    flex-wrap: wrap;
}
.button-toolbar-divider {
    width: 1px;
    height: 22px;
    background: var(--border);
    margin: 0 4px;
    flex-shrink: 0;
}

/* Filter bar — inline chips that toggle server-side filters. */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    margin: 12px 0;
}
.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 999px;
    font-size: 12px;
    color: var(--muted);
    text-decoration: none;
}
.filter-chip:hover { color: var(--text); }
.filter-chip.active {
    background: var(--accent-soft);
    border-color: var(--accent);
    color: var(--text);
}

/* Flash messages — post-action banners. */
.flash {
    padding: 10px 14px;
    border-radius: 6px;
    border: 1px solid var(--border);
    background: var(--panel);
    margin-bottom: 12px;
    font-size: 13px;
}
.flash.info { border-color: var(--accent); background: var(--accent-faint);                            color: var(--accent); }
.flash.ok   { border-color: var(--ok);     background: color-mix(in srgb, var(--ok)   8%, transparent); color: var(--ok); }
.flash.warn { border-color: var(--warn);   background: color-mix(in srgb, var(--warn) 8%, transparent); color: var(--warn); }
.flash.err  { border-color: var(--err);    background: color-mix(in srgb, var(--err)  8%, transparent); color: var(--err); }

/* Stats grid — auto-flowing numeric snapshot. */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
    margin: 12px 0;
}
.stat-card {
    padding: 12px 14px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
}
.stat-card-label {
    font-size: 11px;
    color: var(--muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.stat-card-value {
    font-size: 22px;
    font-weight: 500;
    margin-top: 4px;
}

/* ─── Styleguide page chrome (only used on /styleguide) ───────────── */

.sg-toc {
    margin: 12px 0 24px;
    padding: 10px 14px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    font-size: 12px;
    color: var(--muted);
}
.sg-toc a { color: var(--muted); text-decoration: none; }
.sg-toc a:hover { color: var(--text); }

.sg-section {
    padding: 20px 0;
    border-bottom: 1px dashed var(--border);
    scroll-margin-top: 60px;
}
.sg-section:last-child { border-bottom: none; }
.sg-section h2 { margin: 0 0 4px; }
.sg-section .sg-blurb {
    color: var(--muted);
    font-size: 13px;
    margin: 0 0 16px;
}
.sg-section .sg-example {
    padding: 16px;
    background: rgba(255,255,255,0.02);
    border: 1px solid var(--border);
    border-radius: 6px;
}

.sg-token-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 8px;
}
.sg-token {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 4px;
    font-size: 12px;
}
.sg-token-swatch {
    width: 28px;
    height: 28px;
    border-radius: 4px;
    border: 1px solid var(--border);
    flex-shrink: 0;
}


/* ─── Phase 1.12: Real-time chat surface ─────────────────────────── */

.ai-disclosure-banner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-mid);
    border-radius: 6px;
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
    margin: 16px 0 8px;
}
.ai-disclosure-banner .icon {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    color: var(--accent);
}

.chat-controls {
    display: flex;
    align-items: center;
    gap: 8px;
}

.chat-iframe-container {
    width: 100%;
    min-height: 600px;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    overflow: hidden;
}
.chat-iframe-container:empty {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    font-size: 13px;
}
.chat-iframe-container:empty::before {
    content: 'Click "Start call" to begin the video chat.';
    padding: 24px;
}

.chat-iframe {
    width: 100%;
    height: 600px;
    border: none;
    display: block;
}

/* HeyGen Streaming Avatar uses a <video> element fed by a LiveKit
   MediaStream rather than an iframe. Same container slot, same size
   semantics. */
.chat-video {
    width: 100%;
    height: 600px;
    background: #000;
    object-fit: cover;
    display: block;
}
.chat-iframe-container-popup .chat-video {
    height: 100%;
}

/* ─── Chromeless layout (popup windows) ──────────────────────────── */

body.chromeless {
    /* Override the dashboard's grid layout — popups have no chrome. */
    display: block;
    margin: 0;
    height: 100vh;
    overflow: hidden;
}
.content-chromeless {
    margin: 0;
    padding: 16px 20px;
    height: 100vh;
    width: 100vw;
    box-sizing: border-box;
    overflow: auto;
    display: flex;
    flex-direction: column;
}
.chat-popup-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
}
.chat-popup-title {
    font-size: 16px;
    font-weight: 600;
}
.chat-iframe-container-popup {
    flex: 1 1 auto;
    min-height: 0;     /* allow flex child to shrink */
}
.chat-iframe-container-popup .chat-iframe {
    height: 100%;
}
.chat-iframe-container-popup:empty {
    flex: 1 1 auto;
}

.chat-start-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 12px;
    margin-top: 12px;
}
.chat-start-card {
    display: block;
    padding: 0;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    text-decoration: none;
    color: inherit;
    transition: border-color 0.1s;
    overflow: hidden;
}
.chat-start-card:hover {
    border-color: var(--accent-mid);
}
.chat-start-card-thumb {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    display: block;
    background: var(--code-bg);
}
.chat-start-card-thumb.placeholder {
    background: linear-gradient(135deg, var(--code-bg) 0%, var(--panel) 100%);
}
.chat-start-card-body {
    padding: 12px 14px 14px;
}
.chat-start-card-name {
    font-weight: 600;
    margin-bottom: 4px;
}

/* ─── Embodiments list — Preview / Table dual view ───────────────── */

/* Toolbar card holding the filter row above both views. */
.emb-toolbar-card {
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 12px 14px;
    margin: 16px 0;
}
.emb-filter-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.emb-filter-row > input,
.emb-filter-row > select {
    height: 32px;
    box-sizing: border-box;
}
.emb-filter-text {
    flex: 1 1 200px;
    min-width: 120px;
    padding: 4px 10px;
    background: rgba(0, 0, 0, 0.15);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: inherit;
    font-size: 13px;
}
.emb-filter-text:focus { outline: 2px solid var(--accent); outline-offset: -2px; }
.emb-filter-select {
    flex: 0 0 auto;
    padding: 4px 10px;
    background: rgba(0, 0, 0, 0.15);
    border: 1px solid var(--border);
    border-radius: 4px;
    color: inherit;
    font-size: 13px;
    cursor: pointer;
}

/* Ethnicity + build dropdowns size themselves to the longest option
   text by default ("Greek-American (white)" pushes the closed-state
   width to ~280px). Cap them so the toolbar fits one row; the popup
   when clicked still expands to show full option text. */
.emb-filter-select[data-filter-key="ethnicity"],
.emb-filter-select[data-filter-key="build"] {
    max-width: 150px;
}
/* View toggle (segmented buttons; right-aligned inside the filter row,
   matched to the 32px height of the filter inputs/selects). */
.emb-view-toggle {
    display: inline-flex;
    flex: 0 0 auto;
    margin-left: auto;
    height: 32px;
    box-sizing: border-box;
    border: 1px solid var(--border);
    border-radius: 4px;
    overflow: hidden;
}
.emb-view-toggle button {
    height: 100%;
    background: transparent;
    border: none;
    border-radius: 0;
    padding: 0 10px;
    color: var(--muted);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    line-height: 1;
}
.emb-view-toggle button + button { border-left: 1px solid var(--border); }
.emb-view-toggle button:hover { background: rgba(255, 255, 255, 0.04); color: inherit; }
.emb-view-toggle button.active {
    background: var(--accent-soft);
    color: var(--accent);
}
.emb-view-toggle .icon { width: 14px; height: 14px; }

/* Preview grid — auto-fill tiles with face image + tiny meta. */
.emb-preview-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 16px;
}
.emb-card {
    display: block;
    text-decoration: none;
    color: inherit;
    background: var(--panel);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
    transition: transform 0.12s ease, border-color 0.12s ease;
}
.emb-card:hover {
    transform: translateY(-2px);
    border-color: var(--accent);
}
.emb-card-img {
    display: block;
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    background: rgba(0, 0, 0, 0.2);
}
.emb-card-img.placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--muted);
    font-size: 11px;
}
.emb-card-img.placeholder::before {
    content: '(not rendered)';
    padding: 8px;
    text-align: center;
}
.emb-card-meta {
    padding: 8px 10px 10px;
}
.emb-card-title {
    font-size: 12px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.emb-card-sub {
    font-size: 11px;
    margin-top: 2px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The two view panes — JS toggles [hidden] on whichever is inactive. */
.emb-view[hidden] { display: none; }

/* ─── Voices casting library ─────────────────────────────────────── */

/* Compact audio player for the voices list page's ▶ Play column. */
.voice-row-audio {
    /* 32px matches .persona-voice-sample — compact but high enough
       for Chrome / Safari / Firefox to keep the play button rendered
       and clickable. (28px clipped it.) */
    height: 32px;
    max-width: 220px;
    vertical-align: middle;
}

/* Small face thumbnail rendered next to each voice's name on the
   /voices list — face + audio side-by-side so the operator can
   match voice to person at a glance. Sized to keep row height
   close to .voice-row-audio (32px) without forcing a re-layout. */
.voice-row-name {
    display: flex;
    align-items: center;
    gap: 8px;
}
.voice-row-thumb {
    width: 36px;
    height: 36px;
    object-fit: cover;
    border-radius: 50%;
    border: 1px solid var(--border);
    flex-shrink: 0;
    display: block;
}
.voice-row-thumb-placeholder {
    background: rgba(255, 255, 255, 0.04);
    border-style: dashed;
}

/* Default-voice indicator chip (★ {gender}) on the voices list. */
.voice-default-chip {
    display: inline-block;
    padding: 2px 8px;
    background: var(--accent-soft);
    color: var(--accent);
    border: 1px solid var(--accent-mid);
    border-radius: 4px;
    font-size: 11px;
    font-weight: 500;
}

/* =====================================================================
   SIBYL CANONICAL STRUCTURAL COMPONENTS
   ---------------------------------------------------------------------
   Ported verbatim (live values) from the dashboard shell
   src/public/index.html <style>. Appended LAST so these win over any
   Prometheus-era duplicates above. These are the canonical class names
   the dashboard uses and the catalog teaches. Keep in sync with the app
   shell if the app shell changes (this styleguide is the source of
   truth — the app should change to match THIS, not vice-versa).
   ===================================================================== */

/* -- Cards -- */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 16px; min-width: 0; }
.card .label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; margin-bottom: 6px; }
.card .value { font-size: 24px; font-weight: 700; font-family: 'Courier New', monospace; }
.card .sub   { color: var(--muted); font-size: 11px; margin-top: 4px; }
.card-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 10px; }
.card-header h3 { margin: 0; font-size: 14px; font-weight: 600; }
.card-footer { display: flex; gap: 8px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }

/* -- Section header row (canonical: holds .breadcrumb + .spacer + actions) -- */
.section-header { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.section-header h2 { font-size: 14px; font-weight: 600; margin: 0; }
.section-header .spacer { flex: 1; }

/* -- Breadcrumb page header (CANONICAL page header) -- */
.breadcrumb { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; margin: 0; }
.breadcrumb .crumb { display: inline-flex; align-items: center; gap: 6px; }
.breadcrumb .crumb-icon { font-size: 15px; line-height: 1; }
.breadcrumb .crumb-section { color: var(--muted); }
.breadcrumb .crumb-page { color: var(--text); }
.breadcrumb .crumb-sep { color: var(--muted); font-weight: 400; }

/* -- SIM/LIVE mode switch -- */
.mode-switch { display: flex; gap: 0; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.mode-switch button { background: transparent; border: none; color: var(--muted); padding: 4px 12px; cursor: pointer; font-size: 12px; border-radius: 0; }
.mode-switch button.active { background: var(--blue); color: #fff; }

/* -- Tabs -- */
.tabs { display: flex; flex-wrap: wrap; row-gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 16px; }
.tab { display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; cursor: pointer; color: var(--muted); border-bottom: 2px solid transparent; font-size: 13px; white-space: nowrap; }
.tab.active { color: var(--blue); border-bottom-color: var(--blue); }
.tab .tab-icon { font-size: 14px; line-height: 1; }

/* -- Stat grid -- */
.stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 12px; }
.stat-box { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 14px; }
.stat-box .s-label { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: .06em; margin-bottom: 4px; }
.stat-box .s-value { font-size: 18px; font-weight: 700; font-family: 'Courier New', monospace; }
.stat-box .s-sub { color: var(--muted); font-size: 11px; margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* -- Tables -- */
.table-wrap { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; overflow: auto; }
.table-wrap table { width: 100%; border-collapse: collapse; font-size: 12px; }
.table-wrap th { padding: 8px 12px; text-align: left; color: var(--muted); font-weight: 600; border-bottom: 1px solid var(--border); white-space: nowrap; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; }
.table-wrap td { padding: 8px 12px; border-bottom: 1px solid rgba(48,54,61,.6); white-space: nowrap; vertical-align: top; }
.table-wrap tr:last-child td { border-bottom: none; }
.table-wrap tr:hover > td { background: rgba(255,255,255,.03); }
.table-wrap th.sortable { cursor: pointer; user-select: none; }
.table-wrap th.sortable:hover { color: var(--text); }
.table-pagination { display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; font-size: 12px; color: var(--muted); }
.table-pagination + table, .table-pagination ~ table { border-top: 1px solid var(--border); }

/* -- Pills / status badges -- */
.pill  { display: inline-block; padding: 1px 7px; border-radius: 10px; font-size: 11px; font-weight: 600; }
.pill.yes  { background: rgba(63,185,80,.15);  color: var(--green); }
.pill.no   { background: rgba(248,81,73,.15);  color: var(--red); }
.pill.sim  { background: rgba(210,153,34,.12); color: var(--yellow); }
.pill.live { background: rgba(248,81,73,.12);  color: var(--red); }
.pill.off  { background: rgba(139,148,158,.12); color: var(--muted); }
.pill-filter { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 11px; cursor: pointer; background: var(--surface); border: 1px solid var(--border); color: var(--muted); transition: all .15s; }
.pill-filter:hover { border-color: var(--blue); color: var(--text); }
.pill-filter.active { background: rgba(88,166,255,.12); border-color: var(--blue); color: var(--blue); font-weight: 600; }

/* -- Loading & empty (unified canonical states) -- */
@keyframes sg-spin { to { transform: rotate(360deg); } }
.spinner { width: 22px; height: 22px; border: 2px solid var(--border); border-top-color: var(--blue); border-radius: 50%; animation: sg-spin .7s linear infinite; flex-shrink: 0; }
.loading-state { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 80px 40px; color: var(--muted); font-size: 13px; }
.empty { color: var(--muted); padding: 24px; text-align: center; }

/* -- Modal (canonical overlay; supersedes the 5 hand-rolled variants) -- */
.modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 1000; display: flex; align-items: center; justify-content: center; }
.modal { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 20px 24px; width: min(440px, 92vw); max-height: 86vh; overflow: auto; }
.modal-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.modal-header h3 { margin: 0; font-size: 15px; font-weight: 600; }

/* -- Toast (canonical; supersedes the 3 copy-pasted showToast copies) -- */
.toast { position: fixed; bottom: 24px; right: 24px; background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--blue); color: var(--text); padding: 10px 16px; border-radius: 8px; font-size: 13px; font-weight: 600; z-index: 1100; box-shadow: 0 6px 24px rgba(0,0,0,.4); }
.toast.ok  { border-left-color: var(--green); }
.toast.err { border-left-color: var(--red); }

/* -- Guidance-block styling (the usage manual around each example) -- */
.sg-guide { background: rgba(88,166,255,.04); border: 1px solid var(--border); border-left: 3px solid var(--blue); border-radius: 6px; padding: 12px 16px; margin: 0 0 12px; font-size: 13px; }
.sg-guide dl { display: grid; grid-template-columns: 130px 1fr; gap: 4px 14px; margin: 0; }
.sg-guide dt { color: var(--muted); font-weight: 600; text-transform: uppercase; font-size: 10px; letter-spacing: .06em; padding-top: 3px; }
.sg-guide dd { margin: 0; }
.sg-guide .do  { color: var(--green); }
.sg-guide .dont { color: var(--red); }
.sg-guide ul { margin: 2px 0 0; padding-left: 16px; }
.sg-guide code, .sg-supersedes code { background: rgba(255,255,255,.06); padding: 1px 5px; border-radius: 3px; font-size: 12px; }
.sg-supersedes { font-size: 12px; color: var(--muted); margin-top: 6px; }
.sg-supersedes strong { color: var(--yellow); }
