/* Scrolling Stories design tokens. The only file that defines raw colour, type, spacing,
   radius, shadow, motion and layer values for product chrome. Every stylesheet references
   these properties; story content (fonts, looks, author CSS) is out of scope.
   Spec: docs/design-system/foundations.md */
:root {
  /* ---- Surfaces ---- */
  --ss-paper: #f3efe6;            /* page background */
  --ss-print: #fffcf6;            /* panels, cards, sheets, fields */
  --ss-fill: #e9e3d6;             /* tab tracks, selected nav item, placeholders */
  --ss-surround: #e6e0d3;         /* area around the preview stage */
  --ss-white: #ffffff;              /* photo borders, text on filled accents */
  --ss-fill-highlight: #f0eadf;     /* skeleton shimmer */
  --ss-stage: #121412;            /* anything that shows the story */

  /* ---- Lines ---- */
  --ss-line: #e0d9cb;             /* dividers; decorative only */
  --ss-line-control: #8f8676;     /* edge of a control; 3:1 on paper and print (WCAG 1.4.11) */

  /* ---- Text ---- */
  --ss-ink: #26231e;              /* body text */
  --ss-ink-heading: #233329;      /* serif titles and headings */
  --ss-ink-2: #5a5448;            /* secondary text */
  --ss-ink-3: #6f685b;            /* hints, placeholders, meta; 4.5:1 on paper and print only */
  --ss-ink-on-dark: #f3efe6;      /* text on stage and on filled accents */

  /* ---- Accents ---- */
  --ss-forest: #2e4b3c;           /* primary action, links, selection, focus */
  --ss-forest-hover: #243b2f;
  --ss-forest-active: #1c3025;
  --ss-forest-tint: #e4ebe3;      /* selected row, featured tag */
  --ss-ochre: #9c6b2e;            /* chapters: flags, rules, icons */
  --ss-ochre-text: #7a521d;       /* ochre as text (4.5:1) */
  --ss-ochre-tint: #f1e5cf;
  --ss-terracotta: #b0543a;       /* playhead; destructive icons and fills */
  --ss-terracotta-text: #9a4630;  /* destructive text (4.5:1 on paper) */
  --ss-terracotta-tint: #f6e2da;
  --ss-moss: #3e5a2e;             /* published, success */
  --ss-moss-tint: #e6ecdc;
  --ss-heather: #5d5078;          /* private link, members-only mark */
  --ss-heather-tint: #ebe6ef;

  /* ---- Provider marks (#229): a sign-in button wears its provider's own colour ---- */
  --ss-brand-google: #ffffff;     /* Google: a white button, the coloured G, a grey border */
  --ss-brand-apple: #000000;      /* Apple: black, with a white mark and label */
  --ss-brand-facebook: #0866ff;   /* Facebook blue; a white label reads at 4.8:1 */

  /* ---- Focus ---- */
  --ss-focus: var(--ss-forest);
  --ss-focus-on-dark: #b8d3b0;    /* focus and active state on stage and reader chrome */

  /* ---- Timeline lanes (white text passes 4.5:1 on each) ---- */
  --ss-lane-photo: #577687;
  --ss-lane-photo-tint: #e1e8ea;
  --ss-lane-text: #4f7a5e;
  --ss-lane-text-tint: #e1ebe2;
  --ss-lane-map: #5f7433;
  --ss-lane-overlay: #985f72;
  --ss-lane-backdrop: #6e5f86;
  --ss-lane-advanced: #7d6a58;

  /* ---- Reader chrome (over the author's imagery) ---- */
  --ss-chrome-bg: rgba(14, 16, 14, 0.72);
  --ss-chrome-bg-strong: rgba(14, 16, 14, 0.9);
  --ss-chrome-blur: 10px;
  --ss-chrome-track: rgba(243, 239, 230, 0.32);

  /* ---- Type ---- */
  --ss-font-display: "Newsreader", Georgia, "Times New Roman", serif;
  --ss-font-ui: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --ss-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --ss-display-xl: 2.875rem;      /* 46px public story title */
  --ss-display-l: 2.5rem;         /* 40px page title */
  --ss-display-m: 1.75rem;        /* 28px card headline */
  --ss-display-s: 1.25rem;        /* 20px inspector and panel title */
  --ss-display-xs: 1.0625rem;     /* 17px story card and list titles */
  --ss-text-lg: 1rem;             /* 16px long help, public body */
  --ss-text-md: 0.875rem;         /* 14px default UI text */
  --ss-text-sm: 0.8125rem;        /* 13px controls, table cells, secondary */
  --ss-text-xs: 0.75rem;          /* 12px labels, meta; the floor */
  --ss-text-field: var(--ss-text-md);  /* text typed into a field; 16px on touch, see below */

  --ss-leading-tight: 1.1;
  --ss-leading-ui: 1.45;
  --ss-leading-prose: 1.65;
  --ss-weight-regular: 400;
  --ss-weight-medium: 500;
  --ss-weight-semibold: 600;

  /* ---- Space (4px grid) ---- */
  --ss-space-1: 0.25rem;
  --ss-space-2: 0.5rem;
  --ss-space-3: 0.75rem;
  --ss-space-4: 1rem;
  --ss-space-5: 1.25rem;
  --ss-space-6: 1.5rem;
  --ss-space-8: 2rem;
  --ss-space-10: 2.5rem;
  --ss-space-12: 3rem;
  --ss-space-16: 4rem;

  /* ---- Radius ---- */
  --ss-radius-xs: 3px;            /* thumbnails */
  --ss-radius-sm: 6px;            /* tags, timeline blocks, stage */
  --ss-radius-md: 8px;            /* buttons, fields, chips, list rows */
  --ss-radius-lg: 12px;           /* cards, menus, dialogs */
  --ss-radius-xl: 16px;           /* bottom sheets, reader bar */
  --ss-radius-round: 999px;       /* avatars, switches, dots */

  /* ---- Size ---- */
  --ss-control-sm: 28px;          /* timeline and toolbar controls */
  --ss-control-md: 34px;          /* default desktop control */
  --ss-control-lg: 42px;          /* page-level call to action */
  --ss-touch: 44px;               /* minimum target on touch layouts */
  --ss-icon-sm: 16px;
  --ss-icon-md: 20px;

  /* ---- Elevation ---- */
  --ss-shadow-print: 0 1px 2px rgba(38, 35, 30, 0.12), 0 3px 8px rgba(38, 35, 30, 0.06);
  --ss-shadow-raised: 0 1px 2px rgba(38, 35, 30, 0.08);
  --ss-shadow-menu: 0 10px 24px rgba(38, 35, 30, 0.14), 0 2px 6px rgba(38, 35, 30, 0.08);
  --ss-shadow-dialog: 0 24px 48px rgba(38, 35, 30, 0.2), 0 8px 16px rgba(38, 35, 30, 0.1);
  --ss-shadow-stage: 0 14px 34px rgba(38, 35, 30, 0.2);
  --ss-scrim: rgba(38, 35, 30, 0.45);

  /* ---- Motion (chrome only; story motion is the renderer's) ---- */
  --ss-duration-fast: 120ms;
  --ss-duration-base: 200ms;
  --ss-duration-slow: 320ms;
  --ss-ease: cubic-bezier(0.2, 0, 0, 1);

  /* ---- Layers ---- */
  --ss-z-sticky: 10;
  --ss-z-menu: 100;
  --ss-z-sheet: 200;
  --ss-z-dialog: 300;
  --ss-z-toast: 400;

  /* ---- Layout ---- */
  --ss-topbar-h: 56px;
  --ss-sidebar-w: 240px;
  --ss-storyboard-w: 268px;
  --ss-inspector-w: 336px;
  --ss-timeline-h: 254px;
  --ss-tabbar-h: 66px;
  --ss-content-max: 1200px;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --ss-duration-fast: 0ms;
    --ss-duration-base: 0ms;
    --ss-duration-slow: 0ms;
  }
}

/* iOS Safari magnifies the page when a field it focuses has text under 16px, and never
   undoes it. Every field on a touch layout is at least that. */
@media (pointer: coarse) {
  :root {
    --ss-text-field: 1rem;
  }
}

/* The display steps drop on a phone: a 46px or 40px page title is a line and a half of a
   344px screen, and every page opens with one. The ladder stays three wide so a section
   heading never reads as loud as the page's own name. */
@media (max-width: 599px) {
  :root {
    --ss-display-xl: 2rem;          /* 32px */
    --ss-display-l: 1.75rem;        /* 28px */
    --ss-display-m: 1.375rem;       /* 22px */
  }
}

/* Breakpoints (custom properties can't be used in media queries; use these literals):
   phone < 600px · tablet 600–959px · desktop ≥ 960px (editor switches layout here) · wide ≥ 1440px */

/* Webfonts are linked from static/fonts/fonts.css by the pages that mount the renderer, so Django's {% static %} can stamp them. */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #000; color: #fff; }

#story-container {
    width: 100%;
    min-height: 100vh;
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}
#story-container:focus { outline: 2px solid rgba(78, 185, 172, 0.65); outline-offset: -2px; }

.chapter { position: relative; }

.chapter-bg {
    position: sticky;
    top: 0;
    width: 100%;
    height: 100vh;
    overflow: hidden;
    z-index: 0;
    margin-bottom: -100vh;
    background: #111;
}

.chapter-bg .bg-image {
    position: absolute;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    will-change: transform;
}
.chapter-bg .bg-image.hidden { opacity: 0; visibility: hidden; }
.chapter-bg .bg-image.active { opacity: 1; visibility: visible; }

.bg-image.lqip-loading {
    filter: blur(20px);
}
.bg-image.loaded {
    filter: blur(0);
    transition: filter 0.6s ease;
}

.page-section {
    position: relative;
    min-height: 100vh;
    display: flex;
    z-index: 2;
    pointer-events: none;
}

.page-sticky-wrapper {
    position: sticky;
    top: 0;
    width: 100%;
    height: 100vh;
    display: flex;
    overflow: hidden;
    z-index: 2;
    pointer-events: none;
}

.page-section.pos-left,  .page-sticky-wrapper.pos-left  { justify-content: flex-start; padding-left: 5%; }
.page-section.pos-center,.page-sticky-wrapper.pos-center { justify-content: center; }
.page-section.pos-right, .page-sticky-wrapper.pos-right  { justify-content: flex-end; padding-right: 5%; }

.text-block {
    /* em-scaled children below; keyframes and text_font_size rewrite this */
    font-size: 1rem;
    padding: 2rem 2.5rem;
    background: rgba(0,0,0,0.6);
    color: #fff;
    border-radius: 8px;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    will-change: transform, opacity;
    pointer-events: auto;
    align-self: center;
    position: relative;
    z-index: 3;
}

.text-block.text-block--title {
    background: transparent !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    border-radius: 0;
    box-shadow: none;
}

.text-block.w-narrow { max-width: 400px; width: 90%; }
.text-block.w-medium { max-width: 600px; width: 90%; }
.text-block.w-wide   { max-width: 800px; width: 90%; }

.text-block h1 { font-size: 2.5em; margin-bottom: 1rem; font-weight: 700; line-height: 1.2; }
.text-block h2 { font-size: 1.8em; margin-bottom: 0.75rem; font-weight: 600; line-height: 1.3; }
.text-block h3 { font-size: 1.4em; margin-bottom: 0.5rem; font-weight: 600; }
.text-block p  { font-size: 1.1em; line-height: 1.7; margin-bottom: 1rem; }
.text-block p:last-child { margin-bottom: 0; }
.text-block a { color: #7dd4e8; text-decoration: underline; }
.text-block em { font-style: italic; }
.text-block strong { font-weight: 700; }
.text-block ul, .text-block ol { margin-left: 1.5rem; margin-bottom: 1rem; line-height: 1.7; }
.text-block li { margin-bottom: 0.3rem; }
.text-block blockquote { border-left: 3px solid rgba(255,255,255,0.4); padding-left: 1rem; margin: 1rem 0; font-style: italic; opacity: 0.9; }
.text-block hr { border: none; border-top: 1px solid rgba(255,255,255,0.2); margin: 1.5rem 0; }
.text-block code { background: rgba(255,255,255,0.15); padding: 0.15em 0.4em; border-radius: 3px; font-size: 0.9em; }
.text-block pre { background: rgba(0,0,0,0.4); padding: 1rem; border-radius: 4px; overflow-x: auto; margin: 1rem 0; }
.text-block pre code { background: none; padding: 0; }
.text-block img { max-width: 100%; height: auto; border-radius: 4px; margin: 0.5rem 0; }

.page-overlay-container {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
    transition: opacity 0.6s ease;
}

.page-overlay-img {
    position: absolute;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    will-change: transform;
}
.page-overlay-img.page-overlay-video {
    object-fit: cover;
    background-image: none;
}
.page-overlay-img.hidden { opacity: 0; visibility: hidden; }
.page-overlay-img.active { opacity: 1; visibility: visible; }
.page-overlay-img.lqip-loading {
    filter: blur(20px);
}
.page-overlay-img.loaded {
    filter: blur(0);
    transition: filter 0.6s ease, opacity 1s ease;
}

.error-message {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    padding: 2rem;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    color: #ff6b6b;
    text-align: center;
}
.error-message h2 { font-size: 1.5rem; margin-bottom: 0.75rem; }
.error-message p { font-size: 1.1rem; opacity: 0.8; max-width: 400px; }

/* Phone (0–599px) */
.bp-phone .text-block.w-narrow { max-width: 90vw; }
.bp-phone .text-block.w-medium { max-width: 95vw; }
.bp-phone .text-block.w-wide   { max-width: 100vw; }
.bp-phone .text-block { padding: 1.25rem 1.5rem; font-size: 0.95rem; }
.bp-phone .text-block.text-block--title { padding: 0; }
.bp-phone .page-section.pos-left,
.bp-phone .page-sticky-wrapper.pos-left { padding-left: 3%; }
.bp-phone .page-section.pos-right,
.bp-phone .page-sticky-wrapper.pos-right { padding-right: 3%; }

/* Tablet (600–1023px) */
.bp-tablet .text-block { padding: 1.5rem 2rem; }
.bp-tablet .text-block.text-block--title { padding: 0; }

/* Wide (1920px+) */
.bp-wide .text-block { font-size: 1.08rem; }

.chapter-bg video {
    position: absolute;
    object-fit: cover;
    pointer-events: none;
}

.bg-image.slide-enter,
.bg-image.slide-exit {
    will-change: transform;
}

.chapter.transition-crossfade {
    will-change: opacity;
}
.chapter.transition-slide {
    will-change: transform;
    position: relative;
}

.text-block.keyframe-active {
    position: relative;
    will-change: left, top, max-width, height, font-size, opacity;
}

.auto-scroll-control {
    position: fixed;
    top: max(12px, env(safe-area-inset-top, 0px));
    right: max(12px, env(safe-area-inset-right, 0px));
    left: auto;
    bottom: auto;
    /* wide enough for the speeds and the share buttons on one line; wraps on a phone */
    max-width: min(100vw - 24px - env(safe-area-inset-left, 0px) - env(safe-area-inset-right, 0px), 29rem);
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 24px;
    padding: 6px 14px;
    opacity: 0;
    pointer-events: none;
    transform: translateY(-10px);
    transition: opacity 0.35s ease, transform 0.35s ease;
    user-select: none;
}
.auto-scroll-control.visible {
    opacity: 1;
    pointer-events: auto;
    transform: translateY(0);
}
.auto-scroll-label {
    font-size: 0.75rem;
    color: rgba(255, 255, 255, 0.6);
    letter-spacing: 0.03em;
    white-space: nowrap;
}
.auto-scroll-speeds {
    display: flex;
    gap: 2px;
}
.auto-scroll-btn {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.72rem;
    padding: 3px 10px;
    border-radius: 14px;
    cursor: pointer;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
    white-space: nowrap;
    line-height: 1.4;
}
.auto-scroll-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
}
.auto-scroll-btn.active {
    background: rgba(125, 184, 255, 0.25);
    border-color: rgba(125, 184, 255, 0.5);
    color: #7db8ff;
}

