    details[title] > summary > svg { width: 14px !important; height: 14px !important; }
    .chart-wrapper { height: auto !important; }

    /* AoV-specific role classes. Generic concepts (gallery
       grid, sortable table, status badges, …) live upstream in
       HTMXObjects; this block only carries roles peculiar to
       the AoV gallery shell. */
    .aov-plot-area { width: 100%; min-width: 0; max-width: 100%; overflow-x: auto; }
    /* config(frame=…) player after a plot: play/pause, slider, frame label. */
    .aov-frame { display: flex; align-items: center; gap: 0.5em; margin: 0.25em 0; }
    .aov-frame > .aov-frame-play { width: auto; margin: 0; padding: 0.2em 0.7em; line-height: 1.2; }
    .aov-frame > .aov-frame-slider { flex: 1; min-width: 4em; margin: 0; }
    .aov-frame > .aov-frame-value { min-width: 4ch; font-variant-numeric: tabular-nums; }
    .aov-grid-page { width: 100vw; padding: 0.5rem; font-size: 0.5em; }
    /* Dense compact grid (16 cols) and gallery static grid (4 cols).
       Both compose with upstream `.htmxo-grid`, supplying only the
       column-count + gap variables; child styling stays scoped here. */
    .aov-grid-dense  { --htmxo-grid-cols: 16; --htmxo-grid-gap: 0.25rem; }
    .aov-grid-static { --htmxo-grid-cols: 4;  --htmxo-grid-gap: 0.5rem; }
    /* Compact gallery cells: <figure> in a grid container; <figcaption> is the title. */
    .aov-grid-dense > figure, .aov-grid-static > figure {
        margin: 0; border: 1px solid var(--pico-muted-border-color);
        border-radius: 0.2rem; padding: 0.2rem;
        overflow: hidden; min-width: 0;
    }
    .aov-grid-dense > figure > figcaption, .aov-grid-static > figure > figcaption {
        font-weight: bold; white-space: nowrap; overflow: hidden;
        text-overflow: ellipsis; margin-bottom: 0.1rem;
    }
    /* Static gallery cards: <article><header><a/><button/></header><img/></article>. */
    .aov-grid-static > article {
        margin: 0; padding: 0.5rem; min-width: 0; overflow: hidden;
    }
    .aov-grid-static > article > header {
        padding: 0 0 0.25rem; margin: 0;
        display: flex; align-items: center; flex-wrap: wrap;
    }
    .aov-grid-static > article > header > a {
        font-size: 0.9em; font-weight: bold; text-decoration: none;
    }
    .aov-grid-dense > figure img, .aov-grid-static > figure img,
    .aov-grid-static > article img { width: 100%; }
    .aov-cb-mid { vertical-align: middle; margin-right: 0.3em; }
    .aov-context-bar { padding: 0.5rem 0; font-size: 0.75em; opacity: 0.6; display: flex; gap: 1em; align-items: center; }
    /* Plot nav: a strip of role=button anchors. The first one
       ("← Gallery") pushes everything after it to the right. */
    .aov-plot-nav { display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 1rem; align-items: center; }
    .aov-plot-nav > a:first-child { margin-right: auto; }
    .aov-plot-nav > a { margin: 0.1rem; font-size: 0.85em; padding: 0.3rem 0.6rem; }

    /* Responsive demo cells. The demo's whole point is to
       showcase widths, so the cell width is the cell's *role*
       and lives on a `data-cell` attribute. */
    .aov-demo-page > [data-cell="half"]          { width: 50%; }
    .aov-demo-page > [data-cell="three-fifths"]  { width: 60%; }
    .aov-demo-page > [data-cell="row"]           { display: flex; gap: 1rem; }
    .aov-demo-page > [data-cell="row"] > div     { flex: 1; }

    /* Semantic roles. Bare <pre> and <small> rely on Pico defaults. */
    .aov-code-scroll { max-height: 25rem; overflow-y: auto; }
    .aov-static-section { margin-bottom: 2rem; }
    .aov-static-section h3 { margin-bottom: 0.5rem; }
    .aov-detail h4, .aov-demo-page h4 { margin-top: 1.5rem; }
    .aov-detail .aov-json-details { margin-top: 1rem; }
    .aov-card-with-specs > details { margin-top: 0.5rem; }
    .aov-card-with-specs > details + details { margin-top: 0.25rem; }
    .aov-brush-stats { margin-top: 1rem; }

    /* Captioned-plot data preview: <details data-mode="pretty|raw">
       wraps a role=group toggle and two [data-view] body divs. The
       mode attribute drives visibility; aria-pressed drives the
       button state. */
    .aov-data-preview[data-mode="pretty"] > [data-view="raw"] { display: none; }
    .aov-data-preview[data-mode="raw"]    > [data-view="pretty"] { display: none; }
