/* === Base Styles === */

/* === Layout === */

/* === Topbar === */

/* === Sidebar === */

/* === Content === */
/* === Base Styles === */
/* From: contact.css */
.info-block {
  background-color: #1a1a2b;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  padding: 1rem;
  font-size: 0.85rem;
  color: #ccc;
}

.info-title {
  font-weight: bold;
  font-size: 0.95rem;
  margin-bottom: 0.8rem;
  color: #fff;
}

.info-line {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0.0rem 0;
  line-height: 1.2;
}

.info-line a {
  color: #50fa7b;
  text-decoration: none;
}

.info-line a:hover {
  text-decoration: underline;
}

/* === Desktop Styles === */
/* From: templeta-desktop.css */
html,
body {
  height: 100%;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: sans-serif;
  background-color: #f9f9f9;
  color: #333;
}

.topbar {
  background-color: #000;
  color: #fff;
  padding: 0.5rem 1rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: sticky;
  top: 0;
  z-index: 1000;
}

.topbar-left {
  display: flex;
  align-items: center;
}

.topbar h1 {
  font-size: 1.2rem;
  margin: 0 0 0 0.5rem;
}

.topbar nav a {
  color: #fff;
  margin-left: 1rem;
  text-decoration: none;
  font-size: 0.9rem;
}

.menu-toggle {
  display: none;
  font-size: 1.4rem;
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
}

.layout {
  display: grid;
  grid-template-columns: 20% 1fr; /* hoanghd3 */
  min-height: calc(100vh - 50px);
}

.content {
  padding: 1rem;
  width: 100%;
  max-width: none;
  overflow-x: hidden;
}

.breadcrumb {
  font-size: 0.9rem;
  margin-bottom: 1rem;
  color: #666;
}

.breadcrumb a {
  color: #666;
  text-decoration: none;
}

.breadcrumb a:hover {
  text-decoration: underline;
}

.pagination {
  display: flex;
  justify-content: space-between;
  margin-top: 2rem;
  padding-top: 1rem;
  border-top: 1px solid #ddd;
}

.pagination a {
  background: #eee;
  padding: 6px 12px;
  border-radius: 4px;
  text-decoration: none;
  color: #333;
}

.pagination a:hover {
  background: #ddd;
}

.footer {
  text-align: center;
  margin-top: 2rem;
  padding: 2rem 0rem 4rem 0rem;
  font-size: 1rem;
  font-weight: 500;
  color: #333;
  border-top: 1px solid #ccc;
  /* background-color: #fdfdfd; */
}

img {
  max-width: 100%;
}

pre {
  overflow-x: auto;
  white-space: pre;
}

pre code {
  display: block;
  white-space: pre;
  word-break: break-word;
  min-width: 100%;
}

.code-block-wrapper {
  position: relative;
  margin-bottom: 1rem;
}

.code-block-wrapper pre {
  margin: 0;
  overflow-x: auto;
  background: #f4f4f4;
  padding: 1rem;
  border-radius: 6px;
}

.code-block-wrapper pre code {
  display: block;
  min-width: 100%;
  white-space: pre;
}

.copy-btn {
  position: absolute;
  /* top: 8px; */
  right: 8px;
  z-index: 10;
  padding: 4px 8px;
  font-size: 0.75rem;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  opacity: 0.7;
  transition: opacity 0.2s ease;
}

.copy-btn:hover {
  opacity: 1;
}

.sidebar-header {
  text-align: center;
  /* margin-bottom: 2rem; */
}

.sidebar-header h2 {
  font-size: 1.3rem;
  margin-bottom: 0.4rem;
  color: #fff;
}

.sidebar-header p {
  font-size: 0.85rem;
  color: #bbb;
  margin: 0;
}

details summary {
  cursor: pointer;
  font-weight: bold;
  color: #50fa7b;
  margin-bottom: 0.5rem;
}

.tool-group {
  list-style: none;
  padding-left: 1rem;
  margin: 0 0 1rem 0;
}

.tool-group li {
  margin: 0.3rem 0;
}

.tool-group a {
  color: #fff;
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.95rem;
}

.tool-group a:hover {
  text-decoration: underline;
}

.subcat {
  color: #ccc;
  font-size: 0.9rem;
  margin: 0.6rem 0 0.2rem;
}

.tool-subgroup summary {
  cursor: pointer;
  font-weight: bold;
  font-size: 0.95rem;
  margin-top: 0.8rem;
  padding-left: 0.2rem;
  color: #ccc;
}

.tool-subgroup[open] summary {
  color: #fff;
}

.sidebar-search {
  /* was a flat 1rem regardless of whether #content-search-hint is shown
     (owner-reported 2026-09: still a visible gap between the search box
     and New folder/New file even with the hint correctly hidden) - kept
     small here so the two sit right next to each other by default, and
     .content-search-hint's own margin-top is what pushes New folder/File
     down when the hint actually appears. */
  margin-bottom: 0;
}

.sidebar-search input {
  width: 100%;
  padding: 0.6rem 0.8rem;
  font-size: 0.9rem;
  border-radius: 999px;
  border: 1px solid #ccc;
  outline: none;
  background-color: #f9f9f9;
  color: #333;
  font-family: inherit;
}

.sidebar-search input:focus {
  border-color: #50fa7b;
  background-color: #fff;
}

.qr-wrapper {
  margin-left: 2%;
}

.qr-img {
  width: 200px;
  border-radius: 16px;
}

.qr-note {
  color: #666;
  font-size: 0.9rem;
  margin-top: 0.5rem;
}

.menu-left {
  position: absolute;
  left: 0.5rem;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* the flex gap above already spaces it from the next item - the button's
   own margin-right (needed elsewhere it's used without a flex gap) would
   otherwise stack on top and push it noticeably farther from the Admin
   button than every other gap in this row. */
.topbar-right .theme-toggle { margin-right: 0; }

.desktop-links {
  display: flex;
  gap: 1rem;
  color: #fff;
  text-decoration: none;
  font-size: 0.85rem;
}

/* From: slidebar.css */
.sidebar {
    font-family: 'Segoe UI', system-ui, sans-serif;
    background-color: #1e1e2f;
    color: #ccc;
    padding: 0.7rem;
    height: 100%;
    overflow-y: auto;
  }

  .sidebar-header h2 {
    margin: 0;
    font-size: 1.3rem;
    color: #ffffff;
  }

  .sidebar-header p {
    margin: 0.25rem 0 1rem 0;
    font-size: 0.85rem;
    color: #999;
  }

  .sidebar select {
    width: 100%;
    padding: 6px 12px;
    border-radius: 999px;
    font-size: 0.9rem;
    border: none;
    background-color: #fff;
    color: #333;
    font-family: inherit;
    margin-bottom: 1rem;
  }

  .sidebar-search input {
    width: 100%;
    padding: 8px;
    border-radius: 8px;
    border: none;
    font-size: 0.9rem;
    /* was 1.2rem - a SECOND, separate bottom margin stacking on top of
       .sb-new-actions's own margin-top below, making that gap bigger than
       the one above the search box (owner-reported 2026-09: wanted both
       gaps equal). Zeroed so .sb-new-actions's margin-top is the ONLY
       thing controlling this gap, matching how .sidebar select's
       margin-bottom is the ONLY thing controlling the gap above. */
    margin-bottom: 0;
    background-color: #2b2b3d;
    color: #000000;
  }

.sidebar > details {
  margin-bottom: 1rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

/* Loại bỏ border cho nhóm con (subcategory) */
.sidebar details.tool-subgroup {
  border: none;
  margin-bottom: 0.5rem;
  padding-bottom: 0; 
}

.sidebar::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 2px;
  height: 100%;
  /* background: linear-gradient(to bottom, rgba(255,255,255,0.05), rgba(255,255,255,0.15)); */
}

  .sidebar summary {
    font-weight: bold;
    font-size: 0.95rem;
    cursor: pointer;
    color: #eee;
    padding: 4px 0;
  }

  .sidebar ul {
    list-style: none;
    padding-left: 1rem;
    margin-top: 0.4rem;
  }

  .sidebar li {
    margin-bottom: 0.3rem;
  }

  .sidebar a {
    color: #ccc;
    text-decoration: none;
    font-size: 0.88rem;
    display: block;
    padding: 2px 0;
  }

  .sidebar a:hover {
    color: #50fa7b;
  }

  .sidebar .tool-subgroup summary {
    font-size: 0.9rem;
    font-weight: 600;
    color: #bbb;
  }

  .sidebar .info-block {
    margin-top: 2rem;
    padding: 1rem;
    background-color: #273845;
    border-radius: 8px;
    font-size: 0.85rem;
    line-height: 1.5;
    color: #ccc;
  }

  .sidebar .info-block a {
    color: #ffffff;
    text-decoration: none;
  }

  .sidebar .info-block a:hover {
    text-decoration: underline;
  }

.sidebar .info-block {
  margin-top: 2rem;
  background-color: #1a1a2b;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  padding: 1rem;
  font-size: 0.85rem;
  color: #ccc;
}

.sidebar .info-title {
  font-weight: bold;
  font-size: 0.95rem;
  margin-bottom: 0.5rem;
  color: #fff;
}

.sidebar .info-block ul {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

.sidebar .info-block li {
  margin-bottom: 0.4rem;
}

/* === Mobile Styles === */
/* From: logo.css */
.header {
  width: 100%;
  display: flex;
  justify-content: center;
}

.site-logo {
  display: flex;
  align-items: center;
}

.site-title {
  text-decoration: none;
  color: inherit;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.logo-icon {
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.logo-text {
  font-size: 1.1rem;
  margin: 0;
  color: #fff;
  white-space: nowrap;
}

@media (max-width: 768px) {
  .header {
    justify-content: center;
  }
  .site-logo {
    width: auto;
  }
  .logo-text {
    font-size: 1rem;
  }
}

@media (max-width: 768px) {
  .topbar {
    display: flex;
    flex-direction: column;
    align-items: center;
  }

  .topbar-left {
    width: 100%;
    display: flex;
    justify-content: center;
    margin-bottom: 0.5rem;
  }

  .menu-left {
    position: absolute;
    left: 1rem;
    top: 1rem;
  }

  .topbar-right {
    text-align: center;
  }
}

/* From: template-mobile.css */
@media (max-width: 768px) {
  .layout {
    display: block;
  }

  .topbar nav {
    display: none;
  }

  .sidebar h2 {
    display: block;
    font-size: 1.1rem;
    margin: 2rem auto 0rem auto;
  }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%; /* hoanghd3 */
    height: 100%;
    padding-top: 50px;
    z-index: 999;
    background-color: #1e1e2f;
    transform: translateX(-100%);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .sidebar.active {
    transform: translateX(0);
    width: 100%;
  }

  .menu-toggle {
    display: block;
    position: absolute;
    left: 1rem;
    top: 50%;
    transform: translateY(-50%);
    font-size: 1.4rem;
    background: none;
    border: none;
    color: #fff;
    cursor: pointer;
  }

  .content {
    padding: 1rem;
  }

  .topbar h1 {
    font-size: 1rem;
  }

  .topbar-left {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    position: relative;
  }

  .topbar-left h1 {
    margin-left: 0;
  }

  .qr-wrapper {
    margin-left: auto;
    margin-right: auto;
    text-align: center;
  }

  .qr-note {
    margin-left: 0;
  }

  .desktop-links {
    display: none;
  }

  .topbar {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0.6rem 1rem;
    text-align: center;
  }

  .topbar-left {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    width: 100%;
  }

  .menu-left {
    position: absolute;
    left: 0.5rem;
    top: 50%;
    transform: translateY(-50%);
  }



      .topbar {
        background-color: #000;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0.5rem 1rem;
        position: sticky;
        top: 0;
        z-index: 1000;
      }

      .center-logo {
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        display: flex;
        align-items: center;
        gap: 0.5rem;
      }

      .site-title {
        display: flex;
        align-items: center;
        text-decoration: none;
        color: inherit;
        gap: 0.5rem;
      }

      .logo-icon {
        width: 32px;
        height: 32px;
        object-fit: contain;
      }

      .logo-text {
        font-size: 1.2rem;
        margin: 0;
        color: #fff;
        white-space: nowrap;
      }

      .menu-left {
        z-index: 2;
      }

      .topbar-right {
        z-index: 2;
        display: flex;
        align-items: center;
        gap: 1rem;
      }

      @media (max-width: 768px) {
        .center-logo {
          position: static;
          transform: none;
          margin: 0 auto;
        }
        .topbar {
          flex-direction: column;
        }
        .topbar-right {
          justify-content: center;
          margin-top: -0.5rem;
        }
      }
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

@media (max-width: 768px) {
  .topbar-left {
    justify-content: center;
    width: 100%;
    position: relative;
  }

  .site-title {
    margin: 0 auto;
  }


/* === Breadcrumb === */

/* === Pagination === */

/* === Footer === */

/* === Code Blocks === */

/* === Copy Button === */

/* === QR === */

/* === Logo === */

/* === Responsive === */
}

/* === Sidebar Tree Indentation by Level === */
.sidebar details {
  margin: 0.4rem 0;
}

/* Indentation for folder summaries */
.sidebar summary {
  font-weight: bold;
  font-size: 0.95rem;
  color: #eee;
  padding: 4px 0;
  margin-left: 0rem; /* reset default */
}

/* Indentation using inline styles from Jinja: do nothing extra */

/* List styling */
.sidebar ul {
  list-style: none;
  margin: 0.2rem 0;
  padding-left: 0;
}

.sidebar li {
  margin: 0.2rem 0;
}

/* File links */
.sidebar a {
  color: #ccc;
  text-decoration: none;
  font-size: 0.88rem;
  display: block;
  padding: 2px 0;
  transition: color 0.2s ease;
}

.sidebar a:hover {
  color: #50fa7b;
}

html {
  zoom: 100%;
}

.note-card {
  flex: 1 1 260px;
  background-color: #ffffff;
  padding: 1rem;
  border-radius: 12px;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.08);
  transition: all 0.25s ease;
  border: 1px solid transparent;
}

/* Hover effect */
.note-card:hover {
  border: 1px solid rgba(0, 200, 150, 0.4);
  box-shadow: 0 0 0 2px rgba(0, 200, 150, 0.2), 0 0 10px rgba(0, 200, 150, 0.15);
  background-color: #f9f9f9;
  cursor: pointer;
}

/* Folder (summary) */
.tree-summary {
  font-weight: 500;
  font-size: 1.02rem;
  color: #000;
  padding: 2px 6px;
  border-radius: 8px;
  transition: all 0.2s ease;
  border: 1px solid transparent;
  box-shadow: 0 0 6px rgba(0, 0, 0, 0.02);
  display: inline-block;
  line-height: 1.2;
}

.tree-summary:hover {
  background-color: #f8f8f8;
  border: 1px solid rgba(0, 200, 150, 0.3);
  box-shadow: 0 0 0 1px rgba(0, 200, 150, 0.15);
  color: #000;
  cursor: pointer;
}

/* File (a tag) */
.tree-file {
  display: inline-block;
  font-size: 0.93rem;
  color: #222;
  text-decoration: none;
  padding: 1px 8px;
  border-radius: 8px;
  transition: all 0.2s ease;
  border: 1px solid transparent;
  line-height: 1.3;
}

.tree-file:hover {
  background-color: #f9f9f9;
  border: 1px solid rgba(0, 200, 150, 0.3);
  box-shadow: 0 0 0 1px rgba(0, 200, 150, 0.1);
  text-decoration: none;
}

/* === Layout Scroll Patch (Applied by Assistant) === */
html, body {
  height: 100%;
  margin: 0;
  overflow: hidden; /* ✅ Ensures independent scroll for sidebar and content */
}

.layout-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  /* mobile browsers (Safari in particular): 100vh sizes against the
     LARGEST possible viewport (toolbar collapsed), not the one actually
     visible - so with the toolbar showing, the bottom of the page (article
     footer, sidebar's last item) renders below the fold and needs an extra
     manual scroll to reach. 100dvh tracks the CURRENT visible viewport;
     unsupported browsers just skip this whole declaration and keep 100vh. */
  height: 100dvh;
}

.layout {
  display: flex;
  flex: 1;
  overflow: hidden;
}

.sidebar {
  width: 21%;
  flex-shrink: 0;
  overflow-y: auto;
  background-color: #1e1e2f;
  color: #ccc;
}

.content {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
  padding-bottom: calc(1rem + env(safe-area-inset-bottom));   /* home-indicator clearance */
}

.tree-line:hover {
  background-color: #f5f7f9;
}

/* === Markdown list indent fix (content area) === */
.article.md ul,
.article.md ol {
  padding-left: 1.6rem !important;  /* thụt cấp 1 */
  margin-left: 0 !important;
}

.article.md ul ul,
.article.md ol ul,
.article.md ul ol,
.article.md ol ol {
  padding-left: 1.25rem !important; /* thụt cấp 2+ */
}

.article.md li { margin: .2rem 0; }


/* Thêm CSS để làm nổi bật bài đang xem (Tùy chọn) */
/* Làm nổi bật link bài viết đang đọc */
.active-link {
    color: #007bff !important; /* Màu xanh hoặc màu thương hiệu của bạn */
    font-weight: bold;
    border-radius: 4px;
    padding: 2px 5px;
}

/* Đảm bảo summary không bị mất định dạng khi mở */
details[open] > summary {
    color: #fff;
}

#sidebar-container {
    height: calc(100vh - 60px); /* Chiều cao trừ đi phần topbar của bạn */
    overflow-y: auto;           /* Cho phép cuộn bên trong sidebar */
    position: relative;
}

/* Áp dụng cho các link bài viết trong sidebar */
#sidebar-container ul li a {
    display: block;          /* Bắt buộc để thuộc tính width/overflow hoạt động */
    white-space: nowrap;     /* Không cho phép chữ xuống dòng */
    overflow: hidden;        /* Ẩn phần chữ bị thừa ra ngoài lề */
    text-overflow: ellipsis; /* Biến phần chữ thừa thành dấu "..." */
    width: 100%;             /* Chiếm hết chiều ngang của li */
    padding-right: 5px;      /* Khoảng cách nhỏ để không chạm sát lề phải */
    text-decoration: none;
}

/* Đảm bảo danh sách (ul) không bị tràn */
#sidebar-container ul {
    overflow: hidden;
    padding-right: 10px;
}


/* Ẩn thanh cuộn cho Chrome, Safari và Opera */
.sidebar::-webkit-scrollbar,
#sidebar-container::-webkit-scrollbar,
.content::-webkit-scrollbar {
    display: none;
}

/* Ẩn thanh cuộn cho IE, Edge và Firefox */
.sidebar,
#sidebar-container,
.content {
    -ms-overflow-style: none;  /* IE and Edge */
    scrollbar-width: none;  /* Firefox */
}

/* Định vị nút trong header của sidebar */
.sidebar-header {
    position: relative;
}

#sidebar-collapse-btn {
    position: absolute;
    top: 0;
    right: 0;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.2);
    color: #ffffff;
    border-radius: 4px;
    cursor: pointer;
    padding: 2px 6px;
    font-size: 12px;
    transition: all 0.2s;
}

