/* Player chrome. All colours resolve through the monochrome ramps in
   theme.css (--ink / --paper / --gN flip between dark and light mode).
   The only literal blacks/whites left are overlays drawn ON TOP OF images,
   which must stay dark-on-image regardless of UI theme. */

:root {
    --subtitle-font-size: 24px;
    --subtitle-color: rgb(var(--g50));
    --subtitle-bg: rgb(var(--g900) / 0.94);
}

.subtitle-display {
    font-family: var(--reading-font, inherit);
    font-size: var(--subtitle-font-size);
    color: var(--subtitle-color);
    background: var(--subtitle-bg);
    border: 1px solid rgb(var(--ink) / 0.2);
    line-height: 1.6;
}

/* The RSVP context (full-text reading view) follows the reading font too; the
   RSVP stage itself stays monospace so the pivot column doesn't shift. */
.rsvp-context {
    font-family: var(--reading-font, inherit);
}

.subtitle-word-window {
    display: grid;
    grid-template-columns: minmax(0, 1fr) max-content minmax(0, 1fr);
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    min-height: 4.75rem;
}

.subtitle-side {
    display: flex;
    min-width: 0;
    gap: 0.5rem;
    overflow: hidden;
    white-space: nowrap;
}

.subtitle-left {
    justify-content: flex-end;
}

.subtitle-right {
    justify-content: flex-start;
}

.subtitle-word {
    cursor: pointer;
    display: inline-block;
    flex: 0 0 auto;
    max-width: min(44vw, 34rem);
    overflow: visible;
    text-align: center;
    white-space: nowrap;
    transition: color 0.1s, background 0.1s;
    padding: 0.2rem 0.35rem;
}

.subtitle-word.active {
    color: rgb(var(--paper));
    font-weight: 600;
    background: rgb(var(--ink));
}

.subtitle-word.muted {
    color: rgb(var(--g200) / 0.55);
}

.subtitle-word:hover {
    text-decoration: underline;
}

/* ---- Image caption / credit overlay ----
   A bottom gradient bar over the scene image. Stays out of the way while
   reading (opacity 0) and fades in on hover, or stays pinned when the user
   clicks the small info badge. Never blocks the image (pointer-events: none),
   except the source link once the bar is revealed.
   Drawn over artwork: keeps literal black/white in both themes. */
.scene-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    margin: 0;
    padding: 2.75rem 1rem 0.7rem;
    background: linear-gradient(to top,
        rgba(0, 0, 0, 0.88) 0%,
        rgba(0, 0, 0, 0.55) 55%,
        rgba(0, 0, 0, 0) 100%);
    color: #f1f1f1;
    font-size: 0.8rem;
    line-height: 1.45;
    text-align: left;
    opacity: 0;
    transform: translateY(0.4rem);
    transition: opacity 0.25s ease, transform 0.25s ease;
    pointer-events: none;
}

#scene-area:hover .scene-caption,
#scene-area.caption-pinned .scene-caption {
    opacity: 1;
    transform: translateY(0);
}

.scene-caption-text {
    display: block;
    color: #fafafa;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

.scene-caption-credit {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.72rem;
    color: rgba(229, 229, 229, 0.78);
}

.scene-caption-credit a {
    color: #ffffff;
    text-decoration: underline;
    pointer-events: none;
}

#scene-area:hover .scene-caption-credit a,
#scene-area.caption-pinned .scene-caption-credit a {
    pointer-events: auto;
}

/* Subtle hint that a caption/credit is available; click to pin it open. */
.scene-caption-badge {
    position: absolute;
    bottom: 0.5rem;
    right: 0.5rem;
    width: 1.45rem;
    height: 1.45rem;
    padding: 0;
    border: none;
    background: rgba(0, 0, 0, 0.55);
    color: rgba(245, 245, 245, 0.9);
    font-size: 0.9rem;
    line-height: 1;
    text-align: center;
    cursor: pointer;
    opacity: 0.5;
    transition: opacity 0.2s ease, background 0.2s ease;
}

.scene-caption-badge:hover {
    opacity: 1;
}

.scene-caption-badge.active {
    background: #ffffff;
    color: #0a0a0a;
    opacity: 1;
}

