/* portal-toc.css - sticky in-section table of contents for portal pages.
 *
 * Z5.1 polish item #1 (P6 quadruple-vouched across Z3.1+Z3.2+Z3.3+Z5.1).
 * Auto-generated by portal-toc.js from .va-portal-content h2 nodes when
 * the page has 3+ h2 sections. Desktop: pinned to the right of main
 * content. Mobile (<=820px): collapses to a floating "Sections" pill at
 * the bottom-right that expands a bottom-sheet on tap.
 *
 * Lives in a separate file (NOT portal.css) to avoid merge collisions
 * with the concurrent Z5.2 hex-viewer work that owns portal.css token
 * additions this round.
 *
 * Token vocabulary: inherits :root variables from portal.css (--bg-card,
 * --border, --fg-muted, --gold, --green, --mono). No new design tokens.
 *
 * License: (c) 2026 Virtus Cyber Academy.
 */

/* ============================================================
 * Desktop: right-rail sticky TOC.
 * ============================================================ */
.va-portal-toc {
  position: sticky;
  top: 4rem;                       /* clears the 3rem sticky header + a hair */
  align-self: start;
  width: 14rem;
  max-height: calc(100vh - 5rem);
  overflow-y: auto;
  margin: 1.5rem 1rem 1.5rem 0;
  padding: 0.8rem 0.6rem 0.8rem 0.8rem;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: var(--mono);
  font-size: 0.78rem;
  line-height: 1.4;
}

.va-portal-toc-heading {
  margin: 0 0 0.5rem 0;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--border);
  color: var(--fg-muted);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.va-portal-toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.va-portal-toc-item {
  margin: 0.1rem 0;
}

.va-portal-toc-link {
  display: block;
  padding: 0.25rem 0.45rem;
  color: var(--fg);
  border-left: 2px solid transparent;
  border-radius: 0 2px 2px 0;
  text-decoration: none;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
  word-break: break-word;
}

.va-portal-toc-link:hover {
  background: var(--bg-deep);
  color: var(--gold);
  text-decoration: none;
}

.va-portal-toc-item--active > .va-portal-toc-link {
  background: rgba(74, 222, 128, 0.10);
  border-left-color: var(--green);
  color: var(--green);
  font-weight: 600;
}

/* Visually de-emphasize nested H3 entries when included. Currently the
 * generator only collects H2; this rule reserves space for a future
 * upgrade to include H3 sub-sections without re-flowing this file. */
.va-portal-toc-list--sub {
  list-style: none;
  margin: 0.15rem 0 0.2rem 0.8rem;
  padding: 0;
  font-size: 0.74rem;
}

/* ============================================================
 * Scene sub-entries.
 *
 * R-Z5-POLISH-STICKY-TOC-UNIFIED-2026-05-16. Each H2 entry that owns
 * one or more `[data-scene-key][data-scene-label]` containers in its
 * section gets a nested `<ul class="va-portal-toc-list--scenes">` with
 * one `<li class="va-portal-toc-scene-item">` per scene. Sub-entries
 * are visually subordinate (indented, smaller font, semi-muted) until
 * the scene becomes the active sub-entry within its parent H2.
 *
 * Active-state semantics: the parent H2 item carries `--active` when
 * any of its scenes is the active scene OR the H2 itself is the deepest
 * intersecting heading. The active scene item carries both
 * `va-portal-toc-item--active` (for the shared visual treatment) AND
 * `va-portal-toc-scene-item--active` (for the scene-specific accent so
 * the scene highlight reads as distinct from the H2 highlight).
 * ============================================================ */
.va-portal-toc-list--scenes {
  list-style: none;
  margin: 0.2rem 0 0.4rem 0.8rem;
  padding: 0 0 0 0.4rem;
  border-left: 1px dashed var(--border);
  font-size: 0.72rem;
}

.va-portal-toc-scene-item {
  margin: 0;
}

.va-portal-toc-scene-link {
  display: block;
  padding: 0.18rem 0.4rem;
  color: var(--fg-muted);
  border-left: 2px solid transparent;
  border-radius: 0 2px 2px 0;
  text-decoration: none;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
  word-break: break-word;
  line-height: 1.35;
}

.va-portal-toc-scene-link:hover {
  background: var(--bg-deep);
  color: var(--gold);
  text-decoration: none;
}

/* Active scene sub-entry: amber accent instead of green so it reads as
 * subordinate-but-distinct from the H2 active treatment. */