#sidebar-collapse-btn:hover {
    background: rgba(80, 250, 123, 0.2);
}

/* Hiệu ứng thu nhỏ Sidebar */
.sidebar {
    transition: width 0.3s ease, padding 0.3s ease;
    overflow-x: hidden;
}

.sidebar.collapsed {
    width: 0 !important;
    padding: 0 !important;
    min-width: 0 !important;
}

/* Ẩn resizer khi sidebar đóng */
.sidebar.collapsed + #sidebar-resizer {
    display: none;
}

/* --- Nút mở Sidebar (Expand Button) --- */
#sidebar-expand-btn {
    position: fixed; /* Cố định vị trí trên màn hình */
    top: 70px;       /* Cách đỉnh một chút, ngang tầm với header cũ */
    left: 0;
    z-index: 999;    /* Đảm bảo nó nằm trên cùng */
    
    /* Giao diện "mờ" và tinh tế */
    background-color: rgba(26, 27, 38, 0.8); /* Màu nền tối bán trong suốt */
    color: #ffffff;  /* Màu xanh theme */
    border: 1px solid rgba(80, 250, 123, 0.3);
    border-left: none; /* Bỏ viền trái để trông dính vào mép */
    border-radius: 0 6px 6px 0; /* Bo tròn góc phải */
    padding: 10px 5px;
    font-size: 14px;
    cursor: pointer;
    box-shadow: 2px 2px 5px rgba(0,0,0,0.2);

    /* Mặc định ẩn đi */
    opacity: 0;
    pointer-events: none; /* Không thể bấm khi đang ẩn */
    transform: translateX(-100%); /* Dịch chuyển ra ngoài màn hình */
    transition: all 0.3s ease;
}

/* Hiệu ứng hover cho nút mở */
#sidebar-expand-btn:hover {
    background-color: rgba(80, 250, 123, 0.2);
    padding-left: 8px; /* Hiệu ứng nhích nhẹ khi rê chuột */
}

/* --- Kích hoạt trạng thái --- */

/* Khi body có class này, nút mở sẽ hiện ra */
body.sidebar-is-collapsed #sidebar-expand-btn {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(0); /* Trượt vào màn hình */
}

/* Đồng thời, khi body có class này, sidebar sẽ đóng lại */
body.sidebar-is-collapsed .sidebar {
    width: 0 !important;
    padding: 0 !important;
    min-width: 0 !important;
}

/* Ẩn luôn thanh resizer cho gọn */
body.sidebar-is-collapsed #sidebar-resizer {
    display: none;
}

/* ============================================================================
   REFACTOR ADDITIONS (2026-07) — everything below was added during the
   cleanup; the rules above are the original stylesheet.
   Sections: 1) auth pages  2) sidebar resize/overlay  3) responsive audit
   ============================================================================ */

/* --- 1) Auth pages (login/register), matching the dark night theme ------- */
.auth-page {
  min-height: 100vh;
  height: auto;
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1rem;
  overflow: auto;
  font-family: sans-serif;
  color: #eafcf1;
  background-color: #050f0a;
  background-image:
    linear-gradient(#16301f 1px, transparent 1px),
    linear-gradient(90deg, #16301f 1px, transparent 1px);
  background-size: 56px 56px;
}

.auth-box {
  background-color: #0c2114;
  border: 1px solid #215436;
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45);
  padding: 2rem;
  width: 100%;
  max-width: 340px;
}

.auth-brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  margin-bottom: 1.2rem;
}

.auth-brand img {
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.auth-brand span {
  color: #fff;
  font-weight: bold;
  letter-spacing: 0.18em;
  text-shadow: 0 0 20px rgba(0, 229, 126, 0.35);
}

.auth-box h2 {
  margin: 0 0 1rem;
  color: #fff;
}

.auth-box input {
  width: 100%;
  min-height: 44px;              /* comfortable tap target */
  padding: 10px 12px;
  margin-bottom: 0.8rem;
  border: 1px solid #215436;
  border-radius: 10px;
  background: #0a1b11;
  color: #eafcf1;
  font-size: 16px;               /* prevents iOS zoom-on-focus */
  transition: border-color 0.25s, box-shadow 0.25s;
}

.auth-box input::placeholder { color: #54785f; }

.auth-box input:focus {
  outline: none;
  border-color: #00e57e;
  box-shadow: 0 0 0 3px rgba(0, 229, 126, 0.15);
}

.auth-box button {
  width: 100%;
  min-height: 44px;
  padding: 10px;
  border: 1px solid #215436;
  border-radius: 10px;
  background: rgba(0, 229, 126, 0.12);
  color: #00e57e;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: 0.2s;
}

.auth-box button:hover {
  background: rgba(0, 229, 126, 0.22);
  border-color: #00e57e;
  box-shadow: 0 0 12px rgba(0, 229, 126, 0.3);
}

.auth-box p {
  text-align: center;
  font-size: 0.9rem;
  color: #8fb8a1;
}

.auth-box a { color: #50fa7b; text-decoration: none; }
.auth-box a:hover { text-decoration: underline; }

.auth-home-link {
  display: block;
  text-align: center;
  margin-top: 1rem;
  padding: 10px 0;               /* ≥44px tap area */
  font-size: 0.9rem;
}

.auth-box .flashes {
  margin: 1rem 0 0;
  padding-left: 1.1rem;
  color: #ff5d6c;
  font-size: 0.9rem;
}

/* Chrome/Safari autofill painted the inputs white-on-white — pin the
   dark surface and light text (inset shadow is the only reliable way) */
.auth-box input:-webkit-autofill,
.auth-box input:-webkit-autofill:hover,
.auth-box input:-webkit-autofill:focus {
  -webkit-box-shadow: 0 0 0 1000px #0a1b11 inset;
  box-shadow: 0 0 0 1000px #0a1b11 inset;
  -webkit-text-fill-color: #eafcf1;
  caret-color: #eafcf1;
  border: 1px solid #215436;
  transition: background-color 99999s ease-in-out 0s;
}

.auth-switch {
  text-align: center;
  margin: 0.4rem 0 0;
  font-size: 0.92rem;
  color: #8fb8a1;
}

.auth-switch a {
  display: inline-block;
  padding: 8px 6px;       /* comfortable tap target */
  font-weight: 600;
}

/* --- 2) Sidebar: drag-to-resize (desktop) + overlay (mobile/tablet) ------ */

/* Drag handle between sidebar and content (desktop only) */
#sidebar-resizer {
  flex: 0 0 6px;
  cursor: col-resize;
  background: transparent;
  position: relative;
  transition: background 0.2s;
}

/* thin visible affordance line, brightens on hover/drag */
#sidebar-resizer::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 2px;
  width: 2px;
  background: rgba(255, 255, 255, 0.08);
  transition: background 0.2s;
}

#sidebar-resizer:hover::after,
body.sidebar-resizing #sidebar-resizer::after {
  background: rgba(80, 250, 123, 0.8);
}

/* no width animation while actively dragging (avoids lag/jank) */
body.sidebar-resizing .sidebar { transition: none !important; }
body.sidebar-resizing { user-select: none; -webkit-user-select: none; cursor: col-resize; }

/* Close (✕) button inside the sidebar — overlay mode only */
.sidebar-close-btn {
  display: none;
  position: absolute;
  top: 2.5rem;
  right: 0.6rem;
  width: 28px;
  height: 28px;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 8px;
  color: #fff;
  font-size: 0.85rem;
  cursor: pointer;
  z-index: 2;
}

.sidebar-close-btn:hover { background: rgba(80, 250, 123, 0.2); }

/* Dark scrim behind the overlay sidebar */
.sidebar-scrim {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  z-index: 998;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
}

/* Tablet & mobile (≤1024px): sidebar becomes a full-screen overlay.
   These rules sit at the end of the file so they win over the older
   768px-era rules above with equal specificity. */
@media (max-width: 1024px) {
  /* NOTE: .layout must STAY flex here. The page scrolls inside
     main.content (html/body are overflow:hidden), which only gets a
     constrained, scrollable height as a flex child. The sidebar is
     position:fixed in overlay mode, so flex simply gives main the full
     row. (The old stylesheet's mobile `display:block` rule was dead —
     overridden by a later `display:flex` — which is why old mobile
     scrolled; making block actually apply froze scrolling.) */

  .menu-toggle { display: block; }

  /* smooth momentum scrolling for the article column on iOS */
  main.content { -webkit-overflow-scrolling: touch; }

  /* no drag-resize, no desktop collapse chrome in overlay mode */
  #sidebar-resizer { display: none; }
  #sidebar-expand-btn { display: none !important; }
  #sidebar-collapse-btn { display: none; }
  body.sidebar-is-collapsed .sidebar { width: 100% !important; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    width: 100% !important;   /* overrides any persisted desktop width */
    height: 100%;
    height: 100dvh;   /* same toolbar-collapse issue as .layout-container */
    padding-top: 50px;
    padding-bottom: env(safe-area-inset-bottom);   /* home-indicator clearance */
    z-index: 999;
    background-color: #1e1e2f;
    transform: translateX(-100%);
    transition: transform 0.3s ease;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }

  .sidebar.active { transform: translateX(0); }

  .sidebar-close-btn { display: flex; }

  .sidebar-scrim { display: block; }
  .sidebar-scrim.visible { opacity: 1; pointer-events: auto; }

  /* comfortable tap targets in the tree */
  #sidebar-container ul li a { padding: 10px 5px 10px 0; }
  #sidebar-container summary { padding: 10px 0; }
}

@media (min-width: 1025px) {
  .sidebar-scrim { display: none !important; }
  .sidebar-close-btn { display: none !important; }
}

/* ---------- folder panel (owner 2026-08): right-edge slide-out listing
   sibling articles in the SAME folder as the current one. Independent
   from .sidebar - works identically on desktop AND mobile (no breakpoint
   gating), always an overlay so it never reflows page layout. ---------- */
