<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{COURSE_TITLE}} Mockup</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,600;9..144,700;9..144,800&family=JetBrains+Mono:wght@400;600;700&family=Source+Sans+3:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
  :root {
    --bg:#fbfaf7;
    --paper:#ffffff;
    --ink:#1c1815;
    --inkSub:#3a322d;
    --mute:#8a7f73;
    --veryDim:#bdb3a5;
    --rule:#ece6dc;
    --maroon:#8C1D40;
    --maroonD:#5e122c;
    --gold:#FFC627;
    --goldDk:#8b6b00;
    --canvas-link:#0374b5;
    --canvas-border:#c7cdd1;
    --canvas-table-head:#f5f5f5;
    --rail:284px;
    --aside:220px;
  }
  *, *::before, *::after { box-sizing:border-box; }
  html { scroll-behavior:smooth; }
  body {
    margin:0;
    background:var(--bg);
    color:var(--ink);
    font-family:"Source Sans 3", "Helvetica Neue", Arial, sans-serif;
    font-size:15px;
    line-height:1.5;
  }
  button, input { font:inherit; }
  a { color:inherit; }
  .top-bar {
    height:64px;
    display:flex;
    align-items:center;
    padding:0 32px;
    gap:18px;
    background:var(--paper);
    border-bottom:1px solid var(--rule);
  }
  .asu-badge {
    width:30px;
    height:30px;
    background:var(--maroon);
    color:#fff;
    display:grid;
    place-items:center;
    border-radius:6px;
    font-weight:800;
    font-size:14px;
    flex:0 0 auto;
  }
  .top-copy { line-height:1.15; min-width:0; }
  .top-eyebrow {
    font-size:10.5px;
    color:var(--mute);
    letter-spacing:.18em;
    text-transform:uppercase;
    white-space:nowrap;
  }
  .top-primary { font-size:14px; font-weight:600; color:var(--ink); }
  .top-right {
    margin-left:auto;
    display:flex;
    align-items:center;
    gap:18px;
    font-size:12px;
    color:var(--mute);
    min-width:0;
  }
  .top-rule { width:1px; height:14px; background:var(--rule); }
  .mono { font-family:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
  .sr-only {
    position:absolute;
    width:1px;
    height:1px;
    padding:0;
    margin:-1px;
    overflow:hidden;
    clip:rect(0, 0, 0, 0);
    white-space:nowrap;
    border:0;
  }
  .print-btn, .edit-btn {
    background:transparent;
    border:1px solid var(--rule);
    color:var(--ink);
    padding:7px 14px;
    border-radius:99px;
    font-size:12px;
    cursor:pointer;
  }
  .edit-btn {
    padding:5px 12px;
    color:var(--inkSub);
    font-size:11.5px;
  }
  .print-btn:hover, .edit-btn:hover { border-color:var(--maroon); color:var(--maroon); }
  .print-btn:focus-visible, .edit-btn:focus-visible, .toc-filter:focus-visible, .toc-module-header:focus-visible, .toc-page:focus-visible, .back-to-top:focus-visible {
    outline:3px solid var(--gold);
    outline-offset:2px;
  }
  .pylon-hero {
    background:var(--maroon);
    color:#fff;
    padding:28px 40px 26px;
    border-bottom:2px solid var(--ink);
    position:relative;
    overflow:hidden;
  }
  .pylon-hero::before {
    content:"";
    position:absolute;
    right:-20px;
    top:-30px;
    bottom:-20px;
    width:460px;
    pointer-events:none;
    background-image:
      linear-gradient(to top right, transparent 49.7%, rgba(255,198,39,0.30) 49.7%, rgba(255,198,39,0.30) 50.3%, transparent 50.3%),
      linear-gradient(to top left, transparent 49.7%, rgba(255,198,39,0.30) 49.7%, rgba(255,198,39,0.30) 50.3%, transparent 50.3%);
    background-size:460px 320px, 460px 320px;
    background-position:center bottom, center bottom;
    background-repeat:no-repeat;
  }
  .pylon-hero::after {
    content:"";
    position:absolute;
    right:40px;
    bottom:0;
    width:260px;
    height:180px;
    pointer-events:none;
    background:
      linear-gradient(to top right, transparent 49.7%, rgba(255,198,39,0.45) 49.7%, rgba(255,198,39,0.45) 50.3%, transparent 50.3%),
      linear-gradient(to top left, transparent 49.7%, rgba(255,198,39,0.45) 49.7%, rgba(255,198,39,0.45) 50.3%, transparent 50.3%);
  }
  .hero-inner {
    position:relative;
    z-index:1;
    display:flex;
    align-items:flex-end;
    gap:36px;
  }
  .pylon-number {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:800;
    font-size:124px;
    color:var(--gold);
    letter-spacing:-.05em;
    line-height:.82;
    padding-bottom:6px;
    flex:0 0 auto;
  }
  .hero-title-block { flex:1; padding-bottom:12px; min-width:240px; }
  .hero-eyebrow {
    font-size:11px;
    letter-spacing:.28em;
    text-transform:uppercase;
    color:rgba(255,255,255,.78);
    margin-bottom:8px;
    font-weight:700;
  }
  .hero-title {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:600;
    font-size:46px;
    line-height:1;
    letter-spacing:-.025em;
    color:#fff;
    margin:0;
    max-width:720px;
  }
  .hero-stats {
    display:flex;
    gap:28px;
    align-items:flex-end;
    padding-bottom:14px;
    padding-right:8px;
    position:relative;
    z-index:2;
  }
  .hero-stat-label {
    font-size:10px;
    letter-spacing:.26em;
    text-transform:uppercase;
    color:rgba(255,255,255,.75);
    font-weight:700;
  }
  .hero-stat-value {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:700;
    font-size:30px;
    color:var(--gold);
    letter-spacing:-.02em;
    line-height:1;
    margin-top:4px;
  }
  .shell-body {
    display:grid;
    grid-template-columns:var(--rail) minmax(0, 1fr) var(--aside);
  }
  .toc-rail {
    background:var(--paper);
    border-right:1px solid var(--rule);
    padding:30px 0 24px;
  }
  .toc-sticky { position:sticky; top:24px; }
  .toc-heading { padding:0 22px 14px; }
  .toc-kicker {
    font-size:10px;
    letter-spacing:.26em;
    text-transform:uppercase;
    color:var(--maroon);
    font-weight:700;
  }
  .toc-title {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:600;
    font-size:22px;
    line-height:1.1;
    letter-spacing:-.02em;
    color:var(--ink);
    margin-top:6px;
  }
  .version-pill {
    display:inline-flex;
    align-items:center;
    gap:6px;
    margin-top:12px;
    padding:3px 10px;
    border-radius:99px;
    background:rgba(140,29,64,.07);
    color:var(--maroon);
    font-size:10.5px;
    font-weight:600;
    letter-spacing:.04em;
  }
  .filter-wrap { padding:4px 22px 14px; position:relative; }
  .toc-filter {
    width:100%;
    padding:8px 12px 8px 30px;
    background:var(--bg);
    border:1px solid var(--rule);
    border-radius:5px;
    color:var(--ink);
    font-size:12px;
  }
  .filter-wrap svg {
    position:absolute;
    left:32px;
    top:14px;
    width:11px;
    height:11px;
    color:var(--mute);
    pointer-events:none;
  }
  .toc-tree {
    max-height:calc(100vh - 280px);
    overflow:auto;
    border-top:1px solid var(--rule);
  }
  .toc-module { border-bottom:1px solid var(--rule); }
  .toc-module-header {
    width:100%;
    padding:11px 22px;
    display:flex;
    align-items:center;
    gap:12px;
    cursor:pointer;
    background:transparent;
    border:0;
    text-align:left;
    color:inherit;
  }
  .toc-module.active .toc-module-header { background:rgba(255,198,39,.06); }
  .toc-mod-code {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:700;
    font-size:22px;
    letter-spacing:-.03em;
    line-height:1;
    color:var(--maroon);
    min-width:36px;
  }
  .toc-mod-title {
    font-size:12.5px;
    color:var(--inkSub);
    line-height:1.3;
    font-weight:500;
    flex:1;
  }
  .toc-arrow {
    font-size:9.5px;
    color:var(--mute);
  }
  .toc-module.collapsed .toc-arrow { transform:rotate(-90deg); }
  .toc-module.collapsed .toc-pages { display:none; }
  .toc-pages {
    list-style:none;
    margin:0;
    padding:2px 0 10px;
  }
  .toc-page {
    display:grid;
    grid-template-columns:22px 10px 1fr;
    align-items:center;
    padding:5px 14px 5px 22px;
    border-left:2px solid transparent;
    color:var(--inkSub);
    text-decoration:none;
    line-height:1.3;
  }
  .toc-page.active {
    border-left-color:var(--maroon);
    margin-left:-2px;
    background:rgba(255,198,39,.12);
    color:var(--maroon);
    font-weight:700;
  }
  .toc-index {
    color:var(--veryDim);
    font-size:10px;
  }
  .toc-type-dot {
    width:6px;
    height:6px;
    border-radius:50%;
    background:var(--veryDim);
    box-sizing:border-box;
  }
  .toc-type-dot.type-overview, .toc-type-dot.type-lecture { background:var(--maroon); }
  .toc-type-dot.type-assignment { background:var(--goldDk); }
  .toc-type-dot.type-discussion, .toc-type-dot.type-quiz, .toc-type-dot.type-page { background:var(--veryDim); }
  .toc-page.placeholder { color:var(--mute); font-style:italic; }
  .toc-page.placeholder .toc-type-dot {
    width:8px;
    height:8px;
    background:transparent;
    border:1.5px dashed var(--maroon);
  }
  .toc-page-title {
    margin-left:8px;
    font-size:12px;
  }
  .toc-subheader {
    padding:7px 20px 6px 38px;
    color:var(--mute);
    font-size:11.5px;
    font-style:italic;
    line-height:1.25;
    text-align:center;
  }
  .toc-subheader span {
    display:inline-flex;
    align-items:center;
    gap:8px;
    max-width:100%;
  }
  .toc-subheader span::before, .toc-subheader span::after {
    content:"";
    width:18px;
    height:1px;
    background:var(--rule);
  }
  .toc-empty {
    padding:8px 22px;
    color:var(--mute);
    font-size:12px;
    display:none;
  }
  .main {
    padding:36px 36px 60px;
    min-width:0;
  }
  .module-prelude {
    margin:28px 0 12px;
    scroll-margin-top:18px;
  }
  .module-prelude-top {
    display:flex;
    align-items:baseline;
    gap:18px;
    margin-bottom:6px;
  }
  .module-code {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:600;
    font-size:14px;
    color:var(--maroon);
    letter-spacing:.05em;
  }
  .module-title {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:600;
    font-size:30px;
    margin:0;
    line-height:1.1;
    letter-spacing:-.02em;
    flex:1;
    color:var(--inkSub);
  }
  .module-prelude.active .module-title { color:var(--ink); }
  .module-counts {
    font-size:11.5px;
    color:var(--mute);
    display:flex;
    gap:12px;
    white-space:nowrap;
  }
  .module-counts strong { font-weight:700; }
  .module-counts .ready { color:var(--maroon); }
  .module-counts .draft { color:var(--goldDk); }
  .module-counts .empty { color:var(--veryDim); }
  .module-rule {
    height:1px;
    background:var(--rule);
    position:relative;
    margin-top:8px;
  }
  .module-progress-fill {
    position:absolute;
    left:0;
    top:-1px;
    height:3px;
    width:0;
    background:var(--gold);
  }
  .module-prelude.active .module-progress-fill { background:var(--maroon); }
  {{MODULE_PROGRESS_CSS}}
  .module-subheader-divider {
    display:flex;
    align-items:center;
    justify-content:center;
    gap:14px;
    margin:18px 0 20px;
    color:var(--mute);
    font-size:14px;
    font-style:italic;
    scroll-margin-top:24px;
  }
  .module-subheader-divider::before, .module-subheader-divider::after {
    content:"";
    height:1px;
    background:var(--rule);
    flex:1;
    max-width:220px;
  }
  .page-section {
    background:var(--paper);
    border-radius:6px;
    border:1px solid var(--rule);
    margin:14px 0;
    position:relative;
    scroll-margin-top:18px;
  }
  .page-header {
    padding:14px 24px 12px;
    border-bottom:1px solid var(--rule);
    display:flex;
    align-items:center;
    gap:14px;
  }
  .type-pill {
    background:var(--bg);
    color:var(--inkSub);
    padding:3px 10px;
    font-size:10.5px;
    letter-spacing:.18em;
    text-transform:uppercase;
    font-weight:700;
    border:1px solid var(--rule);
    border-radius:99px;
  }
  .page-id {
    font-size:11px;
    color:var(--mute);
  }
  .page-header-spacer { flex:1; }
  .status-pill {
    display:flex;
    align-items:center;
    gap:6px;
    font-size:10.5px;
    letter-spacing:.18em;
    text-transform:uppercase;
    font-weight:700;
  }
  .status-pill.ready { color:var(--maroon); }
  .status-pill.draft { color:var(--goldDk); }
  .status-pill.placeholder { color:#9a8b7a; }
  .status-dot {
    width:7px;
    height:7px;
    border-radius:50%;
    background:currentColor;
  }
  .status-pill.placeholder .status-dot {
    background:transparent;
    border:1.5px dashed var(--maroon);
  }
  .page-grid {
    display:grid;
    grid-template-columns:1fr;
  }
  .page-grid.has-note { grid-template-columns:minmax(0, 1fr) 200px; }
  .page-title {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-weight:600;
    font-size:24px;
    line-height:1.1;
    letter-spacing:-.02em;
    margin:0;
    color:var(--ink);
    flex:1 1 220px;
    min-width:180px;
  }
  .instructor-note {
    padding:22px 22px 22px 18px;
    border-left:1px solid var(--rule);
    background:#fcfaf3;
  }
  .note-title {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-style:italic;
    font-size:11.5px;
    color:var(--maroon);
    margin-bottom:6px;
    font-weight:600;
    letter-spacing:.02em;
  }
  .note-text { font-size:12.5px; color:var(--inkSub); line-height:1.5; }
  .note-author {
    margin-top:14px;
    display:flex;
    align-items:center;
    gap:6px;
    font-size:10.5px;
    color:var(--mute);
    letter-spacing:.06em;
  }
  .note-avatar {
    width:18px;
    height:18px;
    border-radius:50%;
    background:var(--maroon);
    color:#fff;
    display:inline-grid;
    place-items:center;
    font-size:9px;
    font-weight:700;
  }
  .placeholder-empty {
    padding:22px;
    border:1.5px dashed var(--maroon);
    background:rgba(140,29,64,.05);
    color:var(--maroonD);
    display:flex;
    align-items:center;
    gap:14px;
    border-radius:6px;
  }
  .placeholder-empty strong {
    font-size:13px;
    letter-spacing:.15em;
    text-transform:uppercase;
  }
  .side-panel { padding:36px 24px 0 0; }
  .side-sticky { position:sticky; top:90px; }
  .side-kicker {
    font-size:10px;
    letter-spacing:.22em;
    text-transform:uppercase;
    color:var(--mute);
    margin-bottom:8px;
  }
  .side-summary {
    font-family:"Fraunces", Georgia, "Times New Roman", serif;
    font-size:22px;
    font-weight:600;
    line-height:1.15;
    letter-spacing:-.01em;
    margin-bottom:14px;
  }
  .side-rule { height:1px; background:var(--rule); margin:14px 0; }
  .legend, .shortcuts {
    list-style:none;
    margin:0;
    padding:0;
    font-size:12.5px;
    color:var(--inkSub);
    line-height:1.7;
  }
  .legend-dot {
    display:inline-block;
    width:8px;
    height:8px;
    border-radius:99px;
    margin-right:8px;
    vertical-align:middle;
  }
  .legend-dot.ready { background:var(--maroon); }
  .legend-dot.draft { background:var(--gold); }
  .legend-dot.placeholder {
    background:transparent;
    border:1.5px dashed var(--maroon);
    margin-right:6px;
  }
  .shortcuts {
    font-size:11.5px;
    color:var(--mute);
  }
  .footer {
    text-align:center;
    padding:32px 24px 0;
    color:var(--mute);
    font-size:12px;
  }
  .back-to-top {
    position:fixed;
    bottom:24px;
    right:24px;
    width:44px;
    height:44px;
    border-radius:50%;
    background:var(--maroon);
    color:white;
    border:0;
    cursor:pointer;
    display:none;
    align-items:center;
    justify-content:center;
    box-shadow:0 2px 8px rgba(0,0,0,.2);
    font-size:20px;
    z-index:50;
  }
  .back-to-top.visible { display:flex; }
  .back-to-top:hover { background:var(--maroonD); }

  .page-content {
    padding: 24px 32px;
  }

  /* Canvas user_content styles */
  .page-content h1 { font-size: 1.75em; font-weight: 500; margin: 0.5em 0; }
  .page-content h2 { font-size: 1.5em; font-weight: 500; margin: 1em 0 0.5em; }
  .page-content h3 { font-size: 1.25em; font-weight: 500; margin: 1em 0 0.5em; }
  .page-content h4 { font-size: 1.1em; font-weight: 500; margin: 1em 0 0.5em; }
  .page-content p { margin: 0 0 1em; }
  .page-content a { color: var(--canvas-link); text-decoration: none; }
  .page-content ul, .page-content ol { margin: 0 0 1em 1.5em; }
  .page-content li { margin: 0.25em 0; }
  .page-content table { border-collapse: collapse; width: 100%; margin: 1em 0; }
  .page-content th, .page-content td { border: 1px solid var(--canvas-border); padding: 8px 12px; text-align: left; }
  /* Default th styling. Use :not([style*="background"]) so per-page inline styles win without !important. */
  .page-content th:not([style*="background"]) { background: var(--canvas-table-head); font-weight: 500; }
  .page-content th[style*="background"] { font-weight: 500; }
  /* A <tr> with an inline background should color the whole row: make its
     cells transparent so the row background shows through. */
  .page-content tr[style*="background"] > th,
  .page-content tr[style*="background"] > td { background: transparent; }
  .page-content img { max-width: 100%; height: auto; }

  @media print {
    .top-bar, .toc-rail, .side-panel, .back-to-top { display:none !important; }
    .shell-body { display:block; }
    .main { padding:0; }
    .pylon-hero { color:#000; background:#fff; border-bottom:2px solid #000; }
    .pylon-hero::before, .pylon-hero::after { display:none; }
    .page-section { break-inside:avoid; }
  }
  @media (max-width: 1100px) {
    .shell-body { grid-template-columns:var(--rail) minmax(0, 1fr); }
    .side-panel { display:none; }
    .hero-inner { flex-wrap:wrap; }
    .hero-stats { width:100%; padding-left:160px; }
  }
  @media (max-width: 760px) {
    .top-bar { padding:0 18px; }
    .top-right .faculty-name, .top-rule { display:none; }
    .shell-body { display:block; }
    .toc-rail { border-right:0; border-bottom:1px solid var(--rule); }
    .toc-sticky, .side-sticky { position:static; }
    .toc-tree { max-height:none; }
    .main { padding:24px 18px 44px; }
    .pylon-hero { padding:26px 22px; }
    .pylon-number { font-size:86px; }
    .hero-title { font-size:36px; }
    .hero-stats { padding-left:0; gap:18px; }
    .module-prelude-top, .page-header { align-items:flex-start; flex-wrap:wrap; }
    .module-counts { width:100%; }
    .page-grid.has-note { grid-template-columns:1fr; }
    .instructor-note { border-left:0; border-top:1px solid var(--rule); }
  }
</style>
</head>
<body>
<header class="top-bar">
  <div class="asu-badge" aria-hidden="true">A</div>
  <div class="top-copy">
    <div class="top-eyebrow">{{TERM}} &middot; {{COURSE_CODE}} &middot; Faculty preview</div>
    <div class="top-primary">Arizona State University</div>
  </div>
  <div class="top-right">
    <span class="faculty-name">Prof. {{FACULTY}}</span>
    <span class="top-rule" aria-hidden="true"></span>
    <span class="mono">{{VERSION}} &middot; {{PAGE_COUNT}}p &middot; {{UPDATED}}</span>
    <button class="print-btn" type="button" onclick="window.print()">Print</button>
  </div>
</header>

<section class="pylon-hero" aria-labelledby="preview-title">
  <div class="hero-inner">
    <div class="pylon-number">{{PYLON_NUMBER}}</div>
    <div class="hero-title-block">
      <div class="hero-eyebrow">{{TERM}} &middot; Prof. {{FACULTY}}</div>
      <h1 class="hero-title" id="preview-title">{{COURSE_TITLE}}</h1>
    </div>
    <div class="hero-stats" aria-label="Preview counts">
      <div class="hero-stat">
        <div class="hero-stat-label">Pages</div>
        <div class="hero-stat-value">{{PAGE_COUNT}}</div>
      </div>
      <div class="hero-stat">
        <div class="hero-stat-label">Modules</div>
        <div class="hero-stat-value">{{MODULE_COUNT}}</div>
      </div>
      <div class="hero-stat">
        <div class="hero-stat-label">Assignments</div>
        <div class="hero-stat-value">{{ASSIGNMENT_COUNT}}</div>
      </div>
    </div>
  </div>
</section>

<div class="shell-body">
  <aside class="toc-rail" aria-label="Contents">
    <div class="toc-sticky">
      <div class="toc-heading">
        <div class="toc-kicker">CONTENTS</div>
        <div class="toc-title">Jump to any module or page.</div>
        <div class="version-pill mono">{{VERSION}} &middot; {{PAGE_COUNT}} pages</div>
      </div>
      <div class="filter-wrap">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="7"></circle><path d="M21 21l-4.3-4.3"></path></svg>
        <label class="sr-only" for="tocFilter">Filter pages</label>
        <input class="toc-filter mono" id="tocFilter" type="search" autocomplete="off" placeholder="Filter pages&hellip;">
      </div>
      <nav class="toc-tree" id="tocTree">
        {{NAV_ITEMS}}
      </nav>
      <div class="toc-empty" id="tocEmpty">No matching pages.</div>
    </div>
  </aside>

  <main class="main">
    {{CONTENT_SECTIONS}}
    <div class="footer">Mockup {{VERSION}} &middot; Generated {{DATE}}</div>
  </main>

  <aside class="side-panel" aria-label="Preview summary">
    <div class="side-sticky">
      <div class="side-kicker">THIS PREVIEW</div>
      <div class="side-summary">{{MODULE_COUNT}} modules, {{PAGE_COUNT}} pages, in one scroll.</div>
      <div class="side-rule"></div>
      <div class="side-kicker">Legend</div>
      <ul class="legend">
        <li><span class="legend-dot ready"></span>Ready</li>
        <li><span class="legend-dot draft"></span>Draft</li>
        <li><span class="legend-dot placeholder"></span>Placeholder</li>
      </ul>
      <div class="side-rule"></div>
      <div class="side-kicker">Shortcuts</div>
      <ul class="shortcuts mono">
        <li>j / k - next / prev page</li>
        <li>g m - go to module</li>
        <li>/ - search {{PAGE_COUNT}} pages</li>
      </ul>
    </div>
  </aside>
</div>

<button class="back-to-top" id="backToTop" type="button" title="Back to top" aria-label="Back to top">&uarr;</button>

<script>
(function() {
  var modules = Array.prototype.slice.call(document.querySelectorAll(".toc-module"));
  var links = Array.prototype.slice.call(document.querySelectorAll(".toc-page"));
  var sections = Array.prototype.slice.call(document.querySelectorAll(".page-section"));
  var moduleMarkers = Array.prototype.slice.call(document.querySelectorAll(".module-prelude, .module-subheader-divider"));
  var filter = document.getElementById("tocFilter");
  var empty = document.getElementById("tocEmpty");
  var backToTop = document.getElementById("backToTop");
  var pendingShortcut = "";
  var pendingShortcutTimer = null;

  modules.forEach(function(mod) {
    var button = mod.querySelector(".toc-module-header");
    if (!button) return;
    button.addEventListener("click", function() {
      var collapsed = mod.classList.toggle("collapsed");
      button.setAttribute("aria-expanded", String(!collapsed));
    });
  });

  function setActive(id) {
    links.forEach(function(link) {
      var active = link.getAttribute("href") === "#" + id;
      link.classList.toggle("active", active);
      if (active) {
        link.setAttribute("aria-current", "page");
        var mod = link.closest(".toc-module");
        if (mod) mod.classList.add("active");
      } else {
        link.removeAttribute("aria-current");
      }
    });
    modules.forEach(function(mod) {
      if (!mod.querySelector(".toc-page.active")) mod.classList.remove("active");
    });
  }

  if ("IntersectionObserver" in window && sections.length) {
    var observer = new IntersectionObserver(function(entries) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) setActive(entry.target.id);
      });
    }, { threshold: 0.2, rootMargin: "-80px 0px -60% 0px" });
    sections.forEach(function(section) { observer.observe(section); });
  }

  if (filter) {
    filter.addEventListener("input", function() {
      var query = filter.value.trim().toLowerCase();
      var anyModule = false;
      modules.forEach(function(mod) {
        var rows = Array.prototype.slice.call(mod.querySelectorAll(".toc-page, .toc-subheader"));
        var hasMatch = false;
        rows.forEach(function(row) {
          var haystack = (row.getAttribute("data-search") || row.textContent || "").toLowerCase();
          var match = !query || haystack.indexOf(query) !== -1;
          row.style.display = match ? "" : "none";
          if (match) hasMatch = true;
        });
        mod.style.display = hasMatch ? "" : "none";
        if (query && hasMatch) {
          mod.classList.remove("collapsed");
          var button = mod.querySelector(".toc-module-header");
          if (button) button.setAttribute("aria-expanded", "true");
        }
        if (hasMatch) anyModule = true;
      });
      if (empty) empty.style.display = anyModule ? "none" : "block";
    });
  }

  function activeElementIsTextInput() {
    var active = document.activeElement;
    var tag = (active && active.tagName || "").toLowerCase();
    return tag === "input" || tag === "textarea";
  }

  function nearestTopIndex(elements) {
    if (!elements.length) return -1;
    var closestIndex = 0;
    var closestDistance = Infinity;
    elements.forEach(function(element, index) {
      var distance = Math.abs(element.getBoundingClientRect().top);
      if (distance < closestDistance) {
        closestDistance = distance;
        closestIndex = index;
      }
    });
    return closestIndex;
  }

  function scrollToElement(element) {
    if (!element) return;
    element.scrollIntoView({ behavior:"smooth", block:"start" });
    if (element.id && element.classList.contains("page-section")) setActive(element.id);
  }

  function clearPendingShortcut() {
    pendingShortcut = "";
    if (pendingShortcutTimer) window.clearTimeout(pendingShortcutTimer);
    pendingShortcutTimer = null;
  }

  function setPendingShortcut(key) {
    clearPendingShortcut();
    pendingShortcut = key;
    pendingShortcutTimer = window.setTimeout(clearPendingShortcut, 1200);
  }

  document.addEventListener("keydown", function(event) {
    if (activeElementIsTextInput() || event.altKey) return;
    var key = event.key.toLowerCase();
    if ((key === "/" && !event.metaKey && !event.ctrlKey) ||
        ((event.metaKey || event.ctrlKey) && key === "k")) {
      event.preventDefault();
      clearPendingShortcut();
      if (filter) {
        filter.focus();
        filter.select();
      }
      return;
    }
    if (event.metaKey || event.ctrlKey) return;
    if (pendingShortcut === "g") {
      if (key === "m") {
        var markerIndex = nearestTopIndex(moduleMarkers);
        var nextMarker = moduleMarkers[markerIndex + 1];
        if (nextMarker) {
          event.preventDefault();
          scrollToElement(nextMarker);
        }
      }
      clearPendingShortcut();
      return;
    }
    if (key === "g") {
      event.preventDefault();
      setPendingShortcut("g");
      return;
    }
    var sectionIndex = nearestTopIndex(sections);
    if (key === "j" && sections[sectionIndex + 1]) {
      event.preventDefault();
      clearPendingShortcut();
      scrollToElement(sections[sectionIndex + 1]);
    } else if (key === "k" && sections[sectionIndex - 1]) {
      event.preventDefault();
      clearPendingShortcut();
      scrollToElement(sections[sectionIndex - 1]);
    } else {
      clearPendingShortcut();
    }
  });

  window.addEventListener("scroll", function() {
    if (!backToTop) return;
    backToTop.classList.toggle("visible", window.scrollY > 400);
  });
  if (backToTop) {
    backToTop.addEventListener("click", function() {
      window.scrollTo({ top:0, behavior:"smooth" });
    });
  }
})();
</script>
</body>
</html>
