/* ============================================================================
   RootPro — blog reading experience
   ----------------------------------------------------------------------------
   Every element here is appended to <body> as a fixed overlay. Nothing is
   inserted into <article>, because the article lives inside a React-hydrated
   tree and extra nodes there get removed when React recovers from a hydration
   mismatch.

   Why each piece exists (these are behavioural, not decorative):

   PROGRESS BAR   Visible progress toward a goal measurably increases completion
                  (goal-gradient effect). It also reduces *perceived* length,
                  which is what actually drives people to abandon long reads.
   CONTENTS RAIL  Chunking a wall of text into named sections lowers cognitive
                  load, and a scroll-spy marker answers "where am I / how much
                  is left" without the reader having to scrub the scrollbar.
   READING TIME   Setting an explicit expectation up front reduces bounce: people
                  abandon when length is unknown, not when it is long.
   BACK TO TOP    Removes the friction of a long scroll-back, and only appears
                  once it is actually needed so it never competes for attention.
   SHARE          Sharing is an impulse. If it needs more than one tap the
                  impulse is gone.
   ========================================================================== */

:root {
  --rp-rail-w: 232px;
  --rp-z: 90;
}

/* ==========================================================================
   1. READING PROGRESS
   ========================================================================== */

.rp-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 3px;
  z-index: calc(var(--rp-z) + 20);
  background: transparent;
  pointer-events: none;
}
.rp-progress__bar {
  height: 100%;
  width: 0;
  border-radius: 0 2px 2px 0;
  background: linear-gradient(
    90deg,
    var(--color-primary-500, #4f3ff0),
    var(--color-primary-300, #9a8cff)
  );
  /* transform is compositor-only; animating width would trigger layout on
     every scroll frame. */
  transform-origin: 0 50%;
  transition: opacity .25s ease;
}
@media (prefers-reduced-motion: reduce) {
  .rp-progress__bar { transition: none; }
}

/* ==========================================================================
   2. CONTENTS RAIL  (>= 1280px)
   --------------------------------------------------------------------------
   The article is max-w-3xl (768px) and centred, so at 1280px there is exactly
   256px of clear space either side. A 232px rail at right:24px fits without
   ever overlapping the text.
   ========================================================================== */

.rp-toc {
  position: fixed;
  top: 50%;
  right: 24px;
  translate: 0 -50%;
  width: var(--rp-rail-w);
  max-height: 70vh;
  z-index: var(--rp-z);
  display: none;               /* enabled by the media query below */
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, .09));
  border-radius: var(--radius-lg, 18px);
  background: color-mix(in srgb, var(--surface-1, #0c0e1a) 88%, transparent);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  font-family: var(--font-body, inherit);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .rp-toc { background: var(--surface-1, #0c0e1a); }
}

.rp-toc__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border-subtle, rgba(255, 255, 255, .09));
}
.rp-toc__title {
  font-size: .625rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--fg-faint, #8d93b0);
}
.rp-toc__meta {
  font-size: .625rem;
  color: var(--fg-faint, #8d93b0);
  white-space: nowrap;
}

.rp-toc__list {
  list-style: none;
  margin: 0; padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  display: flex; flex-direction: column; gap: 2px;
}
.rp-toc__list::-webkit-scrollbar { width: 6px; }
.rp-toc__list::-webkit-scrollbar-thumb {
  background: var(--border-strong, rgba(255, 255, 255, .17));
  border-radius: 99px;
}

.rp-toc__link {
  display: block;
  padding: 6px 10px;
  border-left: 2px solid transparent;
  border-radius: 0 6px 6px 0;
  color: var(--fg-muted, #8f94b5);
  font-size: .8125rem;
  line-height: 1.4;
  text-decoration: none;
  transition: color .15s ease, background .15s ease, border-color .15s ease;
  /* Long headings truncate to two lines rather than pushing the rail wide. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.rp-toc__link:hover {
  color: var(--fg-primary, #f6f7fd);
  background: color-mix(in srgb, var(--fg-primary, #fff) 5%, transparent);
}
/* Two cues for the active section, not just colour: a filled rail marker plus
   weight. Colour alone is not an accessible signal. */
.rp-toc__link[aria-current="true"] {
  color: var(--fg-primary, #f6f7fd);
  border-left-color: var(--color-primary-400, #7a64fb);
  background: color-mix(in srgb, var(--color-primary-500, #4f3ff0) 12%, transparent);
  font-weight: 500;
}

@media (min-width: 1280px) {
  .rp-toc { display: flex; }
}

/* ==========================================================================
   3. FLOATING ACTIONS  (contents / share / top)
   ========================================================================== */

.rp-fab-stack {
  position: fixed;
  right: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: calc(var(--rp-z) + 10);
  display: flex; flex-direction: column; gap: 10px;
  align-items: flex-end;
}

.rp-fab {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px;                       /* 44px: comfortable touch target */
  min-width: 44px;
  padding: 0 14px;
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, .09));
  border-radius: 999px;
  background: color-mix(in srgb, var(--surface-2, #12142a) 92%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  color: var(--fg-secondary, #c6cae2);
  font-family: var(--font-body, inherit);
  font-size: .8125rem; font-weight: 500;
  cursor: pointer;
  box-shadow: 0 6px 20px rgba(0, 0, 0, .28);
  transition: opacity .2s ease, transform .2s ease, color .15s ease, border-color .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.rp-fab:hover {
  color: var(--fg-primary, #f6f7fd);
  border-color: var(--color-primary-400, #7a64fb);
}
.rp-fab:active { transform: scale(.95); }
.rp-fab svg { width: 16px; height: 16px; flex: none; }

/* Hidden until useful, so it never competes with the content for attention. */
.rp-fab.is-hidden {
  opacity: 0;
  transform: translateY(8px) scale(.9);
  pointer-events: none;
}

/* The contents button is only an alternative to the rail, so hide it once the
   rail is visible. */
@media (min-width: 1280px) {
  .rp-fab[data-rp="contents"] { display: none; }
}

/* ==========================================================================
   4. CONTENTS SHEET  (< 1280px)
   ========================================================================== */

.rp-sheet {
  position: fixed; inset: 0;
  z-index: calc(var(--rp-z) + 30);
  display: flex; align-items: flex-end;
  background: rgba(4, 5, 12, .55);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0; pointer-events: none;
  transition: opacity .22s ease;
}
.rp-sheet.is-open { opacity: 1; pointer-events: auto; }

.rp-sheet__panel {
  width: 100%;
  max-height: 78dvh;
  display: flex; flex-direction: column;
  padding: 14px 18px calc(24px + env(safe-area-inset-bottom, 0px));
  border-radius: 22px 22px 0 0;
  background: var(--surface-1, #0c0e1a);
  border: 1px solid var(--border-subtle, rgba(255, 255, 255, .09));
  border-bottom: 0;
  translate: 0 100%;
  transition: translate .28s cubic-bezier(.2, 0, 0, 1);
}
.rp-sheet.is-open .rp-sheet__panel { translate: 0 0; }

/* Grab handle: signals the sheet is dismissable. */
.rp-sheet__panel::before {
  content: "";
  width: 38px; height: 4px;
  margin: 0 auto 14px;
  border-radius: 99px;
  background: var(--border-strong, rgba(255, 255, 255, .17));
  flex: none;
}
.rp-sheet .rp-toc__list { max-height: 60dvh; }
.rp-sheet .rp-toc__link { font-size: .9375rem; padding: 10px 12px; }

@media (min-width: 1280px) { .rp-sheet { display: none; } }
@media (prefers-reduced-motion: reduce) {
  .rp-sheet, .rp-sheet__panel, .rp-fab { transition: none; }
}

/* ==========================================================================
   5. ARTICLE IMAGE STABILITY
   --------------------------------------------------------------------------
   The exported article images carry no width/height attributes, so the browser
   cannot reserve space and the text jumps when they decode. A default
   aspect-ratio removes that shift; any image that does declare dimensions
   overrides it naturally.
   ========================================================================== */

article img:not([width]):not([height]) {
  aspect-ratio: 16 / 9;
  width: 100%;
  height: auto;
  object-fit: cover;
  background: var(--surface-2, #12142a);
}

/* ==========================================================================
   6. PRINT
   ========================================================================== */

@media print {
  .rp-progress, .rp-toc, .rp-fab-stack, .rp-sheet { display: none !important; }
}