.va-portal-toc-scene-item--active > .va-portal-toc-scene-link {
  background: rgba(251, 191, 36, 0.10);
  border-left-color: var(--gold);
  color: var(--gold);
  font-weight: 600;
}

/* ============================================================
 * Visited-scene badge + reset link.
 *
 * R-Z5-POLISH-SCENE-CHECKMARKS-2026-05-16. Per-scene progress dot in
 * the documentation-site idiom (Stripe / MDN / DigitalOcean docs all
 * use the same amber-checkmark pattern). Visited scenes lift the
 * sub-entry text from semi-muted to the standard foreground so a
 * student scanning the TOC sees the visited entries pop while the
 * unvisited ones recede. The check-badge itself uses Palette B amber
 * to match the rest of the academy's progress / certificate accents.
 *
 * Composition with the active accent: a sub-entry can be both active
 * AND visited simultaneously. The active rule (above) wins on the
 * link's background + border-left-color; the visited rule below adds
 * the badge + bumps the muted color back to foreground when not active.
 * ============================================================ */
.va-toc-visited-mark {
  display: inline-block;
  margin-right: 0.15rem;
  color: var(--gold);
  font-weight: 700;
  font-family: var(--mono);
  /* Slight visual lift so the checkmark sits centered with the scene
   * label text rather than dropping below the baseline. */
  line-height: 1;
}

.va-portal-toc-scene-item--visited > .va-portal-toc-scene-link {
  /* Visited but not-currently-active: lift the muted color to standard
   * foreground so the reader can scan visited entries at a glance. */
  color: var(--fg);
}

.va-portal-toc-scene-item--visited.va-portal-toc-scene-item--active
  > .va-portal-toc-scene-link {
  /* Active beats visited on the link color so the active accent stays
   * unambiguous; the checkmark itself remains amber and visible. */
  color: var(--gold);
}

.va-portal-toc-footer {
  margin: 0.6rem 0 0 0;
  padding-top: 0.45rem;
  border-top: 1px dashed var(--border);
  text-align: right;
}

