/**
 * Resource Visualizations — shared styles.
 *
 * DESIGN CONTRACT — follow the DRE theme.
 * ----------------------------------------------------------------------------
 * This module is styled to match the Africa Multiple "Digital Research
 * Environment" Omeka S theme:
 *   https://github.com/AM-Digital-Research-Environment/DRE-theme
 *
 * Every colour, surface, border, radius, shadow and spacing value is taken
 * from the theme's CSS custom properties (design tokens) rather than being
 * hard-coded. The theme defines those tokens on :root (light) and re-defines
 * them under `body[data-theme="dark"]` and `@media (prefers-color-scheme:dark)`,
 * so by *referencing* them the module automatically follows the active light /
 * dark theme — including the live theme toggle — with no extra JS.
 *
 * The `--rv-*` aliases below are the ONLY place this module names a colour.
 * They are declared on `body` (not :root) on purpose: the theme flips its
 * tokens at `body[data-theme=...]`, and declaring the aliases on `body` lets
 * each alias resolve the *active* token from the body's own cascade.
 *
 * The hard-coded values in `var(--token, fallback)` are fallbacks for when the
 * module is used in a theme that does NOT provide the DRE tokens. When the DRE
 * theme is present its token always wins, so the fallback is ignored.
 *
 * ►► When adding new styles, ALWAYS reference a `--rv-*` alias (or a DRE theme
 *    token directly). Never introduce a raw hex / rgb colour. ◄◄
 */

/* ------------------------------------------------------------------ */
/*  Design tokens — aliases onto the DRE theme variables               */
/* ------------------------------------------------------------------ */