/* Share control: inside the auto-scroll toolbar, so it inherits its reveal/hide. */
.reader-share {
    display: flex;
    gap: 4px;
    align-items: center;
    padding-left: 8px;
    margin-left: 2px;
    border-left: 1px solid rgba(255, 255, 255, 0.15);
}
.reader-share-btn {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.72rem;
    font-family: inherit;
    padding: 3px 10px;
    border-radius: 14px;
    cursor: pointer;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
    white-space: nowrap;
    line-height: 1.4;
}
.reader-share-btn:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
}
.reader-share-btn[hidden] {
    display: none;
}

/* Copy-link toast: the 72px keeps it clear of the toolbar and the progress bars. */
.reader-toast {
    position: fixed;
    left: 50%;
    bottom: max(72px, calc(env(safe-area-inset-bottom, 0px) + 72px));
    transform: translate(-50%, 8px);
    z-index: 10000;
    max-width: min(90vw, 24rem);
    padding: 8px 16px;
    border-radius: 20px;
    background: rgba(0, 0, 0, 0.82);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: 0.8rem;
    text-align: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s ease, transform 0.25s ease;
}
.reader-toast.visible {
    opacity: 1;
    transform: translate(-50%, 0);
}
@media (prefers-reduced-motion: reduce) {
    .reader-toast {
        transition: opacity 0.25s ease;
        transform: translate(-50%, 0);
    }
}

/* Built-in event classes (css-class events) */

.dark-overlay .chapter-bg::after,
.dark-overlay .page-sticky-wrapper::after    { content:''; position:absolute; inset:0; background:rgba(0,0,0,0.45); z-index:1; pointer-events:none; transition:opacity 0.6s ease; }
.light-overlay .chapter-bg::after,
.light-overlay .page-sticky-wrapper::after   { content:''; position:absolute; inset:0; background:rgba(255,255,255,0.25); z-index:1; pointer-events:none; transition:opacity 0.6s ease; }
.warm-overlay .chapter-bg::after,
.warm-overlay .page-sticky-wrapper::after    { content:''; position:absolute; inset:0; background:rgba(255,160,60,0.15); z-index:1; pointer-events:none; transition:opacity 0.6s ease; }
.cool-overlay .chapter-bg::after,
.cool-overlay .page-sticky-wrapper::after    { content:''; position:absolute; inset:0; background:rgba(60,120,255,0.15); z-index:1; pointer-events:none; transition:opacity 0.6s ease; }
.vignette .chapter-bg::after,
.vignette .page-sticky-wrapper::after        { content:''; position:absolute; inset:0; z-index:1; pointer-events:none; box-shadow:inset 0 0 120px 40px rgba(0,0,0,0.7); transition:opacity 0.6s ease; }