/* When hovering (and not pinned) the bar already shows, so hide the hint. */
#scene-area:hover:not(.caption-pinned) .scene-caption-badge {
    opacity: 0;
}

/* ---- Story mini-map (videogame UI) ----
   A panel to the right of the scene image: a zoomed crop of the book's
   thematic map, centered on the story's current location with a pulsing
   marker. Hover opens the full map over the scene area; click pins it. */
.story-map-panel {
    display: flex;
    flex-direction: column;
    width: 15rem;
    flex: 0 0 auto;
}

@media (max-width: 900px) {
    .story-map-panel { display: none; }
}

.story-map-frame {
    border: 1px solid rgb(var(--ink) / 0.45);
    overflow: hidden;
    background: rgb(var(--g950));
    box-shadow: 4px 4px 0 rgb(var(--ink) / 0.25);
}

.story-map-panel.pinned .story-map-frame {
    border-color: rgb(var(--ink));
    box-shadow: 4px 4px 0 rgb(var(--ink) / 0.55);
}

.story-map-viewport {
    position: relative;
    height: 11rem;
    overflow: hidden;
    cursor: pointer;
    background: rgb(var(--g950));
}

.story-map-img {
    position: absolute;
    top: 0;
    left: 0;
    max-width: none;
    transition: transform 0.9s ease, width 0.3s ease, height 0.3s ease;
    filter: saturate(0.92) brightness(0.96);
}

.story-map-viewport:hover .story-map-img {
    filter: none;
}

/* Location preview: a real image of the current place, sat below the map in
   a frame of the same footprint (11rem viewport + label). */
.story-map-preview {
    margin-top: 0.6rem;
}

.story-map-preview-viewport {
    cursor: default;
}

.story-map-preview-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    filter: saturate(0.95) brightness(0.97);
}