body {
    /* Surfaces — warm stone (mirrors the DRE light theme, never cold grey) */
    --rv-bg:              var(--surface, #fdfcfa);          /* cards, panels      */
    --rv-bg-raised:       var(--surface-raised, #fffefb);   /* hovered / floating */
    --rv-bg-sunken:       var(--surface-sunken, #f1ede6);   /* wells, chips       */
    --rv-overlay:         var(--surface-overlay, rgba(253, 252, 250, 0.92));

    /* Borders — warm low-chroma neutrals */
    --rv-border:          var(--border, #dcd6cb);
    --rv-border-light:    var(--border-light, #eae5dd);
    --rv-border-strong:   var(--border-strong, #c3b9a9);

    /* Text — warm near-neutral inks */
    --rv-heading-color:   var(--ink-strong, #33291f);
    --rv-text-strong:     var(--ink, #473e33);
    --rv-text-color:      var(--ink-light, #6c6357);

    /* Brand accent (Uni-Grün via the theme; the fallback IS Uni-Grün) */
    --rv-accent:          var(--primary, #007a50);
    --rv-accent-hover:    var(--primary-hover, #00633f);
    --rv-accent-contrast: var(--primary-contrast, #fffef9);

    /* Radii, shadows, focus — straight from the theme's token set */
    --rv-radius:          var(--radius-lg, 12px);
    --rv-radius-sm:       var(--radius-sm, 6px);
    --rv-shadow:          var(--shadow-lg, 0 4px 16px rgba(0, 0, 0, 0.12));
    --rv-shadow-sm:       var(--shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.12));
    --rv-focus-ring:      var(--ring-focus, 0 0 0 3px rgba(0, 122, 80, 0.32));
}

/*
 * Dark fallbacks for NON-DRE host themes only. When the DRE theme is active it
 * already supplies dark values for --surface / --border / --ink-* / --primary,
 * so `var(--token, …)` resolves to the theme token and these fallbacks are
 * never used. They simply keep the module usable (and dark-aware) if dropped
 * into a theme that lacks the DRE token set but honours prefers-color-scheme.
 */
@media (prefers-color-scheme: dark) {
    body {
        /* Forest-dark (mirrors the DRE dark theme), lifted green accent. */
        --rv-bg:            var(--surface, #1b211e);
        --rv-bg-raised:     var(--surface-raised, #212724);
        --rv-bg-sunken:     var(--surface-sunken, #161b18);
        --rv-overlay:       var(--surface-overlay, rgba(27, 33, 30, 0.92));

        --rv-border:        var(--border, #39423d);
        --rv-border-light:  var(--border-light, #2c3531);
        --rv-border-strong: var(--border-strong, #4c554f);

        --rv-heading-color: var(--ink-strong, #f3f1ec);
        --rv-text-strong:   var(--ink, #e3e0d9);
        --rv-text-color:    var(--ink-light, #aaa498);

        --rv-accent:          var(--primary, #3fb488);
        --rv-accent-hover:    var(--primary-hover, #5cc49d);
        --rv-accent-contrast: var(--primary-contrast, #14201a);

        --rv-shadow:    var(--shadow-lg, 0 4px 16px rgba(0, 0, 0, 0.5));
        --rv-shadow-sm: var(--shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.45));
    }
}

/* ------------------------------------------------------------------ */
/*  Block wrapper                                                      */
/* ------------------------------------------------------------------ */

.resource-vis-block {
    margin: 2rem 0;
}

.resource-vis-block h3 {
    /* Inherit the host theme's global h3 size/weight (DRE theme: 1.5rem, and
       1.875rem from >=768px, weight 700) so the module's section headings match
       the theme's own headings and the "Linked resources" disclosure, stepping
       cleanly down from the page h1/h2. Chart titles are <h4>, so they are
       unaffected. */
    color: var(--rv-heading-color);
    margin: 0 0 0.75rem;
}

/* ------------------------------------------------------------------ */
/*  Collapsible section                                                 */
/*                                                                      */
/*  Mirrors the DRE theme's "Linked resources" disclosure: a native     */
/*  <details> with a summary head (heading + chevron) over a panel.     */
/*  Used by the Knowledge Graph block and the async dashboards so the    */
/*  heavy visualizations can be collapsed. Expanded by default; charts   */
/*  re-fit on re-expand (see the `toggle` handler in dashboard-core.js). */
/* ------------------------------------------------------------------ */

details.rv-collapsible {
    display: block;
}

/* Summary head — heading on the left, a chevron that flips on the right.
   The whole bar toggles the panel. */
.rv-collapsible__head {
    list-style: none;               /* strip the native disclosure triangle… */
    display: flex;                  /* …and flex display drops the list marker */
    align-items: center;
    gap: 1rem;
    margin: 0;
    padding: 0.4rem 0;
    cursor: pointer;
    border-bottom: 1px solid var(--rv-border);
}

.rv-collapsible__head::-webkit-details-marker {
    display: none;
}

.rv-collapsible__head:focus-visible {
    outline: 2px solid var(--rv-accent);
    outline-offset: 3px;
    border-radius: var(--rv-radius-sm);
}

/* Reuse the block heading style; just neutralise its margin in the flex head. */
.rv-collapsible__head h3 {
    margin: 0;
    transition: color 0.15s ease;
}

.rv-collapsible__head:hover h3 {
    color: var(--rv-accent);
}

/* CSS chevron: points down when closed, flips up when open. */
.rv-collapsible__chevron {
    flex-shrink: 0;
    margin-left: auto;
    width: 0.6rem;
    height: 0.6rem;
    border-right: 2px solid var(--rv-text-color);
    border-bottom: 2px solid var(--rv-text-color);
    transform: translateY(-2px) rotate(45deg);
    transition: transform 0.2s ease, border-color 0.15s ease;
}

.rv-collapsible__head:hover .rv-collapsible__chevron {
    border-color: var(--rv-accent);
}

details.rv-collapsible[open] > .rv-collapsible__head .rv-collapsible__chevron {
    transform: translateY(1px) rotate(225deg);
}

.rv-collapsible__panel {
    padding-top: 1.25rem;
}

@media (prefers-reduced-motion: reduce) {
    .rv-collapsible__chevron,
    .rv-collapsible__head h3 {
        transition: none;
    }
}

/* ------------------------------------------------------------------ */
/*  Knowledge graph                                                    */
/* ------------------------------------------------------------------ */

.knowledge-graph-block {
    position: relative;
}

.knowledge-graph-toolbar {
    position: absolute;
    top: 0;
    right: 0;
    z-index: 10;
    display: flex;
    gap: 0.25rem;
}

.knowledge-graph-container {
    width: 100%;
    height: 520px;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    background: var(--rv-bg);
}

/* Fullscreen mode */
.knowledge-graph-block.rv-fullscreen {
    position: fixed;
    inset: 0;
    z-index: 9999;
    margin: 0;
    padding: 1rem;
    background: var(--rv-bg);
}

.knowledge-graph-block.rv-fullscreen .knowledge-graph-container {
    height: calc(100vh - 5rem);
}

.knowledge-graph-block.rv-fullscreen .knowledge-graph-toolbar {
    top: 1rem;
    right: 1rem;
}

/* Collapsible knowledge graph — the summary head sits at the top, so the
   floating toolbar is positioned within the panel (over the graph's corner),
   and fullscreen hides the head so the graph fills the screen. */
.knowledge-graph-block .rv-collapsible__panel {
    position: relative;
}

.knowledge-graph-block .knowledge-graph-toolbar {
    top: 1.6rem;
    right: 0.5rem;
}

.knowledge-graph-block.rv-fullscreen > .rv-collapsible__head {
    display: none;
}

.knowledge-graph-block.rv-fullscreen .rv-collapsible__panel {
    padding-top: 0;
}

/* ------------------------------------------------------------------ */
/*  Knowledge-graph filter panel                                       */
/* ------------------------------------------------------------------ */

.rv-kg-filters {
    position: relative;
}

.rv-kg-filters-toggle.rv-btn-active {
    background: var(--rv-accent);
    color: var(--rv-accent-contrast);
    border-color: var(--rv-accent);
}

.rv-kg-filters-panel {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 0.4rem;
    padding: 0.75rem 1rem;
    width: 300px;
    background: var(--rv-bg);
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    box-shadow: var(--rv-shadow);
    z-index: 20;
}

/* Each slider block: label row on top, slider row below, description last. */
.rv-kg-slider {
    margin-bottom: 0.7rem;
    padding-bottom: 0.7rem;
    border-bottom: 1px solid var(--rv-border);
}

.rv-kg-slider:last-child {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: none;
}

/* Label sits on its own line above the slider. */
.rv-kg-slider label {
    display: block;
    font-size: 0.82rem;
    color: var(--rv-heading-color);
    width: 100%;
}

.rv-kg-slider-label {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 0.3rem;
    font-weight: 600;
}

/* Slider sits on its own row, full width. */
.rv-kg-slider input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    display: block;
    width: 100%;
    height: 6px;
    margin: 0.35rem 0 0;
    padding: 0;
    border: none;
    border-radius: 3px;
    background: var(--rv-border);
    outline: none;
    cursor: pointer;
}

.rv-kg-slider input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--rv-accent);
    border: 2px solid var(--rv-bg);
    box-shadow: var(--rv-shadow-sm);
    cursor: pointer;
}

.rv-kg-slider input[type="range"]::-moz-range-thumb {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--rv-accent);
    border: 2px solid var(--rv-bg);
    box-shadow: var(--rv-shadow-sm);
    cursor: pointer;
}

.rv-kg-slider input[type="range"]::-moz-range-track {
    height: 6px;
    border-radius: 3px;
    background: var(--rv-border);
}

.rv-kg-slider-value {
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
    color: var(--rv-accent);
    font-weight: 700;
}

.rv-kg-slider-desc {
    display: block;
    font-size: 0.72rem;
    color: var(--rv-text-color);
    margin-top: 0.35rem;
    line-height: 1.35;
}

/* ------------------------------------------------------------------ */
/*  Item location map                                                  */
/* ------------------------------------------------------------------ */

.rv-item-map-panel {
    margin-top: 1.25rem;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    padding: 1rem;
    background: var(--rv-bg);
}

.rv-item-map-panel h4 {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--rv-heading-color);
    margin: 0 0 0.4rem;
}

.rv-item-map-legend {
    display: flex;
    gap: 1rem;
    font-size: 0.82rem;
    color: var(--rv-text-color);
    margin-bottom: 0.6rem;
}

.rv-legend-dot {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    margin-right: 0.3rem;
    vertical-align: middle;
}

.rv-item-map-container {
    width: 100%;
    height: 300px;
    border-radius: 6px;
}

/* ------------------------------------------------------------------ */
/*  Dashboard                                                          */
/* ------------------------------------------------------------------ */

.dashboard-header {
    display: flex;
    align-items: baseline;
    gap: 1rem;
    margin-bottom: 1rem;
}

.dashboard-header h3 {
    /* Inherit the host theme's global h3 scale -- see .resource-vis-block h3. */
    margin: 0;
    color: var(--rv-heading-color);
}

/* Inline count/meta badge used by the Discursive Communities, What's New and
   item-page dashboard headers (the Collection Overview "Visualisations" header
   no longer shows one). */
.dashboard-total {
    font-size: 0.9rem;
    color: var(--rv-text-color);
    background: var(--rv-bg);
    padding: 0.15em 0.6em;
    border-radius: 12px;
    border: 1px solid var(--rv-border);
}

.dashboard-charts {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.25rem;
}

.chart-panel {
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    padding: 1rem;
    background: var(--rv-bg);
    overflow: hidden;
    min-width: 0;
}

.chart-panel-wide {
    grid-column: 1 / -1;
}

.chart-panel h4 {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--rv-heading-color);
    margin: 0 0 0.5rem;
    overflow-wrap: break-word;
    word-break: break-word;
}

/* Chart-level toolbar (save button, inline with title). */
.rv-chart-toolbar {
    margin-left: auto;
    display: flex;
    gap: 0.25rem;
    flex-shrink: 0;
}

/* Dashboard toolbar buttons are slightly smaller than knowledge graph ones. */
.rv-toolbar-btn {
    width: 1.6rem;
    height: 1.6rem;
}

.dashboard-header h3,
.resource-vis-block h3 {
    overflow-wrap: break-word;
    word-break: break-word;
}

.chart-description {
    font-size: 0.82rem;
    color: var(--rv-text-color);
    margin: 0 0 0.5rem;
    line-height: 1.4;
}

/* Word-count slider for wordcloud panels. */
.rv-word-slider {
    display: flex;
    align-items: center;
    margin: 0 0 0.4rem;
    font-size: 0.8rem;
    color: var(--rv-text-color);
}

.rv-word-slider label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}

.rv-word-slider-caption {
    color: var(--rv-text-color);
    white-space: nowrap;
}

.rv-word-slider input[type="range"] {
    /* A compact, fixed-width control — the slider is not meant to span the whole
       panel (a full-width track reads as a dead gap on the right). */
    width: 220px;
    max-width: 100%;
    height: 4px;
    accent-color: var(--rv-accent);
    cursor: pointer;
}

.rv-word-slider-value {
    min-width: 3ch;
    text-align: left;
    font-variant-numeric: tabular-nums;
}

.chart-container {
    width: 100%;
    max-width: 100%;
    height: 350px;
}

.chart-container-tall {
    height: 420px;
}

/* ------------------------------------------------------------------ */
/*  Buttons                                                            */
/* ------------------------------------------------------------------ */

/* Override theme button resets (e.g. Lively sets padding/border-radius/bg on all buttons).
   Double class selector for specificity over theme's `button, .button` rules. */
button.rv-btn,
button.rv-toolbar-btn,
.rv-btn,
.rv-toolbar-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    min-width: 0;
    padding: 0;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius-sm);
    background: var(--rv-bg);
    cursor: pointer;
    font-size: 1rem;
    color: var(--rv-text-color);
    line-height: 1;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    text-decoration: none;
}

button.rv-btn:hover,
button.rv-toolbar-btn:hover,
.rv-btn:hover,
.rv-toolbar-btn:hover {
    background: var(--rv-bg-raised);
    color: var(--rv-accent);
    border-color: var(--rv-accent);
}

button.rv-btn:focus-visible,
button.rv-toolbar-btn:focus-visible,
.rv-btn:focus-visible,
.rv-toolbar-btn:focus-visible {
    outline: none;
    box-shadow: var(--rv-focus-ring);
    border-color: var(--rv-accent);
}

.rv-toolbar-btn-active {
    background: var(--rv-accent) !important;
    color: var(--rv-accent-contrast) !important;
    border-color: var(--rv-accent) !important;
}

/* ------------------------------------------------------------------ */
/*  Loading / error states                                             */
/* ------------------------------------------------------------------ */

.rv-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    gap: 0.75rem;
    color: var(--rv-text-color);
    font-size: 0.9rem;
}

.rv-spinner {
    width: 32px;
    height: 32px;
    border: 3px solid var(--rv-border);
    border-top-color: var(--rv-accent);
    border-radius: 50%;
    animation: rv-spin 0.8s linear infinite;
}

@keyframes rv-spin {
    to { transform: rotate(360deg); }
}

.rv-no-data,
.rv-error {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    color: var(--rv-text-color);
    font-size: 0.9rem;
    margin: 0;
}

/* ------------------------------------------------------------------ */
/*  Map attribution                                                    */
/* ------------------------------------------------------------------ */

.chart-panel .maplibregl-ctrl-attrib:not(.maplibregl-compact-show) {
    background: none;
    padding: 0;
}

.chart-panel .maplibregl-ctrl-attrib:not(.maplibregl-compact-show) a,
.chart-panel .maplibregl-ctrl-attrib:not(.maplibregl-compact-show) span {
    display: none;
}

/* ------------------------------------------------------------------ */
/*  Map popups                                                         */
/* ------------------------------------------------------------------ */

/* Theme the MapLibre popup surface so it matches light / dark like the rest
   of the module (MapLibre's stylesheet defaults to a white card). */
.resource-vis-block .maplibregl-popup-content,
.rv-item-map-panel .maplibregl-popup-content {
    background: var(--rv-bg);
    color: var(--rv-text-strong);
    box-shadow: var(--rv-shadow);
}

.resource-vis-block .maplibregl-popup-anchor-top .maplibregl-popup-tip,
.rv-item-map-panel .maplibregl-popup-anchor-top .maplibregl-popup-tip {
    border-bottom-color: var(--rv-bg);
}

.resource-vis-block .maplibregl-popup-anchor-bottom .maplibregl-popup-tip,
.rv-item-map-panel .maplibregl-popup-anchor-bottom .maplibregl-popup-tip {
    border-top-color: var(--rv-bg);
}

.resource-vis-block .maplibregl-popup-anchor-left .maplibregl-popup-tip,
.rv-item-map-panel .maplibregl-popup-anchor-left .maplibregl-popup-tip {
    border-right-color: var(--rv-bg);
}

.resource-vis-block .maplibregl-popup-anchor-right .maplibregl-popup-tip,
.rv-item-map-panel .maplibregl-popup-anchor-right .maplibregl-popup-tip {
    border-left-color: var(--rv-bg);
}

/* Consistent close button for ALL MapLibre popups in the module. */
.resource-vis-block .maplibregl-popup-close-button,
.rv-item-map-panel .maplibregl-popup-close-button {
    font-size: 18px;
    font-weight: bold;
    width: 24px;
    height: 24px;
    line-height: 24px;
    padding: 0;
    color: var(--rv-text-color);
    background: transparent;
    border: none;
    border-radius: 3px;
}

.resource-vis-block .maplibregl-popup-close-button:hover,
.rv-item-map-panel .maplibregl-popup-close-button:hover {
    color: var(--rv-heading-color);
    background: var(--rv-bg-sunken);
}

/* Map legend — rendered BELOW the map (appended to the .chart-panel by
   ns.mountMapLegend), never overlaid on the basemap, so it can't cover
   countries, markers or their labels. The cluster-partner map's toggleable
   legend (.rv-cluster-legend) uses the same below-the-map placement. */
.rv-map-legend {
    display: inline-flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 0.6rem;
    max-width: 100%;
    background: var(--rv-bg-sunken);
    color: var(--rv-text-strong);
    border-radius: 4px;
    padding: 6px 10px;
    font-size: 0.78rem;
    line-height: 1.6;
}

.rv-map-legend-row {
    display: flex;
    align-items: center;
    gap: 6px;
}

.rv-map-legend-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 1px solid var(--rv-border-strong);
    flex-shrink: 0;
}

.rv-map-legend-line {
    width: 16px;
    height: 2px;
    flex-shrink: 0;
    opacity: 0.6;
}

/* Choropleth legend: a flush row of ramp swatches between min/max labels. */
.rv-map-legend-swatch {
    display: inline-block;
    width: 16px;
    height: 10px;
    flex-shrink: 0;
}

.rv-choropleth-legend .rv-map-legend-row {
    gap: 0;
}

.rv-choropleth-legend .rv-map-legend-row > span:first-child,
.rv-choropleth-legend .rv-map-legend-row > span:last-child {
    margin: 0 4px;
}

.rv-map-legend-caption {
    margin-top: 2px;
    color: var(--rv-text-color);
    opacity: 0.75;
}

/* Co-author network relationship key — the colour legend for the edges, mounted
   below the graph (in the .chart-panel) like the map legends. Reuses
   .rv-map-legend-row / .rv-map-legend-line for each swatch, but lays them out in
   one horizontal, wrapping row. */
.rv-edge-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 16px;
    margin-top: 0.6rem;
    padding: 6px 10px;
    background: var(--rv-bg-sunken);
    color: var(--rv-text-strong);
    border-radius: 4px;
    font-size: 0.78rem;
    line-height: 1.6;
}

.rv-edge-legend .rv-map-legend-line {
    width: 18px;
    height: 3px;
    opacity: 1;
}

.rv-map-popup {
    max-width: 320px !important;
}

.rv-map-popup .maplibregl-popup-content {
    max-height: 350px;
    overflow-y: auto;
}

.rv-popup-content {
    font-size: 0.85rem;
    line-height: 1.4;
    max-width: 300px;
}

.rv-popup-content strong {
    font-size: 0.95rem;
}

.rv-popup-count {
    color: var(--rv-text-color);
    font-size: 0.8rem;
}

.rv-popup-sub {
    margin-top: 2px;
    color: var(--rv-text-color);
    opacity: 0.8;
    font-size: 0.8rem;
}

/* Cluster-partner map (Collection Overview): colour-coded dot markers with a
   toggleable legend. Colours are set inline per category by the builder
   (dashboard-charts-cluster-map.js); shape/stroke live here. */
.rv-cluster-marker {
    border-radius: 50%;
    border: 2px solid var(--rv-border);
    box-shadow: var(--rv-shadow-sm);
    cursor: pointer;
    transition: transform 120ms ease;
}

.rv-cluster-marker:hover {
    transform: scale(1.15);
}

.rv-cluster-legend {
    /* Sits below the map (within the panel) so it never covers markers. */
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 4px 14px;
    margin-top: 0.6rem;
    padding: 6px 12px;
}

.rv-cluster-legend__item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 4px;
    border: 0;
    background: none;
    color: var(--rv-text-strong);
    font: inherit;
    font-size: 0.78rem;
    line-height: 1.4;
    cursor: pointer;
    border-radius: 4px;
    transition: opacity 120ms ease, color 120ms ease;
}

.rv-cluster-legend__item:hover {
    color: var(--rv-accent);
}

.rv-cluster-legend__item:focus-visible {
    outline: 2px solid var(--rv-accent);
    outline-offset: 2px;
}

.rv-cluster-legend__item.is-off {
    opacity: 0.45;
}

.rv-cluster-legend__item.is-off .rv-cluster-legend__label {
    text-decoration: line-through;
}

.rv-cluster-legend__dot {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    border: 1px solid var(--rv-border-strong);
    flex-shrink: 0;
}

.rv-popup-items {
    list-style: none;
    margin: 0.4rem 0;
    padding: 0;
    max-height: 220px;
    overflow-y: auto;
}

.rv-popup-items li {
    padding: 0.2rem 0;
    border-bottom: 1px solid var(--rv-border-light);
}

.rv-popup-items li:last-child {
    border-bottom: none;
}

.rv-popup-items a {
    color: var(--rv-accent);
    text-decoration: none;
    font-size: 0.82rem;
}

.rv-popup-items a:hover {
    text-decoration: underline;
}

.rv-popup-pagination {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin: 0.4rem 0;
    font-size: 0.8rem;
    color: var(--rv-text-color);
}

.rv-popup-pagination button {
    background: var(--rv-bg-raised);
    border: 1px solid var(--rv-border);
    border-radius: 3px;
    cursor: pointer;
    padding: 0.2rem 0.5rem;
    font-size: 0.9rem;
    line-height: 1;
    min-width: 28px;
    color: var(--rv-text-strong);
}

.rv-popup-pagination button:hover {
    background: var(--rv-bg-sunken);
}

.rv-popup-location-link {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.78rem;
    color: var(--rv-text-color);
    text-decoration: none;
}

.rv-popup-location-link:hover {
    color: var(--rv-accent);
}

/* ------------------------------------------------------------------ */
/*  Compare Projects                                                   */
/* ------------------------------------------------------------------ */

.compare-selectors {
    display: flex;
    align-items: flex-end;
    gap: 1rem;
    margin-bottom: 1.5rem;
    flex-wrap: wrap;
}

.compare-selector {
    flex: 1;
    min-width: 250px;
}

.compare-selector-label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--rv-heading-color);
    margin-bottom: 0.35rem;
}

.compare-select {
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    background: var(--rv-bg);
    color: var(--rv-heading-color);
    font-size: 0.88rem;
    cursor: pointer;
    appearance: auto;
}

.compare-select:focus {
    outline: none;
    border-color: var(--rv-accent);
    box-shadow: var(--rv-focus-ring);
}

.compare-vs {
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--rv-text-color);
    flex-shrink: 0;
    align-self: flex-end;
    padding-bottom: 0.45rem;
}

/* Searchable entity picker (Compare) — an ARIA combobox replacing the native
   <select>: type to filter the index, arrow keys to navigate, Enter to choose. */
.rv-combobox {
    position: relative;
}

.rv-combobox-input {
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    background: var(--rv-bg);
    color: var(--rv-heading-color);
    font-size: 0.88rem;
    font-family: inherit;
}

.rv-combobox-input::placeholder {
    color: var(--rv-text-color);
    opacity: 0.85;
}

.rv-combobox-input:focus {
    outline: none;
    border-color: var(--rv-accent);
    box-shadow: var(--rv-focus-ring);
}

.rv-combobox-list {
    position: absolute;
    z-index: 30;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    margin: 0;
    padding: 0.25rem 0;
    list-style: none;
    max-height: 18rem;
    overflow-y: auto;
    background: var(--rv-bg-raised);
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius-sm);
    box-shadow: var(--rv-shadow);
}

.rv-combobox-list[hidden] {
    display: none;
}

.rv-combobox-option {
    padding: 0.4rem 0.75rem;
    font-size: 0.85rem;
    color: var(--rv-text-strong);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rv-combobox-option.is-active,
.rv-combobox-option:hover {
    background: var(--rv-bg-sunken);
    color: var(--rv-heading-color);
}

.rv-combobox-option[aria-selected="true"] {
    font-weight: 600;
    color: var(--rv-accent);
}

.rv-combobox-group {
    position: sticky;
    top: 0;
    padding: 0.4rem 0.75rem 0.2rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--rv-text-color);
    background: var(--rv-bg-raised);
}

.rv-combobox-empty,
.rv-combobox-more {
    padding: 0.5rem 0.75rem;
    font-size: 0.8rem;
    color: var(--rv-text-color);
    font-style: italic;
}

/* Compare: in-page entity-type switcher (Compare any-entity block) — a row of
   icon + label pills; the active type is a filled accent pill. */
.compare-type-switcher {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1.25rem;
}

.compare-type-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    padding: 0.4rem 0.85rem;
    font-size: 0.85rem;
    font-weight: 500;
    line-height: 1.2;
    color: var(--rv-text-strong);
    background: var(--rv-bg);
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    appearance: none;
    -webkit-appearance: none;
}

.compare-type-btn:hover {
    background: var(--rv-bg-raised);
    border-color: var(--rv-border-strong);
    color: var(--rv-heading-color);
}

.compare-type-btn:focus-visible {
    outline: none;
    box-shadow: var(--rv-focus-ring);
}

.compare-type-btn.is-active {
    background: var(--rv-accent);
    border-color: var(--rv-accent);
    color: var(--rv-accent-contrast);
}

.compare-type-icon {
    width: 1rem;
    height: 1rem;
    flex-shrink: 0;
}

/* Compare: overlaid A/B radar headline */
.compare-radar-row {
    display: flex;
    justify-content: center;
    margin-bottom: 1.5rem;
}

.compare-radar-panel {
    max-width: 560px;
    width: 100%;
}

/* Project Explorer */
.explorer-controls {
    margin-bottom: 1.5rem;
}

.explorer-selector {
    max-width: 480px;
}

.explorer-selector-label {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--rv-heading-color);
    margin-bottom: 0.35rem;
}

.explorer-content {
    min-height: 120px;
}

/* What's New */
.whats-new-windows {
    margin-bottom: 1.25rem;
}

.whats-new-heading {
    margin: 1.5rem 0 0.75rem;
    color: var(--rv-heading-color);
}

.whats-new-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 0.6rem;
}

.whats-new-card {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius-sm);
    background: var(--rv-bg-raised);
    text-decoration: none;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.whats-new-card:hover {
    border-color: var(--rv-accent);
    box-shadow: var(--rv-shadow-sm);
}

.whats-new-card-title {
    color: var(--rv-heading-color);
    font-weight: 600;
    font-size: 0.9rem;
    line-height: 1.3;
}

.whats-new-card-date {
    color: var(--rv-text-color);
    font-size: 0.78rem;
}

/* Sibling-items sparkline (item pages) */
.sibling-sparkline-block {
    margin: 1rem 0;
}

.sibling-sparkline-head h4 {
    margin: 0 0 0.4rem;
    color: var(--rv-heading-color);
    font-size: 0.95rem;
}

.sibling-sparkline-link {
    cursor: pointer;
}

.sibling-sparkline-link:hover {
    color: var(--rv-accent);
}

.sibling-sparkline-chart {
    height: 150px;
    width: 100%;
}

/* Stats cards */
.compare-stats {
    display: grid !important;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1rem;
    margin-bottom: 1.25rem;
    align-items: stretch;
}

.compare-stat-card {
    flex: 1;
    min-width: 120px;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    padding: 0.75rem 1rem;
    background: var(--rv-bg);
    text-align: center;
}

.compare-stat-card.compare-stat-accent {
    border-color: var(--rv-accent);
}

.compare-stat-value {
    display: block;
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--rv-heading-color);
    line-height: 1.2;
}

.compare-stat-accent .compare-stat-value {
    color: var(--rv-accent);
}

.compare-stat-label {
    display: block;
    font-size: 0.8rem;
    color: var(--rv-text-color);
    margin-top: 0.2rem;
}

.compare-stat-label small {
    font-size: 0.75rem;
    opacity: 0.8;
}

/* Shared subjects badges */
.compare-shared {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 1.25rem;
}

.compare-shared-label {
    font-size: 0.82rem;
    font-weight: 600;
    color: var(--rv-heading-color);
    margin-right: 0.25rem;
}

.compare-badge {
    display: inline-block;
    font-size: 0.78rem;
    color: var(--rv-heading-color);
    background: var(--rv-bg);
    border: 1px solid var(--rv-border);
    border-radius: 12px;
    padding: 0.15em 0.6em;
}

.compare-badge-muted {
    color: var(--rv-text-color);
    font-style: italic;
}

/* Chart pair rows — always 2 columns for side-by-side comparison */
.compare-chart-row {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.compare-chart-row > .compare-chart-panel {
    min-width: 0;
    max-width: 100%;
    overflow: hidden;
    width: auto;
}

.compare-chart-panel .chart-container {
    width: 100%;
    max-width: 100%;
}

.compare-content .rv-no-data {
    padding: 2rem 0;
}

/* ------------------------------------------------------------------ */
/*  Collection Overview — summary stat cards (amira-style)             */
/* ------------------------------------------------------------------ */

/* The Collection Overview / Publications blocks lead with the stat-card grid
   directly under the page-title block, so the module's default 2rem top margin
   stacks with the heading and leaves too big a gap. Drop it for those blocks
   only (embedded item-page dashboards have no .rv-stat-cards, so are untouched). */
.resource-vis-block:has(.rv-stat-cards) {
    margin-top: 0;
}

.rv-stat-cards {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.rv-stat-card {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 1rem 1.25rem;
    background: var(--rv-bg);
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    box-shadow: var(--rv-shadow-sm);
    transition: border-color 0.15s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.rv-stat-card:hover {
    border-color: var(--rv-accent);
    box-shadow: var(--rv-shadow);
    transform: translateY(-2px);
}

.rv-stat-body {
    min-width: 0;
}

.rv-stat-label {
    margin: 0;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--rv-text-color);
}

.rv-stat-value {
    margin: 0.35rem 0 0;
    font-size: 1.9rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--rv-heading-color);
    font-variant-numeric: tabular-nums;
}

.rv-stat-sub {
    margin: 0.25rem 0 0;
    font-size: 0.75rem;
    color: var(--rv-text-color);
}

.rv-stat-badge {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: var(--rv-radius-sm);
    background: var(--rv-bg-sunken);
    color: var(--rv-accent);
}

.rv-stat-icon {
    width: 1.25rem;
    height: 1.25rem;
}

@media (max-width: 768px) {
    .rv-stat-cards {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (max-width: 420px) {
    .rv-stat-cards {
        grid-template-columns: 1fr;
    }
}

/* ------------------------------------------------------------------ */
/*  Responsive                                                         */
/* ------------------------------------------------------------------ */

@media (max-width: 600px) {
    .dashboard-charts {
        grid-template-columns: 1fr;
    }

    .knowledge-graph-container {
        height: 350px;
    }

    .rv-kg-filters-panel {
        width: 250px;
    }

    .chart-container {
        height: 280px;
    }

    .compare-chart-row {
        grid-template-columns: 1fr;
    }

    .compare-selectors {
        flex-direction: column;
    }

    .compare-vs {
        text-align: center;
        padding: 0;
    }
}

/* ------------------------------------------------------------------ */
/*  Photo Browsing block (masonry / map / timeline + lightbox)         */
/* ------------------------------------------------------------------ */

.rv-empty {
    padding: 24px;
    text-align: center;
    color: var(--rv-text-color);
    font-size: 0.9rem;
}

.photo-browse-heading {
    margin: 0 0 14px;
    color: var(--rv-heading-color);
}

.photo-browse-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.photo-view-toggle {
    display: inline-flex;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius-sm);
    overflow: hidden;
}

.photo-view-btn {
    border: 0;
    background: var(--rv-bg);
    color: var(--rv-text-strong);
    padding: 6px 16px;
    font-size: 0.85rem;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.photo-view-btn + .photo-view-btn {
    border-left: 1px solid var(--rv-border);
}

.photo-view-btn:hover:not(.is-active) {
    background: var(--rv-bg-sunken);
}

.photo-view-btn.is-active {
    background: var(--rv-accent);
    color: var(--rv-accent-contrast);
}

.photo-browse-count {
    color: var(--rv-text-color);
    font-size: 0.85rem;
}

.photo-browse-stage {
    position: relative;
    min-height: 200px;
}

/* `hidden` alone loses to the timeline's display:flex — force it off. */
.photo-browse-stage .photo-view[hidden] {
    display: none !important;
}

/* --- Masonry (responsive round-robin columns, built by the engine) --- */
.photo-masonry {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

.photo-masonry-col {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Carded tile shared by masonry + timeline. */
.photo-card {
    display: block;
    width: 100%;
    margin: 0;
    padding: 0;
    text-align: left;
    background: var(--rv-bg);
    color: var(--rv-text-strong);
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius-sm);
    overflow: hidden;
    cursor: pointer;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}

.photo-card:hover,
.photo-card:focus-visible {
    transform: translateY(-2px);
    border-color: var(--rv-accent);
    box-shadow: var(--rv-shadow);
    outline: none;
}

/* Image frame — reserves the box with a muted placeholder BEFORE the image
   loads, so lazy images never reflow or flash in; it then settles from the 4:3
   placeholder to the image's natural ratio (set inline by the engine on load). */
.photo-card-frame {
    position: relative;
    width: 100%;
    background: var(--rv-bg-sunken);
    overflow: hidden;
    display: block;
    transition: aspect-ratio 0.2s ease-out;
}

.photo-card-frame.is-broken {
    aspect-ratio: 4 / 3;
}
.photo-card-frame.is-broken .photo-card-img {
    display: none;
}

.photo-card-img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: cover;
    /* Fade the image in once it has decoded (engine adds .is-loaded) so it
       eases over the muted placeholder instead of popping. */
    opacity: 0;
    transition: opacity 0.4s ease, transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
}
.photo-card-img.is-loaded {
    opacity: 1;
}
.photo-card:hover .photo-card-img.is-loaded {
    transform: scale(1.03);
}

.photo-card-body {
    padding: 10px 12px 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.photo-card-title {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--rv-heading-color);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.photo-card-subtitle {
    margin: 0;
    font-size: 0.78rem;
    color: var(--rv-text-color);
}

.photo-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.photo-card-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 0.72rem;
    color: var(--rv-text-color);
    background: var(--rv-bg-sunken);
    border-radius: 999px;
    padding: 2px 8px;
    max-width: 100%;
    overflow: hidden;
    white-space: nowrap;
}
.photo-card-chip > * { flex: none; }

.photo-chip-icon {
    width: 12px;
    height: 12px;
    flex: none;
}

/* --- Map --- */
.photo-map {
    height: min(70vh, 560px);
    min-height: 360px;
    border-radius: var(--rv-radius);
    overflow: hidden;
    border: 1px solid var(--rv-border);
}

/* --- Timeline (horizontal strip grouped by year) --- */
.photo-timeline {
    display: flex;
    gap: 18px;
    align-items: flex-start;
    overflow-x: auto;
    padding-bottom: 12px;
}

.photo-timeline-group {
    flex: 0 0 auto;
}

.photo-timeline-year {
    font-weight: 700;
    color: var(--rv-heading-color);
    margin-bottom: 8px;
    padding-bottom: 4px;
    border-bottom: 2px solid var(--rv-accent);
}

.photo-timeline-items {
    display: grid;
    grid-template-columns: repeat(2, 110px);
    gap: 8px;
}

.photo-timeline-items .photo-card {
    margin: 0;
}

/* Compact (timeline) cards are image-only: fix the frame to a square thumb. */
.photo-card.is-compact .photo-card-frame {
    width: 110px;
    height: 110px;
    aspect-ratio: auto;
}

/* --- Lightbox --- */
body.photo-lightbox-open {
    overflow: hidden;
}

.photo-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
}

.photo-lightbox[hidden] {
    display: none;
}

.photo-lightbox-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.82);
}

.photo-lightbox-body {
    position: relative;
    z-index: 1;
    display: flex;
    max-width: 94vw;
    max-height: 92vh;
    background: var(--rv-bg-raised);
    border-radius: var(--rv-radius);
    overflow: hidden;
    box-shadow: var(--rv-shadow);
}

.photo-lightbox-figure {
    margin: 0;
    background: #000;
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1 1 auto;
    min-width: 0;
}

.photo-lightbox-figure img {
    max-width: 72vw;
    max-height: 92vh;
    width: auto;
    height: auto;
    display: block;
    object-fit: contain;
}

.photo-lightbox-meta {
    flex: 0 0 280px;
    width: 280px;
    padding: 20px 22px;
    overflow-y: auto;
}

.photo-lightbox-title {
    margin: 0 0 14px;
    color: var(--rv-heading-color);
    font-size: 1.05rem;
    line-height: 1.35;
}

.photo-lightbox-fields {
    margin: 0 0 18px;
}

.photo-lightbox-fields dt {
    color: var(--rv-text-color);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 10px;
}

.photo-lightbox-fields dd {
    margin: 2px 0 0;
    color: var(--rv-text-strong);
}

.photo-lightbox-link {
    display: inline-block;
    color: var(--rv-accent);
    font-weight: 600;
    text-decoration: none;
}

.photo-lightbox-link:hover {
    color: var(--rv-accent-hover);
    text-decoration: underline;
}

.photo-lightbox-close,
.photo-lightbox-nav {
    position: absolute;
    z-index: 2;
    border: 0;
    background: rgba(0, 0, 0, 0.45);
    color: #fff;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    transition: background 0.15s;
}

.photo-lightbox-close:hover,
.photo-lightbox-nav:hover {
    background: rgba(0, 0, 0, 0.75);
}

.photo-lightbox-close {
    top: 14px;
    right: 16px;
    width: 38px;
    height: 38px;
    font-size: 1.1rem;
}

.photo-lightbox-nav {
    top: 50%;
    transform: translateY(-50%);
    width: 46px;
    height: 46px;
    font-size: 2rem;
    line-height: 1;
}

.photo-lightbox-prev { left: 14px; }
.photo-lightbox-next { right: 14px; }

@media (max-width: 680px) {
    .photo-lightbox-body {
        flex-direction: column;
        max-height: 94vh;
    }

    .photo-lightbox-figure img {
        max-width: 94vw;
        max-height: 58vh;
    }

    .photo-lightbox-meta {
        flex-basis: auto;
        width: auto;
        max-height: 34vh;
    }

    .photo-lightbox-nav {
        width: 38px;
        height: 38px;
        font-size: 1.6rem;
    }
}

/* ------------------------------------------------------------------ */
/*  Partner credit (featured-collection galleries)                     */
/* ------------------------------------------------------------------ */

.photo-browse-partner {
    margin: -6px 0 14px;
    font-size: 0.82rem;
    color: var(--rv-text-color);
}

/* ------------------------------------------------------------------ */
/*  Issue table-of-contents modal (ILAM journal issues)               */
/* ------------------------------------------------------------------ */

.photo-toc {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: clamp(16px, 5vh, 64px) 16px;
    overflow-y: auto;
}
.photo-toc[hidden] { display: none; }

.photo-toc-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
}