.folder-panel-tab {
  position: fixed; top: 50%; right: 0; transform: translateY(-50%);
  z-index: 997; background: #1e1e2f; color: #ccc; border: 1px solid rgba(255, 255, 255, .14);
  border-right: none; border-radius: 10px 0 0 10px; padding: 12px 10px;
  cursor: pointer; font-size: 15px; box-shadow: -2px 0 10px rgba(0, 0, 0, .25);
}
.folder-panel-tab:hover { background: #2b2b3d; color: #fff; }
.folder-panel-scrim {
  display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, .55);
  z-index: 999; opacity: 0; pointer-events: none; transition: opacity .25s ease;
}
.folder-panel-scrim.visible { display: block; opacity: 1; pointer-events: auto; }
.folder-panel {
  position: fixed; top: 0; right: 0; height: 100%; height: 100dvh; width: 300px; max-width: 86vw;
  background: #1e1e2f; color: #ccc; z-index: 1000; transform: translateX(100%);
  transition: transform .25s ease; display: flex; flex-direction: column;
  box-shadow: -4px 0 24px rgba(0, 0, 0, .4); padding-bottom: env(safe-area-inset-bottom);
}
.folder-panel.open { transform: translateX(0); }
.folder-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid rgba(255, 255, 255, .1); flex-shrink: 0;
}
.folder-panel-head b { color: #fff; font-size: 15px; }
.folder-panel-x { background: none; border: none; color: #999; font-size: 16px; cursor: pointer; padding: 2px 4px; }
.folder-panel-x:hover { color: #fff; }
.folder-panel-list { overflow-y: auto; padding: 8px 0; flex: 1; -webkit-overflow-scrolling: touch; }
.folder-panel-item, .folder-panel-sub {
  display: block; padding: 9px 16px; color: #ccc; text-decoration: none;
  font-size: 13.5px; border-left: 3px solid transparent;
}
.folder-panel-item:hover, .folder-panel-sub:hover { background: rgba(255, 255, 255, .06); color: #fff; }
.folder-panel-item.current {
  background: rgba(0, 229, 126, .1); border-left-color: #00e57e; color: #fff; font-weight: 600;
}
.folder-panel-sub { color: #9fb4c9; }
.folder-panel-empty { padding: 16px; color: #777; font-size: 13px; }
/* owner 2026-09: the base rules above were hardcoded to one fixed dark
   palette with no theme awareness at all - coincidentally readable against
   html.night's own dark background, but a jarring dark slab dropped onto
   the light ivory theme-light page. Same "give every new-ish component its
   own per-theme colors" discipline as everything else touched this
   session, just applied late to a component built earlier. */
html.night .folder-panel-tab, html.night .folder-panel {
  background: var(--n-panel2); color: var(--n-muted); border-color: var(--n-line2);
}
html.night .folder-panel-tab:hover { background: var(--n-panel); color: var(--n-brand); border-color: var(--n-brand); }
html.night .folder-panel-head { border-bottom-color: var(--n-line); }
html.night .folder-panel-head b { color: var(--n-ink); }
html.night .folder-panel-x { color: var(--n-dim); }
html.night .folder-panel-x:hover { color: var(--n-ink); }
html.night .folder-panel-item, html.night .folder-panel-sub { color: var(--n-muted); }
html.night .folder-panel-item:hover, html.night .folder-panel-sub:hover {
  background: rgba(0, 229, 126, .08); color: var(--n-brand);
}
html.night .folder-panel-item.current {
  background: rgba(0, 229, 126, .12); border-left-color: var(--n-brand); color: var(--n-ink);
}
html.night .folder-panel-sub { color: var(--n-dim); }
html.night .folder-panel-empty { color: var(--n-dim); }

/* ---------- prev/next article nav (owner 2026-08), bottom of article -
   built from the same folder-siblings data as the panel above. ---------- */
.article-nav {
  display: flex; gap: 12px; margin: 32px 0 8px; padding-top: 16px;
  border-top: 1px solid rgba(255, 255, 255, .1);
}
/* Same recurring bug class as #download-docx/.share-tool-panel this
   session: an author-stylesheet `display` on the same element beats the
   browser's own [hidden]{display:none} UA rule regardless of specificity,
   so folder-panel.js setting navEl.hidden=true (no prev/next sibling to
   show - e.g. a single-article folder, or the homepage, which has no
   folder-nav concept at all) still left an empty flex box with just its
   border-top visible - an extra divider line stacking with .footer's own
   border-top right above it. */
.article-nav[hidden] { display: none; }
.article-nav-prev, .article-nav-next {
  flex: 1; display: flex; flex-direction: column; gap: 4px; padding: 12px 14px;
  border: 1px solid rgba(255, 255, 255, .12); border-radius: 10px;
  text-decoration: none; color: #ccc; min-width: 0;
}
.article-nav-next { text-align: right; align-items: flex-end; }
.article-nav-prev:hover, .article-nav-next:hover { background: rgba(255, 255, 255, .06); color: #fff; border-color: rgba(255, 255, 255, .22); }
.article-nav-label { font-size: 11.5px; text-transform: uppercase; letter-spacing: .04em; color: #888; }
.article-nav-title {
  font-size: 14px; font-weight: 600; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; max-width: 100%;
}
@media (max-width: 600px) {
  .article-nav-title { white-space: normal; }
}

/* --- 3) Responsive audit fixes (375 / 768 / 1024 / 1440) ----------------- */

/* Edit / Copy page HTML / Download .md button row above the article.
   Right-aligned on desktop (was an inline style); on phones flex-end left
   the row pinned hard against the right edge while everything else in the
   article (breadcrumb, title, body text) is flush left - the mismatch read
   as "misaligned". Wrap + left-align instead, matching the rest of the
   page's flow. */
.page-tools { display: flex; justify-content: flex-end; gap: 8px; margin: 8px 0 12px; }
@media (max-width: 768px) {
  .page-tools { justify-content: flex-start; flex-wrap: wrap; }
}

/* images never overflow the article column */
.md img,
.markdown-body img,
.html-wrapper img {
  max-width: 100%;
  height: auto;
  cursor: zoom-in;
}

/* click-to-zoom popup (article-fix.js) - shows the image at its real source
   resolution, uncapped by the column/.img-embed width limits. Styled to
   match the admin Image Library's own popup (.imglib-lightbox/.imglib-panel)
   instead of a full-bleed photo-viewer: a framed card on a dimmed backdrop. */
.img-lb-overlay {
  position: fixed;
  inset: 0;
  z-index: 3000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 28px;
  background: rgba(0, 0, 0, 0.7);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.img-lb-overlay.show { opacity: 1; pointer-events: auto; }
.img-lb-panel {
  display: inline-flex;   /* shrink-wraps the image's actual rendered size - no dead space around it */
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  max-width: 98vw;
  max-height: 98vh;
  background: #0a1b11;
  border: 1px solid #215436;
  border-radius: 12px;
  padding: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  overflow: hidden;   /* panel now hugs the image, so this just gives clean rounded corners */
}
.img-lb-panel img {
  display: block;
  border-radius: 6px;   /* light rounding, matches the panel's */
  cursor: zoom-in;   /* clicking enlarges the image itself (JS sets explicit width/height), doesn't close */
  transition: width 0.2s ease, height 0.2s ease;
}
.img-lb-close {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: transparent;
  color: #8fb8a1;
  border: 1px solid #215436;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.img-lb-close:hover { color: #eafcf1; border-color: #00e57e; }

@media (max-width: 768px) {
  /* Owner 2026-08: two prior attempts at "wide tables scroll sideways
     instead of stretching the page" both forced `display: block` (with
     width:100%, then width:fit-content) directly on the <table> itself -
     re-purposing a table element as a block box is exactly what kept
     causing a phantom empty box on narrow/short tables (the block box
     painted its background/border across the full forced width while the
     rows only rendered at their real, narrower width - two different
     width strategies, same root cause, same visible bug).

     Fixed properly this time by never touching the table's own display/
     width at all: static/js/article-fix.js's wrapTablesForScroll() wraps
     every plain table (see run()) in a plain .md-table-scroll div, and
     ONLY that wrapper gets overflow-x - the table inside keeps its normal
     table layout and 100% width, which already sizes itself correctly
     either way (shrinks with short content, scrolls via the wrapper when
     wider than the screen). This mirrors .sl-conv-table-wrap, the exact
     same wrapper-div pattern already proven for the conv-table feature. */
  .md-table-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* standalone HTML tool/article pages get a scroll gutter too */
  .html-wrapper { overflow-x: auto; }

  /* readable body text (≥14px) and code on phones */
  .md { font-size: 14px; }
  .md pre code { font-size: 13px; }

  /* embedded audio players (english articles) fit the column */
  .md audio,
  .html-wrapper audio,
  audio { max-width: 100%; width: 100%; }

  /* topbar controls stay reachable and don't overlap */
  .topbar-right { flex-wrap: wrap; justify-content: center; row-gap: 0.3rem; }
  .login-info a { display: inline-block; padding: 8px 4px; }
  .menu-toggle { min-width: 44px; min-height: 44px; }
  .theme-toggle { min-width: 40px; min-height: 40px; }

  /* copy buttons remain tappable */
  .copy-all-btn { min-height: 44px; }
  .codebox-header .copy-btn { min-height: 32px; }
}

/* --- 4) Web docs editor + sidebar context menu (2026-07 feature) --------- */
.ctx-menu {
  position: fixed;
  z-index: 2000;
  min-width: 220px;
  background: #1a1a2b;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5);
  padding: 4px;
}

.ctx-item {
  display: block;
  padding: 10px 12px;
  border-radius: 6px;
  color: #eafcf1;
  text-decoration: none;
  font-size: 0.92rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ctx-item:hover { background: rgba(0, 229, 126, 0.15); color: #50fa7b; }

#new-doc-btn {
  display: inline-block;
  margin-top: 6px;
  padding: 6px 10px;
  border: 1px solid #215436;
  border-radius: 8px;
  color: #50fa7b;
  text-decoration: none;
  font-size: 0.85rem;
}

#new-doc-btn:hover { background: rgba(0, 229, 126, 0.15); border-color: #00e57e; }

.editor-page {
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background-color: #101018;
  color: #eafcf1;
}

.editor-shell {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 10px;
  gap: 8px;
}

.editor-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}

#editor-meta { display: flex; gap: 8px; flex: 1; min-width: 240px; align-items: center; }
#editor-docnav { display: flex; gap: 6px; align-items: center; }
#editor-docnav-pos { font-size: 12.5px; color: #8fb8a1; white-space: nowrap; }
#editor-docnav button:disabled { opacity: .35; cursor: not-allowed; }

#editor-meta input {
  min-height: 40px;
  padding: 8px 10px;
  border: 1px solid #215436;
  border-radius: 8px;
  background: #0a1b11;
  color: #eafcf1;
  font-size: 15px;
}

#editor-meta #new-folder { flex: 1.2; min-width: 140px; }
#editor-meta #new-name { flex: 1; min-width: 120px; }

.editor-crumb { font-size: 0.95rem; color: #8fb8a1; }
.editor-crumb strong { color: #fff; }

.editor-actions { display: flex; gap: 8px; align-items: center; }

.editor-tab, .editor-save, .editor-view-link {
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid #215436;
  border-radius: 8px;
  background: transparent;
  color: #eafcf1;
  cursor: pointer;
  font-size: 0.9rem;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}

.editor-tab.active { background: rgba(0, 229, 126, 0.15); color: #50fa7b; border-color: #00e57e; }
.editor-save { background: rgba(0, 229, 126, 0.2); color: #00e57e; font-weight: 600; }
.editor-save:hover { box-shadow: 0 0 12px rgba(0, 229, 126, 0.3); }

.editor-status { padding: 8px 12px; border-radius: 8px; font-size: 0.9rem; }
.editor-status.ok { background: rgba(0, 229, 126, 0.12); color: #50fa7b; }
.editor-status.err { background: rgba(255, 93, 108, 0.12); color: #ff5d6c; }

.editor-panes { flex: 1; display: flex; gap: 10px; min-height: 0; }

.editor-write-pane { flex: 1; min-height: 0; display: flex; }

/* VSCode-style line-number gutter: a plain <textarea> can't report per-line
   render positions once text wraps, so wrap is turned OFF (wrap="off" +
   white-space:pre below) - that keeps 1 logical line = 1 visual line,
   which is the only way the gutter numbers can stay honestly in sync via
   just scrollTop mirroring (updateGutter() in editor.js). Long lines
   scroll horizontally instead, same tradeoff VSCode's default makes. */
#editor-gutter {
  flex: 0 0 auto;
  min-width: 38px;
  padding: 14px 8px 14px 0;
  border: 1px solid #215436;
  border-right: none;
  border-radius: 10px 0 0 10px;
  background: #08150d;
  color: #3f6b4f;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14px;
  line-height: 1.6;
  text-align: right;
  overflow: hidden;
  user-select: none;
  white-space: pre;
}

#editor-text {
  flex: 1;
  min-height: 0;
  min-width: 0;
  resize: none;
  padding: 14px;
  border: 1px solid #215436;
  border-radius: 0 10px 10px 0;
  background: #0a1b11;
  color: #eafcf1;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 14px;
  line-height: 1.6;
  white-space: pre;
  overflow-x: auto;
}

#editor-text:focus { outline: none; border-color: #00e57e; }
#editor-write-pane:focus-within #editor-gutter { border-color: #00e57e; }

.editor-preview {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 14px 18px;
  border: 1px solid #215436;
  border-radius: 10px;
  background: #071409;          /* same night surface as the site content */
  color: #eafcf1;
}

/* the night theme keys most rules off html.night; the editor page is
   always dark, so pin readable body text explicitly */
.editor-preview p, .editor-preview li, .editor-preview td { color: #eafcf1; }
.editor-preview h1, .editor-preview h2, .editor-preview h3 {
  color: #00e57e;
  text-shadow: 0 0 22px rgba(0, 229, 126, 0.22);
}
.editor-preview a { color: #3fd9d0; }
.editor-preview strong { color: #c9f24b; }
.editor-preview pre {
  background: #04120a !important;
  color: #d7f5e4;
  border: 1px solid #16301f;
  border-radius: 8px;
  padding: 12px;
}
.editor-preview code:not(pre code) {
  background: rgba(0, 229, 126, 0.1);
  border: 1px solid #215436;
  color: #c9f24b;
  border-radius: 6px;
  padding: 1px 6px;
}
.editor-preview table { border: 1px solid #215436; background: #0a1b11; }
.editor-preview th { color: #00e57e; background: #0c2114; }
.editor-preview th, .editor-preview td { border: 1px solid #16301f; padding: 6px 10px; }
.editor-preview blockquote {
  background: #0a1b11;
  border-left: 4px solid #00e57e;
  color: #8fb8a1;
  margin: 8px 0;
  padding: 8px 12px;
}

@media (max-width: 900px) {
  .editor-panes { flex-direction: column; }
  .editor-actions { width: 100%; justify-content: flex-end; }
}


/* --- 5) Category listing redesign + themed tree view (2026-07) ----------- */
.cat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 1.2rem;
}

.cat-head h1 { margin: 0; }

html.night .cat-head h1 {
  color: var(--n-ink);
  text-shadow: 0 0 22px rgba(0, 229, 126, 0.25);
}

.view-toggle-form { margin: 0; }

/* ===== folder intro (owner 2026-09): a README.md sitting directly in a
   category/subfolder renders here, ABOVE the usual subfolder+article card
   grid (never replacing it - see _find_readme's docstring). .cat-readme-wrap
   is the ONE shared panel (border/background) holding BOTH the intro text
   AND the listing below it - owner-reported 2026-09: as two separate
   blocks (intro panel, then bare listing underneath) it read as
   disconnected; a single frame with a divider reads as one "about this
   folder" section instead. Only exists in the DOM at all when there's a
   README (category.html: empty class otherwise), so a folder without one
   renders exactly as before - no border, no padding, nothing added. */
.cat-readme-wrap {
  background: #f5f7f9;
  border: 1px solid #e2e5e9;
  border-left: 4px solid #0b62ff;
  border-radius: 10px;
  padding: 1.1rem 1.4rem 1.4rem;
  margin-bottom: 1.5rem;
}
.cat-readme { margin-bottom: 0; }
.cat-readme a { text-decoration: none; }
.cat-readme a:hover { text-decoration: underline; }
.cat-readme-sep { border: 0; border-top: 1px dashed #d8dbe0; margin: 1.1rem 0; }
html.night .cat-readme-wrap {
  background: var(--n-panel2);
  border-color: var(--n-line2);
  border-left-color: var(--n-brand);
}
html.night .cat-readme-sep { border-top-color: var(--n-line2); }

.view-toggle {
  min-height: 40px;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid #ccc;
  background: #f5f5f5;
  color: #333;
  cursor: pointer;
  font-size: 0.9rem;
  transition: 0.2s;
}

html.night .view-toggle {
  background: var(--n-panel);
  color: var(--n-muted);
  border-color: var(--n-line2);
}

html.night .view-toggle:hover {
  color: var(--n-brand);
  border-color: var(--n-brand);
  box-shadow: 0 0 12px rgba(0, 229, 126, 0.3);
}

/* section header = folder breadcrumb */
.cat-section { margin-top: 2rem; }
.cat-section h2 {
  font-size: 1.05rem;
  font-weight: 600;
  margin: 0 0 0.8rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px dashed #ddd;
}
html.night .cat-section h2 { border-bottom-color: var(--n-line2); }
.cat-crumb { color: #888; font-weight: 500; }
.cat-crumb-last { color: #222; }
html.night .cat-crumb { color: var(--n-dim); }
html.night .cat-crumb-last { color: var(--n-lime); }
.cat-sep { margin: 0 0.45rem; color: #bbb; }
html.night .cat-sep { color: var(--n-line2); }

/* ===== sidebar "search content" hint + /search results page (owner 2026-09) ===== */
/* No `display` property here on purpose - visibility is fully owned by the
   element's own inline style (toggled in main.js), never by a class rule.
   An earlier version set `display: block` here + relied on the `hidden`
   attribute/[hidden] selector to hide it, which an inline `style="display:
   none"` on the element in sidebar.html now makes moot - but keeping NO
   competing `display` here at all means there is nothing left that could
   ever fight the inline toggle again (owner-reported 2026-09: even an
   explicit `.content-search-hint[hidden] { display: none }` guard wasn't
   reliably winning, worth eliminating the ambiguity entirely rather than
   chasing cascade order further). */
.content-search-hint { margin-top: 4px; font-size: 0.82rem; color: #888; text-decoration: none; }
.content-search-hint:hover { text-decoration: underline; }
html.night .content-search-hint { color: var(--n-muted); }
html.night .content-search-hint:hover { color: var(--n-brand); }

.search-page-form { display: flex; gap: 8px; margin: 1rem 0 1.4rem; max-width: 560px; }
.search-page-form input[type="text"] {
  flex: 1; padding: 8px 12px; border-radius: 8px; border: 1px solid #ccc; font-size: 1rem;
}
.search-page-meta { color: #666; margin-bottom: 1rem; }
.search-results { display: flex; flex-direction: column; gap: 1.3rem; }
.search-result-title { font-size: 1.05rem; font-weight: 600; text-decoration: none; color: #1a73e8; }
.search-result-title:hover { text-decoration: underline; }
.search-result-path { font-size: 0.82rem; color: #888; margin: 2px 0 4px; }
.search-result-snippet { margin: 0; color: #444; line-height: 1.55; }
.search-result-snippet mark { background: rgba(255, 214, 0, .5); color: inherit; border-radius: 2px; padding: 0 1px; }

html.night .search-page-form input[type="text"] {
  background: var(--n-panel2); color: var(--n-ink); border-color: var(--n-line2);
}
html.night .search-page-meta { color: var(--n-dim); }
html.night .search-result-title { color: var(--n-brand); }
html.night .search-result-path { color: var(--n-dim); }
html.night .search-result-snippet { color: var(--n-muted); }
html.night .search-result-snippet mark { background: rgba(0, 229, 126, .28); color: var(--n-ink); }

.cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1rem;
}

.cat-card {
  display: block;
  padding: 1rem 1.1rem;
  border: 1px solid #e2e2e2;
  border-radius: 12px;
  background: #fff;
  text-decoration: none;
  color: inherit;
}

.cat-card-title { font-weight: 700; font-size: 1.02rem; }
html.night .cat-card-title { color: var(--n-ink); }

.cat-card-desc {
  margin-top: 0.5rem;
  font-size: 0.88rem;
  line-height: 1.55;
  color: #666;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
html.night .cat-card-desc { color: var(--n-muted); }
html.night .cat-card:hover .cat-card-title { color: var(--n-brand); }

/* themed tree view (replaces the old inline light-gray colors) */
.tree-view { font-size: 0.95rem; }
.tree-branch { margin-left: 0.4rem; padding-left: 0.6rem; border-left: 1px dashed #ccc; }
.tree-branch.tree-root { margin-left: 0; padding-left: 0; border-left: none; }
html.night .tree-branch { border-left-color: var(--n-line2); }

.tree-line { line-height: 1.7; margin: 0.15rem 0; padding: 3px 6px; border-radius: 6px; }
.tree-folder { font-weight: 600; color: #333; }
.tree-folder-root { font-size: 1.05rem; }
html.night .tree-folder { color: var(--n-ink); }
html.night .tree-folder-root { color: var(--n-lime); text-shadow: 0 0 14px rgba(201, 242, 75, 0.2); }

.tree-doc { margin-left: 1.2rem; color: #555; }
.tree-doc a { text-decoration: none; color: inherit; }
html.night .tree-doc { color: var(--n-muted); }
html.night .tree-doc a:hover { color: var(--n-brand); text-shadow: 0 0 12px rgba(0, 229, 126, 0.5); }
html.night .tree-line:hover { background: rgba(0, 229, 126, 0.06); }

@media (max-width: 768px) {
  .cat-grid { grid-template-columns: 1fr; }
}


/* --- 6) Tablet topbar fix (769–1024px): the ☰ toggle was absolutely
   positioned (a phone-era rule) and sat on top of the logo, because the
   phone layout centers the logo in a column topbar but the tablet range
   kept the desktop left-aligned row. In this range the toggle becomes a
   normal flex item at the start of the row instead. ---------------------- */
@media (min-width: 769px) and (max-width: 1024px) {
  .menu-left {
    position: static;
    left: auto;
    top: auto;
  }

  .menu-toggle {
    position: static;
    transform: none;
    min-width: 44px;
    min-height: 44px;
    margin-right: 0.4rem;
  }
}


/* --- 6b) Phone topbar (≤768px): the centered logo could touch the
   absolutely-positioned ☰ on narrow screens (pre-existing in the original
   stylesheet). Reserve the toggle's width on both sides and let the title
   ellipsize instead of colliding. ---------------------------------------- */
@media (max-width: 768px) {
  .menu-toggle { z-index: 2; }

  .topbar-left {
    padding: 0 60px;
    box-sizing: border-box;
  }

  .site-title { max-width: 100%; overflow: hidden; }

  .logo-text {
    font-size: 1rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}


/* delete affordances (editor + context menu) */
.editor-del {
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid rgba(255, 93, 108, 0.5);
  border-radius: 8px;
  background: transparent;
  color: #ff5d6c;
  cursor: pointer;
  font-size: 0.9rem;
}

.editor-del:hover {
  background: rgba(255, 93, 108, 0.12);
  border-color: #ff5d6c;
  box-shadow: 0 0 12px rgba(255, 93, 108, 0.25);
}

.ctx-item-danger { color: #ff5d6c; }
.ctx-item-danger:hover { background: rgba(255, 93, 108, 0.12); color: #ff5d6c; }


/* flash categories on the auth pages (register success is NOT an error) */
.auth-box .flashes { padding-left: 0; list-style: none; }
.flash {
  margin-top: 0.8rem;
  padding: 10px 12px;
  border-radius: 10px;
  font-size: 0.9rem;
  border: 1px solid;
}
.flash-success {
  color: #50fa7b;
  border-color: rgba(0, 229, 126, 0.5);
  background: rgba(0, 229, 126, 0.1);
  box-shadow: 0 0 14px rgba(0, 229, 126, 0.15);
}
.flash-info, .flash-message {
  color: #3fd9d0;
  border-color: rgba(63, 217, 208, 0.4);
  background: rgba(63, 217, 208, 0.08);
}
.flash-error {
  color: #ff5d6c;
  border-color: rgba(255, 93, 108, 0.4);
  background: rgba(255, 93, 108, 0.1);
}

/* editor breadcrumb separators: "notes / report / 📝 ..." */
.editor-crumb .crumb-sep { margin: 0 0.45rem; color: #54785f; }

/* ===== Support chat widget (floating, bottom-right) ===== */
#support-fab {
  position: fixed; right: 22px; bottom: 22px; z-index: 1200;
  width: 56px; height: 56px; border-radius: 50%;
  border: 1px solid rgba(0, 229, 126, 0.55);
  background: linear-gradient(135deg, #00e57e, #3fd9d0);
  color: #04120a; font-size: 24px; cursor: pointer;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.45), 0 0 22px rgba(0, 229, 126, 0.35);
  transition: transform .15s ease, box-shadow .15s ease;
  display: flex; align-items: center; justify-content: center;
}
#support-fab:hover { transform: translateY(-2px) scale(1.05); }
#support-fab.open .support-fab-icon { transform: rotate(90deg); }
.support-fab-icon { transition: transform .2s ease; }

#support-panel {
  position: fixed; right: 22px; bottom: 90px; z-index: 1200;
  width: 340px; max-width: calc(100vw - 32px);
  max-height: min(560px, calc(100vh - 120px)); overflow-y: auto;
  background: linear-gradient(180deg, rgba(12, 33, 20, 0.99), rgba(10, 27, 17, 0.99));
  border: 1px solid #215436; border-radius: 16px; padding: 16px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55), 0 0 30px rgba(0, 229, 126, 0.08);
}
.support-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; margin-bottom: 10px; }
.support-title { font-weight: 700; color: #eafcf1; font-size: 16px; }
.support-sub { color: #8fb8a1; font-size: 12.5px; margin-top: 3px; }
#support-close {
  background: transparent; border: 1px solid #215436; color: #8fb8a1;
  border-radius: 8px; width: 28px; height: 28px; cursor: pointer; flex: 0 0 auto;
}
#support-close:hover { color: #eafcf1; border-color: #00e57e; }

.support-label { display: block; color: #8fb8a1; font-size: 12.5px; margin: 10px 0 4px; }
.support-label .req { color: #ff5d6c; }
.support-input {
  width: 100%; box-sizing: border-box;
  background: #0a1b11; color: #eafcf1;
  border: 1px solid #215436; border-radius: 10px;
  padding: 9px 11px; font-size: 14px; font-family: inherit;
  outline: none; transition: border-color .15s, box-shadow .15s;
}
.support-input:focus {
  border-color: #00e57e;
  box-shadow: 0 0 0 1px rgba(0, 229, 126, 0.35), 0 0 14px rgba(0, 229, 126, 0.18);
}
textarea.support-input { resize: vertical; min-height: 84px; }

/* honeypot: parked far off-screen, never display:none (bots skip those) */
#sp-website { position: absolute; left: -5000px; top: -5000px; height: 1px; width: 1px; opacity: 0; }

.support-send {
  width: 100%; margin-top: 14px; padding: 11px;
  background: linear-gradient(90deg, #00e57e, #3fd9d0);
  color: #04120a; font-weight: 700; font-size: 14px;
  border: none; border-radius: 10px; cursor: pointer;
  transition: filter .15s ease, transform .05s ease;
}
.support-send:hover { filter: brightness(1.08); }
.support-send:active { transform: translateY(1px); }
.support-send:disabled { opacity: .6; cursor: wait; }

.support-error {
  margin-top: 10px; padding: 9px 11px; border-radius: 10px; font-size: 13px;
  background: rgba(255, 93, 108, 0.1); border: 1px solid rgba(255, 93, 108, 0.45); color: #ff5d6c;
}
.support-done { text-align: center; padding: 18px 6px 6px; }
.support-done-icon { font-size: 40px; }
.support-done-text { color: #eafcf1; margin: 10px 0 4px; line-height: 1.5; }

@media (max-width: 520px) {
  #support-panel { right: 12px; left: 12px; width: auto; bottom: 84px; }
  #support-fab { right: 16px; bottom: 16px; }
}

/* ===== Support widget: menu + live chat ===== */
.support-option {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: #0a1b11; border: 1px solid #215436; border-radius: 12px;
  padding: 12px 14px; margin-top: 10px; cursor: pointer; text-align: left;
  color: #eafcf1; font-family: inherit; font-size: 14px;
  transition: border-color .15s, box-shadow .15s, transform .05s;
}
.support-option:hover {
  border-color: #00e57e;
  box-shadow: 0 0 14px rgba(0, 229, 126, 0.15);
}
.support-option:active { transform: translateY(1px); }
.support-option-icon { font-size: 20px; }
.support-option b { display: block; font-size: 14px; }
.support-option small { color: #8fb8a1; font-size: 12px; }

.support-offline-note {
  margin-top: 10px; padding: 9px 11px; border-radius: 10px; font-size: 12.5px;
  background: rgba(143, 184, 161, 0.08); border: 1px solid #215436; color: #8fb8a1;
  line-height: 1.5;
}
.support-offline-note a { color: #00e57e; }

#support-back-row { margin-top: 12px; text-align: center; }
#support-back { color: #8fb8a1; font-size: 12.5px; text-decoration: none; }
#support-back:hover { color: #00e57e; }

#chat-messages {
  height: 260px; overflow-y: auto; padding: 8px 2px;
  display: flex; flex-direction: column; gap: 8px;
  border: 1px solid #16301f; border-radius: 12px;
  background: rgba(10, 27, 17, 0.6); padding: 10px;
}
.chat-bubble {
  max-width: 82%; padding: 8px 12px; border-radius: 14px;
  font-size: 13.5px; line-height: 1.45; white-space: pre-wrap; word-break: break-word;
}
.chat-bubble.me {
  align-self: flex-end;
  background: linear-gradient(135deg, rgba(0, 229, 126, 0.22), rgba(63, 217, 208, 0.18));
  border: 1px solid rgba(0, 229, 126, 0.4); color: #eafcf1;
  border-bottom-right-radius: 4px;
}
.chat-bubble.agent {
  align-self: flex-start;
  background: #0c2114; border: 1px solid #215436; color: #eafcf1;
  border-bottom-left-radius: 4px;
}
.chat-inputrow { display: flex; gap: 8px; margin-top: 10px; align-items: flex-end; }
.chat-inputrow textarea { flex: 1; min-height: 40px; max-height: 110px; }
.chat-send-btn {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: 12px;
  background: linear-gradient(135deg, #00e57e, #3fd9d0); color: #04120a;
  border: none; font-size: 16px; cursor: pointer; font-weight: 700;
}
.chat-send-btn:hover { filter: brightness(1.08); }
.chat-send-btn:disabled { opacity: .5; cursor: not-allowed; }
#ch-website { position: absolute; left: -5000px; top: -5000px; height: 1px; width: 1px; opacity: 0; }

/* ===== Google sign-in button (auth pages) ===== */
.auth-divider {
  display: flex; align-items: center; gap: 10px;
  margin: 18px 0 14px; color: #54785f; font-size: 12.5px;
}
.auth-divider::before, .auth-divider::after {
  content: ""; flex: 1; height: 1px; background: #215436;
}
.google-btn {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; box-sizing: border-box; padding: 11px;
  background: #0a1b11; color: #eafcf1; text-decoration: none;
  border: 1px solid #215436; border-radius: 10px;
  font-size: 14px; font-weight: 600;
  transition: border-color .15s, box-shadow .15s, transform .05s;
}
.google-btn:hover {
  border-color: #00e57e;
  box-shadow: 0 0 14px rgba(0, 229, 126, 0.18);
}
.google-btn:active { transform: translateY(1px); }

/* ===== Admin console ===== */
.admin-body { background: #071409; color: #eafcf1; margin: 0; font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
.admin-top { display: flex; align-items: center; gap: 22px; padding: 12px 20px;
  background: #0c2114; border-bottom: 1px solid #215436; flex-wrap: wrap; }
.admin-brand { font-weight: 800; color: #00e57e; }
.admin-nav { display: flex; gap: 4px; flex: 1; }
.admin-nav a { color: #8fb8a1; text-decoration: none; padding: 7px 12px; border-radius: 8px; font-size: 14px; }
.admin-nav a:hover { color: #eafcf1; background: #0a1b11; }
.admin-nav a.on { color: #04120a; background: linear-gradient(90deg, #00e57e, #3fd9d0); font-weight: 700; }
.admin-me {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #8fb8a1;
  font-size: 13px;
}
.admin-me .theme-toggle { margin-right: 0; flex: 0 0 auto; }
.admin-me-user { display: flex; align-items: center; gap: 6px; color: #eafcf1; font-weight: 600; }
.admin-me a { color: #00e57e; text-decoration: none; }
.admin-me a:hover { text-decoration: underline; }
.admin-me a + a { border-left: 1px solid #215436; padding-left: 10px; }
.admin-main { max-width: 1100px; margin: 26px auto; padding: 0 20px; }
.admin-h1 { color: #00e57e; font-size: 24px; }
.admin-h2 { color: #3fd9d0; font-size: 18px; margin-top: 30px; }
.admin-hint { color: #8fb8a1; font-size: 13.5px; }
.admin-cards { display: flex; gap: 12px; flex-wrap: wrap; margin: 16px 0; }
.admin-card { display: flex; gap: 10px; align-items: center; padding: 14px 16px; min-width: 180px;
  background: #0c2114; border: 1px solid #215436; border-radius: 12px; }
.admin-card.off { border-color: rgba(255, 93, 108, 0.5); }
.admin-card small { display: block; color: #8fb8a1; font-size: 12px; max-width: 240px; }
.admin-card.stat b { font-size: 26px; color: #00e57e; }
.admin-table { width: 100%; border-collapse: collapse; margin-top: 14px; background: #0a1b11;
  border: 1px solid #16301f; border-radius: 12px; overflow: hidden; }
.admin-table th { text-align: left; font-size: 12px; text-transform: uppercase; color: #00e57e;
  background: #0c2114; padding: 10px 12px; border-bottom: 1px solid #215436; }
.admin-table td { padding: 10px 12px; border-bottom: 1px solid #16301f; font-size: 14px; vertical-align: middle; }
.admin-table tr:hover td { background: rgba(0, 229, 126, 0.04); }
.admin-input { background: #071409; color: #eafcf1; border: 1px solid #215436; border-radius: 8px;
  padding: 7px 10px; font-size: 13.5px; width: 100%; box-sizing: border-box; }
.admin-input:focus { outline: none; border-color: #00e57e; box-shadow: 0 0 0 1px rgba(0,229,126,.3); }
.mono { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 13px; }
.popup-banner-thumb { width: 120px; height: auto; border-radius: 6px; display: block; }
.flags label { display: block; color: #8fb8a1; font-size: 12.5px; white-space: nowrap; }
.row-actions { white-space: nowrap; }
/* Voice Profiles' Voice-ID cell mixes a fill-width <select> with a fixed
   ▶-preview button - plain `width:100%` on the select left no room for
   the button and squeezed it under the select's own dropdown arrow. */
.vp-voice-cell { display: flex; align-items: center; gap: 6px; }
.vp-voice-cell select.vp-voice { flex: 1; min-width: 0; width: auto; }
.vp-voice-cell .vp-listen { flex: none; }
.admin-btn { background: #0c2114; color: #eafcf1; border: 1px solid #215436; border-radius: 8px;
  padding: 7px 10px; font-size: 13px; cursor: pointer; margin: 1px; }
.admin-btn:hover { border-color: #00e57e; }
.admin-btn.danger:hover { border-color: #ff5d6c; color: #ff5d6c; }
.admin-tester { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.admin-tester .admin-input { width: 260px; }
.wpi-log {
  background: #0a1b11; color: #cfe9da; border: 1px solid #215436; border-radius: 8px;
  padding: 12px 14px; height: 420px; overflow-y: auto; white-space: pre-wrap;
  word-break: break-word; font-size: 12.5px; line-height: 1.55; margin-top: 14px;
}
#test-result { font-size: 14px; }
.admin-msg { position: fixed; bottom: 20px; right: 20px; padding: 12px 16px; border-radius: 10px;
  font-size: 14px; z-index: 500; }
.admin-msg.okk { background: rgba(0, 229, 126, .12); border: 1px solid rgba(0, 229, 126, .5); color: #50fa7b; }
.admin-msg.err { background: rgba(255, 93, 108, .12); border: 1px solid rgba(255, 93, 108, .5); color: #ff5d6c; }

/* ===== Admin picker & chips ===== */
.chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 6px; min-height: 4px; }
.chip { display: inline-flex; align-items: center; gap: 5px; background: #0c2114; border: 1px solid #215436;
  border-radius: 20px; padding: 3px 6px 3px 10px; font-size: 12.5px; }
.chip.all { border-color: #00e57e; color: #50fa7b; }
.chip.orphan { border-color: rgba(255, 193, 7, .6); color: #ffc107; }
.chip-x { background: none; border: none; color: #8fb8a1; cursor: pointer; font-size: 12px; padding: 0 3px; }
.chip-x:hover { color: #ff5d6c; }
.orphan-badge { color: #ffc107; font-size: 12px; cursor: help; }
.chosen-path { color: #3fd9d0; margin-left: 8px; }
.picker-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .55); z-index: 600;
  display: flex; align-items: center; justify-content: center; }
.picker-overlay[hidden] { display: none; } /* author display:flex must not defeat the hidden attribute */
.picker-box { width: min(560px, 94vw); max-height: 82vh; display: flex; flex-direction: column;
  background: #0a1b11; border: 1px solid #215436; border-radius: 14px; padding: 16px; gap: 10px;
  box-shadow: 0 18px 60px rgba(0, 0, 0, .5); }
.picker-head { display: flex; justify-content: space-between; align-items: center; color: #00e57e; }
.picker-all { color: #eafcf1; font-size: 14px; padding: 4px 2px; }
.picker-tree { overflow: auto; border: 1px solid #16301f; border-radius: 10px; padding: 8px; flex: 1; min-height: 200px; }
.picker-tree.disabled { opacity: .35; pointer-events: none; }
.picker-row { padding: 3px 0; font-size: 14px; display: flex; align-items: center; gap: 4px; }
.picker-row label { cursor: pointer; }
.picker-row.folder > label { font-weight: 600; }
.picker-caret { width: 16px; cursor: pointer; color: #8fb8a1; user-select: none; }
.picker-level { margin-left: 2px; font-size: 12px; opacity: .8; }
.picker-legend { font-size: 12px; color: #8fb8a1; }
.picker-foot { display: flex; justify-content: space-between; align-items: center; }
.admin-btn.primary { background: linear-gradient(90deg, #00e57e, #3fd9d0); color: #04120a; font-weight: 700; border: none; }

/* Edit link: no underline */
.edit-doc-btn, a.edit-doc-btn { text-decoration: none !important; }

/* topbar admin shortcut */
.topbar-admin-btn { color: #04120a !important; background: linear-gradient(90deg, #00e57e, #3fd9d0);
  padding: 4px 12px; border-radius: 999px; font-weight: 700; font-size: 13px;
  text-decoration: none; margin-right: 12px; }
.topbar-admin-btn:hover { box-shadow: 0 0 14px rgba(0,229,126,.45); }

/* topbar google avatar */
.topbar-avatar { width: 26px; height: 26px; border-radius: 50%; vertical-align: middle;
  margin-right: 6px; border: 1px solid #215436; }

/* ===== Recents (sidebar) ===== */
.recents-block { margin: 14px 0 4px; padding: 10px 12px; background: #0a1b11;
  border: 1px solid #16301f; border-radius: 12px; }
.recents-title { color: #3fd9d0; font-size: 12px; text-transform: uppercase;
  letter-spacing: .08em; margin-bottom: 6px; }
.recents-list { list-style: none; margin: 0; padding: 0; }
.recents-list li { padding: 3px 0; font-size: 13.5px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }

/* ===== public online pill ===== */
.online-pill { position: fixed; left: 16px; bottom: 16px; z-index: 300;
  display: flex; align-items: center; gap: 7px; padding: 7px 13px;
  background: rgba(10, 27, 17, .92); border: 1px solid #215436; border-radius: 999px;
  color: #cfe9da; font-size: 13px; backdrop-filter: blur(6px);
  box-shadow: 0 6px 22px rgba(0, 0, 0, .35); }
.online-dot { width: 8px; height: 8px; border-radius: 50%; background: #00e57e;
  box-shadow: 0 0 8px rgba(0, 229, 126, .8); animation: online-breath 2.4s ease-in-out infinite; }
@keyframes online-breath { 50% { opacity: .5; } }

/* ===== editor: draggable split divider ===== */
.editor-panes.split { position: relative; }
#pane-divider { width: 7px; cursor: col-resize; align-self: stretch;
  background: transparent; border-left: 1px solid #215436; margin: 0 1px;
  transition: border-color .15s; flex: 0 0 auto; }
#pane-divider:hover, #pane-divider.dragging { border-left-color: #00e57e; }

/* ===== site-wide flash toasts (fixes flashes stranded in the session) ===== */
.site-toasts { position: fixed; top: 74px; right: 18px; z-index: 700;
  display: flex; flex-direction: column; gap: 8px; max-width: min(380px, 90vw); }
.site-toast { padding: 11px 15px; border-radius: 10px; font-size: 14px;
  background: rgba(10, 27, 17, .95); border: 1px solid #215436; color: #cfe9da;
  box-shadow: 0 8px 26px rgba(0, 0, 0, .4); backdrop-filter: blur(6px);
  transition: opacity .6s, transform .6s; }
.site-toast.success { border-color: rgba(0, 229, 126, .55); color: #50fa7b; }
.site-toast.error { border-color: rgba(255, 93, 108, .55); color: #ff5d6c; }
.site-toast.fade { opacity: 0; transform: translateX(12px); }

/* ===== "new session" popup banner (owner 2026-09, Admin -> Popup Banner) ===== */
.popup-banner-overlay {
  position: fixed; inset: 0; z-index: 2000;
  background: rgba(0, 0, 0, .65);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.popup-banner-box {
  position: relative; max-width: min(480px, 100%); max-height: 90vh;
  animation: popup-banner-in .2s ease-out;
}
.popup-banner-img { display: block; width: 100%; height: auto; max-height: 90vh;
  object-fit: contain; border-radius: 10px; box-shadow: 0 20px 60px rgba(0, 0, 0, .5); }
.popup-banner-close {
  position: absolute; top: -14px; right: -14px; width: 32px; height: 32px;
  border-radius: 50%; border: none; background: #fff; color: #111;
  font-size: 16px; line-height: 1; cursor: pointer;
  box-shadow: 0 2px 10px rgba(0, 0, 0, .4);
}
.popup-banner-close:hover { background: #e5484d; color: #fff; }
@keyframes popup-banner-in {
  from { opacity: 0; transform: scale(.94); }
  to { opacity: 1; transform: scale(1); }
}

/* banners render markdown -> unwrap the paragraph margins */
.site-banner-1 p, .site-banner-2 p, .site-quote p { margin: 0; display: inline; }
.site-quote { border-left: 3px solid #00e57e; background: #0a1b11; padding: .8rem 1.1rem;
  border-radius: 8px; color: #8fb8a1; font-style: italic; margin: 1.4rem 0 0; }

/* long-press friendliness on touch devices */
#sidebar-container a, #sidebar-container summary {
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.ctx-menu .ctx-item { min-height: 40px; display: flex; align-items: center; } /* finger-sized */
/* .ctx-menu/.dm-pick-overlay are appended to document.body (fixed-position
   overlays, not nested inside #sidebar-container), so the rule above never
   reached their items - iOS's own long-press callout (Copy/Open/Share) or
   text-selection could intercept a tap meant for these, especially right
   after the long-press that opened the ctx-menu in the first place. */
.ctx-menu, .ctx-item, .dm-pick-overlay, .dm-pick-item, .dm-pick-x {
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
  touch-action: manipulation;
}

/* ===== admin pages must scroll normally =====
   The site shell locks html/body (overflow:hidden) and scrolls inside
   .main-content — the admin console reuses style.css and inherited the
   lock, so tall admin pages could not scroll AT ALL (desktop included).
   The admin <html> now carries .admin-html to opt out. */
html.admin-html, html.admin-html body { height: auto; min-height: 100%; overflow: auto; }

/* sidebar cards markdown */
.info-card-md p { margin: 4px 0; }
.info-card-md ul { margin: 4px 0; padding-left: 18px; }
/* #download-md/#download-media elements no longer exist (removed this
   session - Copy .md replaced download-md, download-media was a
   misunderstood feature that got fully reverted); only #download-docx is
   still real. The [hidden] rule matters: an ID selector's specificity
   beats the browser's own `[hidden] { display: none }` UA style, so
   without it template.html's `{% if not is_md_page %}hidden{% endif %}`
   on this button had zero visible effect (owner-reported 2026-09: stayed
   visible on folder-listing pages with `hidden` sitting right there in
   the DOM, doing nothing) - same class of bug as .picker-overlay[hidden]
   above, just missing here. */
a#download-docx { text-decoration: none; display: inline-block; }
a#download-docx[hidden] { display: none; }

/* register avatar field */
.auth-file-label { display: block; color: #8fb8a1; font-size: 13px; margin: 10px 0; }
.auth-file-label input { display: block; margin-top: 6px; color: #cfe9da; }

/* ===== admin image library ===== */
.imglib-toolbar { display: flex; gap: 10px; margin: 14px 0; flex-wrap: wrap; }
.imglib-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
.imglib-cell { background: #0a1b11; border: 1px solid #16301f; border-radius: 10px; padding: 8px;
  cursor: pointer; transition: border-color .2s, transform .2s; }
.imglib-cell:hover { border-color: #00e57e; transform: translateY(-2px); }
.imglib-cell img { width: 100%; height: 110px; object-fit: contain; background: #04120a; border-radius: 6px; }
.imglib-name { font-size: 12px; color: #8fb8a1; margin-top: 6px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; }
.imglib-pager { display: flex; gap: 12px; align-items: center; margin: 16px 0; }
.imglib-lightbox { position: fixed; inset: 0; background: rgba(0,0,0,.7); z-index: 800;
  display: flex; align-items: center; justify-content: center; padding: 20px; }
.imglib-lightbox[hidden] { display: none; }
.imglib-panel { background: #0a1b11; border: 1px solid #215436; border-radius: 14px;
  max-width: 720px; width: 100%; max-height: 92vh; overflow-y: auto; padding: 18px; }
.imglib-preview { text-align: center; }
.imglib-preview img { max-width: 100%; max-height: 40vh; border-radius: 8px; }
.imglib-meta { color: #8fb8a1; font-size: 12.5px; margin-top: 8px; word-break: break-all; }
.imglib-opts { display: flex; gap: 12px; align-items: flex-end; flex-wrap: wrap; margin: 8px 0; }
.imglib-opts label, .imglib-panel > label { color: #8fb8a1; font-size: 13px; display: block; }

/* ===== admin file manager (uploads/files/, any extension) ===== */
.admin-code { background: #04120a; border: 1px solid #16301f; border-radius: 8px;
  padding: 10px 14px; color: #c9f24b; font-size: 13px; overflow-x: auto; margin: 10px 0; }
.filemgr-toolbar { display: flex; gap: 10px; align-items: center; margin: 14px 0; flex-wrap: wrap; }
.filemgr-breadcrumb { color: #8fb8a1; font-size: 13px; }
.filemgr-breadcrumb a { color: #00e57e; text-decoration: none; cursor: pointer; }
.filemgr-breadcrumb a:hover { text-decoration: underline; }
.filemgr-list { border: 1px solid #16301f; border-radius: 10px; overflow: hidden; }
.filemgr-row { display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  border-bottom: 1px solid #16301f; }
.filemgr-row:last-child { border-bottom: none; }
.filemgr-row:hover { background: #0a1b11; }
.filemgr-row .icon { font-size: 18px; flex: 0 0 auto; width: 22px; text-align: center; }
.filemgr-row .name { flex: 1; min-width: 0; color: #eafcf1; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.filemgr-row.folder .name { cursor: pointer; }
.filemgr-row.folder .name:hover { color: #00e57e; }
.filemgr-row .meta { color: #8fb8a1; font-size: 12px; flex: 0 0 auto; min-width: 64px; text-align: right; }
.filemgr-row .actions { display: flex; gap: 6px; flex: 0 0 auto; }

/* ===== /share/<token> standalone read-only view ===== */
/* html/body { overflow:hidden; height:100% } is a SITE-WIDE rule (near the
   top of this file) built for the main layout, where .content is the only
   scrollable region. The share page doesn't use that layout at all, so
   without this override there was nowhere for tall articles to scroll -
   content just got clipped at one screenful. */
.share-page { overflow: auto; height: auto; }
.share-body { background: #071409; color: #eafcf1; margin: 0; overflow: visible; height: auto;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; min-height: 100vh; min-height: 100dvh; }
.share-banner { background: #0c2114; border-bottom: 1px solid #215436; color: #8fb8a1;
  font-size: 13px; text-align: center; padding: 10px 16px; }
.share-main { max-width: 860px; margin: 0 auto; padding: 32px 24px 64px; }
.share-title { color: #00e57e; font-size: 1.8rem; margin-bottom: 1.2rem; }

/* Share-link panel on the article page itself (editors only) */
.share-tool-panel { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: -4px 0 12px; }
/* same [hidden]-defeated-by-author-display bug as content-search-hint/
   download-docx above - found during that audit (2026-09). Low visual
   impact here (an empty flex box with no visible children just collapses
   near-zero height) which is likely why nobody had noticed it yet, but
   share-tool.js's `panel.hidden = true` was never actually doing anything. */
.share-tool-panel[hidden] { display: none; }
.share-tool-panel #share-status { color: #8fb8a1; font-size: 13px; }
.share-tool-panel #share-url { padding: 6px 10px; font-size: 12.5px; border-radius: 8px;
  background: #0a1b11; color: #eafcf1; border: 1px solid #215436; }

/* unused-images review list */
.imglib-unused-list { max-height: 55vh; overflow-y: auto; border: 1px solid #16301f; border-radius: 10px; }
.imglib-unused-row { display: flex; align-items: center; gap: 12px; padding: 8px 12px;
  border-bottom: 1px solid #16301f; }
.imglib-unused-row:last-child { border-bottom: none; }
.imglib-unused-row img { width: 44px; height: 44px; object-fit: contain; background: #04120a;
  border-radius: 6px; flex: 0 0 auto; }
.imglib-unused-row .path { flex: 1; min-width: 0; font-size: 13px; color: #eafcf1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.imglib-unused-row .size { color: #8fb8a1; font-size: 12px; flex: 0 0 auto; }

/* multi-select on the main image grid (owner request: bulk-delete
   ANY chosen images, not just the auto-detected "unused" ones) */
.imglib-cell { position: relative; }
.imglib-cell .imglib-cb { position: absolute; top: 6px; left: 6px; z-index: 2;
  width: 18px; height: 18px; cursor: pointer; }
.imglib-cell.selected { border-color: #00e57e; box-shadow: 0 0 0 2px rgba(0,229,126,.25); }
.imglib-bulkbar { display: flex; align-items: center; gap: 10px; margin: 10px 0; }
.imglib-bulkbar[hidden] { display: none; }

/* ===== admin sound library (grid+table hybrid: lightweight rows, a real
   waveform only loads lazily in the preview lightbox - not per row, which
   would mean one WaveSurfer + one audio fetch per visible row) ===== */
.sndlib-row-cb { width: 16px; height: 16px; cursor: pointer; }
.snd-wave-box { margin: 10px 0 6px; min-height: 46px; }
.snd-wave-box .sl-controls { margin-top: 8px; }

/* ===== PUBLIC embed classes (used by snippets pasted into markdown) ===== */
.img-embed { margin: 1.2rem 0; }
.img-embed img { width: 100%; height: auto; border-radius: 8px; display: block; }
.img-embed.img-center { margin-left: auto; margin-right: auto; }
.img-embed.img-center .img-caption { text-align: center; }
.img-embed.img-left { float: left; margin-right: 1.2rem; max-width: 45%; }
.img-embed.img-right { float: right; margin-left: 1.2rem; max-width: 45%; }
.img-caption { color: #8fb8a1; font-size: 13px; font-style: italic; margin: 6px 0 0; }

/* .content has an intentionally unbounded width (max-width: none, so wide
   tables/code don't get squeezed) - fine for text, but an embed left at
   its full-width default (max-width:100% - both the Embed builder's and
   wp_url2md.py's default) then also scales unbounded and looks huge on
   wide desktop monitors, even for a purely decorative cover image. Cap
   ONLY that specific case; deliberately smaller widths (25/40/50/60/75%,
   chosen by hand in the Embed builder) are left alone. min() still lets
   it shrink normally on phone/tablet, where the column is already
   narrower than the cap. */
.img-embed[style*="max-width:100%"] { max-width: min(100%, 720px) !important; }

/* Admin-only hover-delete button (owner 2026-09) - injected by
   img-delete.js, hidden until hover so it never intrudes for regular
   readers or on touch devices without a hover state. */
.img-embed { position: relative; }
.img-embed-del {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  background: rgba(0, 0, 0, 0.6); color: #fff; border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 7px; padding: 4px 8px; cursor: pointer; font-size: 14px; line-height: 1;
  opacity: 0; transition: opacity 0.15s, background 0.15s, border-color 0.15s;
}
.img-embed:hover .img-embed-del { opacity: 1; }
.img-embed-del:hover { background: #e5484d; border-color: #e5484d; }

/* ===== circular avatar editor (register + profile) ===== */
.av-circle { width: 96px; height: 96px; border-radius: 50%; margin: 6px auto 10px;
  border: 2px dashed #215436; background: #0a1b11 center/cover no-repeat; cursor: pointer;
  display: flex; align-items: center; justify-content: center; transition: border-color .2s; }
.av-circle:hover, .av-circle:focus { border-color: #00e57e; outline: none; }
.av-circle .av-hint { color: #54785f; font-size: 30px; }
.av-circle.has-img { border-style: solid; }
.av-circle.has-img .av-hint { display: none; }
.topbar-profile-link { text-decoration: none; color: inherit; }
.topbar-profile-link:hover strong { text-shadow: 0 0 10px rgba(0,229,126,.5); }

/* register labels + required mark; sidebar new-folder; docmenu picker */
.auth-lbl { display: block; color: #8fb8a1; font-size: 12.5px; margin: 8px 0 3px; text-align: left; }
.auth-box .req { color: #ff5d6c; }
/* 1rem top margin - matches .sidebar select's margin-bottom exactly, so the
   gap above "New folder/New file" equals the gap above the search box
   (owner-reported 2026-09: wanted the two gaps visually even). */
.sb-new-actions { display: flex; gap: 8px; margin: 1rem 0 2px; }
.sb-new-folder { display: block; flex: 1; min-width: 0; margin: 0; padding: 7px 10px;
  background: #0a1b11; border: 1px dashed #215436; border-radius: 10px; color: #8fb8a1;
  cursor: pointer; font-size: 13px; }
.sb-new-folder:hover { color: #00e57e; border-color: #00e57e; }
.dm-pick-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 2100;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
.dm-pick { background: #0a1b11; border: 1px solid #215436; border-radius: 14px;
  width: min(440px, 94vw); max-height: 76vh; display: flex; flex-direction: column; padding: 14px; }
.dm-pick-head { display: flex; justify-content: space-between; align-items: center; color: #eafcf1; }
.dm-pick-x { background: none; border: none; color: #8fb8a1; font-size: 16px; cursor: pointer; }
.dm-pick-filter { margin: 10px 0; padding: 8px 11px; background: #04120a; color: #eafcf1;
  border: 1px solid #16301f; border-radius: 9px; }
.dm-pick-list { overflow-y: auto; }
.dm-pick-item { display: block; padding: 9px 10px; color: #cfe9da; text-decoration: none;
  border-radius: 8px; font-size: 14px; }
.dm-pick-item:hover { background: #0c2114; color: #00e57e; }
.dm-pick-empty { color: #54785f; padding: 10px; font-size: 13px; }
.dm-pick-new { display: flex; gap: 6px; margin: 10px 0 0; }
.dm-pick-new .dm-pick-newfolder { flex: 1; margin: 0; }
.dm-pick-new .dm-pick-newfolder-btn { white-space: nowrap; }

/* ===== editor: scan & localize external image URLs (static/js/editor.js) ===== */
.img-scan-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 1500;
  display: flex; align-items: center; justify-content: center; padding: 16px; }
.img-scan-panel { background: #0a1b11; border: 1px solid #215436; border-radius: 14px;
  width: min(640px, 94vw); max-height: 82vh; display: flex; flex-direction: column; padding: 16px; }
.img-scan-head { display: flex; justify-content: space-between; align-items: center; color: #eafcf1; margin-bottom: 10px; }
.img-scan-x { background: none; border: none; color: #8fb8a1; font-size: 16px; cursor: pointer; }
.img-scan-list { overflow-y: auto; display: flex; flex-direction: column; gap: 8px; }
.img-scan-item { display: flex; gap: 10px; align-items: center; padding: 8px; background: #0c2114;
  border: 1px solid #16301f; border-radius: 10px; }
.img-scan-check { flex-shrink: 0; }
.img-scan-thumb { width: 64px; height: 64px; object-fit: cover; border-radius: 6px;
  background: #04120a; border: 1px solid #16301f; flex-shrink: 0; }
.img-scan-info { min-width: 0; flex: 1; }
.img-scan-url { color: #cfe9da; font-size: 12.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.img-scan-status { color: #54785f; font-size: 12px; margin-top: 3px; }
.img-scan-item.broken { opacity: .6; }
.img-scan-item.broken .img-scan-status { color: #f0b429; }
.img-scan-item.done .img-scan-status { color: #00e57e; }
.img-scan-item.failed .img-scan-status { color: #ff5d6c; }
.img-scan-actions { display: flex; align-items: center; gap: 10px; margin-top: 12px;
  padding-top: 12px; border-top: 1px dashed #215436; color: #cfe9da; font-size: 13.5px; }
.img-scan-spacer { flex: 1; }

/* ===== site-styled alert/confirm/prompt (static/js/dialogs.js) ===== */
.sl-modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,.6); z-index: 2000;
  display: flex; align-items: center; justify-content: center; padding: 20px;
  animation: sl-modal-fade .15s ease; }
@keyframes sl-modal-fade { from { opacity: 0; } to { opacity: 1; } }
.sl-modal-panel { background: #0a1b11; border: 1px solid #215436; border-radius: 16px;
  width: min(440px, 94vw); padding: 26px 26px 20px; box-shadow: 0 20px 60px rgba(0,0,0,.5); }
.sl-modal-title { color: #eafcf1; font-size: 1.15rem; font-weight: 700; margin-bottom: 8px; }
.sl-modal-msg { color: #8fb8a1; font-size: 14px; line-height: 1.5; white-space: pre-wrap; }
.sl-modal-input { width: 100%; margin-top: 14px; padding: 11px 13px; font-size: 14px;
  background: #04120a; color: #eafcf1; border: 1px solid #16301f; border-radius: 10px;
  outline: none; transition: border-color .15s; }
.sl-modal-input:focus { border-color: #00e57e; }
.sl-modal-input[readonly] { color: #cfe9da; cursor: text; }
.sl-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 22px; }
.sl-modal-btn { display: inline-flex; align-items: center; gap: 8px; padding: 8px 16px;
  border-radius: 10px; font-size: 14px; font-weight: 600; cursor: pointer; border: 1px solid transparent;
  background: #0c2114; color: #cfe9da; border-color: #215436; transition: .15s; }
.sl-modal-btn:hover { border-color: #00e57e; }
.sl-modal-btn.sl-modal-ok { background: linear-gradient(90deg, #00e57e, #3fd9d0); color: #04120a; border: none; }
.sl-modal-btn.sl-modal-ok:hover { filter: brightness(1.08); }
.sl-modal-btn.sl-modal-ok.danger { background: #ff5d6c; color: #250506; }
.sl-modal-kbd { font-size: 10px; padding: 1px 6px; border-radius: 5px; opacity: .75;
  background: rgba(0,0,0,.2); }
.sl-modal-ok .sl-modal-kbd { background: rgba(0,0,0,.15); }

/* breathing room under the last sidebar card (owner: sat mép nhìn không thẩm mỹ) */
.sidebar { padding-bottom: 16px; }
.sidebar .info-block:last-child { margin-bottom: 14px; }

/* ===== reading progress rail (static/js/reading-progress.js) =====
   Two INDEPENDENT choices (Admin -> Config -> Site), combined freely:
     position: default = vertical rail on the right edge (pinned there
               regardless of sidebar width - the page hides its native
               scrollbar entirely, so this is the only scroll feedback on
               the site). .rp-top = horizontal bar on top instead.
     color:    default = solid theme color ("bar"). .rp-gradient = a
               colorful rainbow fill ("gradient", Firefox-loading-bar
               inspired) - works with EITHER position.
   Same two elements (#rail wraps #fill) built once by reading-progress.js
   regardless of which combination is picked; only classes + which CSS
   dimension (height vs width) JS writes to differ. */
#reading-progress-rail {
  position: fixed; top: 0; right: 0; width: 3px; height: 100vh;
  background: rgba(127, 127, 127, .18);
  z-index: 500; pointer-events: none;
}
#reading-progress-fill {
  width: 100%; height: 0%; position: relative;
  --rp-rgb: 0, 229, 126; /* green theme default; the 3 Claude/Cobalt
                             themes override this to --c-accent-rgb below. */
  background: rgb(var(--rp-rgb));
  transition: height .15s ease-out;
  box-shadow: 0 0 10px rgba(var(--rp-rgb), .55);
}
html.theme-light #reading-progress-fill,
html.theme-dark #reading-progress-fill,
html.theme-cobalt #reading-progress-fill {
  --rp-rgb: var(--c-accent-rgb);
}
/* gradient color variant (either position) - only overrides --rp-rgb (a
   fixed pink accent, independent of the active site theme) and the
   background/box-shadow; the pop-dot/keyframes below stay driven by the
   SAME --rp-rgb variable either way, so they don't need their own copy. */
#reading-progress-rail.rp-gradient #reading-progress-fill {
  --rp-rgb: 236, 72, 153;
  background: linear-gradient(180deg, #4f9eff, #a855f7, #ff6bcb, #ffd54f);
  background-size: 100% 100vh;
  background-attachment: fixed;
}
/* top position (either color) - horizontal instead of vertical. .topbar
   is position:sticky; z-index:1000 with an opaque background - the
   default rail's z-index:500 sits below it (fine normally, since the
   vertical rail never overlaps the topbar), but a bar pinned to the very
   top needs to clear it explicitly. */
#reading-progress-rail.rp-top {
  top: 0; left: 0; right: auto; width: 100%; height: 3px;
  z-index: 1001;
}
#reading-progress-rail.rp-top #reading-progress-fill {
  width: 0%; height: 100%;
  transition: width .15s ease-out;
}
#reading-progress-rail.rp-top.rp-gradient #reading-progress-fill {
  background: linear-gradient(90deg, #4f9eff, #a855f7, #ff6bcb, #ffd54f);
  background-size: 100vw 100%;
}
/* owner 2026-08: no persistent dot (invisible at rest - scale(0)/opacity:0)
   but a one-off "pop" celebration right when the reader hits the end -
   reading-progress.js toggles .rp-complete, forcing a reflow first so it
   can replay on every subsequent visit to the end, not just the first. */
#reading-progress-fill::after {
  content: ""; position: absolute; left: 50%; bottom: -4px;
  width: 12px; height: 12px; border-radius: 50%;
  background: rgb(var(--rp-rgb));
  transform: translateX(-50%) scale(0);
  opacity: 0;
}
#reading-progress-rail.rp-top #reading-progress-fill::after {
  left: auto; right: -4px; bottom: 50%; top: auto;
  transform: translateY(50%) scale(0);
}
#reading-progress-rail.rp-complete #reading-progress-fill::after {
  animation: rp-pop .8s ease-out;
}
#reading-progress-rail.rp-top.rp-complete #reading-progress-fill::after {
  animation: rp-pop-h .8s ease-out;
}
@keyframes rp-pop {
  0% {
    transform: translateX(-50%) scale(0); opacity: 0;
    box-shadow: 0 0 0 0 rgba(var(--rp-rgb), .9);
  }
  30% {
    transform: translateX(-50%) scale(1.8); opacity: 1;
    box-shadow: 0 0 26px 10px rgba(var(--rp-rgb), .9);
  }
  100% {
    transform: translateX(-50%) scale(0); opacity: 0;
    box-shadow: 0 0 0 0 rgba(var(--rp-rgb), 0);
  }
}
@keyframes rp-pop-h {
  0% {
    transform: translateY(50%) scale(0); opacity: 0;
    box-shadow: 0 0 0 0 rgba(var(--rp-rgb), .9);
  }
  30% {
    transform: translateY(50%) scale(1.8); opacity: 1;
    box-shadow: 0 0 26px 10px rgba(var(--rp-rgb), .9);
  }
  100% {
    transform: translateY(50%) scale(0); opacity: 0;
    box-shadow: 0 0 0 0 rgba(var(--rp-rgb), 0);
  }
}

/* ===== bilingual dialog player (```dialog markdown blocks) ===== */
.sl-dialog, .sl-dialog-full { margin: 1.2rem 0; }
.sl-line { background: #0a1b11; border: 1px solid #16301f; border-radius: 12px;
  padding: 12px 14px; margin-bottom: 12px; }
.sl-line-en { color: #eafcf1; line-height: 1.55; }
.sl-vi-btn { background: none; border: none; cursor: pointer; font-size: 15px; }
.sl-line-vi { color: #8fb8a1; margin-top: 8px; padding-top: 8px; border-top: 1px dashed #215436; }
.sl-wave { margin: 8px 0 4px; min-height: 46px; }
.sl-controls { display: flex; gap: 5px; flex-wrap: wrap; }
.sl-controls button { background: #0c2114; border: 1px solid #215436; color: #cfe9da;
  border-radius: 7px; padding: 3px 9px; cursor: pointer; font-size: 12.5px; }
.sl-controls button:hover { border-color: #00e57e; color: #00e57e; }
.sl-controls .sl-speed.on { background: #00e57e; color: #04120a; border-color: #00e57e; }
.sl-full { background: #0a1b11; border: 1px solid #16301f; border-radius: 12px; padding: 12px 14px; }
.sl-full-title { margin: 0 0 8px; color: #eafcf1; line-height: 1.55; font-weight: 600; }
.sl-full-note { color: #54785f; font-size: 12.5px; margin-top: 6px; }
.sl-controls .sl-a.on, .sl-controls .sl-b.on { background: #f0b429; color: #04120a; border-color: #f0b429; }
.sl-controls .sl-del:hover { border-color: #e5484d; color: #e5484d; }

/* ===== multi-speaker conversation player — TWO display skins, same
   ```conv data, owner wants both available side by side per-article:
   ```conv -> .sl-conv (flowing paragraphs + 🇻🇳 toggle), ```conv-table ->
   .sl-conv-tbl (plain 2-column table, VI always visible, no toggle). ===== */
.sl-conv, .sl-conv-tbl { margin: 1.2rem 0; }
.sl-conv-line { margin: 0.4rem 0; }
.sl-conv-en { color: #eafcf1; line-height: 1.6; }
.sl-conv-vi { color: #8fb8a1; margin-top: 0.25rem; font-style: italic; }
.sl-conv-vi-btn { background: none; border: none; cursor: pointer; font-size: 15px; vertical-align: -2px; margin-left: 4px; }
.sl-conv-table-wrap { border: 1px solid #16301f; border-radius: 10px; overflow: hidden;
  box-shadow: 0 4px 16px rgba(0,0,0,.35); }
.sl-conv-table { width: 100%; table-layout: fixed; border-collapse: collapse; background: #0a1b11; }
.sl-conv-table th, .sl-conv-table td { padding: 10px 14px; text-align: left;
  border: 1px solid #16301f; vertical-align: top; word-wrap: break-word; overflow-wrap: break-word; }
.sl-conv-table th:first-child, .sl-conv-table td:first-child { width: 55%; }
.sl-conv-table th:last-child, .sl-conv-table td:last-child { width: 45%; }
.sl-conv-table thead th { background: #0c2114; color: #00e57e; font-weight: 700; }
.sl-conv-table tbody td:last-child { color: #8fb8a1; }
.sl-conv-table tbody tr:nth-child(odd) td { background: rgba(0,229,126,.03); }
.sl-conv-table tbody tr:hover td { background: rgba(0,229,126,.07); }
.sl-conv-text { cursor: pointer; color: #eafcf1; transition: color .15s; }
.sl-conv-text:hover, .sl-conv-text.playing { color: #00e57e; }
/* table mode: no sibling button anymore (owner 2026-08 removed the
   separate 🎵 toggle - clicking the text itself now opens the waveform
   AND plays), so the status icon sits directly after the text again. */
.sl-conv-table .sl-conv-text::after { content: "🔊"; opacity: 0; margin-left: 6px; font-size: 13px; transition: opacity .15s; }
.sl-conv-table .sl-conv-text:hover::after, .sl-conv-table .sl-conv-text.playing::after { opacity: 1; }
.sl-conv-table .sl-conv-text.sl-conv-uncached::after { content: "☁️"; opacity: 1; }
/* paragraph mode: the 🇻🇳 button sits right after the text - putting the
   status icon there too (owner 2026-08) collided/overlapped with the flag
   glyph. Move it to AFTER the flag button instead (owner's suggested
   fix), keeping the flag itself snug against the text. */
.sl-conv-vi-btn::after { content: "🔊"; opacity: 0; margin-left: 4px; font-size: 13px; transition: opacity .15s; }
.sl-conv-text:hover ~ .sl-conv-vi-btn::after, .sl-conv-text.playing ~ .sl-conv-vi-btn::after { opacity: 1; }
/* owner 2026-08: mark lines with no cached mp3 yet - visible before the
   click, not just on hover, so it's clear a ~1s ElevenLabs fetch (and
   quota) is about to happen. Flips back to the normal 🔊-on-hover look
   the moment it's actually loaded (conv.js removes this class then). */
.sl-conv-text.sl-conv-uncached ~ .sl-conv-vi-btn::after { content: "☁️"; opacity: 1; }

/* ===== ```phrase sentence-builder blocks (owner 2026-09, static/js/phrase.js) =====
   Deliberately its OWN classes (not reusing .sl-conv-* ) - see phrase.js's
   docstring for why this stays independent of conv.js/dialog.js. */
.sl-phrase-box { margin: 0.8rem 0; padding: 12px 14px; background: #0a1b11;
  border: 1px solid #16301f; border-radius: 10px; }
.sl-phrase-stem { color: #eafcf1; font-weight: 600; cursor: pointer; margin-bottom: 8px;
  padding: 4px 2px 12px; border-bottom: 1px dashed #16301f; transition: color .15s; }
.sl-phrase-stem:hover { color: #00e57e; }
.sl-phrase-list { display: flex; flex-wrap: wrap; gap: 10px; }
/* padding/min-height sized for a comfortable touch target (owner 2026-09:
   the old 5px/10px pill was too small to tap reliably on phone/iPad - the
   whole box has always been the click target in phrase.js, this just makes
   it big enough to actually hit without aiming for the text precisely). */
.sl-phrase-item { color: #cfe9da; cursor: pointer; padding: 12px 16px; border-radius: 8px;
  min-height: 24px; display: flex; align-items: center;
  background: #0c2114; border: 1px solid #215436; font-size: 14px; transition: .15s; }
.sl-phrase-item:hover { border-color: #00e57e; color: #00e57e; }
.sl-phrase-vi { color: #8fb8a1; font-style: italic; font-size: 0.92em; margin-left: 4px; }
.sl-phrase-stem.sl-phrase-playing, .sl-phrase-item.sl-phrase-playing {
  color: #00e57e; border-color: #00e57e; box-shadow: 0 0 0 1px rgba(0, 229, 126, .3); }
.sl-phrase-loading { opacity: .55; cursor: wait; }
.sl-phrase-stem.sl-phrase-uncached::after, .sl-phrase-item.sl-phrase-uncached::after {
  content: " ☁️"; font-size: 12px; }

/* admin-only delete button (owner 2026-09) - hidden until hover, matching
   .img-embed-del's "never intrudes for regular readers" pattern. */
.sl-phrase-del { background: none; border: none; cursor: pointer; font-size: 12px;
  margin-left: 6px; opacity: 0; transition: opacity .15s, color .15s; color: #8fb8a1; vertical-align: 1px; }
.sl-phrase-stem:hover .sl-phrase-del, .sl-phrase-item:hover .sl-phrase-del { opacity: 1; }
.sl-phrase-del:hover { color: #e5484d; }

/* detailed waveform panel per conv/conv-table line (owner 2026-08) -
   reuses .sl-wave/.sl-controls/.sl-a/.sl-b/etc from the ```dialog player
   below for pixel-identical look, wrapped in its own hideable panel that
   opens on a click of the line's own text (see conv.js's wireLine). */
.sl-conv-wave-panel { margin-top: 10px; padding: 10px 12px; background: #0a1b11;
  border: 1px solid #16301f; border-radius: 10px; }
tr.sl-conv-wave-row td { background: #04120a; }
tr.sl-conv-wave-row .sl-conv-wave-panel { margin-top: 0; }

/* A-B range highlight on the waveform + loop toggle */
.sl-wave { position: relative; }
.sl-ab-region { position: absolute; top: 0; bottom: 0; z-index: 5; pointer-events: none;
  background: rgba(240, 180, 41, .20);
  border-left: 2px solid #f0b429; border-right: 2px solid #f0b429; border-radius: 3px; }
.sl-ab-region.mark-only { background: none; border-right: none; }
.sl-controls .sl-loop.on { background: #00e57e; color: #04120a; border-color: #00e57e; }

/* ===== AI chat pane (widget tab + /ai page) ===== */
.ai-pane { display: flex; flex-direction: column; min-height: 0; }
.ai-pane-widget { height: 380px; }
/* min-height:0 is REQUIRED here, not just cosmetic: without it, a flex
   item's automatic minimum height is its content size, so a tall message
   (a long table, say) makes .ai-msgs refuse to shrink inside the fixed
   380px .ai-pane-widget box - it silently pushes .ai-cmd-menu (the "/"
   command palette) and .ai-form out of the visible area instead of
   scrolling internally. The .expanded state already had this override;
   the default (non-expanded) widget size didn't, so the palette only
   ever worked after clicking expand. */
/* ===== conversation picker (owner 2026-08: multiple switchable/deletable
   chat threads, logged-in only - see SL_AI_INIT in static/js/ai.js) ===== */
.ai-conv-bar { display: flex; gap: 8px; padding: 8px 10px; border-bottom: 1px solid #16301f; flex-shrink: 0;
  position: relative; }
/* scope picker for "+ Mới" - anchored right under the button rather than a
   centered full-screen modal (owner 2026-08: wants it "sát chỗ chữ New"). */
.ai-scope-pop { position: absolute; top: 100%; right: 10px; z-index: 50; width: 240px; max-width: calc(100vw - 20px);
  background: #0a1b11; border: 1px solid #215436; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,.35);
  margin-top: 6px; overflow: hidden; }
.ai-scope-head { display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 8px 10px; border-bottom: 1px solid #16301f; font-size: 12.5px; color: #eafcf1; }
.ai-scope-x { background: none; border: none; color: #8fb8a1; font-size: 14px; cursor: pointer; padding: 0 2px; }
.ai-scope-list { max-height: 260px; overflow-y: auto; }
.ai-scope-item { display: block; padding: 8px 10px; color: #cfe9da; text-decoration: none; font-size: 13px;
  border-bottom: 1px solid #0f2417; cursor: pointer; }
.ai-scope-item:last-child { border-bottom: none; }
.ai-scope-item:hover { background: #0c2114; color: #00e57e; }
.ai-conv-toggle, .ai-conv-new { background: #0c2114; border: 1px solid #215436; color: #cfe9da;
  border-radius: 8px; padding: 5px 10px; font-size: 12.5px; cursor: pointer; }
.ai-conv-toggle:hover, .ai-conv-new:hover { border-color: #00e57e; color: #00e57e; }
.ai-conv-new { margin-left: auto; }
.ai-conv-panel { max-height: 220px; overflow-y: auto; border-bottom: 1px solid #16301f;
  background: #04120a; flex-shrink: 0; }
.ai-conv-empty { padding: 12px; font-size: 12.5px; color: #54785f; text-align: center; }
.ai-conv-item { display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border-bottom: 1px solid #16301f; cursor: pointer; }
.ai-conv-item:hover { background: #0a1b11; }
.ai-conv-item.on { background: rgba(0, 229, 126, .08); }
.ai-conv-info { flex: 1; min-width: 0; }
.ai-conv-title { font-size: 13px; color: #eafcf1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ai-conv-meta { font-size: 11px; color: #54785f; margin-top: 2px; }
.ai-conv-del, .ai-conv-ren { background: none; border: none; color: #54785f; cursor: pointer; font-size: 13px;
  padding: 2px 6px; border-radius: 6px; flex-shrink: 0; }
.ai-conv-del:hover { color: #ff5d6c; background: rgba(255, 93, 108, .12); }
.ai-conv-ren:hover { color: #00e57e; background: rgba(0, 229, 126, .12); }
.ai-msgs { flex: 1; min-height: 0; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; }
.ai-msg { max-width: 86%; padding: 8px 12px; border-radius: 12px; font-size: 14px;
  line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.ai-user { align-self: flex-end; background: #0f3d24; color: #eafcf1; border: 1px solid #1c5c38; }
.ai-assistant { align-self: flex-start; background: #0a1b11; color: #cfe9da; border: 1px solid #215436; }
.ai-thinking { opacity: .6; animation: aiPulse 1.1s infinite; }
@keyframes aiPulse { 50% { opacity: .25; } }
.ai-sources { align-self: flex-start; font-size: 12px; color: #8fb8a1; padding: 0 6px; }
.ai-sources a { color: #00e57e; }
.ai-form { display: flex; gap: 8px; padding: 10px; border-top: 1px solid #16301f; flex-shrink: 0; }
.ai-input { flex: 1; resize: none; background: #04120a; color: #eafcf1;
  border: 1px solid #215436; border-radius: 10px; padding: 8px 11px; font-size: 14px; }
.ai-send { background: #00e57e; color: #04120a; border: none; border-radius: 10px;
  padding: 0 16px; font-weight: 700; cursor: pointer; }
.ai-send:disabled { opacity: .5; }
/* dedicated page */
.ai-page-body { background: #04120a; margin: 0; height: 100vh; display: flex; flex-direction: column;
  overflow: hidden; font-family: inherit; }
.ai-page-wrap { display: flex; flex-direction: column; height: 100%; max-width: 860px;
  width: 100%; margin: 0 auto; padding: 18px; box-sizing: border-box; }
.ai-page-head { color: #eafcf1; margin-bottom: 10px; }
.ai-page-head h1 { margin: 6px 0 2px; font-size: 22px; }
.ai-back { color: #8fb8a1; text-decoration: none; font-size: 13px; }
.ai-limit-note { color: #54785f; font-size: 12.5px; }
.ai-pane-page { flex: 1; background: #0a1b11; border: 1px solid #16301f; border-radius: 14px; min-height: 0; }
.support-empty { color: #8fb8a1; font-size: 13px; line-height: 1.6; padding: 12px 6px; }
.support-empty .mono { color: #cfe9da; }

/* SS56: the `hidden` attribute is just UA-level display:none — our
   .ai-pane{display:flex} was overriding it, leaving a 380px blank block
   in EVERY widget view (empty-looking menu, pushed-down chat/form). */
.ai-pane[hidden] { display: none !important; }
#support-widget [hidden] { display: none !important; }

/* ===== SS57: resizable support panel ===== */
#support-panel { display: flex; flex-direction: column; }
#support-panel > *:not(#support-resize) { flex-shrink: 0; }
#support-panel #support-ai { flex-shrink: 1; }
.support-head-actions { display: flex; gap: 6px; align-items: center; }
#support-expand, #support-fullpage {
  background: transparent; border: 1px solid #215436; color: #8fb8a1;
  border-radius: 8px; width: 28px; height: 28px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; text-decoration: none; }
#support-expand:hover, #support-fullpage:hover { border-color: #00e57e; color: #00e57e; }
#support-resize { position: absolute; top: -2px; left: -2px; width: 20px; height: 20px;
  cursor: nwse-resize; border-top: 2px solid #215436; border-left: 2px solid #215436;
  border-top-left-radius: 14px; }
#support-resize:hover { border-color: #00e57e; }
#support-panel.expanded { max-height: none; height: var(--sl-panel-h, 720px); }
#support-panel.expanded .ai-pane-widget { height: auto; flex: 1 1 auto; min-height: 0; }
#support-panel.expanded #support-ai .ai-msgs { flex: 1 1 auto; min-height: 0; }
.ai-input { overflow-y: hidden; }
.ai-meta { align-self: flex-start; font-size: 11px; color: #54785f; padding: 0 6px 4px; }
.ai-send.ai-stop { background: #e5484d; color: #fff; }

/* slash-command palette (SS63) */
.ai-cmd-menu { margin: 0 10px; border: 1px solid #215436; border-radius: 10px;
  background: #07170e; overflow: hidden; flex-shrink: 0; }
.ai-cmd-item { padding: 8px 12px; font-size: 13px; color: #cfe9da; cursor: pointer; }
.ai-cmd-item b { color: #00e57e; }
.ai-cmd-item:hover, .ai-cmd-item.on { background: #0f3d24; }

/* markdown in AI bubbles (SS65) */
.ai-msg code { background: #04120a; border: 1px solid #1c4a2e; border-radius: 5px;
  padding: 1px 5px; font-size: 12.5px; color: #7de3ab; }
.ai-code { position: relative; margin: 8px 0; }
.ai-code pre { background: #04120a; border: 1px solid #1c4a2e; border-radius: 9px;
  padding: 10px 12px; overflow-x: auto; margin: 0; font-size: 12.5px;
  color: #b6f0cf; white-space: pre; }
.ai-copy { position: absolute; top: 6px; right: 6px; background: #0c2114;
  border: 1px solid #215436; color: #cfe9da; border-radius: 6px;
  padding: 2px 7px; cursor: pointer; font-size: 12px; }
.ai-copy:hover { border-color: #00e57e; }
.ai-msg .ai-h { display: block; margin-top: 6px; color: #eafcf1; }
.ai-table { border-collapse: collapse; margin: 8px 0; font-size: 13px; }
.ai-table th, .ai-table td { border: 1px solid #1c4a2e; padding: 5px 10px; text-align: left; }
.ai-table th { background: #0c2114; color: #eafcf1; }
.ai-table td { color: #cfe9da; }

/* --- 6) Phone layout: clean topbar + account block in the sidebar (v73) ---
   PHONE ONLY (≤768px). Tablet (769–1024) and desktop are untouched.
   The topbar keeps just ☰ + logo + site title on one row; the account
   cluster (Welcome / Admin / Logout / theme toggle) moves into the
   sidebar, and the sidebar overlay now sits ABOVE the topbar so its
   title and ✕ button are never covered. */
@media (max-width: 768px) {
  .topbar { flex-direction: row; }
  .topbar .topbar-right { display: none !important; }
  .topbar #theme-toggle { display: none !important; }
  .topbar-left {
    width: 100%;
    margin-bottom: 0;
    justify-content: center;
  }
  .menu-left {
    position: absolute;
    left: 1rem;
    top: 50%;
    transform: translateY(-50%);
  }

  /* overlay ABOVE the sticky topbar (topbar is z-index 1000). padding-top
     is intentionally small (not the 50px topbar clearance from the ≤1024px
     rule above - the overlay covers where the topbar would be) but still
     needs to clear the notch/status-bar safe area on phones, or the
     sidebar title renders partly underneath it. */
  .sidebar { z-index: 1200; padding-top: max(14px, env(safe-area-inset-top)); }
  .sidebar-scrim { z-index: 1150; }

  .sidebar-account {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px 14px;
    margin: 6px 0 14px;
    padding: 12px 14px;
    border-radius: 12px;
    background: #0a1b11;
    border: 1px solid #215436;
  }
  .sidebar-account .sa-user {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: #eafcf1;
    font-size: 0.95rem;
    text-decoration: none;
    min-width: 0;
  }
  .sidebar-account .sa-user strong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 42vw;
  }
  .sidebar-account .sa-user img {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    flex: 0 0 auto;
  }
  .sidebar-account .topbar-admin-btn { padding: 5px 12px; }
  .sidebar-account .sa-link {
    color: #50fa7b;
    font-weight: 600;
    text-decoration: none;
  }
  .sidebar-account .theme-toggle { margin-left: auto; }
}
@media (min-width: 769px) {
  .sidebar-account { display: none !important; }
}

/* Tablet (769-1024px) had the same topbar-covers-sidebar-title bug the v73
   phone fix above already solved, just less visible until now: the ≤1024px
   overlay rule's `padding-top: 50px` assumes the topbar's PHONE height, but
   tablets keep the full Admin/Welcome/Logout/theme-toggle row in the
   topbar (v73 only moves that into .sidebar-account on phones), making the
   topbar taller than 50px there - so the sidebar overlay's own title/✕
   button rendered partly underneath it (owner-reported 2026-09, iPad-class
   tablet). Same fix as phone: put the overlay ABOVE the topbar entirely
   (z-index 1200 > topbar's 1000) so its exact height never needs guessing,
   instead of trying to find a bigger magic padding-top number that would
   just be a different guess. */
@media (min-width: 769px) and (max-width: 1024px) {
  .sidebar { z-index: 1200; padding-top: 14px; }
  .sidebar-scrim { z-index: 1150; }
}

/* --- 7) Admin console header on phones & tablets (v74) -------------------
   Stacked & centered: brand -> account row -> nav menu. Same breakpoint the
   sidebar overlay already switches on (1024px), so "tablet" means the same
   thing here as everywhere else in the site. Desktop (>1024px) keeps the
   single-row layout; only the account-row card frame is dropped there (see
   the borderless .admin-me base rule above). */
@media (max-width: 1024px) {
  .admin-top {
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 14px 12px;
    gap: 12px;
  }
  .admin-brand { order: 1; }
  .admin-me { order: 2; width: 100%; justify-content: center; flex-wrap: wrap; gap: 8px; }
  .admin-me a + a { border-left: none; padding-left: 0; }
  .admin-nav { order: 3; flex: none; width: 100%; justify-content: center; flex-wrap: wrap; row-gap: 2px; }
  .admin-nav a { padding: 6px 10px; font-size: 13px; }
}

/* --- 8) Admin console on phones (v73.1) ---------------------------------
   The admin pages had NO mobile rules: settings tables force a 280px label
   column and button rows never wrap, so the page overflowed sideways
   (clipped "Default" button in the owner's screenshot). PHONE ONLY. */
@media (max-width: 768px) {
  .admin-main { padding: 0 12px; margin: 18px auto; }
  .admin-h1 { font-size: 20px; }

  /* the page itself never scrolls sideways… */
  .admin-body { overflow-x: hidden; }
  /* …because wide tables scroll INSIDE their own box instead (classic
     responsive-table pattern; thead/tbody share one anonymous table box,
     so data-table columns stay aligned) */
  .admin-table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* settings tables: stop forcing the wide label column */
  .admin-table td[style*="width:280"] { width: auto !important; min-width: 120px; }

  /* controls shrink instead of stretching the row */
  .admin-table .admin-input { max-width: 100%; box-sizing: border-box; }
  .admin-table textarea.admin-input { min-width: 180px; }

  /* button clusters wrap onto new lines inside their cell */
  .admin-table .row-actions,
  p.row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    white-space: normal;   /* base rule is nowrap */
  }
  .admin-table .row-actions .admin-btn { white-space: nowrap; }

  /* stat cards go full-width instead of squeezing side by side */
  .admin-cards { gap: 10px; }
  .admin-card { flex: 1 1 100%; min-width: 0; }
}