.va-portal-toc-reset {
  display: inline-block;
  padding: 0.3rem 0.55rem;
  background: transparent;
  color: var(--fg-muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 0.7rem;
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}

.va-portal-toc-reset:hover,
.va-portal-toc-reset:focus {
  background: var(--bg-deep);
  color: var(--gold);
  border-color: var(--gold);
  outline: none;
}

/* ============================================================
 * Section + page progress counters.
 *
 * R-Z5-POLISH-SCENE-PROGRESS-2026-05-16. Thin layer over the round
 * 6/8 visited-tracker. The per-section counter sits inline at the end
 * of each H2 link as a faint mono-numeric "(N/M)" tag; on completion
 * (N == M) it lifts to green + prepends a checkmark so the student
 * sees the section as done at a glance. The page-level rollup sits at
 * the top of the TOC between the "On this page" heading + the H2
 * list; same completion accent.
 *
 * Composition: counters are siblings of the existing scene sub-entry
 * badges (round 6/8) + the active accent (round STICKY-TOC); they do
 * not interact with either.
 * ============================================================ */
.va-toc-section-progress {
  display: inline;
  margin-left: 0.35rem;
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  /* Numerals as tabular figures so the counter does not jitter as the
   * denominator + numerator widths change (1 char vs 2 char). */
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.va-toc-section-progress[data-complete="true"] {
  color: var(--green);
  font-weight: 600;
}

.va-toc-page-progress {
  margin: 0.1rem 0 0.6rem 0;
  padding: 0.4rem 0.5rem;
  background: var(--bg-deep);
  border: 1px solid var(--border);
  border-left: 2px solid var(--gold);
  border-radius: 3px;
  color: var(--fg-muted);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}

.va-toc-page-progress[data-complete="true"] {
  color: var(--green);
  border-left-color: var(--green);
  font-weight: 600;
}

/* ============================================================
 * H3 sub-sub-entries.
 *
 * R-Z5-POLISH-PULSE-H3-2026-05-16. Pages with <h3> headings inside a
 * <h2> section get H3 anchor links indented under the H2 entry. H3
 * entries sit ABOVE the scene sub-entries (page-structure order is
 * H2 > H3 > scenes). H3 entries are pure anchor links: no badges, no
 * observers, no visited tracking. Visually distinct from scene
 * entries (no dashed left rule; solid quarter-opacity left rule;
 * slightly smaller text than scene labels).
 * ============================================================ */
.va-portal-toc-list--h3s {
  list-style: none;
  margin: 0.2rem 0 0.2rem 0.8rem;
  padding: 0 0 0 0.4rem;
  border-left: 1px solid var(--border);
  font-size: 0.7rem;
}

.va-portal-toc-h3-item {
  margin: 0;
}

.va-portal-toc-h3-link {
  display: block;
  padding: 0.15rem 0.4rem;
  color: var(--fg-muted);
  border-left: 2px solid transparent;
  border-radius: 0 2px 2px 0;
  text-decoration: none;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease;
  word-break: break-word;
  line-height: 1.3;
  font-style: italic;
}

.va-portal-toc-h3-link:hover {
  background: var(--bg-deep);
  color: var(--gold);
  text-decoration: none;
}

/* ============================================================
 * Active-scene pulse animation.
 *
 * R-Z5-POLISH-PULSE-H3-2026-05-16. Fires when the IntersectionObserver
 * flips the active scene to a NEW scene (per-scene 5 s dedup window
 * to prevent flicker on scroll-back-and-forth). The TOC scene item
 * gets `data-pulse="active"` for 2 seconds; the CSS animation runs
 * once, then the attribute is removed and the item returns to its
 * idle visual state.
 *
 * Subtle by design: 5% scale lift + amber outline fade. Easy to
 * overdo; this pairs with the existing active-state accent so the
 * pulse reads as "you just arrived" rather than as "look at this".
 *
 * `prefers-reduced-motion: reduce` users get only the color flash;
 * the scale transform is suppressed entirely (no transform property
 * at all; the keyframe is overridden by a flat color-only animation).
 * ============================================================ */
@keyframes va-toc-pulse {
  0% {
    transform: scale(1);
    outline: 1px solid transparent;
    outline-offset: 0;
  }
  30% {
    transform: scale(1.05);
    outline: 1px solid var(--gold);
    outline-offset: 1px;
  }
  100% {
    transform: scale(1);
    outline: 1px solid transparent;
    outline-offset: 0;
  }
}

@keyframes va-toc-pulse-reduced {
  0%, 100% { background-color: transparent; }
  30%      { background-color: rgba(251, 191, 36, 0.18); }
}

.va-portal-toc-scene-item[data-pulse="active"] > .va-portal-toc-scene-link {
  animation: va-toc-pulse 2s ease-out 1;
  /* Keep transform origin centered so the scale lift does not push
   * the link visually rightward in the right-rail layout. */
  transform-origin: center;
}

@media (prefers-reduced-motion: reduce) {
  .va-portal-toc-scene-item[data-pulse="active"] > .va-portal-toc-scene-link {
    /* Suppress the scale transform entirely; replace with a flat
     * color flash so the affordance still registers without motion. */
    animation: va-toc-pulse-reduced 2s ease-out 1;
    transform: none;
    outline: none;
  }
}

/* ============================================================
 * Desktop layout: insert TOC as a 3rd column. The main grid in
 * portal.css uses `var(--sidebar-w) minmax(0, 1fr)`. We override it
 * here when a TOC element is present in the layout so the new column
 * does not push the sidebar.
 *
 * Implementation note: we cannot use :has() in older browsers reliably,
 * so the JS toggles a `va-portal-layout--toc` class on the layout root
 * when it injects the TOC.
 * ============================================================ */
.va-portal-layout--toc {
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr) auto;
}

/* Standalone surfaces (e.g. glossary) do not have the 3-col grid; on
 * desktop we hide the right-rail TOC for these and rely on the mobile
 * pill toggle for navigation. Glossary already has its own letter bar
 * for in-page nav, so the desktop TOC would be redundant. */
.va-portal-toc--standalone {
  display: none;
}

/* ============================================================
 * Mobile (<=820px): floating bottom-right pill toggle + bottom sheet.
 * ============================================================ */
.va-portal-toc-toggle {
  display: none;          /* hidden by default; revealed in mobile @media */
  position: fixed;
  right: 0.8rem;
  bottom: 0.8rem;
  z-index: 28;            /* above content, below the global sidebar drawer */
  min-width: 44px;
  min-height: 44px;
  padding: 0.55rem 0.95rem;
  background: var(--gold);
  color: var(--bg);
  border: none;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}

.va-portal-toc-toggle[aria-expanded="true"] .va-portal-toc-toggle-chev {
  transform: rotate(180deg);
}

.va-portal-toc-toggle-chev {
  display: inline-block;
  margin-left: 0.3rem;
  transition: transform 180ms ease;
}

.va-portal-toc-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 27;
}