.photo-toc-frame {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: minmax(200px, 260px) minmax(0, 1fr);
    width: 100%;
    max-width: 920px;
    background: var(--rv-bg);
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    overflow: hidden;
    box-shadow: var(--rv-shadow);
    animation: photo-toc-in 0.22s cubic-bezier(0.33, 1, 0.68, 1);
}
@keyframes photo-toc-in {
    from { opacity: 0; transform: translateY(8px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
    .photo-toc-frame { animation: none; }
}

.photo-toc-cover {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    background: var(--rv-bg-sunken);
    padding: 18px;
}
.photo-toc-cover img {
    max-width: 100%;
    max-height: 340px;
    width: auto;
    height: auto;
    display: block;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius-sm);
}

.photo-toc-body {
    padding: 20px 22px;
    min-width: 0;
}

.photo-toc-header {
    padding-bottom: 12px;
    margin-bottom: 12px;
    border-bottom: 1px solid var(--rv-border);
}

.photo-toc-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 6px;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--rv-text-color);
}
.photo-toc-eyebrow-icon { width: 14px; height: 14px; }

.photo-toc-title {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: var(--rv-heading-color);
}
.photo-toc-count {
    margin: 4px 0 0;
    font-size: 0.78rem;
    color: var(--rv-text-color);
}