/* ::before, so the bars can combine with the mood overlays' ::after. */
.cinematic-bars .chapter-bg::before,
.cinematic-bars .page-sticky-wrapper::before {
    content:''; position:absolute; inset:0; z-index:2; pointer-events:none;
    background: linear-gradient(to bottom, #000 10vh, transparent 10vh, transparent calc(100% - 10vh), #000 calc(100% - 10vh));
    transition: opacity 0.8s ease;
}

.night-mode   .chapter-bg { filter:brightness(0.65) saturate(1.3); transition:filter 0.8s ease; }
.golden-hour  .chapter-bg { filter:sepia(0.25) brightness(1.1) saturate(1.2); transition:filter 0.8s ease; }
.high-contrast .chapter-bg { filter:contrast(1.4) brightness(1.05); transition:filter 0.8s ease; }
.desaturate   .chapter-bg { filter:saturate(0.3); transition:filter 0.8s ease; }

.text-glow            { text-shadow:0 0 12px rgba(125,184,255,0.6), 0 0 24px rgba(125,184,255,0.3) !important; transition:text-shadow 0.4s ease; }
.text-shadow-heavy    { text-shadow:0 4px 12px rgba(0,0,0,0.8) !important; transition:text-shadow 0.4s ease; }
.text-highlight       { background:linear-gradient(transparent 60%, rgba(255,220,60,0.35) 60%) !important; transition:background 0.4s ease; }
.text-uppercase       { text-transform:uppercase !important; letter-spacing:0.08em !important; }
.text-large           { transform:scale(1.15); transform-origin:center center; transition:transform 0.4s ease; }

.fade-in    { animation:evt-fade-in 0.6s ease both; }
.slide-up   { animation:evt-slide-up 0.6s ease both; }
.slide-left { animation:evt-slide-left 0.6s ease both; }

@keyframes evt-fade-in   { from{opacity:0} to{opacity:1} }
@keyframes evt-slide-up  { from{opacity:0;transform:translateY(30px)} to{opacity:1;transform:translateY(0)} }
@keyframes evt-slide-left{ from{opacity:0;transform:translateX(30px)} to{opacity:1;transform:translateX(0)} }

.reduced-motion .bg-image { transition: opacity 0.3s ease !important; }
.reduced-motion .bg-image.lqip-loading { filter: none; transform: none; }
.reduced-motion .page-overlay-img { transition: opacity 0.3s ease !important; }
.reduced-motion .text-block {
    transition: opacity 0.3s ease !important;
    transform: none !important;
}
.reduced-motion .chapter {
    transition: none !important;
}
.reduced-motion video.bg-image {
    display: block;
}

.v3-root {
    position: relative;
    width: 100%;
    /* As variables, so a stage that is not the whole screen can zero them: a letterboxed stage was padding by a notch in the middle of itself (#336). */
    --v3-safe-top: env(safe-area-inset-top, 0px);
    --v3-safe-right: env(safe-area-inset-right, 0px);
    --v3-safe-bottom: env(safe-area-inset-bottom, 0px);
    --v3-safe-left: env(safe-area-inset-left, 0px);
}

.v3-sticky-viewport {
    position: relative;
    /* The one place the tap-strip width lives; anything in the content layer that answers a press keeps its hit target clear of it (#139). */
    --v3-tap-gutter: 30%;
}

.v3-layer-base,
.v3-layer-map,
.v3-layer-media,
.v3-layer-media-css,
.v3-layer-content,
.v3-layer-global-css {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.v3-layer-base {
    z-index: 1;
    background: #0a0a12;
    overflow: hidden;
}

/* Inner stacks stay overflow:visible so overscan surfaces can extend; the clip is at .v3-layer-base. */
.v3-base-stack {
    position: absolute;
    inset: 0;
    overflow: visible;
}

.v3-base-slot {
    position: absolute;
    inset: 0;
    opacity: 0;
    /* --v3-base-transition-ms is written on .v3-layer-base by the renderer from behavior.transition_ms. */
    transition: opacity var(--v3-base-transition-ms, 450ms) ease;
    pointer-events: none;
}

.v3-layer-base[data-base-behavior='static'] .v3-base-slot {
    opacity: 1;
}

.v3-layer-base[data-base-behavior='timed_cycle'][data-phase='0'] .v3-base-slot[data-slot='0'],
.v3-layer-base[data-base-behavior='timed_cycle'][data-phase='1'] .v3-base-slot[data-slot='1'] {
    opacity: 1;
}

.v3-fill-media {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.v3-media-placeholder {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    text-align: center;
    font-size: 0.9rem;
    color: rgba(255, 255, 255, 0.45);
    background: linear-gradient(160deg, #1a1a2e 0%, #0a0a12 100%);
}

.v3-media-placeholder--placement {
    position: relative;
    inset: auto;
    min-height: 6rem;
    background: rgba(0, 0, 0, 0.25);
    border-radius: 6px;
    color: rgba(255, 255, 255, 0.6);
}

/* Map beat (PCB-17). Shares base's z-index (1), or media-css's (3) for the `map_layer.stack: over`
   host (#238): no integer is free either side, so `build()`'s append order is what stacks the map. */
.v3-layer-map {
    z-index: 1;
    padding: 0;
    pointer-events: none;
    overflow: hidden;
}

.v3-layer-map--over {
    z-index: 3;
}

/* Reader shell with no script (PCB-17): self-contained, because nothing else on the page has laid anything out. */
.v3-noscript {
    /* `body` cannot scroll (the story owns it), so this box scrolls itself. */
    position: fixed;
    inset: 0;
    overflow: auto;
    padding: 3rem 1.25rem;
    font: 16px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
    color: #e8ecef;
}
.v3-noscript h1,
.v3-noscript img,
.v3-noscript p { max-width: 40rem; margin: 0 auto 1rem; }
.v3-noscript h1 { font-size: 1.6rem; line-height: 1.2; }
.v3-noscript img { display: block; width: 100%; height: auto; border-radius: 6px; }
.v3-noscript a { color: inherit; }

.v3-map-layer {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

.v3-map-surface,
.v3-map-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Route under the basemap, not instead of it: tiles arrive a few at a time. */
.v3-map-surface { z-index: 1; opacity: 0; transition: opacity .45s ease; }
.v3-map-canvas { z-index: 0; }
.v3-map-layer.has-tiles .v3-map-surface { opacity: 1; }

.v3-map-pins {
    position: absolute;
    z-index: 2;
    left: max(1rem, env(safe-area-inset-left));
    bottom: max(1rem, env(safe-area-inset-bottom));
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: .25rem;
    max-width: min(42vw, 22rem);
}

.v3-map-pin {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .25rem .5rem;
    border-radius: 999px;
    font-size: .8rem;
    line-height: 1.3;
    color: #f2f6f8;
    background: rgba(12, 18, 24, 0.55);
    /* #93: a ring in the opposite tone, so the chip keeps an edge over any picture. */
    box-shadow: 0 0 0 1px rgba(232, 240, 244, .5);
    opacity: .45;
    transition: opacity .3s ease;
}

.v3-map-pin.is-reached { opacity: .85; }
.v3-map-pin.is-current { opacity: 1; font-weight: 600; }

/* #294: the stop's name, and under it the words the author put on the leg arriving here. */
.v3-map-pin-text { display: flex; flex-direction: column; min-width: 0; }
.v3-map-pin-leg { font-size: .72rem; font-weight: 400; opacity: .82; }

.v3-map-pin-thumb {
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
}

/* Elevation strip (PCB-32); the pins and the credit step up only when a route carries a profile. */
.v3-map-profile {
    position: absolute;
    z-index: 2;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: clamp(3.5rem, 12vh, 6rem);
    pointer-events: none;
}

.v3-map-profile-text {
    position: absolute;
    z-index: 3;
    right: max(.75rem, env(safe-area-inset-right));
    bottom: calc(clamp(3.5rem, 12vh, 6rem) + .5rem);
    margin: 0;
    padding: .2rem .55rem;
    border-radius: 999px;
    font-size: .75rem;
    line-height: 1.3;
    color: #f2f6f8;
    background: rgba(12, 18, 24, 0.55);
}

.v3-map-layer.has-profile .v3-map-pins { bottom: calc(clamp(3.5rem, 12vh, 6rem) + .75rem); }
.v3-map-layer.has-profile .v3-map-attribution { bottom: calc(clamp(3.5rem, 12vh, 6rem) + 2.1rem); }

.v3-map-attribution {
    position: absolute;
    z-index: 2;
    right: max(.5rem, env(safe-area-inset-right));
    bottom: max(.35rem, env(safe-area-inset-bottom));
    font-size: .65rem;
    line-height: 1.2;
    padding: .1rem .35rem;
    border-radius: 3px;
    color: rgba(255, 255, 255, .82);
    background: rgba(10, 14, 18, .45);
}

.v3-map-style-light .v3-map-pin { color: #10181e; background: rgba(240, 244, 246, .8); box-shadow: 0 0 0 1px rgba(16, 24, 30, .45); }
.v3-map-style-terrain .v3-map-pin { color: #2c1e12; background: rgba(244, 241, 230, .8); box-shadow: 0 0 0 1px rgba(44, 30, 18, .45); }

@media (prefers-reduced-motion: reduce) {
    .v3-map-surface { transition: none; }
    .v3-map-pin { transition: none; }
}

.v3-layer-media {
    z-index: 2;
    padding: 0;
    pointer-events: none;
}

/* CSS-cue overlays: pointer-events none so the text stays interactive. */
.v3-layer-media-css {
    z-index: 3;
    padding: 0;
    pointer-events: none;
}

.v3-layer-global-css {
    z-index: 5;
    padding: 0;
    pointer-events: none;
}

/* Above the media (3) and global (5) cue surfaces. Safe area is a calc on `.v3-placement-name-overlay`, not padding here: abspos pills ignore parent padding. */
.v3-layer-placement-names {
    position: absolute;
    inset: 0;
    z-index: 6;
    box-sizing: border-box;
    pointer-events: none;
}

/* Browsers do not interpolate `background-image`, so the renderer crossfades opacity between two stacked surfaces (timeline-renderer.js). */
.v3-css-overlay-surface {
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    z-index: 1;
    transition: opacity 1.25s cubic-bezier(0.33, 1, 0.68, 1);
}

.v3-css-overlay-surface.is-visible {
    opacity: 1;
    z-index: 2;
}

.reduced-motion .v3-css-overlay-surface {
    transition: none;
}

.v3-scroll-progress {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    z-index: 4;
    box-sizing: border-box;
    padding-top: var(--v3-safe-top);
    pointer-events: none;
}

.v3-scroll-progress-row {
    height: 3px;
    margin: 0;
    border-radius: 0;
    background: rgba(255, 255, 255, 0.12);
    overflow: hidden;
}

.v3-scroll-progress-row--local {
    margin-top: 2px;
    background: rgba(255, 255, 255, 0.08);
}

.v3-scroll-progress-fill {
    height: 100%;
    width: 0%;
    border-radius: inherit;
    transform-origin: 0 50%;
}

.v3-scroll-progress-row--story .v3-scroll-progress-fill {
    background: rgba(255, 255, 255, 0.52);
}

.v3-scroll-progress-row--local .v3-scroll-progress-fill {
    background: rgba(255, 255, 255, 0.44);
}

/* The chapter menu (PCB-10) mounts here, a sibling of the aria-hidden progress bars and not a child, so it stays announced and focusable. */
.v3-reader-chrome {
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    z-index: 5;
    box-sizing: border-box;
    padding: calc(var(--v3-safe-top) + 10px) 0 0 max(10px, var(--v3-safe-left));
    pointer-events: none;
}

.v3-chapter-nav {
    position: relative;
    display: inline-block;
    pointer-events: auto;
    font-family: inherit;
}

.v3-chapter-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: rgba(0, 0, 0, 0.62);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: rgba(255, 255, 255, 0.86);
    font-family: inherit;
    font-size: 0.72rem;
    line-height: 1.4;
    padding: 4px 12px;
    border-radius: 14px;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.25s ease, background 0.2s ease;
}

.v3-chapter-btn:hover,
.v3-chapter-btn:focus-visible,
.v3-chapter-nav.is-open .v3-chapter-btn {
    opacity: 1;
    background: rgba(0, 0, 0, 0.82);
}

.v3-chapter-btn:focus-visible,
.v3-chapter-item:focus-visible {
    outline: 2px solid rgba(125, 184, 255, 0.9);
    outline-offset: 2px;
}

.v3-chapter-btn-glyph {
    font-size: 0.8rem;
}

.v3-chapter-panel {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    margin: 0;
    padding: 6px;
    list-style: none;
    min-width: 13rem;
    max-width: min(80vw, 20rem);
    max-height: min(60vh, 24rem);
    overflow-y: auto;
    background: rgba(0, 0, 0, 0.88);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}

.v3-chapter-panel[hidden] {
    display: none;
}

.v3-chapter-item {
    display: block;
    padding: 7px 10px;
    border-radius: 8px;
    color: rgba(255, 255, 255, 0.82);
    text-decoration: none;
    font-size: 0.82rem;
    line-height: 1.35;
}

.v3-chapter-item:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
}

.v3-chapter-item.is-current {
    color: #7db8ff;
    background: rgba(125, 184, 255, 0.14);
}

/* "Read as a page" (PCB-21), beside the chapters. */
.v3-flat-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: 6px;
    pointer-events: auto;
    background: rgba(0, 0, 0, 0.62);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: rgba(255, 255, 255, 0.86);
    font-family: inherit;
    font-size: 0.72rem;
    line-height: 1.4;
    padding: 4px 12px;
    border-radius: 14px;
    text-decoration: none;
    opacity: 0.55;
    transition: opacity 0.25s ease, background 0.2s ease;
}

.v3-flat-link:hover,
.v3-flat-link:focus-visible {
    opacity: 1;
    background: rgba(0, 0, 0, 0.82);
    color: #fff;
}

.v3-flat-link:focus-visible {
    outline: 2px solid rgba(125, 184, 255, 0.9);
    outline-offset: 2px;
}

/* 1.15em, not the bar's 16px: beside 0.72rem text a fixed glyph reads as a badge (#193). */
.v3-flat-link svg {
    flex: none;
    width: 1.15em;
    height: 1.15em;
}

/* Keyboard reader: a way out, and something for Tab to land on (PCB-10). */
.ss-skip-link {
    position: fixed;
    left: 50%;
    top: 0;
    transform: translate(-50%, -150%);
    z-index: 10001;
    padding: 10px 18px;
    background: #0b1a24;
    color: #eaf3f8;
    border: 1px solid rgba(125, 184, 255, 0.7);
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
    font: 500 0.85rem/1.3 system-ui, -apple-system, "Segoe UI", sans-serif;
    text-decoration: none;
}

.ss-skip-link:focus {
    transform: translate(-50%, 0);
}

.ss-story-end,
/* What the `P` key did (#186): read out, never drawn. */
.auto-scroll-status {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

#story-container:focus-visible {
    outline: 3px solid rgba(125, 184, 255, 0.9);
    outline-offset: -3px;
}

/* z-index 3, under `.v3-layer-content` (4), so inline markdown media takes its own taps. Anything
   in the content layer that answers a press owes the gutters `--v3-tap-gutter` of clearance (#139). */
.v3-tap-nav-zones {
    position: absolute;
    inset: 0;
    z-index: 3;
    pointer-events: none;
}

/* Fallback when the strips mount on the scroll container (no strip host). */
.v3-tap-nav-zones--root-fixed {
    position: fixed;
    z-index: 800;
}

.v3-tap-nav-zone {
    position: absolute;
    top: 0;
    bottom: 0;
    width: var(--v3-tap-gutter, 30%);
    border: 0;
    padding: 0;
    margin: 0;
    background: transparent;
    cursor: pointer;
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
}

.v3-tap-nav-zone:focus-visible {
    outline: 2px solid rgba(125, 184, 255, 0.85);
    outline-offset: -2px;
}

.v3-tap-nav-zone--left {
    left: 0;
}

/* Leave top-right clear for the auto-scroll toolbar hotspot. */
.v3-tap-nav-zone--right {
    right: 0;
    top: max(72px, env(safe-area-inset-top, 0px));
}

/* A finger held in a gutter is a step, not a selection (#190); the class goes on at the press, before the platform's long-press timer. */
.v3-tap-nav-holding {
    -webkit-user-select: none;
    user-select: none;
    -webkit-touch-callout: none;
}

.v3-tap-nav-hint {
    position: fixed;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    max-width: min(22rem, calc(100vw - 2.5rem));
    /* An embed's frame can be shorter than the card, which used to put Got it below the
       bottom edge (#273): cap the card and let the words scroll instead. */
    max-height: calc(100% - 1.25rem);
    display: flex;
    overflow: hidden;
    padding: 1.1rem 1.25rem;
    border-radius: 14px;
    background: rgba(12, 14, 18, 0.88);
    border: 1px solid rgba(255, 255, 255, 0.12);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
    pointer-events: none;
    z-index: 8500;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.55s ease, visibility 0.55s ease, transform 0.55s ease;
}

.v3-tap-nav-hint--visible {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, -50%) scale(1);
}

.v3-tap-nav-hint-inner {
    display: flex;
    flex-direction: column;
    min-height: 0;
    width: 100%;
    text-align: center;
    font-size: 0.88rem;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.92);
}

.v3-tap-nav-hint-title {
    flex: none;
    font-weight: 600;
    font-size: 0.95rem;
    margin-bottom: 0.35rem;
    letter-spacing: 0.02em;
}

.v3-tap-nav-hint-text {
    min-height: 0;
    color: rgba(255, 255, 255, 0.78);
    font-size: 0.84rem;
}

/* Put on by `_syncHintOverflow` only when the capped card is cutting the words off (#273):
   a scroll container with nothing to scroll would swallow the reader's first scroll. */
.v3-tap-nav-hint-text--scrolls {
    overflow-y: auto;
    overscroll-behavior: contain;
    pointer-events: auto;
}

.v3-tap-nav-hint-arrows {
    flex: none;
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 0.75rem;
    padding: 0 min(12vw, 3rem);
    opacity: 0.85;
}

.v3-tap-nav-hint-arrow {
    display: inline-block;
    width: 2rem;
    height: 2rem;
    border: solid rgba(255, 255, 255, 0.55);
    border-width: 0 2px 2px 0;
    opacity: 0.75;
}

.v3-tap-nav-hint-arrow--left {
    transform: rotate(135deg);
    animation: v3-tap-hint-nudge-left 2.2s ease-in-out infinite;
}

.v3-tap-nav-hint-arrow--right {
    transform: rotate(-45deg);
    animation: v3-tap-hint-nudge-right 2.2s ease-in-out infinite;
}

@keyframes v3-tap-hint-nudge-left {
    0%, 100% { transform: rotate(135deg) translateX(0); opacity: 0.55; }
    50% { transform: rotate(135deg) translateX(-10px); opacity: 1; }
}

@keyframes v3-tap-hint-nudge-right {
    0%, 100% { transform: rotate(-45deg) translateX(0); opacity: 0.55; }
    50% { transform: rotate(-45deg) translateX(10px); opacity: 1; }
}

.reduced-motion .v3-tap-nav-hint-arrow--left,
.reduced-motion .v3-tap-nav-hint-arrow--right,
.v3-tap-nav-hint--reduced .v3-tap-nav-hint-arrow--left,
.v3-tap-nav-hint--reduced .v3-tap-nav-hint-arrow--right {
    animation: none;
    opacity: 0.75;
}

/* "Got it" (#186): the hint panel stays pointer-transparent, so only this takes a press. */
.v3-tap-nav-hint-dismiss {
    flex: none;
    align-self: center;
    display: inline-block;
    margin-top: 0.85rem;
    min-height: 2.25rem;
    padding: 0 1rem;
    border: 1px solid rgba(255, 255, 255, 0.55);
    border-radius: 999px;
    background: transparent;
    color: rgba(255, 255, 255, 0.92);
    font-family: inherit;
    font-size: 0.84rem;
    font-weight: 500;
    line-height: 1.3;
    cursor: pointer;
    pointer-events: auto;
}

.v3-tap-nav-hint-dismiss:hover {
    background: rgba(255, 255, 255, 0.12);
}

.v3-tap-nav-hint-dismiss:focus-visible {
    outline: 2px solid rgba(125, 184, 255, 0.9);
    outline-offset: 2px;
}

/* A frame this short has no room for the gesture arrows as well as the words and Got it (#273). */
@media (max-height: 280px) {
    .v3-tap-nav-hint {
        max-height: calc(100% - 0.5rem);
        padding: 0.6rem 0.9rem;
    }

    .v3-tap-nav-hint-title {
        margin-bottom: 0.2rem;
    }

    .v3-tap-nav-hint-arrows {
        display: none;
    }

    .v3-tap-nav-hint-dismiss {
        margin-top: 0.5rem;
    }

}

/* One .v3-placement-stage per mounted placement; two can live here while their enter/exit windows overlap. */
.v3-placement-host {
    position: absolute;
    inset: 0;
    overflow: visible;
    pointer-events: none;
}

/* The renderer writes opacity + transform every scroll tick; a CSS transition here would fight the scroll driver. */
.v3-placement-stage {
    position: absolute;
    inset: 0;
    overflow: visible;
    pointer-events: none;
    will-change: opacity, transform;
}

/* Crossfade between bundle items in one placement — the one time-based opacity transition here. */
.v3-placement-crossfade {
    position: absolute;
    inset: 0;
}

.v3-placement-slot {
    position: absolute;
    inset: 0;
    opacity: 0;
    z-index: 1;
    pointer-events: none;
    /* Stacking context so z-index on children beats composited <video> painting over siblings. */
    isolation: isolate;
    /* --v3-placement-transition-ms is written on .v3-placement-crossfade by the renderer from behavior.transition_ms. */
    transition: opacity var(--v3-placement-transition-ms, 400ms) ease;
}

.v3-placement-slot.is-visible {
    opacity: 1;
    z-index: 2;
}

.reduced-motion .v3-placement-slot {
    transition: none;
}

/* Above the cover media: a slot-level background would paint under the video. */
.v3-placement-css-overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    box-sizing: border-box;
    /* Promote above sibling <video> layers (Chrome/Safari often composite video on top otherwise). */
    transform: translateZ(0);
}

.v3-motion-root {
    position: absolute;
    inset: 0;
    overflow: visible;
    transform-origin: center center;
    will-change: transform;
    z-index: 0;
}

/* Oversized so parallax / zoom / Ken Burns never reveal the viewport edges. */
.v3-motion-cover-surface {
    position: absolute;
    transform-origin: center center;
    will-change: transform;
}

.v3-motion-cover-surface .v3-fill-media {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* LQIP under full-res. The wrapper carries .v3-fill-media so ensureCoverSurface + applyKenBurns treat it as a single <img>. */
.v3-fill-media--progressive {
    position: absolute;
    inset: 0;
    overflow: hidden;
}

.v3-fill-media--progressive > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
}

.v3-fill-media-lqip {
    /* The scale keeps the blur's own edges off-screen. */
    filter: blur(18px) saturate(1.15);
    transform: scale(1.06);
    z-index: 1;
}

.v3-fill-media-full {
    opacity: 0;
    z-index: 2;
    transition: opacity 350ms ease;
}

.v3-fill-media--progressive.is-hi-res-loaded .v3-fill-media-full {
    opacity: 1;
}

.reduced-motion .v3-fill-media-full {
    transition: none;
}

/* Ken Burns: time-based drift/scale on the media element, not scroll-driven. */
.v3-ken-burns .v3-ken-burns-media {
    animation: v3KenBurnsDrift var(--v3-kb-dur, 24s) ease-in-out infinite alternate;
    will-change: transform;
}

@keyframes v3KenBurnsDrift {
    from {
        transform: scale(var(--v3-kb-s0, 1)) translate(0, 0);
    }
    to {
        transform: scale(var(--v3-kb-s1, 1.08)) translate(var(--v3-kb-dx, 0), var(--v3-kb-dy, 0));
    }
}

.reduced-motion .v3-ken-burns .v3-ken-burns-media {
    animation: none;
}

.v3-debug-overlay {
    position: fixed;
    top: 8px;
    left: 8px;
    z-index: 10050;
    max-width: min(92vw, 36rem);
    margin: 0;
    padding: 8px 10px;
    font: 11px/1.35 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    color: #e8f7ff;
    background: rgba(8, 12, 22, 0.82);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 6px;
    pointer-events: none;
    white-space: pre-wrap;
    word-break: break-word;
}

.v3-placement-stage .v3-fill-media {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

/* On the slot, not the motion root, so parallax / ken burns never transforms it. */
.v3-placement-name-overlay {
    position: absolute;
    --v3-name-inset: clamp(0.75rem, 2.5vw, 1.75rem);
    right: calc(var(--v3-safe-right) + var(--v3-name-inset));
    bottom: calc(var(--v3-safe-bottom) + var(--v3-name-inset));
    z-index: 3;
    max-width: min(60vw, 28rem);
    padding: 0.4em 0.75em 0.45em;
    font: 500 0.8rem/1.35 -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
    letter-spacing: 0.02em;
    color: rgba(255, 255, 255, 0.92);
    background: rgba(0, 0, 0, 0.35);
    border-radius: 999px;
    backdrop-filter: blur(6px) saturate(1.1);
    -webkit-backdrop-filter: blur(6px) saturate(1.1);
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
    pointer-events: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}


.v3-layer-content {
    z-index: 4;
    padding: 0;
    pointer-events: none;
}

/* v3 built-in overlay classes (same catalogue as the css-class presets above). */
/* Flat washes: background-color stacks under gradient background-image on the same surface. */
.v3-layer-media-css > .v3-css-overlay-surface.dark-overlay,
.v3-layer-global-css > .v3-css-overlay-surface.dark-overlay,
.v3-placement-slot .v3-placement-css-overlay.dark-overlay,
.v3-base-slot.dark-overlay {
    background-color: rgba(0, 0, 0, 0.45);
}

.v3-layer-media-css > .v3-css-overlay-surface.light-overlay,
.v3-layer-global-css > .v3-css-overlay-surface.light-overlay,
.v3-placement-slot .v3-placement-css-overlay.light-overlay,
.v3-base-slot.light-overlay {
    background-color: rgba(255, 255, 255, 0.25);
}

.v3-layer-media-css > .v3-css-overlay-surface.warm-overlay,
.v3-layer-global-css > .v3-css-overlay-surface.warm-overlay,
.v3-placement-slot .v3-placement-css-overlay.warm-overlay,
.v3-base-slot.warm-overlay {
    background-color: rgba(255, 160, 60, 0.15);
}

.v3-layer-media-css > .v3-css-overlay-surface.cool-overlay,
.v3-layer-global-css > .v3-css-overlay-surface.cool-overlay,
.v3-placement-slot .v3-placement-css-overlay.cool-overlay,
.v3-base-slot.cool-overlay {
    background-color: rgba(60, 120, 255, 0.15);
}

.v3-layer-media-css > .v3-css-overlay-surface.vignette,
.v3-layer-global-css > .v3-css-overlay-surface.vignette,
.v3-placement-slot .v3-placement-css-overlay.vignette,
.v3-base-slot.vignette {
    box-shadow: inset 0 0 40px 15px rgba(0, 0, 0, 0.7);
}

.v3-layer-media-css > .v3-css-overlay-surface.vignette-soft,
.v3-layer-global-css > .v3-css-overlay-surface.vignette-soft,
.v3-placement-slot .v3-placement-css-overlay.vignette-soft,
.v3-base-slot.vignette-soft {
    box-shadow: inset 0 0 55px 22px rgba(0, 0, 0, 0.38);
}

.v3-layer-media-css > .v3-css-overlay-surface.cinematic-bars,
.v3-layer-global-css > .v3-css-overlay-surface.cinematic-bars,
.v3-placement-slot .v3-placement-css-overlay.cinematic-bars,
.v3-base-slot.cinematic-bars {
    box-sizing: border-box;
    border-top: 6px solid #000;
    border-bottom: 6px solid #000;
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-brand-sweep,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-brand-sweep,
.v3-placement-slot .v3-placement-css-overlay.gradient-brand-sweep,
.v3-base-slot.gradient-brand-sweep {
    background-color: transparent;
    background-image: linear-gradient(
        135deg,
        rgba(14, 31, 44, 0.78) 0%,
        rgba(22, 74, 107, 0.5) 45%,
        rgba(31, 107, 99, 0.55) 100%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-veil-bottom-25,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-veil-bottom-25,
.v3-placement-slot .v3-placement-css-overlay.gradient-veil-bottom-25,
.v3-base-slot.gradient-veil-bottom-25 {
    background-color: transparent;
    background-image: linear-gradient(
        to top,
        rgba(8, 10, 18, 0.75) 0%,
        rgba(8, 10, 18, 0.38) 14%,
        transparent 25%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-veil-bottom-50,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-veil-bottom-50,
.v3-placement-slot .v3-placement-css-overlay.gradient-veil-bottom-50,
.v3-base-slot.gradient-veil-bottom-50 {
    background-color: transparent;
    background-image: linear-gradient(
        to top,
        rgba(8, 10, 18, 0.82) 0%,
        rgba(8, 10, 18, 0.42) 30%,
        transparent 50%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-veil-bottom-70,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-veil-bottom-70,
.v3-placement-slot .v3-placement-css-overlay.gradient-veil-bottom-70,
.v3-base-slot.gradient-veil-bottom-70 {
    background-color: transparent;
    background-image: linear-gradient(
        to top,
        rgba(5, 6, 12, 0.9) 0%,
        rgba(5, 6, 12, 0.52) 45%,
        transparent 70%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-veil-top-40,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-veil-top-40,
.v3-placement-slot .v3-placement-css-overlay.gradient-veil-top-40,
.v3-base-slot.gradient-veil-top-40 {
    background-color: transparent;
    background-image: linear-gradient(
        to bottom,
        rgba(248, 250, 255, 0.22) 0%,
        rgba(248, 250, 255, 0.07) 22%,
        transparent 40%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-edge-left,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-edge-left,
.v3-placement-slot .v3-placement-css-overlay.gradient-edge-left,
.v3-base-slot.gradient-edge-left {
    background-color: transparent;
    background-image: linear-gradient(to right, rgba(0, 0, 0, 0.64) 0%, transparent 50%);
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-edge-right,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-edge-right,
.v3-placement-slot .v3-placement-css-overlay.gradient-edge-right,
.v3-base-slot.gradient-edge-right {
    background-color: transparent;
    background-image: linear-gradient(to left, rgba(0, 0, 0, 0.64) 0%, transparent 50%);
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-dusk-glow,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-dusk-glow,
.v3-placement-slot .v3-placement-css-overlay.gradient-dusk-glow,
.v3-base-slot.gradient-dusk-glow {
    background-color: transparent;
    background-image: linear-gradient(
        125deg,
        rgba(88, 48, 120, 0.48) 0%,
        rgba(255, 120, 70, 0.2) 52%,
        rgba(40, 65, 110, 0.28) 100%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-night-azure,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-night-azure,
.v3-placement-slot .v3-placement-css-overlay.gradient-night-azure,
.v3-base-slot.gradient-night-azure {
    background-color: transparent;
    background-image: linear-gradient(
        180deg,
        rgba(12, 24, 48, 0.58) 0%,
        rgba(6, 10, 22, 0.78) 62%,
        rgba(0, 0, 0, 0.88) 100%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-dawn-vertical,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-dawn-vertical,
.v3-placement-slot .v3-placement-css-overlay.gradient-dawn-vertical,
.v3-base-slot.gradient-dawn-vertical {
    background-color: transparent;
    background-image: linear-gradient(
        to bottom,
        rgba(255, 214, 180, 0.24) 0%,
        rgba(120, 170, 220, 0.14) 42%,
        rgba(20, 28, 44, 0.38) 100%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.spotlight-bottom,
.v3-layer-global-css > .v3-css-overlay-surface.spotlight-bottom,
.v3-placement-slot .v3-placement-css-overlay.spotlight-bottom,
.v3-base-slot.spotlight-bottom {
    background-color: transparent;
    background-image: radial-gradient(
        120% 85% at 50% 100%,
        rgba(0, 0, 0, 0.8) 0%,
        rgba(0, 0, 0, 0.36) 44%,
        transparent 70%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.gradient-aurora-diagonal,
.v3-layer-global-css > .v3-css-overlay-surface.gradient-aurora-diagonal,
.v3-placement-slot .v3-placement-css-overlay.gradient-aurora-diagonal,
.v3-base-slot.gradient-aurora-diagonal {
    background-color: transparent;
    background-image: linear-gradient(
        205deg,
        rgba(20, 90, 120, 0.35) 0%,
        rgba(180, 90, 160, 0.22) 38%,
        rgba(40, 60, 110, 0.4) 100%
    );
}

.v3-layer-media-css > .v3-css-overlay-surface.atmosphere-lift,
.v3-layer-global-css > .v3-css-overlay-surface.atmosphere-lift,
.v3-base-slot.atmosphere-lift {
    backdrop-filter: brightness(1.08) saturate(1.06);
    -webkit-backdrop-filter: brightness(1.08) saturate(1.06);
}

.v3-layer-media-css > .v3-css-overlay-surface.atmosphere-dreamy,
.v3-layer-global-css > .v3-css-overlay-surface.atmosphere-dreamy,
.v3-base-slot.atmosphere-dreamy {
    backdrop-filter: saturate(1.14) brightness(1.05);
    -webkit-backdrop-filter: saturate(1.14) brightness(1.05);
}

.v3-layer-media-css > .v3-css-overlay-surface.night-mode,
.v3-layer-global-css > .v3-css-overlay-surface.night-mode,
.v3-base-slot.night-mode {
    backdrop-filter: brightness(0.65) saturate(1.3);
    -webkit-backdrop-filter: brightness(0.65) saturate(1.3);
}

.v3-layer-media-css > .v3-css-overlay-surface.golden-hour,
.v3-layer-global-css > .v3-css-overlay-surface.golden-hour,
.v3-base-slot.golden-hour {
    backdrop-filter: sepia(0.25) brightness(1.1) saturate(1.2);
    -webkit-backdrop-filter: sepia(0.25) brightness(1.1) saturate(1.2);
}

.v3-layer-media-css > .v3-css-overlay-surface.high-contrast,
.v3-layer-global-css > .v3-css-overlay-surface.high-contrast,
.v3-base-slot.high-contrast {
    backdrop-filter: contrast(1.4) brightness(1.05);
    -webkit-backdrop-filter: contrast(1.4) brightness(1.05);
}

.v3-layer-media-css > .v3-css-overlay-surface.desaturate,
.v3-layer-global-css > .v3-css-overlay-surface.desaturate,
.v3-base-slot.desaturate {
    backdrop-filter: saturate(0.3);
    -webkit-backdrop-filter: saturate(0.3);
}

/* `backdrop-filter` on a div above <video> usually leaves the video out of the snapshot, so the same adjustment goes on the motion subtree as `filter`. */
.v3-placement-slot:has(> .v3-placement-css-overlay.atmosphere-lift) > .v3-motion-root {
    filter: brightness(1.08) saturate(1.06);
}

.v3-placement-slot:has(> .v3-placement-css-overlay.atmosphere-dreamy) > .v3-motion-root {
    filter: saturate(1.14) brightness(1.05);
}

.v3-placement-slot:has(> .v3-placement-css-overlay.night-mode) > .v3-motion-root {
    filter: brightness(0.65) saturate(1.3);
}

.v3-placement-slot:has(> .v3-placement-css-overlay.golden-hour) > .v3-motion-root {
    filter: sepia(0.25) brightness(1.1) saturate(1.2);
}

.v3-placement-slot:has(> .v3-placement-css-overlay.high-contrast) > .v3-motion-root {
    filter: contrast(1.4) brightness(1.05);
}

.v3-placement-slot:has(> .v3-placement-css-overlay.desaturate) > .v3-motion-root {
    filter: saturate(0.3);
}

.v3-content-host {
    position: absolute;
    inset: 0;
    pointer-events: none;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.85);
}

/* max(clamp, safe area) so tight_bottom / bottom presets clear the notch and home indicator. */
.v3-content-anchor {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    /* 3% of the stage, not the window: `--v3-vw` comes from the renderer (#180); the rem ends scale with `--v3-model` (#322). */
    --v3-anchor-pad: clamp(calc(0.75rem * var(--v3-model, 1)), 3 * var(--v3-vw, 1vw),
                           calc(2.5rem * var(--v3-model, 1)));
    padding: var(--v3-anchor-pad);
    padding-top: max(var(--v3-anchor-pad), var(--v3-safe-top));
    padding-right: max(var(--v3-anchor-pad), var(--v3-safe-right));
    padding-bottom: max(var(--v3-anchor-pad), var(--v3-safe-bottom));
    padding-left: max(var(--v3-anchor-pad), var(--v3-safe-left));
    pointer-events: none;
}

/* Only the inner text column is interactive; the boxed shell's gutters pass taps through to the media below and to scroll gestures. */
.v3-content-block {
    pointer-events: none;
    position: relative;
    text-align: center;
    margin: 0;
    line-height: 1.35;
    will-change: transform, opacity;
    /* Fluid base size so rem-authored copy (converted to em in JS) keeps its proportion of the canvas; tuned over ~320–1440px. `--v3-vw` is the stage's width (#180). */
    font-size: clamp(calc(0.8125rem * var(--v3-model, 1)),
                     calc(0.68rem * var(--v3-model, 1)) + 0.55 * var(--v3-vw, 1vw),
                     calc(1rem * var(--v3-model, 1)));
}

.v3-content-inner {
    /* Shrink-wrap to the ink: the shell stays wide while taps outside it pass through. */
    width: fit-content;
    max-width: 100%;
    margin-left: auto;
    margin-right: auto;
    pointer-events: auto;
    white-space: normal;
}

/* Embed authoring (`?mode=authoring`): the shell drags; right/bottom edge bands resize. */
#story-container.v3-embed-authoring .v3-content-block {
    pointer-events: auto;
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
    box-sizing: border-box;
    outline: 1px dashed rgba(120, 200, 255, 0.5);
    outline-offset: 2px;
    position: relative;
    /* Without this, mobile browsers claim the touch for scrolling and fire pointercancel mid-drag. */
    touch-action: none;
}

/* The bottom-right bracket is the one touch grip (embed-content-authoring `onPointerDown`). */
#story-container.v3-embed-authoring .v3-content-block::after {
    content: '';
    position: absolute;
    right: -7px;
    bottom: -7px;
    width: 22px;
    height: 22px;
    border-right: 3px solid rgba(120, 200, 255, 0.85);
    border-bottom: 3px solid rgba(120, 200, 255, 0.85);
    border-bottom-right-radius: 6px;
    pointer-events: none;
}

/* The ☀ opacity grip is hit-tested by embed-content-authoring `gripGeometry` — keep the geometry in
   step. `--v3-op-grip-top` / `--v3-font-grip-top` push both discs inside a stage shorter than the block (#332). */
#story-container.v3-embed-authoring .v3-content-block {
    --v3-grip-px: 26px;
    --v3-grip-glyph: 16px;
    --v3-grip-glyph-aa: 18px;
}
@media (pointer: coarse) {
    #story-container.v3-embed-authoring .v3-content-block {
        --v3-grip-px: 34px;
        --v3-grip-glyph: 21px;
        --v3-grip-glyph-aa: 23px;
    }
}
#story-container.v3-embed-authoring .v3-content-block::before {
    content: '';
    position: absolute;
    top: var(--v3-op-grip-top, 2px);
    left: 2px;
    width: var(--v3-grip-px);
    height: var(--v3-grip-px);
    border-radius: 50%;
    background-color: rgba(120, 200, 255, 0.85);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23081a2a' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='4'/%3E%3Cpath d='M12 2v2M12 20v2M2 12h2M20 12h2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: var(--v3-grip-glyph) var(--v3-grip-glyph);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
    pointer-events: none;
    z-index: 2;
}

/* The Aa font grip (#117) is a real element, not a pseudo (both are taken above), hit-tested by `gripAt`
   — keep the geometry in step. #145: bottom-left, but under the ☀ on a block below 58px; `--v3-font-grip-top`
   is `fontGripCenterY` clamped into the stage (#332). */
#story-container.v3-embed-authoring .v3-content-block > .v3-content-font-grip {
    position: absolute;
    top: var(--v3-font-grip-top, max(30px, calc(100% - 28px)));
    left: 2px;
    width: var(--v3-grip-px);
    height: var(--v3-grip-px);
    border-radius: 50%;
    background-color: rgba(120, 200, 255, 0.85);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23081a2a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 14h-5'/%3E%3Cpath d='M16 16v-3.5a2.5 2.5 0 0 1 5 0V16'/%3E%3Cpath d='M4.5 13h6'/%3E%3Cpath d='m3 16 4.5-9 4.5 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: var(--v3-grip-glyph-aa) var(--v3-grip-glyph-aa);
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
    pointer-events: none;
    z-index: 2;
}

/* Taken (#332): the press must show before the finger moves. */
#story-container.v3-embed-authoring .v3-content-block[data-v3-grip="opacity"]::before,
#story-container.v3-embed-authoring .v3-content-block[data-v3-grip="font"] > .v3-content-font-grip {
    background-color: rgb(160, 220, 255);
    box-shadow: 0 0 0 3px rgba(8, 26, 42, 0.55), 0 1px 4px rgba(0, 0, 0, 0.35);
}

#story-container.v3-embed-authoring .v3-content-block:active {
    cursor: grabbing;
}

#story-container.v3-embed-authoring .v3-content-inner {
    cursor: inherit;
    outline: none;
    user-select: none;
    -webkit-user-select: none;
}

#story-container.v3-embed-authoring .v3-content-inner a {
    cursor: pointer;
}

/* Full column width: `fit-content` otherwise shrinks the grid to about one thumb. */
.v3-content-inner:has(.v3-inline-media-grid) {
    width: 100%;
    max-width: 100%;
}

.v3-content-inner p {
    margin-bottom: 0.65em;
    line-height: 1.65;
}

.v3-content-inner p:last-child {
    margin-bottom: 0;
}

.v3-content-inner h1 {
    font-size: 2em;
    font-weight: 700;
    margin-bottom: 0.5rem;
}

.v3-content-inner h2 {
    font-size: 1.45em;
    font-weight: 600;
    margin-bottom: 0.45rem;
}

.v3-content-inner a {
    color: #7dd4e8;
    text-decoration: underline;
}

/* Library media embedded in content_markdown (```ss-media … ```) — thumbnail + lightbox */
.v3-content-inner .v3-inline-media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
    /* ~half the box padding at typical scale. */
    gap: 10px 12px;
    width: 100%;
    margin: 0.75em 0;
    box-sizing: border-box;
    align-items: stretch;
    justify-items: stretch;
}

.v3-content-inner .v3-inline-media-grid > .v3-inline-media {
    margin: 0;
    min-width: 0;
    width: 100%;
    max-width: none;
}

.v3-content-inner .v3-inline-media-grid .v3-inline-media-thumb-btn {
    width: 100%;
}

.v3-content-inner .v3-inline-media-grid .v3-inline-media-thumb-wrap,
.v3-content-inner .v3-inline-media-grid .v3-inline-media-bundle-thumb-wrap {
    width: 100%;
    max-width: none;
    max-height: none;
    aspect-ratio: 1;
}

.v3-content-inner .v3-inline-media-grid .v3-inline-media-thumb-img {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    max-height: none;
    object-fit: cover;
}

.v3-content-inner .v3-inline-media-grid .v3-inline-media-thumb-wrap {
    position: relative;
}

.v3-content-inner .v3-inline-media-grid .v3-inline-media-thumb-img--video-fallback {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    min-height: 0;
    max-height: none;
}

.v3-content-inner .v3-inline-media-grid .v3-inline-media-figure {
    margin-top: 0;
    margin-bottom: 0;
    width: 100%;
}

.v3-content-inner > .v3-inline-media {
    margin: 0.75em 0;
    max-width: 100%;
}

.v3-content-inner .v3-inline-media {
    max-width: 100%;
}

.v3-content-inner .v3-inline-media-figure {
    margin: 0.5em 0;
    padding: 0;
    max-width: 100%;
}

.v3-content-inner .v3-inline-media-figure:last-child {
    margin-bottom: 0;
}

.v3-content-inner .v3-inline-media-thumb-btn {
    display: block;
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    border-radius: 6px;
    max-width: 100%;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}

.v3-content-inner .v3-inline-media-thumb-btn:focus-visible {
    outline: 2px solid rgba(125, 212, 232, 0.95);
    outline-offset: 3px;
}

.v3-content-inner .v3-inline-media-thumb-wrap {
    position: relative;
    display: block;
    width: min(100%, 200px);
    max-height: 140px;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(0, 0, 0, 0.35);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

.v3-content-inner .v3-inline-media-thumb-img {
    display: block;
    width: 100%;
    height: auto;
    max-height: 140px;
    object-fit: cover;
    vertical-align: middle;
}

.v3-content-inner .v3-inline-media-thumb-img--video-fallback {
    display: block;
    min-height: 100px;
    background: linear-gradient(145deg, #2a2a35, #1a1a22);
}

.v3-content-inner .v3-inline-media-thumb-play {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    border: 2px solid rgba(255, 255, 255, 0.85);
    pointer-events: none;
}

.v3-content-inner .v3-inline-media-thumb-play::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-40%, -50%);
    border-style: solid;
    border-width: 9px 0 9px 14px;
    border-color: transparent transparent transparent rgba(255, 255, 255, 0.95);
}

.v3-content-inner .v3-inline-media-caption {
    margin-top: 0.35em;
    font-size: 0.78em;
    line-height: 1.3;
    color: rgba(255, 255, 255, 0.72);
    text-align: center;
}

/* Bundle thumbnail: a 2×2 mosaic, mirroring the admin's bundle-card-mosaic. */
.v3-content-inner .v3-inline-media-bundle-thumb-wrap {
    width: min(100%, 200px);
    max-height: none;
    aspect-ratio: 1;
    display: block;
}

.v3-content-inner .v3-inline-media-bundle-mosaic {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: 3px;
    width: 100%;
    height: 100%;
    min-height: 0;
    border-radius: 6px;
    overflow: hidden;
    background: rgba(0, 0, 0, 0.35);
}

.v3-content-inner .v3-inline-media-bundle-tile {
    min-width: 0;
    min-height: 0;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: stretch;
}

.v3-content-inner .v3-inline-media-bundle-tile img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.v3-content-inner .v3-inline-media-bundle-tile--ph,
.v3-content-inner .v3-inline-media-bundle-tile--video-ph {
    background: linear-gradient(135deg, #ececec 0%, #ddd 100%);
}

.v3-content-inner .v3-inline-media-bundle-tile--video-ph {
    background: linear-gradient(145deg, #2a2a35, #1a1a22);
}

.v3-content-inner .v3-inline-media-bundle-tile-play {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid rgba(255, 255, 255, 0.85);
    pointer-events: none;
}

.v3-content-inner .v3-inline-media-bundle-tile-play::after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-40%, -50%);
    border-style: solid;
    border-width: 4px 0 4px 7px;
    border-color: transparent transparent transparent rgba(255, 255, 255, 0.95);
}

.v3-content-inner .v3-inline-media-broken {
    margin: 0.5em 0;
    font-size: 0.88em;
    color: #f0a8a8;
}

/* The lightbox is in lightbox.css; the build appends it here and to the flat view's CSS (PCB-21). */

/* Deliberately empty: opacity/transform come from scroll progress each tick, and a transition here would fight the scroll driver on mount. */
.v3-content-block--keyframed {
}

/* Title: width follows content; `content_width` and keyframe width still apply inline. */
.v3-content-block--title {
    width: fit-content;
    max-width: 100%;
    background: transparent !important;
    box-shadow: none;
    padding: 0 !important;
    border-radius: 0 !important;
}

/* `vw` is the window, so in an embedded pane the column overflowed it; the max-width caps at the anchor, a no-op on the full-window reader. */
.v3-content-block--boxed {
    width: min(92vw, 52rem);
    max-width: 100%;
    text-align: left;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35);
}

.ss-orient--rotate {
    position: fixed;
    inset: 0;
    z-index: 100000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(8, 10, 16, 0.92);
    color: #f0f2f5;
    font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
    -webkit-tap-highlight-color: transparent;
}

.ss-orient__content {
    text-align: center;
    max-width: 22rem;
    padding: 1.5rem 1.25rem 1rem;
}

.ss-orient__icon {
    margin: 0 auto 1.25rem;
    width: 4.5rem;
    height: 4.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ss-orient__device {
    width: 2.2rem;
    height: 3.5rem;
    border-radius: 0.4rem;
    border: 3px solid rgba(255, 255, 255, 0.9);
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
    transform-origin: 50% 50%;
    animation: ss-orient-nudge 2.1s ease-in-out infinite;
}

.ss-orient--reduced .ss-orient__device {
    animation: none;
}

.ss-orient--to-landscape .ss-orient__device {
    animation-name: ss-orient-to-landscape;
}

.ss-orient--to-portrait .ss-orient__device {
    animation-name: ss-orient-to-portrait;
}

@keyframes ss-orient-to-landscape {
    0%,
    100% {
        transform: rotate(0deg);
    }
    50% {
        transform: rotate(-90deg);
    }
}

@keyframes ss-orient-to-portrait {
    0%,
    100% {
        transform: rotate(-90deg);
    }
    50% {
        transform: rotate(0deg);
    }
}

.ss-orient__title {
    font-size: 1.1rem;
    font-weight: 600;
    margin: 0 0 0.5rem;
    line-height: 1.3;
}

.ss-orient__sub {
    font-size: 0.9rem;
    opacity: 0.88;
    margin: 0 0 1.25rem;
    line-height: 1.4;
}

.ss-orient__dismiss,
.ss-orient__try {
    display: inline-block;
    font: inherit;
    font-size: 0.9rem;
    font-weight: 500;
    padding: 0.55rem 1rem;
    border-radius: 0.4rem;
    border: 1px solid rgba(255, 255, 255, 0.35);
    background: rgba(255, 255, 255, 0.1);
    color: inherit;
    cursor: pointer;
    margin: 0.25rem;
}

.ss-orient__try {
    background: rgba(100, 180, 255, 0.25);
    border-color: rgba(150, 200, 255, 0.5);
}

.ss-orient--desktop {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 99990;
    font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
}

.ss-orient__desktop-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1rem;
    padding: 0.6rem 1rem;
    background: linear-gradient(180deg, rgba(12, 16, 24, 0.97) 0%, rgba(20, 24, 32, 0.94) 100%);
    color: #e8eaef;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25);
}

.ss-orient__desktop-text {
    margin: 0;
    flex: 1 1 14rem;
    font-size: 0.88rem;
    line-height: 1.4;
    opacity: 0.95;
}

.ss-orient__desktop-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    align-items: center;
    justify-content: flex-end;
}

/* Reader reactions on the timeline (PCB-34). The glyphs are stroked SVG paths, never code points: an emoji does not look the same on every OS. */
.v3-react-layer {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 6;
}

.v3-react-layer[hidden],
.v3-react-static[hidden] {
    display: none;
}

.v3-react-float {
    position: absolute;
    right: var(--v3-react-x, 12%);
    bottom: 18%;
    display: inline-flex;
    align-items: center;
    gap: 3px;
    color: rgba(255, 255, 255, 0.92);
    filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5));
    animation: v3-react-rise 2.6s cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
    will-change: transform, opacity;
}

.v3-react-float--heart { color: #ff6b8a; }
.v3-react-float--sparkles { color: #ffd166; }
.v3-react-float--laugh { color: #ffe08a; }
.v3-react-float--frown { color: #9cc9ff; }
.v3-react-float--flame { color: #ff9a4d; }
.v3-react-float--thumbs-up { color: #a8e6a1; }

.v3-react-float-n {
    font: 600 0.72rem/1 system-ui, -apple-system, 'Segoe UI', sans-serif;
    color: rgba(255, 255, 255, 0.95);
}

@keyframes v3-react-rise {
    0% { transform: translate3d(0, 0, 0) scale(0.7); opacity: 0; }
    12% { opacity: 1; transform: translate3d(0, -14px, 0) scale(1.05); }
    100% { transform: translate3d(var(--v3-react-drift, 0px), -46vh, 0) scale(0.9); opacity: 0; }
}

/* Reduced motion: the counts sit at their place and never float. */
.v3-react-static {
    position: absolute;
    right: max(12px, env(safe-area-inset-right, 0px));
    bottom: calc(env(safe-area-inset-bottom, 0px) + 96px);
    display: flex;
    flex-direction: column;
    gap: 6px;
    align-items: flex-end;
    pointer-events: none;
    z-index: 6;
}

.v3-react-pin {
    display: inline-flex;
    gap: 8px;
    padding: 4px 10px;
    border-radius: 14px;
    background: rgba(0, 0, 0, 0.62);
    color: rgba(255, 255, 255, 0.9);
    font: 500 0.72rem/1.4 system-ui, -apple-system, 'Segoe UI', sans-serif;
}

.v3-react-pin-item { display: inline-flex; align-items: center; gap: 3px; }

/* The bottom offset clears the auto-scroll toolbar's row. */
.v3-react-bar {
    position: absolute;
    right: max(10px, env(safe-area-inset-right, 0px));
    bottom: calc(env(safe-area-inset-bottom, 0px) + 56px);
    z-index: 7;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    align-items: center;
    gap: 4px;
    max-width: calc(100vw - 20px);
    padding: 4px;
    border-radius: 18px;
    background: rgba(0, 0, 0, 0.62);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    opacity: 0.7;
    transition: opacity 0.25s ease;
    pointer-events: auto;
}

.v3-react-bar:hover,
.v3-react-bar:focus-within {
    opacity: 1;
}

.v3-react-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-width: 32px;
    height: 32px;
    padding: 0 7px;
    border: 0;
    border-radius: 14px;
    background: transparent;
    color: rgba(255, 255, 255, 0.86);
    cursor: pointer;
    font: 500 0.72rem/1 system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/* Same values as `.v3-react-float--*` above: each mark is the colour it floats up in. */
.v3-react-btn--heart { color: #ff6b8a; }
.v3-react-btn--sparkles { color: #ffd166; }
.v3-react-btn--laugh { color: #ffe08a; }
.v3-react-btn--frown { color: #9cc9ff; }
.v3-react-btn--flame { color: #ff9a4d; }
.v3-react-btn--thumbs-up { color: #a8e6a1; }

.v3-react-btn:hover { background: rgba(255, 255, 255, 0.12); }
.v3-react-btn:active { transform: scale(0.92); }
.v3-react-btn:focus-visible { outline: 2px solid rgba(125, 184, 255, 0.9); outline-offset: 2px; }
.v3-react-btn--comments { border-left: 1px solid rgba(255, 255, 255, 0.18); border-radius: 0 14px 14px 0; }
.v3-react-count:empty { display: none; }

@media (pointer: coarse) {
    .v3-react-btn { min-width: 44px; height: 44px; }
}

/* Seven 44px marks and their gaps need 340px; a 357px phone allows 337px, so tighten here. */
@media (max-width: 599px) {
    .v3-react-bar { gap: 2px; }
    .v3-react-btn { min-width: 40px; padding: 0 4px; }
}

.v3-react-note {
    flex-basis: 100%;
    margin: 2px 6px 4px;
    color: rgba(255, 255, 255, 0.86);
    font: 400 0.72rem/1.4 system-ui, -apple-system, 'Segoe UI', sans-serif;
}

.v3-react-note[hidden] { display: none; }

/* "Hide reactions", in the chrome strip and in the reader bar (#246). */
.v3-react-toggle {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-left: 6px;
    pointer-events: auto;
    background: rgba(0, 0, 0, 0.62);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: rgba(255, 255, 255, 0.86);
    font-family: inherit;
    font-size: 0.72rem;
    line-height: 1.4;
    padding: 4px 12px;
    border-radius: 14px;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.25s ease, background 0.2s ease;
}

.v3-react-toggle:hover,
.v3-react-toggle:focus-visible {
    opacity: 1;
    background: rgba(0, 0, 0, 0.82);
    color: #fff;
}

.v3-react-toggle:focus-visible { outline: 2px solid rgba(125, 184, 255, 0.9); outline-offset: 2px; }
.v3-react-toggle[hidden] { display: none; }
.v3-react-toggle .v3-react-glyph { flex: none; }

.v3-react-tray {
    position: absolute;
    right: max(10px, env(safe-area-inset-right, 0px));
    bottom: calc(env(safe-area-inset-bottom, 0px) + 100px);
    z-index: 8;
    width: min(22rem, calc(100vw - 20px));
    max-height: min(60vh, 26rem);
    overflow-y: auto;
    padding: 10px 12px 12px;
    border-radius: 12px;
    background: rgba(0, 0, 0, 0.88);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(255, 255, 255, 0.16);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
    color: rgba(255, 255, 255, 0.88);
    font: 400 0.82rem/1.45 system-ui, -apple-system, 'Segoe UI', sans-serif;
    pointer-events: auto;
}

.v3-react-tray:focus { outline: none; }
.v3-react-tray-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.v3-react-h { margin: 0; font-size: 0.82rem; font-weight: 600; }
.v3-react-close {
    border: 0;
    background: transparent;
    color: inherit;
    font-size: 1.2rem;
    line-height: 1;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 8px;
}
.v3-react-close:hover { background: rgba(255, 255, 255, 0.1); }
.v3-react-close:focus-visible { outline: 2px solid rgba(125, 184, 255, 0.9); }
.v3-react-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.v3-react-comment { display: flex; flex-direction: column; gap: 2px; }
.v3-react-who { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; font-size: 0.76rem; color: rgba(255, 255, 255, 0.7); }
.v3-react-who img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; }
.v3-react-body p { margin: 0 0 4px; }
.v3-react-body a { color: #7db8ff; }
.v3-react-empty, .v3-react-signin { margin: 8px 0 0; color: rgba(255, 255, 255, 0.7); }
.v3-react-signin a { color: #7db8ff; }
.v3-react-form { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.v3-react-label { font-size: 0.74rem; color: rgba(255, 255, 255, 0.7); }
.v3-react-input {
    width: 100%;
    box-sizing: border-box;
    padding: 6px 8px;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.24);
    background: rgba(255, 255, 255, 0.08);
    color: inherit;
    font: inherit;
    resize: vertical;
}
.v3-react-input:focus-visible { outline: 2px solid rgba(125, 184, 255, 0.9); }
/* iOS Safari magnifies the page when a field it focuses has text under 16px. */
@media (pointer: coarse) { .v3-react-input { font-size: var(--ss-text-field, 1rem); } }
.v3-react-submit {
    align-self: flex-end;
    padding: 6px 12px;
    border: 0;
    border-radius: 10px;
    background: #7db8ff;
    color: #0b1a24;
    font: 600 0.78rem/1.2 system-ui, -apple-system, 'Segoe UI', sans-serif;
    cursor: pointer;
}
.v3-react-submit:disabled { opacity: 0.6; cursor: default; }
.v3-react-submit:focus-visible { outline: 2px solid rgba(125, 184, 255, 0.9); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
    /* The JS spawns no float under reduced motion; this is the backstop. */
    .v3-react-float { animation: none; opacity: 0; }
}

/* External embeds (#98): nothing loads until the reader taps, and `.v3-embed--card` is the link-only form for a page that may not frame one. */
.v3-embed {
    position: relative;
    margin: 0 auto 0.6em;
    /* A full-bleed embed covers both tap-nav gutters, so nothing here takes a press (#139); the parts that need one turn it back on below. */
    pointer-events: none;
    text-align: left;
    width: min(80vw, 56em);
    max-width: 100%;
    box-sizing: border-box;
}
.v3-content-inner .v3-embed { width: 100%; margin: 0.75em 0; }
.v3-embed-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #0b0d10;
    border-radius: 8px;
    overflow: hidden;
}
.v3-embed--osm .v3-embed-frame { aspect-ratio: 4 / 3; }
.v3-embed-thumb,
.v3-embed-field {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.v3-embed-field { background: linear-gradient(135deg, #1d2a33, #0e1418); }
.v3-embed-iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    /* Inert until the reader has asked for it: a frame under a finger steals the scroll. */
    pointer-events: none;
}
.v3-embed.is-active .v3-embed-iframe { pointer-events: auto; }
.v3-embed.is-active .v3-embed-thumb,
.v3-embed.is-active .v3-embed-field,
.v3-embed.is-active .v3-embed-play { display: none; }
.v3-embed-play {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.35em;
    margin: 0;
    /* The scrim fills the frame, but its contents — the whole hit target — are laid out between the
       tap-nav gutters (#139); the padding is a share of the frame, so a panel embed lands inside too. */
    padding: 0 var(--v3-tap-gutter, 30%);
    pointer-events: none;
    border: 0;
    background: rgba(0, 0, 0, 0.28);
    color: #fff;
    cursor: pointer;
    font: inherit;
    text-align: center;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}
.v3-embed-play > * { pointer-events: auto; }
.v3-embed-play:hover,
.v3-embed-play:focus-visible { background: rgba(0, 0, 0, 0.44); }
.v3-embed-play:focus-visible { outline: 3px solid #fff; outline-offset: -3px; }
.v3-embed-play-glyph {
    width: 3.4em;
    height: 3.4em;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.92);
    color: #111;
    display: grid;
    place-items: center;
}
.v3-embed-play-glyph svg { width: 1.5em; height: 1.5em; }
.v3-embed-play-text { font-weight: 600; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); }
.v3-embed-play-note { font-size: 0.8em; opacity: 0.9; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); }
.v3-embed-caption {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25em 0.8em;
    align-items: baseline;
    margin: 0.45em 0 0;
    font-size: 0.85em;
    opacity: 0.92;
}
.v3-embed-title { font-weight: 600; }
.v3-embed-link { color: inherit; text-decoration: underline; pointer-events: auto; }

.v3-content-anchor--embed-full { padding: 0; }
.v3-content-block--embed-full {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0 !important;
    padding: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
}
.v3-content-block--embed-full .v3-embed {
    position: absolute;
    inset: 0;
    width: 100%;
    max-width: none;
    margin: 0;
}
.v3-content-block--embed-full .v3-embed-frame {
    position: absolute;
    inset: 0;
    aspect-ratio: auto;
    border-radius: 0;
}
.v3-content-block--embed-full .v3-embed-caption {
    position: absolute;
    left: 1rem;
    bottom: 1rem;
    margin: 0;
    padding: 0.3em 0.6em;
    background: rgba(0, 0, 0, 0.55);
    border-radius: 6px;
}
.v3-content-block--embed-full .v3-embed.is-active .v3-embed-caption { display: none; }
.v3-content-block--embed-full .v3-content-inner {
    position: absolute;
    left: 50%;
    bottom: 3.4rem;
    transform: translateX(-50%);
    max-width: min(90%, 40em);
    padding: 0.6em 1em;
    background: rgba(0, 0, 0, 0.55);
    border-radius: 10px;
}
.v3-content-block--embed-full .v3-content-inner:empty { display: none; }

/* Fullscreen lightbox for inline library media. esbuild.config.mjs appends this file to both
   renderer.css and flat.css (PCB-21), so keep it self-contained. */
.v3-inline-media-lightbox {
    position: fixed;
    inset: 0;
    z-index: 2147483000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: env(safe-area-inset-top, 0) env(safe-area-inset-right, 0) env(safe-area-inset-bottom, 0)
        env(safe-area-inset-left, 0);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.22s ease, visibility 0.22s ease;
}

.v3-inline-media-lightbox.is-open {
    opacity: 1;
    visibility: visible;
}

.v3-inline-media-lightbox__backdrop {
    position: absolute;
    inset: 0;
    margin: 0;
    padding: 0;
    border: none;
    background: rgba(0, 0, 0, 0.92);
    cursor: pointer;
}

.v3-inline-media-lightbox__close {
    position: absolute;
    top: calc(12px + env(safe-area-inset-top, 0));
    right: calc(12px + env(safe-area-inset-right, 0));
    z-index: 2;
    width: 44px;
    height: 44px;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(40, 40, 45, 0.92);
    color: #fff;
    font-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
}

.v3-inline-media-lightbox__close:hover {
    background: rgba(60, 60, 68, 0.95);
}

.v3-inline-media-lightbox__close:focus-visible {
    outline: 2px solid #7dd4e8;
    outline-offset: 2px;
}

.v3-inline-media-lightbox__stage {
    position: relative;
    z-index: 1;
    max-width: min(96vw, 1400px);
    max-height: min(88vh, 1200px);
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

.v3-inline-media-lightbox__stage .v3-inline-media-lightbox__el {
    pointer-events: auto;
    max-width: 100%;
    max-height: min(88vh, 1200px);
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: 4px;
}

.v3-inline-media-lightbox__stage video.v3-inline-media-lightbox__el {
    width: 100%;
    max-height: min(88vh, 1200px);
    background: #000;
}

.v3-inline-media-lightbox__nav {
    position: fixed;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 48px;
    height: 48px;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(40, 40, 45, 0.88);
    color: #fff;
    font-size: 1.75rem;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.45);
    pointer-events: auto;
    -webkit-tap-highlight-color: transparent;
}

.v3-inline-media-lightbox__nav:hover {
    background: rgba(60, 60, 68, 0.94);
}

.v3-inline-media-lightbox__nav:focus-visible {
    outline: 2px solid #7dd4e8;
    outline-offset: 2px;
}

.v3-inline-media-lightbox__nav--prev {
    left: max(10px, env(safe-area-inset-left, 0));
}

.v3-inline-media-lightbox__nav--next {
    right: max(10px, env(safe-area-inset-right, 0));
}

.v3-inline-media-lightbox__nav[hidden] {
    display: none !important;
}

.v3-inline-media-lightbox__counter {
    position: fixed;
    bottom: calc(14px + env(safe-area-inset-bottom, 0));
    left: 50%;
    transform: translateX(-50%);
    z-index: 2;
    padding: 0.35rem 0.75rem;
    border-radius: 999px;
    background: rgba(30, 30, 35, 0.88);
    color: rgba(255, 255, 255, 0.9);
    font-size: 0.85rem;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

.v3-inline-media-lightbox__counter[hidden] {
    display: none !important;
}

.reduced-motion .v3-inline-media-lightbox {
    transition: none;
}

@media (prefers-reduced-motion: reduce) {
    .v3-inline-media-lightbox {
        transition: none;
    }
}

/* Reader chrome (PCB-39), appended to renderer.v2.css after the shared stylesheet so it
   overrides it. The reader's own controls only: nothing here moves a picture. Tokens only. */

/* Scoped to `[data-ui="v2"]`: an embed must not pick up a single declaration from this file. */

/* #333: no double-tap zoom, and no tap delay before a gutter tap. Pinch still zooms. */
[data-ui="v2"],
[data-ui="v2"] body {
  touch-action: manipulation;
}

[data-ui="v2"] {
  --ss-bar-h: 52px;
}

/* How much of the bottom edge the reader bar owns; anything parked there steps up by it.
   Zero until a bar is mounted. On `.v3-root`, so it reads `--v3-safe-bottom` (#336). */
[data-ui="v2"] .v3-root {
  --ss-bar-clear: calc(var(--v3-safe-bottom) + var(--ss-space-3));
  /* How tall a list above the bar may be. `--v3-vh` is one per cent of the stage rather than
     of the window (#180), so this is right in a preview too. */
  --ss-panel-room: calc(
    var(--v3-vh, 1vh) * 100 - var(--ss-bar-h) - var(--v3-safe-bottom) - var(--ss-space-8)
  );
}

[data-ui="v2"] .v3-sticky-viewport.has-reader-bar {
  --ss-bar-clear: calc(var(--v3-safe-bottom) + var(--ss-bar-h) + var(--ss-space-4));
}

/* ---------------------------------------------------------------- the bar and its host --- */

/* The bar takes the whole bottom edge, so the top of the frame stays the author's. */
[data-ui="v2"] .v3-reader-chrome.has-reader-bar {
  top: auto;
  bottom: 0;
  /* Over the reaction bar and its tray (7 and 8 in renderer.css), which park just above. */
  z-index: 9;
  display: flex;
  justify-content: center;
  font-family: var(--ss-font-ui);
  padding: 0 max(var(--ss-space-3), var(--v3-safe-left))
    calc(var(--v3-safe-bottom) + var(--ss-space-3))
    max(var(--ss-space-3), var(--v3-safe-right));
}

/* The hairlines go where the bar took progress over; without a bar they stay. */
[data-ui="v2"] .v3-sticky-viewport.has-reader-bar .v3-scroll-progress {
  display: none;
}

[data-ui="v2"] .ss-reader-bar {
  pointer-events: auto;
  /* The install sheet (#235) is positioned against the bar. */
  position: relative;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: var(--ss-space-3);
  width: 100%;
  /* Each step up is one more control and its gap (#185, #234, #246), so the progress track
     keeps the length it had: measured at 1280px it is 208px. */
  max-width: 64.5rem;
  min-height: var(--ss-bar-h);
  padding: var(--ss-space-2) var(--ss-space-3);
  /* Repeated from .ss-chrome, for a reader page that loads only renderer.v2.css. */
  background: var(--ss-chrome-bg);
  -webkit-backdrop-filter: blur(var(--ss-chrome-blur));
  backdrop-filter: blur(var(--ss-chrome-blur));
  color: var(--ss-ink-on-dark);
  border-radius: var(--ss-radius-xl);
  font-size: var(--ss-text-sm);
  line-height: var(--ss-leading-ui);
  transition: opacity var(--ss-duration-base) var(--ss-ease),
    transform var(--ss-duration-base) var(--ss-ease);
}

/* Out of the way while the story is moving; back on a pause, a tap or a focus. */
[data-ui="v2"] .ss-reader-bar.is-away {
  opacity: 0;
  transform: translateY(calc(var(--ss-space-2) * 1.5));
  pointer-events: none;
}

[data-ui="v2"] .ss-reader-bar :focus-visible {
  outline: 2px solid var(--ss-focus-on-dark);
  outline-offset: 2px;
}

/* ---- Where the reader is ---- */

[data-ui="v2"] .ss-reader-bar__chapter {
  display: flex;
  align-items: baseline;
  gap: var(--ss-space-2);
  margin: 0;
  min-width: 0;
  max-width: 40%;
  color: var(--ss-focus-on-dark);
}

[data-ui="v2"] .ss-reader-bar__chapter[hidden] {
  display: none;
}

[data-ui="v2"] .ss-reader-bar__chapter-num {
  font-variant-numeric: tabular-nums;
  font-size: var(--ss-text-xs);
  font-weight: var(--ss-weight-semibold);
  opacity: 0.9;
}

[data-ui="v2"] .ss-reader-bar__chapter-name {
  font-family: var(--ss-font-display);
  font-style: italic;
  font-size: var(--ss-display-xs);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Progress, one segment per stop ---- */

[data-ui="v2"] .ss-reader-bar__progress {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  gap: 2px;
  min-width: 2rem;
}

[data-ui="v2"] .ss-reader-bar__seg {
  flex: 1 1 0;
  height: 3px;
  border-radius: var(--ss-radius-round);
  background: var(--ss-chrome-track);
  overflow: hidden;
}

[data-ui="v2"] .ss-reader-bar__seg-fill {
  display: block;
  width: 100%;
  height: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--ss-ink-on-dark);
}

[data-ui="v2"] .ss-reader-bar__actions {
  display: flex;
  align-items: center;
  gap: var(--ss-space-2);
  flex: 0 0 auto;
}

/* #246: a slot is a name, not a box, so an empty one spends none of the row's gap. */
[data-ui="v2"] .ss-reader-bar__slot {
  display: contents;
}

/* Every control in the bar is the same pill. */
[data-ui="v2"] .ss-reader-bar__btn,
[data-ui="v2"] .ss-reader-bar .v3-chapter-btn,
[data-ui="v2"] .ss-reader-bar .v3-flat-link,
[data-ui="v2"] .ss-reader-bar .v3-react-toggle,
[data-ui="v2"] .ss-reader-bar .auto-scroll-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ss-space-1);
  min-height: var(--ss-control-sm);
  padding: 0 var(--ss-space-3);
  border: 1px solid transparent;
  border-radius: var(--ss-radius-round);
  background: transparent;
  color: var(--ss-ink-on-dark);
  font: var(--ss-weight-medium) var(--ss-text-sm) / var(--ss-leading-ui) var(--ss-font-ui);
  white-space: nowrap;
  opacity: 1;
  cursor: pointer;
  transition: background var(--ss-duration-fast) var(--ss-ease);
}

[data-ui="v2"] .ss-reader-bar__btn:hover,
[data-ui="v2"] .ss-reader-bar .v3-chapter-btn:hover,
[data-ui="v2"] .ss-reader-bar .v3-flat-link:hover,
[data-ui="v2"] .ss-reader-bar .v3-react-toggle:hover,
[data-ui="v2"] .ss-reader-bar .auto-scroll-btn:hover {
  background: var(--ss-chrome-track);
}

/* ---- Reactions (PCB-34): the show/hide toggle, beside the chapters (#246) ---- */

/* Borrowed whole from the engine, so its own panel look is undone here rather than changed
   in renderer.css, which the embed still loads on its own. */
[data-ui="v2"] .ss-reader-bar .v3-react-toggle {
  margin: 0;
  background: transparent;
  border-color: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  opacity: 1;
}

[data-ui="v2"] .ss-reader-bar .v3-react-toggle[aria-pressed="false"] {
  color: var(--ss-focus-on-dark);
}

/* ---- Auto-scroll, borrowed whole ---- */

/* On its own the toolbar shows and hides itself; in the bar the bar does, so its reveal rules
   are overridden here rather than changed in auto-scroll.js. */
[data-ui="v2"] .ss-reader-bar .auto-scroll-control {
  position: static;
  max-width: none;
  margin: 0;
  padding: 0;
  gap: var(--ss-space-1);
  background: none;
  border: 0;
  border-radius: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  opacity: 1;
  transform: none;
  pointer-events: auto;
  flex-wrap: nowrap;
}

[data-ui="v2"] .ss-reader-bar .auto-scroll-label {
  color: var(--ss-ink-on-dark);
  font-size: var(--ss-text-xs);
  opacity: 0.85;
}

[data-ui="v2"] .ss-reader-bar .auto-scroll-speeds {
  gap: 2px;
}

[data-ui="v2"] .ss-reader-bar .auto-scroll-btn {
  padding: 0 var(--ss-space-2);
  font-size: var(--ss-text-xs);
}

[data-ui="v2"] .ss-reader-bar .auto-scroll-btn.active {
  background: var(--ss-chrome-track);
  border-color: var(--ss-focus-on-dark);
  color: var(--ss-focus-on-dark);
}

/* Above a phone there is no pill: the borrowed toolbar stays a flex item of the row. */
[data-ui="v2"] .ss-reader-bar__speed,
[data-ui="v2"] .ss-reader-bar__speed-panel {
  display: contents;
}

[data-ui="v2"] .ss-reader-bar__speed-btn {
  display: none;
}

[data-ui="v2"] .ss-reader-bar .v3-chapter-btn:focus-visible,
[data-ui="v2"] .ss-reader-bar .v3-chapter-nav.is-open .v3-chapter-btn {
  background: var(--ss-chrome-track);
}

[data-ui="v2"] .ss-reader-bar .v3-chapter-panel {
  top: auto;
  bottom: calc(100% + var(--ss-space-2));
  right: 0;
  left: auto;
  padding: var(--ss-space-1);
  background: var(--ss-chrome-bg-strong);
  border: 0;
  border-radius: var(--ss-radius-lg);
  box-shadow: var(--ss-shadow-menu);
}

[data-ui="v2"] .ss-reader-bar .v3-chapter-item {
  border-radius: var(--ss-radius-md);
  color: var(--ss-ink-on-dark);
  font-size: var(--ss-text-sm);
  padding: var(--ss-space-2) var(--ss-space-3);
}

[data-ui="v2"] .ss-reader-bar .v3-chapter-item:hover {
  background: var(--ss-chrome-track);
  color: var(--ss-ink-on-dark);
}

[data-ui="v2"] .ss-reader-bar .v3-chapter-item.is-current {
  color: var(--ss-focus-on-dark);
  background: var(--ss-chrome-track);
}

[data-ui="v2"] .ss-reader-bar .v3-chapter-item:focus-visible,
[data-ui="v2"] .ss-reader-bar .v3-chapter-btn:focus-visible {
  outline: 2px solid var(--ss-focus-on-dark);
  outline-offset: 2px;
}

/* ---- "Read as a page" (#185): the story's other front door, beside the chapters ---- */

/* The same pill as the rest of the bar; the link's own rule is undone here, not in renderer.css. */
[data-ui="v2"] .ss-reader-bar .v3-flat-link {
  position: relative;
  margin: 0;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  text-decoration: none;
}

[data-ui="v2"] .ss-reader-bar .v3-flat-link:hover,
[data-ui="v2"] .ss-reader-bar .v3-flat-link:focus-visible {
  background: var(--ss-chrome-track);
  color: var(--ss-ink-on-dark);
}

/* #193: the v1 pill sizes this glyph to its own smaller text, so the attributes' size is restored. */
[data-ui="v2"] .ss-reader-bar .v3-flat-link svg {
  flex: none;
  width: 16px;
  height: 16px;
}

/* ---- Full screen (#234): its own control after the page link, before More ---- */

/* The same pill as the rest of the bar (`.ss-reader-bar__btn`); the glyph never shrinks. */
[data-ui="v2"] .ss-reader-bar__fullscreen svg {
  flex: none;
}

/* #235: on an iPhone in Safari, which has no Fullscreen API for a page, the control opens this
   instead. It scrolls rather than run off the top: the shortest window seen is 344px (#327). */
[data-ui="v2"] .ss-reader-bar__sheet {
  position: absolute;
  bottom: calc(100% + var(--ss-space-2));
  left: 50%;
  transform: translateX(-50%);
  box-sizing: border-box;
  width: min(22rem, 100%);
  max-height: calc(100dvh - var(--ss-bar-h) - var(--ss-space-6));
  overflow-y: auto;
  padding: var(--ss-space-4);
  background: var(--ss-chrome-bg-strong);
  border-radius: var(--ss-radius-lg);
  box-shadow: var(--ss-shadow-menu);
  color: var(--ss-ink-on-dark);
  text-align: left;
}

[data-ui="v2"] .ss-reader-bar__sheet[hidden] {
  display: none;
}

[data-ui="v2"] .ss-reader-bar__sheet-title {
  margin: 0 0 var(--ss-space-2);
  font: var(--ss-weight-semibold) var(--ss-text-lg) / var(--ss-leading-ui) var(--ss-font-ui);
}

[data-ui="v2"] .ss-reader-bar__sheet-text {
  margin: 0 0 var(--ss-space-3);
  font-size: var(--ss-text-sm);
  line-height: var(--ss-leading-ui);
}

[data-ui="v2"] .ss-reader-bar__sheet-steps {
  margin: 0 0 var(--ss-space-4);
  padding-left: var(--ss-space-5);
  font-size: var(--ss-text-sm);
  line-height: var(--ss-leading-ui);
}

[data-ui="v2"] .ss-reader-bar__sheet-steps li + li {
  margin-top: var(--ss-space-2);
}

/* "Close" is the orientation prompt's button family: a pill with an edge. */
[data-ui="v2"] .ss-reader-bar__sheet-close {
  border-color: var(--ss-focus-on-dark);
}

/* ---- Share (#246): the bar's own last control, where More used to stand ---- */

[data-ui="v2"] .ss-reader-bar__share {
  position: relative;
}

[data-ui="v2"] .ss-reader-bar__share[hidden] {
  display: none;
}

[data-ui="v2"] .ss-reader-bar__share-btn svg {
  flex: none;
}

[data-ui="v2"] .ss-reader-bar__share-panel {
  position: absolute;
  bottom: calc(100% + var(--ss-space-2));
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
  min-width: 12rem;
  padding: var(--ss-space-1);
  background: var(--ss-chrome-bg-strong);
  border-radius: var(--ss-radius-lg);
  box-shadow: var(--ss-shadow-menu);
}

[data-ui="v2"] .ss-reader-bar__share-panel[hidden] {
  display: none;
}

/* The same elements share-control.js mounts, as rows in a menu rather than pills in a strip. */
[data-ui="v2"] .ss-reader-bar__share-panel .reader-share {
  display: contents;
}

[data-ui="v2"] .ss-reader-bar__share-panel .reader-share-btn {
  display: block;
  width: 100%;
  margin: 0;
  padding: var(--ss-space-2) var(--ss-space-3);
  border: 0;
  border-radius: var(--ss-radius-md);
  background: transparent;
  color: var(--ss-ink-on-dark);
  font: var(--ss-weight-regular) var(--ss-text-sm) / var(--ss-leading-ui) var(--ss-font-ui);
  text-align: left;
  text-decoration: none;
  opacity: 1;
  cursor: pointer;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

[data-ui="v2"] .ss-reader-bar__share-panel .reader-share-btn:hover {
  background: var(--ss-chrome-track);
  color: var(--ss-ink-on-dark);
}

[data-ui="v2"] .ss-reader-bar__share-panel .reader-share-btn:focus-visible {
  outline: 2px solid var(--ss-focus-on-dark);
  outline-offset: -2px;
}

/* ---- Touch: every control clears 44px, and the bar stops competing for width ---- */

@media (pointer: coarse) {
  [data-ui="v2"] {
    --ss-bar-h: 60px;
  }
  [data-ui="v2"] .ss-reader-bar__btn,
  [data-ui="v2"] .ss-reader-bar .v3-chapter-btn,
  [data-ui="v2"] .ss-reader-bar .v3-flat-link,
  [data-ui="v2"] .ss-reader-bar .v3-react-toggle,
  [data-ui="v2"] .ss-reader-bar .auto-scroll-btn,
  [data-ui="v2"] .ss-reader-bar__share-panel .reader-share-btn,
  [data-ui="v2"] .v3-tap-nav-hint-dismiss {
    min-height: var(--ss-touch);
  }
  [data-ui="v2"] .ss-reader-bar .v3-chapter-item {
    display: flex;
    align-items: center;
    min-height: var(--ss-touch);
  }
  /* A control showing only its glyph was 26px across. The row wraps rather than overflow if a
     story has enough controls that they no longer fit. */
  [data-ui="v2"] .ss-reader-bar__btn,
  [data-ui="v2"] .ss-reader-bar .v3-flat-link,
  [data-ui="v2"] .ss-reader-bar .v3-react-toggle {
    min-width: var(--ss-touch);
  }
  [data-ui="v2"] .ss-reader-bar__actions { flex-wrap: wrap; row-gap: var(--ss-space-1); }
}

/* #166, #234: installed or full screen there is no browser chrome and the status bar draws over
   the page. Everything else clears the bottom inset already, so only the orientation prompt
   changes: a fixed full-frame layer, it wears all four insets. */
@media (display-mode: standalone), (display-mode: fullscreen) {
  [data-ui="v2"] .ss-orient--rotate {
    box-sizing: border-box;
    padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
      env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
  }
}

/* #234, #246: the words show only at the bar's full 64.5rem — 1032px plus 24px of gutter. Below
   that each control keeps its glyph and its name and loses them. Clipped, never removed. */
@media (max-width: 1055px) {
  [data-ui="v2"] .ss-reader-bar__fullscreen,
  [data-ui="v2"] .ss-reader-bar__share-btn,
  [data-ui="v2"] .ss-reader-bar .v3-react-toggle {
    padding: 0 var(--ss-space-2);
  }
  [data-ui="v2"] .ss-reader-bar__share-text,
  [data-ui="v2"] .ss-reader-bar .v3-react-toggle__text,
  [data-ui="v2"] .ss-reader-bar__fullscreen-text {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* #185: below this the link keeps its glyph and its name and loses the words — clipped, the
   way `.ss-story-end` is, never `display: none`. */
@media (max-width: 899px) {
  [data-ui="v2"] .ss-reader-bar .v3-flat-link {
    padding: 0 var(--ss-space-2);
  }
  [data-ui="v2"] .ss-reader-bar .v3-flat-link__text {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* A phone gets two rows on purpose — where you are, then what you can do. Nothing is dropped. */
@media (max-width: 599px) {
  [data-ui="v2"] {
    --ss-bar-h: 104px;
  }
  [data-ui="v2"] .ss-reader-bar {
    flex-wrap: wrap;
    gap: var(--ss-space-2);
  }
  [data-ui="v2"] .ss-reader-bar__chapter {
    flex: 1 1 auto;
    max-width: none;
  }
  [data-ui="v2"] .ss-reader-bar__progress {
    flex: 1 1 40%;
  }
  [data-ui="v2"] .ss-reader-bar__actions {
    flex: 1 1 100%;
    justify-content: space-between;
  }
  [data-ui="v2"] .ss-reader-bar .auto-scroll-label {
    display: none;
  }
  /* The four speeds go behind one pill and Chapters gets its words back: its glyph-only pill
     was 21px wide, under the 24px floor. */
  [data-ui="v2"] .ss-reader-bar {
    padding-left: var(--ss-space-2);
    padding-right: var(--ss-space-2);
  }
  [data-ui="v2"] .ss-reader-bar__actions {
    gap: 2px;
  }
  [data-ui="v2"] .ss-reader-bar .v3-chapter-btn {
    padding: 0 var(--ss-space-2);
  }

  [data-ui="v2"] .ss-reader-bar__btn,
  [data-ui="v2"] .ss-reader-bar .v3-chapter-btn,
  [data-ui="v2"] .ss-reader-bar .v3-flat-link,
  [data-ui="v2"] .ss-reader-bar .v3-react-toggle,
  [data-ui="v2"] .ss-reader-bar .auto-scroll-btn {
    padding: 0 var(--ss-space-1);
  }
  [data-ui="v2"] .ss-reader-bar .auto-scroll-speeds {
    gap: 1px;
  }

  /* The chapter list hangs off the bar, not off the button: the button sits on the second
     row, so a list positioned against it covered the row above and ran off the left edge. */
  [data-ui="v2"] .ss-reader-bar .v3-chapter-nav {
    position: static;
  }
  [data-ui="v2"] .ss-reader-bar .v3-chapter-panel {
    left: 0;
    right: 0;
    min-width: 0;
    max-width: none;
    max-height: min(var(--ss-panel-room), 18rem);
  }

  [data-ui="v2"] .ss-reader-bar__speed-btn {
    display: inline-flex;
  }
  [data-ui="v2"] .ss-reader-bar__speed-btn svg {
    flex: none;
  }
  [data-ui="v2"] .ss-reader-bar__speed-panel {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(100% + var(--ss-space-2));
    box-sizing: border-box;
    max-height: min(var(--ss-panel-room), 16rem);
    overflow-y: auto;
    padding: var(--ss-space-1);
    background: var(--ss-chrome-bg-strong);
    -webkit-backdrop-filter: blur(var(--ss-chrome-blur));
    backdrop-filter: blur(var(--ss-chrome-blur));
    border-radius: var(--ss-radius-lg);
    box-shadow: var(--ss-shadow-menu);
  }
  [data-ui="v2"] .ss-reader-bar__speed-panel.is-open {
    display: block;
  }
  [data-ui="v2"] .ss-reader-bar__speed-panel .auto-scroll-control {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }
  [data-ui="v2"] .ss-reader-bar__speed-panel .auto-scroll-label {
    display: block;
    padding: var(--ss-space-2) var(--ss-space-3) var(--ss-space-1);
    color: var(--ss-ink-on-dark);
    font-size: var(--ss-text-xs);
    opacity: 0.85;
  }
  [data-ui="v2"] .ss-reader-bar__speed-panel .auto-scroll-speeds {
    flex-direction: column;
    gap: 2px;
  }
  [data-ui="v2"] .ss-reader-bar__speed-panel .auto-scroll-btn {
    justify-content: flex-start;
    padding: 0 var(--ss-space-3);
    border-radius: var(--ss-radius-md);
    font-size: var(--ss-text-sm);
  }
}

/* On a phone on its side the heading costs the row that made a four-speed list scroll. The
   toolbar keeps its own `aria-label`, so nothing loses a name. */
@media (max-width: 599px) and (max-height: 420px) {
  [data-ui="v2"] .ss-reader-bar__speed-panel .auto-scroll-label {
    display: none;
  }
}

/* ------------------------------------------------------- the rest of the reader's chrome --- */

/* The caption pill: the same family, above the bar rather than in the corner behind it. */
[data-ui="v2"] .v3-placement-name-overlay {
  bottom: var(--ss-bar-clear);
  padding: var(--ss-space-1) var(--ss-space-3);
  background: var(--ss-chrome-bg);
  -webkit-backdrop-filter: blur(var(--ss-chrome-blur));
  backdrop-filter: blur(var(--ss-chrome-blur));
  border-radius: var(--ss-radius-round);
  color: var(--ss-ink-on-dark);
  font: var(--ss-weight-medium) var(--ss-text-xs) / var(--ss-leading-ui) var(--ss-font-ui);
  letter-spacing: normal;
  text-shadow: none;
}

/* The skip link is the first thing Tab reaches, so it looks like the chrome. */
[data-ui="v2"] .ss-skip-link {
  padding: var(--ss-space-3) var(--ss-space-5);
  background: var(--ss-chrome-bg-strong);
  -webkit-backdrop-filter: blur(var(--ss-chrome-blur));
  backdrop-filter: blur(var(--ss-chrome-blur));
  color: var(--ss-ink-on-dark);
  border: 1px solid var(--ss-focus-on-dark);
  border-top: 0;
  border-bottom-left-radius: var(--ss-radius-lg);
  border-bottom-right-radius: var(--ss-radius-lg);
  font: var(--ss-weight-medium) var(--ss-text-sm) / var(--ss-leading-ui) var(--ss-font-ui);
}

/* The ring goes inside: the link is pinned to the top edge, so an offset one is clipped. */
[data-ui="v2"] .ss-skip-link:focus,
[data-ui="v2"] .ss-skip-link:focus-visible {
  outline: 2px solid var(--ss-focus-on-dark);
  outline-offset: -5px;
}

[data-ui="v2"] #story-container:focus-visible {
  outline: 3px solid var(--ss-focus-on-dark);
  outline-offset: -3px;
}

[data-ui="v2"] .v3-tap-nav-zone:focus-visible {
  outline: 2px solid var(--ss-focus-on-dark);
  outline-offset: -2px;
}

/* The first-visit hint and the copy-link toast: same panel, same pill. */
[data-ui="v2"] .v3-tap-nav-hint {
  padding: var(--ss-space-5);
  border: 0;
  border-radius: var(--ss-radius-xl);
  background: var(--ss-chrome-bg-strong);
  -webkit-backdrop-filter: blur(var(--ss-chrome-blur));
  backdrop-filter: blur(var(--ss-chrome-blur));
  box-shadow: var(--ss-shadow-dialog);
}

[data-ui="v2"] .v3-tap-nav-hint-inner {
  font-family: var(--ss-font-ui);
  color: var(--ss-ink-on-dark);
}

[data-ui="v2"] .v3-tap-nav-hint-title {
  font-family: var(--ss-font-display);
  font-size: var(--ss-display-s);
  font-weight: var(--ss-weight-medium);
  letter-spacing: normal;
  color: var(--ss-ink-on-dark);
}

[data-ui="v2"] .v3-tap-nav-hint-text {
  color: var(--ss-ink-on-dark);
  font-size: var(--ss-text-sm);
}

[data-ui="v2"] .v3-tap-nav-hint-arrow {
  border-color: var(--ss-focus-on-dark);
}

/* "Got it" (#186) is the orientation prompt's button family. */
[data-ui="v2"] .v3-tap-nav-hint-dismiss {
  margin-top: var(--ss-space-4);
  min-height: var(--ss-control-sm);
  padding: 0 var(--ss-space-4);
  border: 1px solid var(--ss-focus-on-dark);
  border-radius: var(--ss-radius-md);
  background: transparent;
  color: var(--ss-ink-on-dark);
  font: var(--ss-weight-medium) var(--ss-text-sm) / var(--ss-leading-ui) var(--ss-font-ui);
}

[data-ui="v2"] .v3-tap-nav-hint-dismiss:hover {
  background: var(--ss-chrome-track);
}

[data-ui="v2"] .v3-tap-nav-hint-dismiss:focus-visible {
  outline: 2px solid var(--ss-focus-on-dark);
  outline-offset: 2px;
}

/* On the body, not in the bar, so it reads the page-level values rather than the viewport's. */
[data-ui="v2"] .reader-toast {
  bottom: calc(env(safe-area-inset-bottom, 0px) + var(--ss-bar-h) + var(--ss-space-8));
  padding: var(--ss-space-2) var(--ss-space-4);
  border: 0;
  border-radius: var(--ss-radius-round);
  background: var(--ss-chrome-bg-strong);
  -webkit-backdrop-filter: blur(var(--ss-chrome-blur));
  backdrop-filter: blur(var(--ss-chrome-blur));
  color: var(--ss-ink-on-dark);
  font: var(--ss-weight-medium) var(--ss-text-sm) / var(--ss-leading-ui) var(--ss-font-ui);
}

/* A full-frame interruption, so it is the stage rather than a translucent panel. */
[data-ui="v2"] .ss-orient--rotate {
  background: var(--ss-stage);
  color: var(--ss-ink-on-dark);
  font-family: var(--ss-font-ui);
}

[data-ui="v2"] .ss-orient__device {
  border-color: var(--ss-ink-on-dark);
  border-radius: var(--ss-radius-sm);
  box-shadow: none;
}

[data-ui="v2"] .ss-orient__title {
  font-family: var(--ss-font-display);
  font-size: var(--ss-display-s);
  font-weight: var(--ss-weight-medium);
}

[data-ui="v2"] .ss-orient__sub {
  font-size: var(--ss-text-md);
  opacity: 1;
  color: var(--ss-ink-on-dark);
}

[data-ui="v2"] .ss-orient__dismiss,
[data-ui="v2"] .ss-orient__try {
  min-height: var(--ss-touch);
  padding: 0 var(--ss-space-4);
  border: 1px solid var(--ss-focus-on-dark);
  border-radius: var(--ss-radius-md);
  background: transparent;
  color: var(--ss-ink-on-dark);
  font: var(--ss-weight-medium) var(--ss-text-sm) / var(--ss-leading-ui) var(--ss-font-ui);
}

[data-ui="v2"] .ss-orient__try {
  background: var(--ss-chrome-track);
}

[data-ui="v2"] .ss-orient__dismiss:focus-visible,
[data-ui="v2"] .ss-orient__try:focus-visible {
  outline: 2px solid var(--ss-focus-on-dark);
  outline-offset: 2px;
}

[data-ui="v2"] .ss-orient__desktop-bar {
  background: var(--ss-chrome-bg-strong);
  -webkit-backdrop-filter: blur(var(--ss-chrome-blur));
  backdrop-filter: blur(var(--ss-chrome-blur));
  border: 0;
  box-shadow: var(--ss-shadow-menu);
  color: var(--ss-ink-on-dark);
  font-family: var(--ss-font-ui);
}

[data-ui="v2"] .ss-orient__desktop-text {
  font-size: var(--ss-text-sm);
  opacity: 1;
}

/* PCB-17/PCB-32: only the look and the place move; the route and the stops are the engine's. */
[data-ui="v2"] .v3-map-pins {
  bottom: var(--ss-bar-clear);
}

[data-ui="v2"] .v3-map-layer.has-profile .v3-map-pins {
  bottom: calc(clamp(3.5rem, 12vh, 6rem) + var(--ss-bar-clear));
}

[data-ui="v2"] .v3-map-pin,
[data-ui="v2"] .v3-map-profile-text,
[data-ui="v2"] .v3-map-attribution {
  background: var(--ss-chrome-bg);
  color: var(--ss-ink-on-dark);
  font-family: var(--ss-font-ui);
}

[data-ui="v2"] .v3-map-pin,
[data-ui="v2"] .v3-map-profile-text {
  border-radius: var(--ss-radius-round);
  font-size: var(--ss-text-xs);
  padding: var(--ss-space-1) var(--ss-space-3);
}

[data-ui="v2"] .v3-map-pin.is-current {
  color: var(--ss-focus-on-dark);
}

[data-ui="v2"] .v3-map-profile {
  bottom: var(--ss-bar-clear);
}

[data-ui="v2"] .v3-map-profile-text {
  bottom: calc(clamp(3.5rem, 12vh, 6rem) + var(--ss-bar-clear) + var(--ss-space-2));
}

[data-ui="v2"] .v3-map-attribution {
  bottom: var(--ss-bar-clear);
  border-radius: var(--ss-radius-xs);
}

[data-ui="v2"] .v3-map-layer.has-profile .v3-map-attribution {
  bottom: calc(clamp(3.5rem, 12vh, 6rem) + var(--ss-bar-clear) + var(--ss-space-6));
}

/* ----------------------------------------------------------- what a reader asked us for --- */

/* Reduced transparency: the same panels, opaque and unblurred. */
@media (prefers-reduced-transparency: reduce) {
  [data-ui="v2"] .ss-reader-bar,
  [data-ui="v2"] .v3-placement-name-overlay,
  [data-ui="v2"] .reader-toast,
  [data-ui="v2"] .ss-skip-link,
  [data-ui="v2"] .v3-tap-nav-hint,
  [data-ui="v2"] .ss-orient__desktop-bar,
  [data-ui="v2"] .v3-map-pin,
  [data-ui="v2"] .v3-map-profile-text,
  [data-ui="v2"] .v3-map-attribution {
    background: var(--ss-chrome-bg-strong);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* Reduced motion cuts rather than damps: the bar appears and disappears, it never slides. */
@media (prefers-reduced-motion: reduce) {
  [data-ui="v2"] .ss-reader-bar {
    transition: none;
  }
  [data-ui="v2"] .ss-reader-bar.is-away {
    transform: none;
  }
}

/* ---- Reader reactions (PCB-34): the bar and the tray clear the reader bar ---- */

/* The same panel as the bar under it, at full strength: at 0.7 over a photograph it read as
   something half-drawn. */
[data-ui="v2"] .v3-sticky-viewport.has-reader-bar .v3-react-bar {
  bottom: var(--ss-bar-clear);
  font-family: var(--ss-font-ui);
  opacity: 1;
  padding: var(--ss-space-1);
  background: var(--ss-chrome-bg);
  border-color: transparent;
  border-radius: var(--ss-radius-xl);
  color: var(--ss-ink-on-dark);
}

[data-ui="v2"] .v3-sticky-viewport.has-reader-bar .v3-react-tray {
  bottom: calc(var(--ss-bar-clear) + 48px);
  font-family: var(--ss-font-ui);
}
[data-ui="v2"] .v3-sticky-viewport.has-reader-bar .v3-react-static {
  bottom: calc(var(--ss-bar-clear) + 48px);
}
/* An empty layer is nothing to hide, so the slot beside the chapters stays empty (#246). */
[data-ui="v2"] .ss-reader-bar .v3-react-toggle[hidden] {
  display: none;
}

/* The caption pill parks in the same corner: a mark's height and a gap lift it clear. */
[data-ui="v2"] .v3-sticky-viewport.has-react-bar .v3-placement-name-overlay {
  bottom: calc(var(--ss-bar-clear) + var(--ss-touch) + var(--ss-space-4));
}

/* ------------------------------------------------- the page as the scroller (spike) --- */

/* `?scrollhost=1` (#248): the page scrolls instead of the container, so an iPhone's bars can
   collapse. A spike, off until `v3/reader-page-scroll.js` puts the class on <html>. The shape
   is `<scrolling-story>`'s: a runway as tall as the story, the stage sticky inside it. */
html.ss-page-scroll[data-ui="v2"],
html.ss-page-scroll[data-ui="v2"] body {
  height: auto;
  overflow: visible;
}

html.ss-page-scroll[data-ui="v2"] .v3-page-scroll-host {
  position: relative;
  width: 100%;
}

html.ss-page-scroll[data-ui="v2"] #story-container {
  position: sticky;
  top: 0;
  /* Not `min-height: 100vh`: with the bars showing, the large viewport is taller than what the
     reader can see. */
  min-height: 0;
  height: 100vh;
  height: 100dvh;
  /* Hidden, not `auto`: the page owns the scrolling, but the box stays a scroll container. */
  overflow: hidden;
}