.va-portal-toc-backdrop[data-open="true"] {
  display: block;
}

/* Mobile presentation flips the sticky right-rail into a bottom sheet
 * that slides up when the pill is tapped. Desktop retains the sticky
 * right-rail; the mobile media query below overrides position + width
 * for the same element so we only need one DOM node. */
@media (max-width: 820px) {
  .va-portal-toc-toggle {
    display: inline-block;
  }

  .va-portal-layout--toc {
    /* On mobile, the layout already collapses to a single column per
     * portal.css; do not add a third column. The TOC element below
     * lifts out of the grid via position: fixed. */
    grid-template-columns: minmax(0, 1fr);
  }

  .va-portal-toc {
    position: fixed;
    inset: auto 0 0 0;
    width: 100%;
    max-height: 60vh;
    margin: 0;
    border-radius: 8px 8px 0 0;
    border: 1px solid var(--border);
    border-bottom: none;
    background: var(--bg-card);
    z-index: 29;
    transform: translateY(100%);
    transition: transform 220ms ease;
    box-shadow: 0 -6px 20px rgba(0, 0, 0, 0.5);
    padding: 1rem 1.1rem 1.4rem 1.1rem;
  }

  .va-portal-toc[data-open="true"] {
    transform: translateY(0);
  }

  /* Mobile presentation overrides the standalone-desktop hide; the
   * mobile pill toggle drives the bottom sheet on every surface. */
  .va-portal-toc--standalone {
    display: block;
  }

  .va-portal-toc-heading {
    font-size: 0.8rem;
  }

  .va-portal-toc-link {
    padding: 0.55rem 0.6rem;
    font-size: 0.9rem;
    min-height: 44px;          /* tap-target floor per mobile baseline */
  }

  /* Mobile scene sub-entries: keep the visual indent + dashed rule but
   * grow the link to the same 44px tap target the parent H2 link uses.
   * Sub-entries render inline under their parent in the bottom-sheet
   * (no separate disclosure; the whole list is scrollable). */
  .va-portal-toc-list--scenes {
    margin: 0 0 0.3rem 1rem;
    padding: 0 0 0 0.6rem;
    font-size: 0.85rem;
  }

  .va-portal-toc-scene-link {
    padding: 0.5rem 0.55rem;
    font-size: 0.85rem;
    min-height: 44px;
    line-height: 1.3;
  }

  /* Mobile reset link: grow to the 44x44 WCAG tap-target floor. The
   * desktop variant uses a denser 0.7rem font + tight padding; the
   * mobile bottom-sheet has the breathing room to size it up. */
  .va-portal-toc-footer {
    text-align: center;
    padding-top: 0.6rem;
    margin-top: 0.8rem;
  }

  .va-portal-toc-reset {
    min-width: 44px;
    min-height: 44px;
    padding: 0.65rem 1.1rem;
    font-size: 0.85rem;
  }

  /* Mobile bottom-sheet: scale up the progress counter font + the
   * page-rollup band so they stay readable at thumbnail viewport size. */
  .va-toc-section-progress {
    font-size: 0.8rem;
    margin-left: 0.45rem;
  }

  .va-toc-page-progress {
    margin: 0 0 0.7rem 0;
    padding: 0.6rem 0.7rem;
    font-size: 0.85rem;
  }

  /* Mobile bottom-sheet: grow H3 link to the 44x44 tap-target floor.
   * Indented under H2 like scene entries; the dashed-vs-solid rule
   * is what distinguishes H3 from scene sub-entries visually. */
  .va-portal-toc-list--h3s {
    margin: 0 0 0.3rem 1rem;
    padding: 0 0 0 0.6rem;
    font-size: 0.85rem;
  }

  .va-portal-toc-h3-link {
    padding: 0.5rem 0.55rem;
    font-size: 0.85rem;
    min-height: 44px;
    line-height: 1.3;
  }
}

/* ============================================================
 * Print: hide the TOC entirely so it does not consume page space.
 * ============================================================ */
@media print {
  .va-portal-toc,
  .va-portal-toc-toggle,
  .va-portal-toc-backdrop {
    display: none !important;
  }
}