.photo-toc-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.photo-toc-item-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid transparent;
    border-radius: var(--rv-radius-sm);
    text-decoration: none;
    color: inherit;
    transition: background 0.15s, border-color 0.15s;
}
.photo-toc-item-link:hover {
    background: var(--rv-bg-sunken);
    border-color: var(--rv-border);
}

.photo-toc-item-main { flex: 1; min-width: 0; }
.photo-toc-item-title {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--rv-text-strong);
    line-height: 1.3;
}
.photo-toc-item-creator {
    margin: 2px 0 0;
    font-size: 0.75rem;
    color: var(--rv-text-color);
}
.photo-toc-item-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: none;
    font-variant-numeric: tabular-nums;
}
.photo-toc-item-pages {
    font-size: 0.75rem;
    color: var(--rv-text-color);
    white-space: nowrap;
}
.photo-toc-item-arrow { display: inline-flex; color: var(--rv-text-color); }
.photo-toc-item-arrow svg { width: 16px; height: 16px; }
.photo-toc-item-link:hover .photo-toc-item-arrow { color: var(--rv-accent); }

.photo-toc-close {
    position: absolute;
    top: 10px;
    right: 12px;
    z-index: 2;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: 50%;
    background: var(--rv-bg-sunken);
    color: var(--rv-text-strong);
    cursor: pointer;
    font-size: 1rem;
    line-height: 1;
}
.photo-toc-close:hover { background: var(--rv-border); }

