{% load i18n ref_tags static %}
<!doctype html>
<html lang="{{ LANGUAGE_CODE }}" data-bs-theme="dark">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="{{ favicon_url }}">
    <title>{% block title %}{{ badge_site_name|default:"Arthexis" }} {% trans "Constellation" %}{% endblock %}</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
      html[data-bs-theme='light'] {
        --bs-body-bg: #f8f9fa;
      }
      html {
        font-size: clamp(16px, 1.2vw, 24px);
      }
      @media (min-width: 1600px) {
        .container {
          max-width: 90%;
        }
      }
      .toolbar svg {
        fill: currentColor;
      }
      .external-link-icon,
      .dropdown-lock-icon {
        width: 0.5em;
        height: 0.5em;
        flex-shrink: 0;
      }
      nav.toc {
        font-size: 0.9rem;
        border-left: 1px solid #dee2e6;
        padding-left: 1rem;
        overflow-wrap: anywhere;
      }
      nav.toc h4 {
        font-size: 1rem;
        margin-top: 0;
        margin-bottom: 0.5rem;
      }
      nav.toc ul {
        list-style: none;
        padding-left: 0;
        margin-bottom: 0;
      }
      nav.toc li {
        margin-bottom: 0.25rem;
      }
      nav.toc ul ul {
        margin-left: 1rem;
      }
      nav.toc a {
        text-decoration: none;
        word-break: break-word;
      }
      nav.toc a:hover {
        text-decoration: underline;
      }
      .nav-item.dropdown .nav-link::after {
        display: none;
      }
      @media (min-width: 992px) {
        .reader-sidebar {
          position: sticky;
          top: 1rem;
          max-height: calc(100vh - 2rem);
          display: flex;
          flex-direction: column;
        }
        .reader-sidebar nav.toc {
          flex: 1 1 auto;
          min-height: 0;
          overflow-y: auto;
        }
        .reader-sidebar .reader-qr-card {
          flex-shrink: 0;
        }
      }
      .reader-qr-card .card-body {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 1.5rem;
      }
      .reader-qr-card .reader-qr-image {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 180px;
        height: 180px;
        max-width: 100%;
        margin: 0 auto;
      }
      .reader-qr-card .reader-qr-image canvas,
      .reader-qr-card .reader-qr-image img {
        max-width: 100%;
        height: auto;
      }
      .nav-item.dropdown:hover .badge,
      .nav-item.dropdown.show .badge {
        background-color: var(--bs-primary);
        color: var(--bs-white);
      }
      .user-info-tooltip {
        display: none;
        position: absolute;
        top: 100%;
        left: 50%;
        transform: translateX(-50%);
        white-space: nowrap;
        margin-top: 0.25rem;
        padding: 0.25rem 0.5rem;
        font-size: 0.75rem;
        border-radius: 0.25rem;
        background-color: var(--bs-dark);
        color: var(--bs-white);
        z-index: 1000;
      }
      .language-select {
        background-color: transparent;
        padding: 0.25rem 0.5rem;
        padding-right: 1.5rem;
        line-height: 1.5;
        height: calc(1.5em + 0.5rem + 2px);
        border-radius: 0.2rem;
        background-position: right 0.5rem center;
      }
      html[data-bs-theme='light'] .language-select {
        color: var(--bs-dark);
        border: 1px solid var(--bs-dark);
      }
      html[data-bs-theme='dark'] .language-select {
        color: var(--bs-light);
        border: 1px solid var(--bs-light);
      }
      .language-select option {
        background-color: var(--bs-body-bg);
        color: var(--bs-body-color);
      }
      .markdown-body {
        font-size: 1rem;
        line-height: 1.7;
      }
      .markdown-body > *:first-child {
        margin-top: 0;
      }
      .markdown-body ul,
      .markdown-body ol {
        padding-left: 1.5rem;
        margin-bottom: 1rem;
      }
      .markdown-body li + li {
        margin-top: 0.25rem;
      }
      .markdown-body ul ul,
      .markdown-body ol ul,
      .markdown-body ul ol,
      .markdown-body ol ol {
        margin-top: 0.5rem;
        margin-bottom: 0.5rem;
        margin-left: 0.5rem;
        padding-left: 1.25rem;
        border-left: 1px solid var(--bs-border-color-translucent, rgba(108, 117, 125, 0.35));
      }
      .markdown-body ul ul {
        list-style-type: circle;
      }
      .markdown-body ul ul ul {
        list-style-type: square;
      }
      .markdown-body ol ol {
        list-style-type: lower-alpha;
      }
      .markdown-body ol ol ol {
        list-style-type: lower-roman;
      }
      .markdown-body table {
        width: 100%;
        border-collapse: collapse;
        margin-bottom: 1.5rem;
        border-radius: 0.85rem;
        overflow: hidden;
        box-shadow: 0 1.25rem 2.5rem rgba(15, 23, 42, 0.12);
        transition: box-shadow 0.2s ease;
      }
      .markdown-body table:hover,
      .markdown-body table:focus-within {
        box-shadow: 0 1.6rem 3.2rem rgba(15, 23, 42, 0.18);
      }
      .markdown-body th,
      .markdown-body td {
        padding: 0.65rem 1rem;
        border: 1px solid var(--bs-border-color-translucent, rgba(108, 117, 125, 0.25));
      }
      html[data-bs-theme='light'] .markdown-body table {
        background: linear-gradient(180deg, rgba(248, 249, 250, 0.95), rgba(255, 255, 255, 0.98));
      }
      html[data-bs-theme='dark'] .markdown-body table {
        background: linear-gradient(180deg, rgba(15, 23, 42, 0.66), rgba(15, 23, 42, 0.82));
      }
      html[data-bs-theme='light'] .markdown-body th {
        background-color: rgba(0, 0, 0, 0.04);
      }
      html[data-bs-theme='dark'] .markdown-body th {
        background-color: rgba(255, 255, 255, 0.08);
      }
      html[data-bs-theme='dark'] .markdown-body th,
      html[data-bs-theme='dark'] .markdown-body td {
        border-color: rgba(255, 255, 255, 0.14);
      }
      html[data-bs-theme='light'] .markdown-body tbody tr:nth-of-type(odd) td {
        background-color: rgba(0, 0, 0, 0.02);
      }
      html[data-bs-theme='dark'] .markdown-body tbody tr:nth-of-type(odd) td {
        background-color: rgba(255, 255, 255, 0.04);
      }
      .markdown-body table caption {
        caption-side: top;
        padding: 1rem;
        font-weight: 600;
        text-align: left;
        letter-spacing: 0.01em;
      }
      .markdown-body thead th {
        font-weight: 600;
        font-size: 0.85rem;
        letter-spacing: 0.04em;
        text-transform: uppercase;
      }
      .markdown-body tbody td:first-child {
        font-weight: 500;
      }
      @media (max-width: 991.98px) {
        .markdown-body table {
          display: block;
          overflow-x: auto;
          white-space: nowrap;
          -webkit-overflow-scrolling: touch;
          border-radius: 1rem;
          box-shadow: 0 1.5rem 3.25rem rgba(15, 23, 42, 0.2);
        }
        .markdown-body table::-webkit-scrollbar {
          height: 0.45rem;
        }
        .markdown-body table::-webkit-scrollbar-thumb {
          background-color: rgba(108, 117, 125, 0.5);
          border-radius: 999px;
        }
        .markdown-body table:focus-visible {
          outline: 0.2rem solid var(--bs-primary);
          outline-offset: 0.35rem;
        }
        .markdown-body th,
        .markdown-body td {
          padding: 0.65rem 0.75rem;
          min-width: 10.5rem;
        }
      }
      .user-story-toggle {
        position: fixed;
        right: 1.75rem;
        bottom: 1.75rem;
        width: 3rem;
        height: 3rem;
        border-radius: 50%;
        border: 0;
        background: linear-gradient(135deg, #facc15, #fb923c);
        color: #1f2937;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 1.25rem 2.5rem rgba(15, 23, 42, 0.35);
        transition: transform 0.2s ease, box-shadow 0.2s ease;
        z-index: 1080;
      }
      .user-story-toggle:hover,
      .user-story-toggle:focus-visible {
        transform: translateY(-2px) scale(1.02);
        box-shadow: 0 1.75rem 3rem rgba(15, 23, 42, 0.45);
      }
      .user-story-toggle svg {
        width: 1.75rem;
        height: 1.75rem;
        display: block;
      }
      body.user-story-open .user-story-toggle {
        visibility: hidden;
        opacity: 0;
        pointer-events: none;
      }
      body.user-story-open {
        overflow: hidden;
      }
      .user-story-overlay {
        position: fixed;
        inset: 0;
        display: flex;
        align-items: flex-end;
        justify-content: flex-end;
        padding: 1.5rem;
        background: rgba(15, 23, 42, 0.45);
        z-index: 1070;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.2s ease;
      }
      .user-story-overlay.show {
        opacity: 1;
        pointer-events: auto;
      }
      .user-story-card {
        width: min(28rem, 100%);
        border-radius: 1rem;
        box-shadow: 0 1.5rem 3rem rgba(15, 23, 42, 0.45);
        background: var(--bs-body-bg);
        color: var(--bs-body-color);
        transform: translateY(1rem);
        transition: transform 0.25s ease;
      }
      .user-story-overlay.show .user-story-card {
        transform: translateY(0);
      }
      .user-story-rating {
        display: inline-flex;
        flex-direction: row-reverse;
        gap: 0.35rem;
      }
      .user-story-feedback-options {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        flex-wrap: wrap;
      }
      .user-story-clipboard {
        margin: 0;
        margin-left: auto;
        display: inline-flex;
        align-items: center;
        gap: 0.35rem;
      }
      .user-story-clipboard .form-check-input {
        margin-top: 0;
      }
      .user-story-rating input {
        position: absolute;
        opacity: 0;
        pointer-events: none;
      }
      .user-story-rating label {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 1.75rem;
        color: rgba(148, 163, 184, 0.7);
        cursor: pointer;
        transition: transform 0.2s ease, color 0.2s ease;
      }
      .user-story-rating label:hover,
      .user-story-rating label:focus-visible,
      .user-story-rating label:hover ~ label {
        color: #fbbf24;
      }
      .user-story-rating input:checked ~ label {
        color: #f59e0b;
      }
      .user-story-rating label:active {
        transform: scale(0.95);
      }
      .user-story-alert {
        transition: opacity 0.2s ease;
      }
      @media (max-width: 767.98px) {
        .user-story-toggle {
          right: 1.25rem;
          bottom: 1.25rem;
        }
        .user-story-overlay {
          align-items: stretch;
          padding: 1rem;
        }
        .user-story-card {
          width: 100%;
          border-radius: 1rem;
        }
      }
      .chat-widget {
        position: fixed;
        left: 1.5rem;
        bottom: 1.5rem;
        z-index: 1090;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
      }
      .chat-toggle {
        position: relative;
        border: 0;
        border-radius: 50%;
        width: 3rem;
        height: 3rem;
        padding: 0;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        background: linear-gradient(135deg, #15803d, #34d399);
        color: #f0fdf4;
        box-shadow: 0 1.25rem 2.5rem rgba(15, 23, 42, 0.35);
        transition: transform 0.2s ease, box-shadow 0.2s ease;
      }
      .chat-toggle:hover,
      .chat-toggle:focus-visible {
        transform: translateY(-2px) scale(1.02);
        box-shadow: 0 1.75rem 3rem rgba(15, 23, 42, 0.45);
      }
      .chat-toggle .chat-toggle-icon {
        display: inline-flex;
      }
      .chat-toggle .chat-toggle-icon svg {
        width: 1.5rem;
        height: 1.5rem;
        display: block;
      }
      .chat-toggle .chat-toggle-label {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
      }
      .chat-toggle .chat-unread {
        position: absolute;
        top: -0.35rem;
        right: -0.35rem;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 1.5rem;
        height: 1.5rem;
        padding: 0 0.35rem;
        border-radius: 999px;
        font-size: 0.65rem;
        background: #16a34a;
        color: #fff;
        box-shadow: 0 0.35rem 0.85rem rgba(14, 116, 44, 0.45);
      }
      .chat-toggle .chat-unread[hidden] {
        display: none;
      }
      .chat-overlay {
        position: fixed;
        inset: 0;
        display: flex;
        align-items: flex-end;
        justify-content: flex-start;
        padding: 1.5rem;
        background: rgba(15, 23, 42, 0.45);
        z-index: 1080;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.2s ease;
      }
      .chat-overlay.show {
        opacity: 1;
        pointer-events: auto;
      }
      .chat-drawer {
        width: min(28rem, 100%);
        border-radius: 1rem;
        background: var(--bs-body-bg);
        color: var(--bs-body-color);
        box-shadow: 0 1.5rem 3rem rgba(15, 23, 42, 0.45);
        border: 1px solid rgba(21, 128, 61, 0.25);
        overflow: hidden;
        transform: translateY(1rem);
        opacity: 0;
        transition: transform 0.25s ease, opacity 0.25s ease;
        display: flex;
        flex-direction: column;
      }
      .chat-overlay.show .chat-drawer {
        transform: translateY(0);
        opacity: 1;
      }
      .chat-widget.open .chat-toggle {
        visibility: hidden;
        opacity: 0;
        pointer-events: none;
      }
      .chat-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 1rem;
        padding: 1rem 1.25rem;
        background: linear-gradient(135deg, rgba(22, 163, 74, 0.18), rgba(16, 185, 129, 0.25));
        border-bottom: 1px solid rgba(21, 128, 61, 0.35);
      }
      .chat-header h2 {
        margin: 0;
        font-size: 1rem;
      }
      .chat-header small {
        display: block;
        font-size: 0.75rem;
        opacity: 0.8;
      }
      .chat-messages {
        flex: 1 1 auto;
        max-height: 18rem;
        overflow-y: auto;
        padding: 1rem 1.25rem;
        display: flex;
        flex-direction: column;
        gap: 0.85rem;
      }
      .chat-message {
        display: flex;
        flex-direction: column;
        gap: 0.2rem;
        font-size: 0.9rem;
        line-height: 1.45;
      }
      .chat-message.staff {
        align-items: flex-end;
      }
      .chat-message.staff .chat-meta {
        text-align: right;
      }
      .chat-bubble {
        padding: 0.6rem 0.9rem;
        border-radius: 0.85rem;
        background: rgba(34, 197, 94, 0.16);
        border: 1px solid rgba(22, 163, 74, 0.15);
        max-width: 100%;
        word-break: break-word;
        white-space: pre-wrap;
      }
      .chat-message.staff .chat-bubble {
        background: rgba(21, 128, 61, 0.22);
        border-color: rgba(21, 128, 61, 0.3);
      }
      .chat-meta {
        font-size: 0.75rem;
        color: rgba(21, 94, 49, 0.75);
      }
      .chat-form {
        border-top: 1px solid rgba(21, 128, 61, 0.25);
        padding: 0.75rem 1.25rem 1.25rem;
        background: var(--bs-body-bg);
      }
      .chat-form textarea {
        resize: vertical;
        min-height: 3.5rem;
      }
      .chat-actions {
        margin-top: 0.5rem;
        display: flex;
        align-items: center;
        justify-content: flex-end;
        gap: 0.75rem;
      }
      .chat-actions .chat-session-hint {
        color: rgba(21, 94, 49, 0.65);
      }
      .chat-form .btn-primary {
        background: linear-gradient(135deg, #15803d, #22c55e);
        border-color: #15803d;
        color: #052e16;
        box-shadow: 0 0.75rem 1.5rem rgba(15, 23, 42, 0.25);
      }
      .chat-form .btn-primary:hover,
      .chat-form .btn-primary:focus-visible {
        background: linear-gradient(135deg, #166534, #16a34a);
        border-color: #166534;
        color: #f0fdf4;
      }
      .chat-session-hint {
        font-size: 0.75rem;
        opacity: 0.7;
      }
      body.chat-open {
        overflow: hidden;
      }
      @media (max-width: 575.98px) {
        .chat-widget {
          left: 1rem;
          bottom: 1rem;
        }
      }
      @media (max-width: 767.98px) {
        .chat-overlay {
          align-items: stretch;
          justify-content: flex-start;
          padding: 1rem;
        }
        .chat-drawer {
          width: 100%;
          max-width: none;
          border-radius: 1rem;
        }
      }
    </style>
    {% block extra_head %}{% endblock %}
  </head>
  <body class="p-3 pb-0 d-flex flex-column min-vh-100">
    <div class="container flex-grow-1 mb-5">
      <nav class="navbar navbar-expand-lg navbar-dark bg-dark py-2 m-0">
        <div class="container-fluid">
          <a class="navbar-brand" href="/">{{ badge_site_name|default:"Arthexis" }}</a>
          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav me-auto mb-2 mb-lg-0">
              {% if nav_modules %}
                {% for module in nav_modules %}
                  {% with landings=module.enabled_landings %}
                    {% if landings|length == 1 %}
                      <li class="nav-item">
                        <a class="nav-link" href="{{ landings.0.path }}">
                          <span class="badge rounded-pill text-bg-secondary">{{ module.menu_label|upper }}</span>
                        </a>
                      </li>
                    {% else %}
                      <li class="nav-item dropdown">
                        <a class="nav-link" href="#" role="button">
                          <span class="badge rounded-pill text-bg-secondary">{{ module.menu_label|upper }}</span>
                        </a>
                        <ul class="dropdown-menu">
                          {% for landing in landings %}
                            <li>
                              <a class="dropdown-item" href="{{ landing.path }}">
                                <span class="d-flex align-items-center justify-content-between gap-2 w-100">
                                  <span>{{ landing.label }}</span>
                                  {% if landing.nav_is_locked %}
                                    <span class="d-inline-flex align-items-center gap-1">
                                      <svg aria-hidden="true" class="dropdown-lock-icon opacity-75">
                                        <use href="#icon-lock"></use>
                                      </svg>
                                      <span class="visually-hidden">
                                        {% if landing.nav_lock_reason == "login" %}
                                          {% trans "Login required" %}
                                        {% else %}
                                          {% trans "Permission required" %}
                                        {% endif %}
                                      </span>
                                    </span>
                                  {% endif %}
                                </span>
                              </a>
                              {% if landing.description %}
                                <small class="dropdown-item-text text-muted">{{ landing.description }}</small>
                              {% endif %}
                            </li>
                          {% endfor %}
                        </ul>
                      </li>
                    {% endif %}
                  {% endwith %}
                {% endfor %}
              {% endif %}
              {% if header_references %}
                <li class="nav-item dropdown">
                  <a class="nav-link" href="#" role="button">
                    <span class="badge rounded-pill text-bg-secondary">CONSTELLATION</span>
                  </a>
                  <ul class="dropdown-menu">
                    {% for reference in header_references %}
                      <li>
                        <a class="dropdown-item d-flex align-items-center justify-content-between gap-2" href="{{ reference.value }}" target="_blank" rel="noopener noreferrer">
                          <span>{{ reference.alt_text }}</span>
                          <svg aria-hidden="true" class="opacity-75 external-link-icon">
                            <use href="#icon-external"></use>
                          </svg>
                          <span class="visually-hidden">{% trans "Opens in a new tab" %}</span>
                        </a>
                      </li>
                    {% endfor %}
                  </ul>
                </li>
              {% endif %}
            </ul>
            <div class="toolbar ms-lg-3 d-flex align-items-center" role="toolbar">
              <button id="theme-toggle" class="btn btn-sm btn-outline-light me-2" onclick="toggleTheme()" aria-label="{% trans "Light Mode" %}">
                <svg aria-hidden="true" width="1.5rem" height="1.5rem">
                  <use href="#icon-sun"></use>
                </svg>
              </button>
              <form action="{% url 'set_language' %}" method="post" class="d-inline me-2">
                {% csrf_token %}
                <input name="next" type="hidden" value="{{ request.get_full_path }}">
                <select name="language" class="form-select form-select-sm d-inline w-auto language-select">
                  {% for lang_code, lang_name in LANGUAGES %}
                    <option value="{{ lang_code }}" {% if lang_code == LANGUAGE_CODE %}selected{% endif %}>{{ lang_code|slice:":2"|upper }}</option>
                  {% endfor %}
                </select>
              </form>
              <a class="btn btn-sm btn-outline-light position-relative user-info-trigger" href="{% if request.user.is_authenticated %}{% url 'admin:index' %}{% else %}{{ login_url }}{% endif %}" aria-label="{% if request.user.is_authenticated %}{% trans "Admin" %}{% else %}{% trans "Login" %}{% endif %}">
                <svg aria-hidden="true" width="1.5rem" height="1.5rem">
                  <use href="#icon-person"></use>
                </svg>
                {% if request.user.is_authenticated %}
                <div class="user-info-tooltip">
                  {{ request.user.username }} - {% if request.user.is_staff %}{% trans "Staff" %}{% else %}{% trans "Not staff" %}{% endif %}
                </div>
                {% endif %}
              </a>
              <button id="share-button" class="btn btn-sm btn-outline-light ms-2" type="button" aria-label="{% trans 'Share' %}">
                <svg aria-hidden="true" width="1.5rem" height="1.5rem">
                  <use href="#icon-share"></use>
                </svg>
              </button>
            </div>
          </div>
        </div>
      </nav>
      {% block content %}{% endblock %}
    </div>
    {% if chat_enabled %}
    <div
      id="chat-widget"
      class="chat-widget"
      data-path="{{ chat_socket_path }}"
      data-session-storage-key="pages.chat.session"
      data-connected-text="{% trans 'Connected' %}"
      data-connecting-text="{% trans 'Connecting…' %}"
      data-disconnected-text="{% trans 'Disconnected' %}"
      data-unread-text="{% trans 'New' %}"
      data-open-text="{% trans 'Need help?' %}"
      data-close-text="{% trans 'Close chat' %}"
      data-session-label="{% trans 'Session' %}"
      data-empty-text="{% trans 'Say hello to start the conversation.' %}"
      data-error-text="{% trans 'We could not send your message. Please retry.' %}"
      data-staff-join-text="{% trans 'A staff member joined the chat.' %}"
      data-staff-leave-text="{% trans 'A staff member left the chat.' %}"
      data-visitor-join-text="{% trans 'You joined the chat.' %}"
      data-visitor-leave-text="{% trans 'You left the chat.' %}"
      data-staff="{% if request.user.is_authenticated and request.user.is_staff %}true{% else %}false{% endif %}"
    >
      <button
        type="button"
        class="chat-toggle"
        data-chat-toggle
        aria-expanded="false"
        aria-controls="chat-drawer"
        aria-label="{% trans 'Need help?' %}"
      >
        <span class="chat-toggle-icon" aria-hidden="true">
          <svg viewBox="0 0 24 24" focusable="false" aria-hidden="true">
            <path
              fill="currentColor"
              d="M12 3c-4.97 0-9 3.582-9 8 0 1.93.78 3.69 2.08 5.08-.097.86-.43 2.348-1.4 3.734a.75.75 0 00.902 1.133c2.115-.633 3.422-1.522 4.09-2.073A10.63 10.63 0 0012 19c4.97 0 9-3.582 9-8s-4.03-8-9-8z"
            ></path>
          </svg>
        </span>
        <span class="chat-toggle-label">{% trans "Need help?" %}</span>
        <span class="chat-unread" data-chat-unread hidden>{% trans "New" %}</span>
      </button>
      <div
        class="chat-overlay"
        data-chat-overlay
        role="presentation"
        hidden
      >
        <section
          id="chat-drawer"
          class="chat-drawer"
          data-chat-drawer
          role="dialog"
          aria-modal="true"
          aria-labelledby="chat-title"
          aria-live="polite"
          aria-label="{% trans 'Support chat' %}"
          tabindex="-1"
        >
          <header class="chat-header">
            <div>
              <h2 class="mb-0" id="chat-title">{% trans "Support" %}</h2>
              <small data-chat-status>{% trans "Connecting…" %}</small>
            </div>
            <button type="button" class="btn-close" data-chat-close aria-label="{% trans 'Close chat' %}"></button>
          </header>
          <div
            class="chat-messages"
            data-chat-messages
            role="log"
            aria-live="polite"
            aria-relevant="additions"
          ></div>
          <form class="chat-form" data-chat-form>
            <label class="visually-hidden" for="chat-message-input">{% trans "Message" %}</label>
            <textarea
              id="chat-message-input"
              class="form-control"
              data-chat-input
              rows="2"
              maxlength="2000"
              placeholder="{% trans 'Type your message…' %}"
              required
            ></textarea>
            <div class="chat-actions">
              <span class="chat-session-hint text-muted" data-chat-session-hint></span>
              <button type="submit" class="btn btn-primary">{% trans "Send" %}</button>
            </div>
          </form>
        </section>
      </div>
    </div>
    {% endif %}
    <button
      type="button"
      id="user-story-toggle"
      class="user-story-toggle"
      aria-haspopup="dialog"
      aria-controls="user-story-overlay"
      aria-expanded="false"
      aria-label="{% trans 'Share your feedback' %}"
    >
      <svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
        <path
          fill="currentColor"
          fill-rule="evenodd"
          d="M11.049 2.927a1 1 0 011.902 0l1.563 4.813a1 1 0 00.95.69h5.063c.969 0 1.371 1.24.588 1.81l-4.096 2.977a1 1 0 00-.364 1.118l1.563 4.813c.3.921-.755 1.688-1.54 1.118l-4.096-2.977a1 1 0 00-1.175 0l-4.096 2.977c-.784.57-1.838-.197-1.539-1.118l1.563-4.813a1 1 0 00-.364-1.118L2.445 10.24c-.783-.57-.38-1.81.588-1.81h5.063a1 1 0 00.95-.69l1.563-4.813z"
          clip-rule="evenodd"
        ></path>
      </svg>
      <span class="visually-hidden">{% trans 'Share your feedback' %}</span>
    </button>
    <div
      id="user-story-overlay"
      class="user-story-overlay"
      role="dialog"
      aria-modal="true"
      aria-labelledby="user-story-title"
      hidden
    >
      <div class="user-story-card card" tabindex="-1">
        <div class="card-header d-flex justify-content-between align-items-start">
          <div>
            <h5 class="card-title mb-1" id="user-story-title">{% trans 'Please provide feedback!' %}</h5>
            <p class="card-subtitle text-muted small mb-0">{% trans 'Tell us how this page worked for you.' %}</p>
          </div>
          <button type="button" class="btn-close" aria-label="{% trans 'Close' %}" data-feedback-close></button>
        </div>
        <div class="card-body">
          <form id="user-story-form" method="post" action="{% url 'pages:user-story-submit' %}">
            {% csrf_token %}
            <input type="hidden" name="path" value="{{ request.get_full_path|default:'/' }}">
          {% if request.user.is_authenticated %}
            <div class="mb-3">
              <label for="user-story-name" class="form-label">{% trans 'Username' %}</label>
              <input
                type="text"
                class="form-control"
                id="user-story-name"
                name="name"
                maxlength="40"
                value="{{ request.user.username|slice:':40' }}"
                readonly
              >
              <div class="form-text">
                {% blocktrans with username=request.user.username %}
                  We'll include your username "{{ username }}" with this feedback. We may contact you via email if your feedback is utilized.
                {% endblocktrans %}
              </div>
            </div>
          {% else %}
            <div class="mb-3">
              <label for="user-story-name" class="form-label">{% trans 'Email address' %}</label>
              <input
                type="email"
                class="form-control"
                id="user-story-name"
                name="name"
                maxlength="40"
                placeholder="{% trans 'name@example.com' %}"
                autocomplete="email"
                inputmode="email"
                required
              >
              <div class="form-text">{% trans 'We may contact you via email if your feedback is utilized.' %}</div>
            </div>
          {% endif %}
            <div class="mb-3">
              <span class="form-label d-block">{% trans 'Your experience on this page' %}</span>
              <div class="user-story-feedback-options">
                <div class="user-story-rating" role="radiogroup" aria-labelledby="user-story-title">
                  <input type="radio" id="user-story-rating-5" name="rating" value="5" required>
                  <label for="user-story-rating-5" title="{% trans 'Excellent' %}" aria-label="{% trans '5 stars' %}">★</label>
                  <input type="radio" id="user-story-rating-4" name="rating" value="4">
                  <label for="user-story-rating-4" title="{% trans 'Great' %}" aria-label="{% trans '4 stars' %}">★</label>
                  <input type="radio" id="user-story-rating-3" name="rating" value="3">
                  <label for="user-story-rating-3" title="{% trans 'Good' %}" aria-label="{% trans '3 stars' %}">★</label>
                  <input type="radio" id="user-story-rating-2" name="rating" value="2">
                  <label for="user-story-rating-2" title="{% trans 'Okay' %}" aria-label="{% trans '2 stars' %}">★</label>
                  <input type="radio" id="user-story-rating-1" name="rating" value="1">
                  <label for="user-story-rating-1" title="{% trans 'Needs improvement' %}" aria-label="{% trans '1 star' %}">★</label>
                </div>
                <input type="hidden" name="take_screenshot" value="1">
                {% if request.user.is_authenticated %}
                  <div class="form-check user-story-clipboard">
                    <input
                      class="form-check-input"
                      type="checkbox"
                      id="user-story-copy-report"
                      name="copy_report"
                      value="1"
                    >
                    <label class="form-check-label" for="user-story-copy-report">{% trans 'Copy to clipboard' %}</label>
                  </div>
                {% endif %}
              </div>
            </div>
            <div class="mb-3">
              <label for="user-story-comments" class="form-label">{% trans 'Detailed comments / feedback' %}</label>
              <textarea
                class="form-control"
                id="user-story-comments"
                name="comments"
                rows="4"
                maxlength="400"
                placeholder="{% trans 'Share details about your experience (max 400 characters)' %}"
                required
              ></textarea>
              <div class="form-text">
                <span id="user-story-char-count">0</span>/400
              </div>
            </div>
            <button type="submit" class="btn btn-primary w-100 py-2">
              {% trans 'Submit feedback' %}
            </button>
            <div id="user-story-success" class="alert alert-success user-story-alert mt-3 d-none" role="status">
              {% trans 'Thank you! Your feedback has been sent.' %}
            </div>
            <div id="user-story-error" class="alert alert-danger user-story-alert mt-3 d-none" role="alert"></div>
          </form>
        </div>
      </div>
    </div>
    <div class="modal fade" id="shareModal" tabindex="-1" aria-labelledby="shareModalLabel" aria-hidden="true">
      <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="shareModalLabel">{% trans 'Share' %}</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Close' %}"></button>
          </div>
          <div class="modal-body text-center">
            <p class="mb-2">{% trans 'Link copied to clipboard' %}</p>
            <input type="text" class="form-control mb-3" id="share-url" readonly>
            <div id="share-qr"></div>
          </div>
        </div>
      </div>
    </div>
    {% render_footer %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/qrcodejs@1.0.0/qrcode.min.js"></script>
    {% if chat_enabled %}
    <script src="{% static 'pages/js/chat.js' %}" defer></script>
    {% endif %}
    <script>
      function setTheme(theme, persist = true) {
        document.documentElement.setAttribute('data-bs-theme', theme);
        if (persist) {
          localStorage.setItem('theme', theme);
        }
        const toggle = document.getElementById('theme-toggle');
        const icon = toggle.querySelector('use');
        toggle.setAttribute('aria-label', theme === 'dark' ? '{% trans "Light Mode" %}' : '{% trans "Dark Mode" %}');
        icon.setAttribute('href', theme === 'dark' ? '#icon-sun' : '#icon-moon');
        icon.setAttribute('xlink:href', theme === 'dark' ? '#icon-sun' : '#icon-moon');

        const navbar = document.querySelector('nav.navbar');
        const buttons = document.querySelectorAll('.toolbar .btn');
        if (theme === 'light') {
          navbar.classList.remove('navbar-dark', 'bg-dark');
          navbar.classList.add('navbar-light', 'bg-body');
          buttons.forEach(btn => {
            btn.classList.remove('btn-outline-light');
            btn.classList.add('btn-outline-dark');
          });
        } else {
          navbar.classList.remove('navbar-light', 'bg-body');
          navbar.classList.add('navbar-dark', 'bg-dark');
          buttons.forEach(btn => {
            btn.classList.remove('btn-outline-dark');
            btn.classList.add('btn-outline-light');
          });
        }
      }

      function toggleTheme() {
        const current = document.documentElement.getAttribute('data-bs-theme') || 'dark';
        setTheme(current === 'dark' ? 'light' : 'dark');
      }

      (function() {
        const saved = localStorage.getItem('theme');
        if (saved) {
          setTheme(saved);
          return;
        }
        setTheme('dark', false);
      })();

      function syncDebugToolbarTheme() {
        const button = document.getElementById('djToggleThemeButton');
        if (!button) {
          return;
        }
        const apply = () => {
          if (localStorage.getItem('theme')) {
            return;
          }
          const djdtTheme = localStorage.getItem('djdt.user-theme');
          if (!djdtTheme) {
            return;
          }
          const resolved = djdtTheme === 'auto'
            ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
            : djdtTheme;
          setTheme(resolved);
        };
        button.addEventListener('click', () => {
          setTimeout(apply);
        });
        apply();
      }

      window.addEventListener('load', syncDebugToolbarTheme);
    </script>
    <script>
      (function() {
        const dropdownItems = Array.from(document.querySelectorAll('.nav-item.dropdown'));
        if (!dropdownItems.length) {
          return;
        }

        const hideItem = item => {
          const menu = item.querySelector('.dropdown-menu');
          item.classList.remove('show');
          if (menu) {
            menu.classList.remove('show');
          }
          item.dataset.clickOpen = 'false';
        };

        const showItem = item => {
          const menu = item.querySelector('.dropdown-menu');
          item.classList.add('show');
          if (menu) {
            menu.classList.add('show');
          }
        };

        const closeOthers = current => {
          dropdownItems.forEach(other => {
            if (other !== current) {
              hideItem(other);
            }
          });
        };

        dropdownItems.forEach(item => {
          const link = item.querySelector('.nav-link');
          const menu = item.querySelector('.dropdown-menu');
          if (!link || !menu) {
            return;
          }

          item.dataset.clickOpen = 'false';

          link.addEventListener('click', event => {
            event.preventDefault();
            event.stopPropagation();

            const isAlreadyOpen = item.classList.contains('show') && item.dataset.clickOpen === 'true';
            closeOthers(item);

            if (isAlreadyOpen) {
              hideItem(item);
            } else {
              showItem(item);
              item.dataset.clickOpen = 'true';
            }
          });

          if (window.matchMedia('(hover: hover)').matches) {
            item.addEventListener('mouseenter', () => {
              if (item.dataset.clickOpen !== 'true') {
                closeOthers(item);
                showItem(item);
              }
            });
            item.addEventListener('mouseleave', () => {
              if (item.dataset.clickOpen !== 'true') {
                hideItem(item);
              }
            });
          }
        });

        document.addEventListener('click', event => {
          dropdownItems.forEach(item => {
            if (item.classList.contains('show') && !item.contains(event.target)) {
              hideItem(item);
            }
          });
        });
      })();
    </script>
      <script>
        document.querySelectorAll('.user-info-trigger').forEach(btn => {
          const tooltip = btn.querySelector('.user-info-tooltip');
          if (!tooltip) {
            return;
          }
          btn.addEventListener('mouseenter', () => {
            tooltip.style.display = 'block';
          });
          btn.addEventListener('mouseleave', () => {
            tooltip.style.display = 'none';
          });
        });
      </script>
      <script>
        document.querySelectorAll('.language-select').forEach(select => {
          select.addEventListener('change', () => {
            const form = select.form;
            const data = new FormData(form);
            fetch(form.action, { method: 'POST', body: data }).then(() => {
              const next = form.querySelector('input[name="next"]').value || '/';
              window.location.href = next;
            });
          });
        });
      </script>
      <script>
        (function() {
          const btn = document.getElementById('share-button');
          const modalEl = document.getElementById('shareModal');
          if (!btn || !modalEl) {
            return;
        }
        const modal = new bootstrap.Modal(modalEl);
        btn.addEventListener('click', () => {
          modal.show();
        });
        modalEl.addEventListener('shown.bs.modal', () => {
          const url = window.location.href;
          const input = document.getElementById('share-url');
          const qr = document.getElementById('share-qr');
          input.value = url;
          if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(url).catch(() => {});
          }
          qr.innerHTML = '';
          new QRCode(qr, {text: url, width: 128, height: 128});
        });
        })();
      </script>
      <script>
        (function() {
          const toggle = document.getElementById('user-story-toggle');
          const overlay = document.getElementById('user-story-overlay');
          const form = document.getElementById('user-story-form');
          if (!toggle || !overlay || !form) {
            return;
          }

          const closeBtn = overlay.querySelector('[data-feedback-close]');
          const card = overlay.querySelector('.user-story-card');
          const successAlert = document.getElementById('user-story-success');
          const errorAlert = document.getElementById('user-story-error');
          const commentField = document.getElementById('user-story-comments');
          const counter = document.getElementById('user-story-char-count');
          const submitBtn = form.querySelector('button[type="submit"]');
          const copyCheckbox = document.getElementById('user-story-copy-report');
          const defaultSuccessMessage = successAlert ? successAlert.textContent.trim() : '';
          const copySuccessMessage = '{% trans "Report copied to clipboard." %}';
          const copyFailureMessage = '{% trans "Feedback sent, but we could not copy the report to your clipboard." %}';
          const anonymousLabel = '{% trans "Anonymous" %}';
          let previousFocus = null;

          const buildToonReport = formData => {
            const rating = formData.get('rating') || 'n/a';
            const comments = (formData.get('comments') || '').toString().trim();
            const nameField = form.querySelector('#user-story-name');
            const username = nameField && nameField.value ? nameField.value.trim() : anonymousLabel;
            const path = formData.get('path') || window.location.pathname || '/';
            const userAgent = navigator.userAgent || 'unknown';
            const language = document.documentElement.lang || '';
            const timestamp = new Date().toISOString();

            return [
              '[TOON-FEEDBACK-REPORT]',
              `user=${username || anonymousLabel}`,
              `path=${path}`,
              `rating=${rating}/5`,
              'comments<<<',
              comments || '(none provided)',
              '>>>',
              `ua=${userAgent}`,
              language ? `lang=${language}` : null,
              `submitted_at=${timestamp}`,
              'screenshot=requested',
            ]
              .filter(Boolean)
              .join('\n');
          };

          const setCharCount = () => {
            if (counter && commentField) {
              counter.textContent = commentField.value.length;
            }
          };

          const resetAlerts = () => {
            if (successAlert) {
              successAlert.textContent = defaultSuccessMessage;
              successAlert.classList.add('d-none');
              successAlert.setAttribute('hidden', '');
            }
            if (errorAlert) {
              errorAlert.classList.add('d-none');
              errorAlert.textContent = '';
              errorAlert.setAttribute('hidden', '');
            }
          };

          const openOverlay = () => {
            if (!overlay.hasAttribute('hidden')) {
              return;
            }
            previousFocus = document.activeElement;
            overlay.removeAttribute('hidden');
            requestAnimationFrame(() => {
              overlay.classList.add('show');
              document.body.classList.add('user-story-open');
              toggle.setAttribute('aria-expanded', 'true');
              if (card) {
                card.focus();
              }
            });
          };

          const closeOverlay = () => {
            if (overlay.hasAttribute('hidden')) {
              return;
            }
            overlay.classList.remove('show');
            document.body.classList.remove('user-story-open');
            toggle.setAttribute('aria-expanded', 'false');
            setTimeout(() => {
              overlay.setAttribute('hidden', '');
              resetAlerts();
              form.reset();
              setCharCount();
              if (previousFocus) {
                previousFocus.focus();
              }
            }, 200);
          };

          toggle.addEventListener('click', () => {
            if (overlay.hasAttribute('hidden')) {
              openOverlay();
            } else {
              closeOverlay();
            }
          });

          if (closeBtn) {
            closeBtn.addEventListener('click', closeOverlay);
          }

          overlay.addEventListener('click', event => {
            if (event.target === overlay) {
              closeOverlay();
            }
          });

          document.addEventListener('keydown', event => {
            if (event.key === 'Escape' && !overlay.hasAttribute('hidden')) {
              closeOverlay();
            }
          });

          if (commentField) {
            commentField.addEventListener('input', setCharCount);
            setCharCount();
          }

          form.addEventListener('submit', async event => {
            event.preventDefault();
            resetAlerts();

            if (submitBtn) {
              submitBtn.disabled = true;
            }

            const formData = new FormData(form);
            const shouldCopy = Boolean(copyCheckbox && copyCheckbox.checked);
            const toonReport = shouldCopy ? buildToonReport(formData) : '';
            try {
              const response = await fetch(form.action, {
                method: 'POST',
                headers: {
                  'X-Requested-With': 'XMLHttpRequest',
                },
                body: formData,
              });

              if (response.ok) {
                form.reset();
                setCharCount();
                if (successAlert) {
                  successAlert.textContent = defaultSuccessMessage;
                  successAlert.classList.remove('d-none');
                  successAlert.removeAttribute('hidden');
                }

                if (shouldCopy && toonReport) {
                  try {
                    await navigator.clipboard.writeText(toonReport);
                    if (successAlert) {
                      successAlert.textContent = `${defaultSuccessMessage} ${copySuccessMessage}`;
                    }
                  } catch (copyError) {
                    if (errorAlert) {
                      errorAlert.textContent = copyFailureMessage;
                      errorAlert.classList.remove('d-none');
                      errorAlert.removeAttribute('hidden');
                    }
                  }
                }
              } else {
                const data = await response.json().catch(() => ({}));
                let message = '';
                if (data && data.errors) {
                  message = Object.values(data.errors)
                    .flat()
                    .join(' ');
                }
                if (!message) {
                  message = '{% trans "We could not submit your feedback. Please try again." %}';
                }
                if (errorAlert) {
                  errorAlert.textContent = message;
                  errorAlert.classList.remove('d-none');
                  errorAlert.removeAttribute('hidden');
                }
              }
            } catch (error) {
              if (errorAlert) {
                errorAlert.textContent = '{% trans "Network error. Please try again." %}';
                errorAlert.classList.remove('d-none');
                errorAlert.removeAttribute('hidden');
              }
            } finally {
              if (submitBtn) {
                submitBtn.disabled = false;
              }
            }
          });
        })();
      </script>
    {% if request.live_update_interval %}
    <script>
      {% block live_update_script %}
      setInterval(() => location.reload(), {{ request.live_update_interval }} * 1000);
      {% endblock %}
    </script>
    {% endif %}
    <svg xmlns="http://www.w3.org/2000/svg" class="base-svgs">
      <symbol viewBox="0 0 24 24" width="1.5rem" height="1.5rem" id="icon-moon"><path d="M0 0h24v24H0z" fill="none"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol>
      <symbol viewBox="0 0 24 24" width="1.5rem" height="1.5rem" id="icon-sun"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol>
      <symbol viewBox="0 0 24 24" width="1.5rem" height="1.5rem" id="icon-person"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></symbol>
      <symbol viewBox="0 0 24 24" width="1.5rem" height="1.5rem" id="icon-share"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/></symbol>
      <symbol viewBox="0 0 24 24" width="1.5rem" height="1.5rem" id="icon-external"><path d="M0 0h24v24H0z" fill="none"/><path d="M14 3h7v7h-2V6.41l-9.29 9.3-1.42-1.42 9.3-9.29H14V3zm-2 4v2H5v10h10v-7h2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h7z"/></symbol>
      <symbol viewBox="0 0 24 24" width="1.5rem" height="1.5rem" id="icon-lock"><path d="M0 0h24v24H0z" fill="none"/><path d="M12 17a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2 2 2 0 0 0-2 2v3a2 2 0 0 0 2 2zm6-8h-1V7a5 5 0 0 0-10 0v2H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2zm-3 0H9V7a3 3 0 0 1 6 0v2z"/></symbol>
      <symbol viewBox="0 0 24 24" width="1.5rem" height="1.5rem" id="icon-star"><path d="M0 0h24v24H0z" fill="none"/><path d="m12 17.27 5.18 3.11-1.64-5.92L20.5 9.5l-6.09-.52L12 3l-2.41 5.98-6.09.52 4.96 4.96-1.64 5.92z"/></symbol>
    </svg>
    {% if request.user.is_authenticated and request.user.is_staff %}
    {% include "core/version_check.html" %}
    {% endif %}
    {% block extra_scripts %}{% endblock %}
  </body>
</html>