.story-map-preview-empty {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: rgb(var(--g400) / 0.6);
    font-family: var(--font-ui);
    font-size: 0.7rem;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

.story-map-label {
    padding: 0.35rem 0.6rem;
    border-top: 1px solid rgb(var(--ink) / 0.35);
    background: rgb(var(--g950) / 0.92);
    color: rgb(var(--ink));
    font-family: var(--font-ui);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.story-map-hint {
    margin-top: 0.3rem;
    font-size: 0.66rem;
    color: rgb(var(--g400) / 0.8);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Markers (shared by mini + expanded). The current one pulses.
   Square markers: this map is drawn by a strict librarian.
   The element is an invisible 22px hit area (so the name pops the moment the
   pointer reaches the point); the visible dot is its ::before. */
.story-map-marker {
    position: absolute;
    width: 22px;
    height: 22px;
    transform: translate(-50%, -50%);
    pointer-events: auto;
}

.story-map-marker::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 9px;
    height: 9px;
    transform: translate(-50%, -50%);
    background: rgb(var(--ink) / 0.65);
    border: 1px solid rgb(var(--paper) / 0.8);
}

.story-map-marker-current {
    z-index: 2;
}

.story-map-marker-current::before {
    width: 13px;
    height: 13px;
    background: rgb(var(--ink));
    border: 2px solid rgb(var(--paper));
    box-shadow: 0 0 0 0 rgb(var(--ink) / 0.7);
    animation: story-map-pulse 1.8s ease-out infinite;
}

@keyframes story-map-pulse {
    0%   { box-shadow: 0 0 0 0 rgb(var(--ink) / 0.65); }
    70%  { box-shadow: 0 0 0 12px rgb(var(--ink) / 0); }
    100% { box-shadow: 0 0 0 0 rgb(var(--ink) / 0); }
}

/* Non-current markers reveal their name on hover (the current one always
   shows it). */
.story-map-marker-quiet .story-map-marker-name {
    display: none;
}

.story-map-marker-quiet:hover .story-map-marker-name {
    display: block;
}

.story-map-marker-quiet:hover {
    z-index: 3;
}

/* Name tag: upper-right of the point by default; map.js adds the flip
   classes only when that side would not fit inside the map. */
.story-map-marker-name {
    position: absolute;
    left: 100%;
    bottom: 100%;
    padding: 0.15rem 0.45rem;
    background: rgb(var(--g950) / 0.88);
    border: 1px solid rgb(var(--ink) / 0.5);
    color: rgb(var(--ink));
    font-family: var(--font-ui);
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    white-space: nowrap;
}

.story-map-name-left .story-map-marker-name {
    left: auto;
    right: 100%;
}

.story-map-name-below .story-map-marker-name {
    bottom: auto;
    top: 100%;
}

/* Expanded full-map overlay over the scene area (spares the mini panel so
   hovering it doesn't un-hover the panel and close itself). */
.story-map-expanded {
    position: absolute;
    inset: 0 15.75rem 0 0;
    z-index: 30;
    display: flex;
    flex-direction: column;
    border: 1px solid rgb(var(--ink) / 0.5);
    background: rgb(var(--g950) / 0.96);
    box-shadow: 8px 8px 0 rgb(var(--ink) / 0.2);
    overflow: hidden;
}

.story-map-big-wrap {
    position: relative;
    flex: 1;
    min-height: 0;
}

/* Sized and offset by map.js (zoom-aware), not object-fit. */
.story-map-big-img {
    position: absolute;
    top: 0;
    left: 0;
    max-width: none;
    will-change: transform;
}

.story-map-marker-layer {
    position: absolute;
    inset: 0;
    pointer-events: none;
}

.story-map-credit {
    padding: 0.3rem 0.75rem;
    border-top: 1px solid rgb(var(--ink) / 0.3);
    background: rgb(var(--g950) / 0.92);
    font-size: 0.68rem;
    color: rgb(var(--g300) / 0.85);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.story-map-credit a {
    color: rgb(var(--ink));
    text-decoration: none;
}

.story-map-credit a:hover {
    text-decoration: underline;
}

/* ---- Location preview: cycling views + larger popup ---- */
/* The small frame is clickable only when it actually holds views. */
.story-map-preview-viewport.has-views {
    cursor: pointer;
}

.story-map-preview-img {
    transition: opacity 0.3s ease;
}

/* Tiny dots, bottom-centre of the small frame: one per available view, the
   current one filled. Hidden when there is only a single view. */
.story-map-preview-dots {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0.4rem;
    display: flex;
    justify-content: center;
    gap: 0.3rem;
    pointer-events: none;
}

.story-map-preview-dot {
    width: 6px;
    height: 6px;
    background: rgb(var(--paper) / 0.45);
    border: 1px solid rgb(var(--ink) / 0.55);
}

.story-map-preview-dot.active {
    background: rgb(var(--paper));
}

/* The expanded location-preview popup reuses the map overlay's footprint and
   chrome; the image is CONTAINED (not cropped) so the whole view is readable. */
.story-map-preview-big-wrap {
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgb(var(--g950));
}

.story-map-preview-big-img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    cursor: pointer;
    filter: saturate(0.95) brightness(0.97);
}

/* Thumbnail strip to jump between the views; the current one is outlined. */
.story-map-preview-thumbs {
    display: flex;
    gap: 0.3rem;
    padding: 0.4rem 0.5rem;
    border-top: 1px solid rgb(var(--ink) / 0.3);
    background: rgb(var(--g950) / 0.92);
    overflow-x: auto;
}

.story-map-preview-thumb {
    width: 4rem;
    height: 2.6rem;
    object-fit: cover;
    cursor: pointer;
    border: 1px solid rgb(var(--ink) / 0.4);
    opacity: 0.6;
    filter: saturate(0.9);
    flex: 0 0 auto;
}

.story-map-preview-thumb.active {
    opacity: 1;
    border-color: rgb(var(--ink));
    box-shadow: 0 0 0 1px rgb(var(--ink));
}

/* ---- Scene-image gallery popup: browse the scene's other images on hover ---- */
.scene-gallery-popup {
    position: absolute;
    inset: 0;
    z-index: 25;
    display: flex;
    flex-direction: column;
    background: rgb(var(--g950) / 0.97);
    border: 1px solid rgb(var(--ink) / 0.5);
}

.scene-gallery-popup.pinned {
    box-shadow: inset 0 0 0 2px rgb(var(--ink));
}

.scene-gallery-big {
    flex: 1;
    min-height: 0;
    width: 100%;
    object-fit: contain;
    cursor: pointer;
    background: rgb(var(--g950));
    filter: saturate(0.97);
}

.scene-gallery-thumbs {
    display: flex;
    gap: 0.3rem;
    padding: 0.45rem 0.5rem;
    border-top: 1px solid rgb(var(--ink) / 0.3);
    background: rgb(var(--g950) / 0.92);
    overflow-x: auto;
    justify-content: center;
}

.scene-gallery-thumb {
    width: 5rem;
    height: 3.2rem;
    object-fit: cover;
    cursor: pointer;
    border: 1px solid rgb(var(--ink) / 0.4);
    opacity: 0.6;
    flex: 0 0 auto;
}

.scene-gallery-thumb.active {
    opacity: 1;
    border-color: rgb(var(--ink));
    box-shadow: 0 0 0 1px rgb(var(--ink));
}

/* ---- RSVP (Rapid Serial Visual Presentation) ---- */
:root {
    --rsvp-font-size: 3rem;
    /* The one deliberate colour in the monochrome UI: the RSVP focal letter
       is red per the ORP research and reference implementations (user call). */
    --rsvp-pivot-color: #f43f5e;
    --reticle: 50%;
}

.rsvp-stage {
    position: relative;
    overflow: hidden;
    height: 9rem;
    background: var(--subtitle-bg);
    border: 1px solid rgb(var(--ink) / 0.2);
    /* Monospace keeps glyph widths stable so the pivot never jitters. */
    font-family: ui-monospace, "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
}

.rsvp-word {
    position: absolute;
    top: 50%;
    left: 0;
    white-space: nowrap;
    font-size: var(--rsvp-font-size);
    line-height: 1;
    color: var(--subtitle-color);
    transform: translate(0, -50%);
    will-change: transform;
}

.rsvp-pre,
.rsvp-pivot,
.rsvp-post {
    display: inline-block;
}

.rsvp-pivot {
    color: var(--rsvp-pivot-color);
}

/* Reticle: a thin tick above and below the focal letter to anchor the eye. */
.rsvp-guide {
    position: absolute;
    left: var(--reticle);
    width: 2px;
    height: 1.5rem;
    background: var(--rsvp-pivot-color);
    opacity: 0.65;
    transform: translateX(-50%);
}

.rsvp-guide-top {
    top: 0;
}

.rsvp-guide-bottom {
    bottom: 0;
}

#rsvp-toggle.rsvp-active {
    background: rgb(var(--ink));
    color: rgb(var(--paper));
    font-weight: 600;
}

/* ---- RSVP context view (click the stage background to read normally) ---- */
.rsvp-context {
    max-height: 60vh;
    overflow-y: auto;
    padding: 1.25rem 1.5rem;
    background: var(--subtitle-bg);
    border: 1px solid rgb(var(--ink) / 0.2);
    color: var(--subtitle-color);
    font-size: 1.25rem;
    line-height: 1.9;
    /* Teleprompter fog: rows fade out into the top and bottom edges as the text
       scrolls past, so words appear/leave by rows rather than popping in. The
       follow scroll is animated in JS, so keep native smooth-scroll off. */
    scroll-behavior: auto;
    -webkit-mask-image: linear-gradient(to bottom,
        transparent 0, #000 18%, #000 80%, transparent 100%);
            mask-image: linear-gradient(to bottom,
        transparent 0, #000 18%, #000 80%, transparent 100%);
    scrollbar-width: none;          /* the view auto-scrolls; hide the bar for the fog look */
}

.rsvp-context::-webkit-scrollbar { width: 0; height: 0; }

.rsvp-context-hint {
    position: sticky;
    top: -1.25rem;
    margin: -1.25rem -1.5rem 1rem;
    padding: 0.5rem 1.5rem;
    background: var(--subtitle-bg);
    font-size: 0.8rem;
    color: rgb(var(--g200) / 0.55);
    backdrop-filter: blur(2px);
}

.rsvp-context-word {
    cursor: pointer;
    padding: 0 1px;
    transition: background 0.1s;
}

.rsvp-context-word:hover {
    text-decoration: underline;
}

.rsvp-context-active {
    background: rgb(var(--ink) / 0.12);
    /* Faux-bold via stroke so the emphasis doesn't widen the word and shove the
       surrounding text. A real font-weight change reflows the line. */
    text-shadow: 0.4px 0 0 currentColor, -0.4px 0 0 currentColor;
}

.rsvp-context-pivot {
    color: var(--rsvp-pivot-color);
}