@media (max-width: 720px) {
    .photo-toc-frame { grid-template-columns: 1fr; }
    .photo-toc-cover { max-height: 240px; }
}

/* ------------------------------------------------------------------ */
/*  Reveal-on-scroll (driven by dashboard-core.js)                     */
/* ------------------------------------------------------------------ */

[data-reveal="hidden"] {
    opacity: 0;
    transform: translateY(12px);
    transition:
        opacity 0.5s cubic-bezier(0.19, 1, 0.22, 1),
        transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
    will-change: opacity, transform;
}
[data-reveal="shown"] {
    opacity: 1;
    transform: none;
}
@media (prefers-reduced-motion: reduce) {
    [data-reveal] {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* ------------------------------------------------------------------ */
/*  Featured collections landing grid                                  */
/* ------------------------------------------------------------------ */

.featured-collections {
    display: grid;
    grid-template-columns: 1fr;
    gap: 20px;
}
@media (min-width: 720px) {
    .featured-collections { grid-template-columns: repeat(2, 1fr); }
}

.collection-card {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--rv-border);
    border-radius: var(--rv-radius);
    background: var(--rv-bg);
    color: var(--rv-text-strong);
    text-decoration: none;
    transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.collection-card:hover {
    transform: translateY(-2px);
    border-color: var(--rv-accent);
    box-shadow: var(--rv-shadow);
}
.collection-card:focus-visible {
    outline: none;
    box-shadow: var(--rv-focus-ring);
}

.collection-card-cover {
    aspect-ratio: 16 / 9;
    background: var(--rv-bg-sunken);
    overflow: hidden;
}
.collection-card-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.4s ease;
}
.collection-card:hover .collection-card-cover img {
    transform: scale(1.03);
}

.collection-card-mosaic {
    display: grid;
    width: 100%;
    height: 100%;
    gap: 2px;
}
.collection-card-mosaic[data-count="1"] { grid-template: 1fr / 1fr; }
.collection-card-mosaic[data-count="2"] { grid-template: 1fr / 1fr 1fr; }
.collection-card-mosaic[data-count="3"] { grid-template: 1fr 1fr / 1fr 1fr; }
.collection-card-mosaic[data-count="3"] img:first-child { grid-row: 1 / span 2; }
.collection-card-mosaic[data-count="4"] { grid-template: 1fr 1fr / 1fr 1fr; }
.collection-card-mosaic img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.collection-card-placeholder {
    display: flex;
    width: 100%;
    height: 100%;
    align-items: center;
    justify-content: center;
    color: var(--rv-text-color);
    background: var(--rv-bg-sunken);
}
.collection-card-placeholder svg { width: 40px; height: 40px; opacity: 0.4; }

.collection-card-body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 18px 20px 20px;
}
.collection-card-title {
    margin: 0;
    font-size: 1.2rem;
    font-weight: 700;
    line-height: 1.25;
    color: var(--rv-heading-color);
}
.collection-card-tagline {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--rv-accent);
}
.collection-card-desc {
    margin: 0;
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--rv-text-color);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.collection-card-partner {
    align-self: flex-start;
    margin: 4px 0 0;
    padding: 2px 10px;
    font-size: 0.72rem;
    color: var(--rv-text-color);
    background: var(--rv-bg-sunken);
    border: 1px solid var(--rv-border);
    border-radius: 999px;
}
.collection-card-footer {
    margin-top: 10px;
    padding-top: 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    border-top: 1px solid var(--rv-border);
}
.collection-card-stats {
    font-size: 0.85rem;
    color: var(--rv-text-strong);
}
.collection-card-stats strong { font-weight: 700; }
.collection-card-stats-alt { color: var(--rv-text-color); }
.collection-card-cta {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--rv-accent);
    white-space: nowrap;
}
.collection-card-cta svg { width: 16px; height: 16px; transition: transform 0.16s ease; }
.collection-card:hover .collection-card-cta svg { transform: translateX(2px); }
