:root {
  --default-font: "Noto Sans", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  --heading-font: "Noto Sans", serif;
  --nav-font: "Noto Sans", sans-serif;
}


/* Global Colors - The following color variables are used throughout the website. Updating them here will change the color scheme of the entire website */
:root {
  --background-color: #faf8f5;
  /* Background color for the entire website, including individual sections */
  --default-color: #49321d;
  /* Default color used for the majority of the text content across the entire website */
  --heading-color: #3d2b1f;
  /* Color for headings, subheadings and title throughout the website */
  --accent-color: #9a7a3a;
  /* Accent color that represents your brand on the website. It's used for buttons, links, and other elements that need to stand out */
  --surface-color: #ffffff;
  /* The surface color is used as a background of boxed elements within sections, such as cards, icon boxes, or other elements that require a visual separation from the global background. */
  --contrast-color: #ffffff;
  /* Contrast color for text, ensuring readability against backgrounds of accent, heading, or default colors. */
}

/* Nav Menu Colors - The following color variables are used specifically for the navigation menu. They are separate from the global colors to allow for more customization options */
:root {
  --nav-color: #6a6a6a;
  /* The default color of the main navmenu links */
  --nav-hover-color: #9a7a3a;
  /* Applied to main navmenu links when they are hovered over or active */
  --nav-mobile-background-color: #ffffff;
  /* Used as the background color for mobile navigation menu */
  --nav-dropdown-background-color: #ffffff;
  /* Used as the background color for dropdown items that appear when hovering over primary navigation items */
  --nav-dropdown-color: #6a6a6a;
  /* Used for navigation links of the dropdown items in the navigation menu. */
  --nav-dropdown-hover-color: #9a7a3a;
  /* Similar to --nav-hover-color, this color is applied to dropdown navigation links when they are hovered over. */
}

/* UI utility tokens — derived from global colors, centralise repeated patterns */
:root {
  /* Semantic colors */
  --color-error: #df1529;
  --color-success: #059652;

  /* Frequently used semi-transparent tones */
  --border-color: color-mix(in srgb, var(--default-color), transparent 90%);
  /* dividers and subtle borders               */
  --bg-subtle: color-mix(in srgb, var(--default-color), transparent 94%);
  /* very faint tinted backgrounds             */
  --bg-wash: color-mix(in srgb, var(--default-color), transparent 98%);
  /* near-white tinted backgrounds             */
  --ghost-color: color-mix(in srgb, var(--default-color), transparent 95%);
  /* near-invisible decorative elements        */
  --muted-light-color: color-mix(in srgb, var(--default-color), transparent 70%);
  /* light muted text (breadcrumbs, etc.)      */
  --muted-color: color-mix(in srgb, var(--default-color), transparent 50%);
  /* secondary / meta text                     */
  --muted-strong-color: color-mix(in srgb, var(--default-color), transparent 40%);
  /* slightly more present muted text         */
  --text-strong-color: color-mix(in srgb, var(--default-color), transparent 30%);
  /* near-body-color text (footer links, etc.) */
  --text-emphasis-color: color-mix(in srgb, var(--default-color), transparent 20%);
  /* strong text, close to --default-color   */
  --muted-soft-color: color-mix(in srgb, var(--default-color), transparent 60%);
  /* soft muted text (hr, social icons)       */
  --input-border-color: color-mix(in srgb, var(--default-color), transparent 70%);
  /* form field borders                      */
  --decorative-rule-color: color-mix(in srgb, var(--default-color), transparent 85%);
  /* decorative separator lines            */
  --overlay-bg: rgba(0, 0, 0, 0.2);
  /* slide/section overlay                     */
  --accent-hover: color-mix(in srgb, var(--accent-color), transparent 20%);
  /* accent color on hover (lighter)           */
  --accent-faint: color-mix(in srgb, var(--accent-color), transparent 90%);
  /* very faint accent tint                    */

  /* Font-size scale */
  --font-xs: 12px;
  --font-sm: 14px;
  --font-base: 16px;
  --font-md: 18px;
  --font-lg: 20px;
  --font-xl: 24px;

  /* Motion */
  --transition-fast: 0.3s;
  --transition-base: 0.5s;

  /* Shape */
  --radius-sm: 4px;
  --radius-md: 5px;
  --radius-base: 6px;
  --radius-lg: 8px;
  --radius-full: 50%;

  /* Elevation */
  --shadow-sm: 0 2px 15px rgba(0, 0, 0, 0.1);
  /* cards, dropdowns */
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.1);
  /* elevated panels  */

  /* Spacing scale */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 40px;
  --space-2xl: 60px;

  /* Z-index scale */
  --z-content: 1;          /* decorative background elements */
  --z-above: 2;            /* content overlays on images */
  --z-loader: 3;           /* spinners / loaders */
  --z-overlay: 10;         /* section loading overlays */
  --z-dropdown: 99;        /* nav dropdowns */
  --z-header: 997;         /* sticky header */
  --z-modal: 1050;         /* modals / floating dropdowns */
  --z-mobile-nav: 9997;    /* mobile nav wrapper */
  --z-mobile-panel: 9998;  /* mobile nav panel */
  --z-mobile-toggle: 9999; /* mobile nav toggle button */
  --z-scroll-top: 99999;   /* scroll-to-top button */
  --z-lightbox: 999999;    /* fullscreen lightbox */
}

/* Color Presets - These classes override global colors when applied to any section or element, providing reuse of the sam color scheme. */

.light-background {
  --background-color: #f7f2ec;
  /* warm tint for section alternation */
  --surface-color: #ffffff;
}

.dark-background {
  --background-color: #060606;
  --default-color: #ffffff;
  --heading-color: #ffffff;
  --surface-color: #252525;
  --contrast-color: #ffffff;
}

/* Smooth scroll */
:root {
  scroll-behavior: smooth;
}

/*--------------------------------------------------------------
# General Styling & Shared Classes
--------------------------------------------------------------*/
html {
  /* Flat backstop colour only. The gradient lives on body::before so that
     scrolling never repaints it (see below). Keeping a solid colour here
     means the canvas is never bare, which is what caused the white flash
     behind the fixed bottom-row buttons on mobile. */
  background-color: var(--background-color);
  min-height: 100%;
}

body {
  color: var(--default-color);
  background-color: transparent;
  font-family: var(--default-font);
  font-feature-settings: "kern" 1, "liga" 1;
  line-height: 1.8;
  /* Sticky footer. `min-height: 100%` cannot work on its own here: a
     percentage height resolves against the parent, and html has no height of
     its own to resolve against, so it was inert. 100dvh is a real length —
     and the dynamic variant, so a phone's collapsing URL bar does not leave a
     strip of background below the footer the way 100vh would.

     The column layout is what lets .main grow: without it a short page (an
     empty Museum History page, a 404) ends wherever its content ends and the
     footer sits partway up the screen. */
  display: flex;
  flex-direction: column;
  min-height: 100dvh;
}

/* Takes up whatever height the header and footer leave, pushing the footer to
   the bottom on a short page and growing normally on a long one.
   `min-height: 0` is not needed — this is a column with no overflow of its
   own — but min-width is: a flex item defaults to min-width:auto, which would
   let a wide table or code block stretch the page into horizontal scroll. */
.main {
  flex: 1 0 auto;
  min-width: 0;
}

/* Fixed background layer.
   Replaces `background-attachment: fixed`, which forced a full repaint of the
   gradient on every scroll frame and flickered on mobile. `inset: 0` tracks the
   viewport directly (no 100vh/100vw mismatch when the mobile URL bar collapses,
   no scrollbar-width overflow), and `will-change: transform` promotes this to
   its own compositor layer so scrolling only translates it. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background-color: var(--background-color);
  background-image: radial-gradient(ellipse at center,
      #ffffff 0%,
      #f5eee5 45%,
      #d9cabb 100%);
  will-change: transform;
  pointer-events: none;
}

a {
  color: var(--accent-color) !important;
  text-decoration: none;
  transition: 0.3s;
}

a:hover {
  color: color-mix(in srgb, var(--accent-color), transparent 25%) !important;
  text-decoration: none;
}

/* Global focus-visible — accessible keyboard focus ring */
:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
}

/* Remove default outline on mouse/touch interaction */
:focus:not(:focus-visible) {
  outline: none;
}

h1,
h2,
h3,
h4,
h5,
h6 {
  color: var(--heading-color);
  font-family: var(--heading-font);
  letter-spacing: -0.02em;
}

.txthover {
  transition: 0.4s ease-in-out;
}

.txthover:hover {
  transform: scale(1.1);
}

.txtboldhover:hover {
  font-weight: bold;
}

/* Announcement date bottom right */
.announcement-date {
  right: 0;
  bottom: 0;
  font-size: 0.85em;
  color: var(--muted-color) !important;
  pointer-events: none;
}

/* Reusable themed scrollbar */
.themed-scrollbar {
  scrollbar-width: thin;
  scrollbar-color: var(--accent-color) var(--bg-subtle);
}

.themed-scrollbar::-webkit-scrollbar {
  width: 8px;
  background: var(--bg-subtle);
}

.themed-scrollbar::-webkit-scrollbar-thumb {
  background: var(--accent-color);
  border-radius: var(--radius-base);
}

.themed-scrollbar::-webkit-scrollbar-thumb:hover {
  background: var(--accent-hover);
}

.themed-scrollbar::-webkit-scrollbar-track {
  background: var(--bg-subtle);
}

/* Announcements column in the trending section. The list scrolls inside the
   column rather than setting the row's height, so on lg+ it ends level with
   the featured post beside it however many announcements there are. Below lg
   the columns stack and the list runs at its natural length. */
/* No bottom margin: the teaser row that follows brings its own padding, and a
   margin here would show as a gap above its tinted band. */
.trending-category {
  margin-bottom: 0;
}

@media (min-width: 992px) {
  .trending-category .announcements-col {
    display: flex;
  }

  .trending-category .announcements-col .trending {
    display: flex;
    flex-direction: column;
    /* The column is a flex item stretched to the row's height, but a
       percentage height on the child resolves against `auto` and collapses,
       so the box is stretched with flex instead and the list scrolls inside
       it. `min-height: 0` lets it shrink below its content. */
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
  }

  .trending-category .announcements-col .trending > h3 {
    flex: 0 0 auto;
  }

  .trending-category .announcements-col .trending-post {
    flex: 1 1 auto;
    overflow-y: auto;
    min-height: 0;
  }
}


/* Shared accent button base */
.btn-accent,
.about .content .read-more,
.comment-form form .btn-primary,
.contact .contact-form button[type=submit] {
  background-color: var(--accent-color) !important;
  color: var(--contrast-color) !important;
  border: 0;
  border-radius: var(--radius-sm);
  padding: 12px 28px;
  font-family: var(--nav-font);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  box-shadow: 0 2px 8px color-mix(in srgb, var(--accent-color), transparent 60%);
  transition: var(--transition-fast);
  cursor: pointer;
}

.btn-accent:hover,
.about .content .read-more:hover,
.comment-form form .btn-primary:hover,
.contact .contact-form button[type=submit]:hover {
  background-color: var(--accent-hover) !important;
  color: var(--contrast-color) !important;
  box-shadow: 0 4px 16px color-mix(in srgb, var(--accent-color), transparent 50%);
  transform: translateY(-1px);
}

/* Contact Form Messages
------------------------------*/
.contact-form .error-message {
  display: none;
  background: var(--color-error);
  color: var(--contrast-color);
  text-align: left;
  padding: 15px;
  margin-bottom: 24px;
  font-weight: 600;
}

.contact-form .sent-message {
  display: none;
  color: var(--contrast-color);
  background: var(--color-success);
  text-align: center;
  padding: 15px;
  margin-bottom: 24px;
  font-weight: 600;
}

.contact-form .loading {
  display: none;
  background: var(--surface-color);
  text-align: center;
  padding: 15px;
  margin-bottom: 24px;
}

.contact-form .loading:before {
  content: "";
  display: inline-block;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  margin: 0 10px -6px 0;
  border: 3px solid var(--accent-color);
  border-top-color: var(--surface-color);
  animation: contact-form-loading 1s linear infinite;
}

@keyframes contact-form-loading {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

/*--------------------------------------------------------------
# Global Header
--------------------------------------------------------------*/
/* Default logo size */
.logo {
  height: 80px;
  /* Default height for larger screens */
}

/* Responsive adjustment for smaller screens */
@media (max-width: 576px) {
  .logo {
    height: 35px;
    /* Smaller height for mobile screens */
  }

  .txthover:hover {
    transform: none;
  }
}

.header {
  color: var(--default-color);
  background-color: transparent;
  padding: 10px 0;
  transition: all var(--transition-base);
  z-index: var(--z-header);
}

/* Backdrop blur lives on a pseudo-element so it does NOT create a containing
   block for position:fixed descendants (the mobile nav overlay). */
.header::before {
  content: '';
  position: absolute;
  inset: 0;
  background-color: rgba(250, 248, 245, 0.88);
  backdrop-filter: blur(8px);
  z-index: -1;
  pointer-events: none;
}

.header .logo {
  line-height: 1;
}

.header .logo img {
  max-height: 36px;
  margin-right: 8px;
}

.header .logo h1 {
  font-size: 30px;
  margin: 0;
  font-weight: 500;
  color: var(--heading-color);
}

.sitename {
  font-size: 1.1rem;
  line-height: 1.25;
  white-space: normal;
  overflow-wrap: break-word;
}

/* Responsive sizing for the site title.

   These must stay AFTER the unconditional .sitename rule above. A media query
   carries no extra specificity, so at equal specificity the later rule wins —
   putting them before it (where the phone rule used to live, up in the
   max-width: 576px block) meant the 1.1rem base silently overrode them at
   every width.

   Large phones and small tablets: the nav has collapsed to the burger menu
   but the title is still full size, so step it down once. */
@media (min-width: 577px) and (max-width: 1199px) {
  .sitename {
    font-size: 0.95rem;
  }
}

/* Phones: the full museum name wraps to two or three lines and competes with
   the logo for the header's width. Smaller again so it stays legible without
   pushing the burger menu off the row. */
@media (max-width: 576px) {
  .sitename {
    font-size: 0.78rem;
    line-height: 1.15;
  }
}

/* Mobile/tablet: the title shares one row with the language switcher and the
   burger, so cap it at two lines. Without the clamp a long name (or a long
   single word) grows the header vertically instead of wrapping tidily. */
@media (max-width: 1199px) {
  .sitename {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: break-word;
  }
}

.header .header-social-links {
  padding-right: 15px;
}

.header .header-social-links a {
  color: var(--muted-strong-color);
  padding-left: 6px;
  display: inline-block;
  transition: var(--transition-fast);
  font-size: var(--font-base);
}

.header .header-social-links a:hover {
  color: var(--accent-color);
}

.header .header-social-links a i {
  line-height: 0px;
}

/* Language Switcher */
.lang-switcher {
  padding-left: 10px;
}

.lang-switcher-btn {
  display: flex;
  align-items: center;
  gap: 5px;
  background: none;
  border: 1px solid color-mix(in srgb, var(--muted-strong-color), transparent 60%);
  border-radius: var(--radius-base);
  color: var(--muted-strong-color);
  font-size: 13px;
  font-family: var(--nav-font);
  padding: 4px 8px;
  cursor: pointer;
  transition: var(--transition-fast);
  white-space: nowrap;
}

.lang-switcher-btn:hover,
.lang-switcher-btn:focus {
  color: var(--accent-color);
  border-color: var(--accent-color);
  outline: none;
  box-shadow: none;
}

.lang-switcher-btn::after {
  font-size: 10px;
  margin-left: 2px;
}

.lang-flag {
  width: 26px;
  height: 18px;
  object-fit: cover;
  border-radius: 2px;
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
}

.lang-switcher-menu {
  min-width: 130px;
  border: 1px solid color-mix(in srgb, var(--default-color), transparent 85%);
  box-shadow: var(--shadow-sm);
  padding: 4px 0;
}

.lang-switcher-menu .lang-option {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-family: var(--nav-font);
  color: var(--nav-color);
  padding: 6px 14px;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
}

.lang-switcher-menu .lang-option:hover {
  color: var(--nav-hover-color);
  background-color: var(--accent-faint);
}

.lang-switcher-menu .lang-option.active {
  color: var(--accent-color);
  font-weight: 600;
}

.lang-switcher-menu form {
  margin: 0;
  padding: 0;
}

/* Desktop: the nav markup sits after the language switcher inside
   .header-right (so mobile gets lang-then-burger on one row), but visually the
   links belong before the flag. Reorder with flex instead of duplicating the
   nav. */
@media (min-width: 1200px) {

  /* .header-right takes all the width left over by the brand, so the nav can
     be centred inside it and the language switcher pinned to the far end.
     Without flex-grow the two would sit packed together at the right edge. */
  .header .header-right {
    flex: 1 1 auto;
    min-width: 0;
  }

  .header .header-right .navmenu {
    order: 1;
    /* auto margins on both sides centre the links in the leftover space */
    margin-left: auto;
    margin-right: auto;
  }

  .header .header-right .lang-switcher {
    order: 2;
    flex-shrink: 0;
  }

  /* me-auto would absorb the leftover width itself and defeat the centring
     above, so drop it here. The brand keeps its natural width instead. */
  .header .header-brand {
    margin-right: 0 !important;
    flex: 0 0 auto;
  }
}

/* Laptops: the full desktop row (brand, seven links at 18px, "Ελληνικά") needs
   about 1620px, so between the burger breakpoint and that it ran off the right
   edge. Rather than moving the burger breakpoint, the longer labels wrap onto
   two lines here. That costs no height, since the 80px logo already sets the
   row's height. The title is narrower, the flag loses its name and the account
   link shows only its icon (the name stays for screen readers and as a
   tooltip). Placed after the 1200px block above so these win at equal
   specificity. Only top-level links (>ul>li>a): the account menu's items are
   .navmenu links too and must keep their own size. */
@media (min-width: 1200px) and (max-width: 1699px) {
  .header .header-brand>a.text-decoration-none {
    margin-right: 1rem !important;
  }

  .header .sitename {
    font-size: 1rem;
    max-width: 220px;
  }

  /* The nav may shrink below its one-line width; each link then gives up width
     in proportion to its length and wraps, so labels break only as far as the
     screen needs and never mid-word (a flex item's minimum is its longest
     word). */
  .header .header-right .navmenu {
    flex: 0 1 auto;
    min-width: 0;
  }

  .header .navmenu>ul>li {
    flex: 0 1 auto;
  }

  .header .navmenu>ul>li>a,
  .header .navmenu>ul>li>a:focus {
    font-size: 17px;
    line-height: 1.2;
    padding-left: 10px;
    padding-right: 10px;
    white-space: normal;
    text-wrap: balance;
    text-align: center;
  }

  .header .navmenu>ul>li>a::after {
    left: 10px;
    right: 10px;
  }

  .header .lang-name {
    display: none;
  }

  .header .user-nav-dropdown>a>span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  .header .user-nav-dropdown>a>i {
    margin-right: 0 !important;
    font-size: 1.25rem;
  }
}

/* Just above the burger breakpoint the wrapped labels at 17px would need a
   third line ("Ο / Σύλλογός / μας"); a size smaller keeps them to two. */
@media (min-width: 1200px) and (max-width: 1299px) {
  .header .sitename {
    max-width: 200px;
  }

  .header .navmenu>ul>li>a,
  .header .navmenu>ul>li>a:focus {
    font-size: var(--font-base);
    padding-left: 8px;
    padding-right: 8px;
  }

  .header .navmenu>ul>li>a::after {
    left: 8px;
    right: 8px;
  }
}

@media (max-width: 1199px) {

  /* Single row: brand takes the leftover width, lang + burger keep theirs.
     nowrap stops the brand from bumping the controls onto a second row when
     the title is long. */
  .header .container-fluid {
    flex-wrap: nowrap;
    column-gap: 8px;
  }

  /* The brand shrinks to whatever is left. min-width: 0 is what actually lets
     it shrink below the title's intrinsic width so the text wraps instead of
     pushing the row wider. */
  .header .header-brand {
    flex: 1 1 auto;
    min-width: 0;
    gap: 8px !important;
  }

  /* me-5 on the title link is desktop spacing for the nav that used to follow
     it; on mobile it just steals width from the title. */
  .header .header-brand>a.text-decoration-none {
    margin-right: 0 !important;
    min-width: 0;
  }

  /* Lang + burger: never shrink, stay pinned right. */
  .header .header-right {
    flex: 0 0 auto;
    margin-left: auto;
    gap: 12px !important;
  }

  /* Hamburger last in the row */
  .header .header-right .navmenu {
    order: 9;
    display: flex;
    align-items: center;
  }

  .lang-name {
    display: none;
  }

  .lang-switcher-btn {
    padding: 4px 6px;
  }
}

/*--------------------------------------------------------------
# Navigation Menu
--------------------------------------------------------------*/
/* Navmenu - Desktop */
@media (min-width: 1200px) {
  .sitename {
    max-width: 260px;
  }

  .navmenu {
    padding: 0;
  }

  .navmenu ul {
    margin: 0;
    padding: 0;
    display: flex;
    list-style: none;
    align-items: center;
  }

  .navmenu li {
    position: relative;
  }

  .navmenu a,
  .navmenu a:focus {
    color: var(--nav-color);
    padding: 18px 15px;
    font-size: var(--font-md);
    font-family: var(--nav-font);
    font-weight: 400;
    display: flex;
    align-items: center;
    justify-content: space-between;
    white-space: nowrap;
    transition: var(--transition-fast);
  }

  .navmenu a i,
  .navmenu a:focus i {
    font-size: var(--font-xs);
    line-height: 0;
    margin-left: 5px;
    transition: 0.3s;
  }

  .navmenu li:last-child a {
    padding-right: 0;
  }

  .navmenu li:hover>a,
  .navmenu .active,
  .navmenu .active:focus {
    color: var(--nav-hover-color);
  }

  .navmenu>ul>li>a {
    position: relative;
  }

  .navmenu>ul>li>a::after {
    content: '';
    position: absolute;
    bottom: 10px;
    left: 15px;
    right: 15px;
    height: 1.5px;
    background: var(--nav-hover-color);
    border-radius: 1px;
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--transition-fast);
  }

  .navmenu>ul>li:hover>a::after,
  .navmenu>ul>li>a.active::after {
    transform: scaleX(1);
  }

  .navmenu .dropdown ul {
    margin: 0;
    padding: 10px 0;
    background: var(--nav-dropdown-background-color);
    display: block;
    position: absolute;
    visibility: hidden;
    left: 14px;
    top: 130%;
    opacity: 0;
    transition: var(--transition-fast);
    border-radius: var(--radius-sm);
    z-index: var(--z-dropdown);
    box-shadow: var(--shadow-sm);
  }

  .navmenu .dropdown ul li {
    min-width: 200px;
  }

  .navmenu .dropdown ul a {
    padding: 10px 20px;
    font-size: 15px;
    text-transform: none;
    color: var(--nav-dropdown-color);
  }

  .navmenu .dropdown ul a i {
    font-size: var(--font-xs);
  }

  .navmenu .dropdown ul a:hover,
  .navmenu .dropdown ul .active:hover,
  .navmenu .dropdown ul li:hover>a {
    color: var(--nav-dropdown-hover-color);
  }

  .navmenu .dropdown:hover>ul {
    opacity: 1;
    top: 100%;
    visibility: visible;
  }

  .navmenu .dropdown .dropdown ul {
    top: 0;
    left: -90%;
    visibility: hidden;
  }

  .navmenu .dropdown .dropdown:hover>ul {
    opacity: 1;
    top: 0;
    left: -100%;
    visibility: visible;
  }
}

/* Navmenu - Mobile */
@media (max-width: 1199px) {
  .mobile-nav-toggle {
    color: var(--nav-color);
    font-size: 28px;
    line-height: 0;
    cursor: pointer;
    transition: color 0.3s;
    z-index: var(--z-mobile-toggle);
  }

  .navmenu {
    padding: 0;
    z-index: var(--z-mobile-nav);
  }

  /* main mobile menu panel */
  .navmenu>ul {
    display: none;
    list-style: none;
    position: absolute;
    inset: 60px 20px 20px 20px;
    padding: 10px 0;
    margin: 0;
    border-radius: var(--radius-lg);
    background-color: var(--nav-mobile-background-color);
    overflow-x: hidden;
    overflow-y: auto;
    transition: 0.3s;
    z-index: var(--z-mobile-panel);
    box-shadow: var(--shadow-sm);
  }

  .navmenu>ul>li {
    list-style: none;
  }

  .navmenu a,
  .navmenu a:focus {
    color: var(--nav-dropdown-color);
    padding: 10px 20px;
    font-family: var(--nav-font);
    font-size: 17px;
    font-weight: 500;
    display: flex;
    align-items: center;
    justify-content: space-between;
    white-space: nowrap;
    text-decoration: none;
    transition: var(--transition-fast);
  }

  .navmenu a i,
  .navmenu a:focus i {
    font-size: var(--font-xs);
    line-height: 0;
    margin-left: 5px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-full);
    transition: var(--transition-fast);
    background-color: var(--accent-faint);
    flex-shrink: 0;
  }

  .navmenu a i:hover,
  .navmenu a:focus i:hover {
    background-color: var(--accent-color);
    color: var(--contrast-color);
  }

  .navmenu a:hover,
  .navmenu .active,
  .navmenu .active:focus {
    color: var(--nav-dropdown-hover-color);
  }

  .navmenu .active i,
  .navmenu .active:focus i {
    background-color: var(--accent-color);
    color: var(--contrast-color);
    transform: rotate(180deg);
  }

  /* generic nested mobile submenus, excluding bootstrap dropdown-menu */
  .navmenu .dropdown ul:not(.dropdown-menu) {
    position: static;
    display: none;
    list-style: none;
    z-index: var(--z-dropdown);
    padding: 10px 0;
    margin: 10px 20px;
    background-color: var(--nav-dropdown-background-color);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: none;
    transition: all 0.3s ease-in-out;
  }

  .navmenu .dropdown ul:not(.dropdown-menu) li {
    list-style: none;
  }

  .navmenu .dropdown ul:not(.dropdown-menu) ul {
    background-color: rgba(33, 37, 41, 0.1);
  }

  .navmenu .dropdown>.dropdown-active {
    display: block;
    background-color: rgba(33, 37, 41, 0.03);
  }

  /* Bootstrap dropdown-menu: force static/inline positioning inside the mobile
     nav overlay. On desktop (≥1200px) this block is inactive; the user menu
     uses data-bs-display="static" so CSS positions it for both hover and
     click. The !important rules below remain, as JS may still open the menu. */
  .navmenu li.dropdown .dropdown-menu {
    display: none;
    position: static !important;   /* intentional: overrides Popper inline styles on mobile */
    inset: auto !important;
    transform: none !important;
    float: none;
    list-style: none;
    margin: 8px 0 0;
    padding: 4px 0 8px 20px;
    min-width: 160px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    background: var(--surface-color);
    box-shadow: var(--shadow-sm);
  }

  .navmenu li.dropdown .dropdown-menu.show {
    display: block !important;
  }

  .navmenu li.dropdown .dropdown-menu li {
    list-style: none;
  }

  .navmenu li.dropdown .dropdown-menu .dropdown-item,
  .navmenu li.dropdown .dropdown-menu button.dropdown-item {
    color: var(--nav-dropdown-color);
    font-size: var(--font-base);
    font-family: var(--nav-font);
    font-weight: 500;
    padding: 8px 0;
    text-align: start;
    background: transparent;
    border: 0;
    width: 100%;
  }

  .navmenu li.dropdown .dropdown-menu .dropdown-item:hover,
  .navmenu li.dropdown .dropdown-menu button.dropdown-item:hover,
  .navmenu li.dropdown .dropdown-menu .dropdown-item:focus,
  .navmenu li.dropdown .dropdown-menu button.dropdown-item:focus {
    color: var(--nav-dropdown-hover-color);
    background-color: rgba(33, 37, 41, 0.03);
  }

  .navmenu li.dropdown .dropdown-menu .dropdown-item.logout-btn {
    color: var(--accent-color);
  }

  .navmenu li.dropdown .dropdown-menu .dropdown-divider {
    border-color: var(--border-color);
    margin: 4px 0;
  }

  .mobile-nav-active {
    overflow: hidden;
  }

  .mobile-nav-active .mobile-nav-toggle {
    color: #fff;
    position: absolute;
    font-size: 32px;
    top: 15px;
    right: 15px;
    margin-right: 0;
    z-index: var(--z-mobile-toggle);
  }

  .mobile-nav-active .navmenu {
    position: fixed;
    inset: 0;
    overflow: hidden;
    background: rgba(33, 37, 41, 0.8);
    transition: 0.3s;
  }

  .mobile-nav-active .navmenu>ul {
    display: block;
  }

  .navmenu .user-nav-dropdown>a {
    justify-content: flex-start;
    gap: 6px;
  }

  .navmenu .user-nav-dropdown>a.dropdown-toggle::after {
    margin-left: auto;
  }

  /* The desktop hover zoom (.txthover) scales these full-width rows from
     their centre, which pushes the label past the panel's clipped left edge.
     The colour change is hover feedback enough here. */
  .navmenu .txthover:hover {
    transform: none;
  }

}

/* Tablets and small laptops: a full-screen panel is a lot of white for seven
   links, so it becomes a drawer under the close button on the right, as tall
   as its content. Phones keep the full-width panel. */
@media (min-width: 576px) and (max-width: 1199px) {
  .navmenu>ul {
    inset: 60px 20px auto auto;
    width: 340px;
    max-height: calc(100vh - 80px);
  }
}


/*--------------------------------------------------------------
# User nav dropdown (authenticated state)
--------------------------------------------------------------*/
.navmenu .dropdown-menu {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: 4px 0;
  font-family: var(--nav-font);
  font-size: 13px;
  background-color: var(--surface-color);
  min-width: 160px;
}

/* The user menu opens on hover (CSS) and on click (Bootstrap). To keep both at
   the same position, the toggle carries data-bs-display="static", so Popper is
   never engaged and the desktop rules in the min-width:1200px block position
   the menu in both cases. Do not re-add data-bs-strategy/Popper here: its
   inline styles outrank this stylesheet and cause the menu to jump on click.

   Width must be pinned explicitly. Hovering shows the menu via the desktop
   `.navmenu .dropdown ul` rule, whose `li { min-width: 200px }` sets the box
   width; clicking adds .show, at which point Bootstrap's own min-width applies
   and the box resolves narrower. Fixing width on both the menu and its items
   makes the two states render identically. */
.navmenu .user-nav-dropdown .dropdown-menu {
  margin-top: 0;
}

/* Desktop only: below 1200px the menu is an inline block inside the mobile nav
   overlay and must stay fluid, so the fixed width is scoped to the breakpoint
   where the floating menu actually renders. */
@media (min-width: 1200px) {
  .navmenu .user-nav-dropdown .dropdown-menu {
    width: 200px;
    min-width: 200px;
  }

  .navmenu .user-nav-dropdown .dropdown-menu li {
    min-width: 0;
  }

  /* The account item is the last link, next to the language switcher, so the
     menu hangs leftwards from its right edge; opening rightwards it ran off
     the screen. */
  .navmenu .user-nav-dropdown .dropdown-menu {
    left: auto;
    right: 0;
  }
}

.navmenu .dropdown-item {
  color: var(--nav-color);
  padding: 7px 16px;
}

.navmenu .dropdown-item:hover,
.navmenu .dropdown-item:focus {
  background-color: var(--accent-faint);
  color: var(--nav-hover-color);
}

.navmenu .dropdown-item.logout-btn {
  color: var(--accent-color);
  font-size: inherit;
}

.navmenu .dropdown-item.logout-btn:hover {
  background-color: var(--accent-faint);
  color: var(--accent-color);
}

.navmenu .dropdown-divider {
  border-color: var(--border-color);
  margin: 4px 0;
}

.navmenu li .dropdown-menu form {
  margin: 0;
  padding: 0;
}

.navmenu li .dropdown-menu button.dropdown-item {
  width: 100%;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
}

/*--------------------------------------------------------------
# Modal — scrollable fix when <form> wraps modal-body + modal-footer
# Bootstrap's modal-dialog-scrollable expects .modal-body to be a
# direct flex child of .modal-content. When a <form> sits in between,
# it breaks the flex chain. Make the form behave as a flex passthrough.
--------------------------------------------------------------*/
.modal-dialog-scrollable .modal-content > form {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  overflow: hidden;
  min-height: 0;
}

/*--------------------------------------------------------------
# Post Entry Links — a card's image and title both link to the post's
# own page, stripped of link chrome so they look like plain text/image.
--------------------------------------------------------------*/
.post-entry-trigger {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  text-align: inherit;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
}

.post-entry-trigger:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 3px;
}

.post-entry-title-trigger {
  color: var(--heading-color);
}

.post-entry-title-trigger:hover {
  text-decoration: underline;
}

/* The image grows inside its frame, which already clips overflow, so the card
   itself keeps its size and the grid does not shift. */
.image-loading-wrapper.post-entry-zoom img {
  transition: opacity var(--transition-fast) ease, transform var(--transition-fast) ease;
}

.post-entry-zoom:hover img,
.post-entry-zoom:focus-visible img {
  transform: scale(1.05);
}

@media (prefers-reduced-motion: reduce) {
  .image-loading-wrapper.post-entry-zoom img {
    transition: opacity var(--transition-fast) ease;
  }
}

/*--------------------------------------------------------------
# Post Author byline — the avatar + name shown on a post's own page
--------------------------------------------------------------*/
.post-author {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-width: 0;
}

.post-author img {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  object-fit: cover;
  flex-shrink: 0;
}

.post-author-name {
  font-size: var(--font-sm);
  font-weight: 600;
  color: var(--muted-strong-color);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/*--------------------------------------------------------------
# Login Modal
--------------------------------------------------------------*/
#loginModal .modal-content {
  background-color: var(--background-color);
  color: var(--default-color);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  font-family: var(--default-font);
}

#loginModal .modal-header {
  background-color: var(--heading-color);
  color: var(--contrast-color);
  border-bottom: none;
  border-radius: 9px 9px 0 0;
  padding: 16px 20px;
}

#loginModal .modal-title {
  font-family: var(--heading-font);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--contrast-color);
}

#loginModal .btn-close {
  filter: invert(1);
  opacity: 0.8;
}

#loginModal .btn-close:hover {
  opacity: 1;
}

#loginModal .modal-body {
  padding: 24px 28px;
}

#loginModal #loginError {
  font-size: 0.875rem;
  font-family: var(--nav-font);
  background-color: color-mix(in srgb, var(--color-error), transparent 90%);
  border-color: color-mix(in srgb, var(--color-error), transparent 60%);
  color: var(--color-error);
  border-radius: var(--radius-base);
  padding: 8px 12px;
}

#loginModal .form-label {
  color: var(--muted-strong-color);
  font-size: 0.875rem;
  font-family: var(--nav-font);
  margin-bottom: 4px;
}

#loginModal .form-control {
  background-color: var(--surface-color);
  border: 1px solid var(--input-border-color);
  border-radius: var(--radius-base);
  color: var(--default-color);
  font-family: var(--default-font);
  transition: border-color 0.2s, box-shadow 0.2s;
}

#loginModal .form-control:focus {
  border-color: var(--accent-color);
  box-shadow: 0 0 0 3px var(--accent-faint);
  outline: none;
}

#loginModal .form-check-input:checked {
  background-color: var(--accent-color);
  border-color: var(--accent-color);
}

#loginModal .form-check-label {
  color: var(--muted-color);
  font-size: 0.875rem;
  font-family: var(--nav-font);
}

#loginModal a {
  color: var(--accent-color);
  font-size: 0.875rem;
  font-family: var(--nav-font);
}

#loginModal a:hover {
  color: var(--nav-hover-color);
}


/*--------------------------------------------------------------
# Global Footer
--------------------------------------------------------------*/
.footer {
  color: var(--default-color);
  background-color: var(--background-color);
  font-size: var(--font-sm);
  position: relative;
}

.footer .footer-top {
  padding-top: 28px;
  padding-bottom: 8px;
  border-top: 1px solid var(--border-color);
}

.footer .footer-about .logo {
  line-height: 1;
  margin-bottom: 8px;
}

.footer .footer-about .logo img {
  max-height: 40px;
  margin-right: 6px;
}

.footer .footer-about .logo span {
  color: var(--heading-color);
  font-family: var(--heading-font);
  font-size: var(--font-md);
  font-weight: 700;
  letter-spacing: 0.5px;
}

.footer .footer-about p {
  font-size: var(--font-sm);
  font-family: var(--heading-font);
}

.footer .social-links a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  border: 1px solid var(--accent-color);
  font-size: var(--font-sm);
  color: var(--accent-color);
  margin-right: 8px;
  transition: var(--transition-fast);
}

/* The facebook and instagram marks are solid glyphs whose shape is carried by
   knocked-out cut-outs (the "f", the lens and corner dot). A white glyph on the
   filled hover state collapses into a gold blob, because the cut-outs show the
   accent fill. Darkening the glyph instead inverts the rest state: gold fill,
   dark glyph body, cut-outs reading gold. */
.footer .social-links a:hover {
  background-color: var(--accent-color);
  border-color: var(--accent-color);
}

/* The global `a` / `a:hover` rules near the top of this file set
   `color: var(--accent-color) !important`, so a plain `color` here loses and
   the glyph paints gold on the gold hover fill — a featureless disc. The
   facebook and instagram marks are solid glyphs whose shape comes from
   knocked-out cut-outs, so they need the body dark and the cut-outs gold.
   Setting the color on the ::before that actually paints the glyph, with
   !important to match, is what survives those globals. */
.footer .social-links a:hover i::before {
  color: var(--background-color) !important;
}

.footer h4 {
  font-size: var(--font-base);
  font-weight: bold;
  position: relative;
  padding-bottom: 12px;
}

.footer .footer-links {
  margin-bottom: 0;
}

.footer .footer-links ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.footer .footer-links ul i {
  padding-right: 2px;
  font-size: var(--font-xs);
  line-height: 0;
}

.footer .footer-links ul li {
  padding: 5px 0;
  display: flex;
  align-items: center;
}

.footer .footer-links ul li:first-child {
  padding-top: 0;
}

.footer .footer-links ul a {
  display: inline-block;
  line-height: 1;
  transition: color 0.25s ease;
}

.footer .footer-links ul a:hover {
  color: #fff;
}

.footer .footer-contact p {
  margin-bottom: 5px;
}

/* Each contact item (label + value) wraps as one unit, so a narrow screen can
   never split "Email:" away from the address that follows it. */
.footer .footer-contact-item {
  display: inline-block;
  white-space: nowrap;
}

/* The address itself may still wrap internally if it is longer than the
   viewport — better than forcing horizontal overflow.
   The colour override is needed because the global `a` rule sets
   `var(--accent-color) !important`, which is too dark against the footer's
   .dark-background to meet contrast requirements; inherit the footer's own
   text colour instead, as the previous <span> markup did. */
.footer .footer-contact-item a {
  overflow-wrap: anywhere;
  color: inherit !important;
  text-decoration: none;
}

.footer .footer-contact-item a:hover,
.footer .footer-contact-item a:focus-visible {
  color: #fff !important;
  text-decoration: underline;
}

/* Below 576px stack Tel and Email on their own lines and drop the separator,
   rather than letting the break depend on string length (which varies by
   locale and by the final contact values). */
@media (max-width: 575.98px) {
  .footer .footer-contact-item {
    display: block;
  }

  .footer .footer-contact-sep {
    display: none;
  }
}

.footer .copyright {
  padding: 14px 0;
  border-top: 1px solid var(--border-color);
}

.footer .copyright p {
  margin-bottom: 0;
}

.footer .credits {
  margin-top: 8px;
  font-size: 13px;
}

.footer .credits a {
  color: var(--default-color);
}

/*--------------------------------------------------------------
# Preloader
--------------------------------------------------------------*/
#preloader {
  position: fixed;
  inset: 0;
  z-index: var(--z-lightbox);
  overflow: hidden;
  background: var(--background-color);
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all 0.6s ease-out;
}

#preloader img {
  width: auto;
  height: 100px;
  animation: pulse 1.5s infinite ease-in-out;
}

@keyframes pulse {

  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }

  50% {
    opacity: 0.5;
    transform: scale(1.1);
  }
}

/*--------------------------------------------------------------
# Scroll Top Button
--------------------------------------------------------------*/
.scroll-top {
  position: fixed;
  visibility: hidden;
  opacity: 0;
  right: 15px;
  bottom: 15px;
  z-index: var(--z-scroll-top);
  background-color: var(--accent-color);
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  pointer-events: none;
  transition: opacity 0.4s ease, visibility 0.4s ease;
  /* Pre-allocate a GPU compositing layer so the browser doesn't create one
     mid-frame on mobile, which causes a full-width white flash on first paint. */
  will-change: opacity;
  transform: translateZ(0);
}

/* Accessibility: focus style for keyboard navigation */
.scroll-top:focus {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
}

.scroll-top i {
  font-size: var(--font-xl);
  color: var(--contrast-color);
  line-height: 0;
}

.scroll-top:hover {
  background-color: var(--accent-hover);
  color: var(--contrast-color);
}

.scroll-top.active {
  visibility: visible;
  opacity: 0.65 !important;
  pointer-events: auto;
}

.scroll-top.active:hover {
  opacity: 1 !important;
}

/*--------------------------------------------------------------
# Disable aos animation delay on mobile devices
--------------------------------------------------------------*/
@media screen and (max-width: 768px) {
  [data-aos-delay] {
    transition-delay: 0 !important;
  }
}

/*--------------------------------------------------------------
# Global Page Titles & Breadcrumbs
--------------------------------------------------------------*/
.page-title {
  color: var(--default-color);
  background-color: var(--background-color);
  padding: 25px 0;
  position: relative;
  border-bottom: 1px solid var(--border-color);
}

.page-title h1 {
  font-size: var(--font-xl);
  font-weight: 700;
}

.page-title .breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: var(--font-sm);
  font-weight: 400;
}

.page-title .breadcrumbs ol li+li {
  padding-left: 10px;
}

.page-title .breadcrumbs ol li+li::before {
  content: "/";
  display: inline-block;
  padding-right: 10px;
  color: var(--muted-light-color);
}

/*--------------------------------------------------------------
# Global Sections
--------------------------------------------------------------*/
section,
.section {
  color: var(--default-color);
  padding: 1rem 0;
  scroll-margin-top: 90px;
  overflow: clip;
}

@media (max-width: 1199px) {

  section,
  .section {
    scroll-margin-top: 66px;
  }
}

/*--------------------------------------------------------------
# Global Section Titles
--------------------------------------------------------------*/
.section-title {
  margin-bottom: 2rem;
  position: relative;
}

.section-title .section-title-container {
  padding-bottom: 12px;
  border-bottom: 1px solid color-mix(in srgb, var(--accent-color), transparent 75%);
}

@media (max-width: 767px) {
  .section-title .section-title-container {
    flex-direction: column;
    align-items: flex-start !important;
    gap: 6px;
  }
}

.section-title h1,
.section-title h2 {
  font-size: 40px;
  font-weight: 400;
}

.section-title p {
  margin-bottom: 0;
}

.section-title p a {
  color: var(--default-color);
  text-transform: uppercase;
  font-size: var(--font-xs);
  letter-spacing: 0.5px;
  border-bottom: 1.5px solid var(--default-color);
  font-family: var(--nav-font);
  font-weight: 500;
  padding-bottom: 2px;
}

/*--------------------------------------------------------------
# Slider Section
--------------------------------------------------------------*/
.slider {
  background-color: transparent;
}

.slider .swiper-pagination .swiper-pagination-bullet {
  background-color: color-mix(in srgb, var(--default-color) 90%, white 15%);
  width: 18px;
  height: 18px;
}

.slider .swiper-pagination .swiper-pagination-bullet-active {
  background-color: var(--accent-color);
  width: 22px;
  height: 22px;
}

.slider .swiper-wrapper {
  align-items: stretch;
}

.slider .swiper-slide {
  height: 600px;
  min-height: 0;
  position: relative;
  display: flex;
  align-items: flex-end;
  background-repeat: no-repeat;
  background-size: auto 100%;
  background-position: center top;
  overflow: hidden;
  background-color: var(--slider-dark-bg);
}

/* Wide screens: the rule above scales the photo to the slide's height and lets
   its width fall where it may. That covers the slide only while the container
   is narrower than a landscape photo drawn 600px tall — past roughly 1200px it
   is not, so the picture stops short of the sides and the fixed 600px leaves
   the slide shallow against the width. `cover` fills both axes instead,
   trimming the top and bottom of a wide photo rather than letting the slide
   background show through. The height grows with the viewport for the same
   reason: 600px was sized against a ~992px container and reads as a band on a
   1600px one. 56dvh with a 600px floor keeps the slide proportionate without
   ever getting shorter than it is today, and caps at 760px so the section
   below stays in view on a tall monitor. */
@media (min-width: 1200px) {
  .slider .swiper-slide {
    height: clamp(600px, 56dvh, 760px);
    background-size: cover;
    background-position: center center;
  }
}

.slider .swiper-slide::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.25) 35%, transparent 65%);
  z-index: 1;
}

/* Phone: `contain` used to letterbox every slide. The photographs are all
   landscape (roughly 4:3 to 16:9) while the slide at this width is close to
   square, so fitting one whole put dark bars above and below it and left the
   picture a fraction of the frame. `cover` fills the slide instead, trimming
   the sides of a wide photo rather than shrinking it. This is deliberately
   different from the rule above, which scales to the slide's height and lets
   the width fall where it may — that works on a wide viewport but is what
   produced the bars here.

   The height grows with it: 300px was sized for a letterboxed image, and a
   filled frame at that height reads as a strip. 60dvh keeps the slide a
   presence on the screen while leaving the section below it visible, so the
   page still invites a scroll. `dvh` rather than `vh` for the reason body
   gives above — a phone's collapsing URL bar must not resize the slide. */
@media (max-width: 576px) {
  .slider .swiper-slide {
    height: 60dvh;
    min-height: 300px;
    background-size: cover;
    background-position: center center;
  }
}

.slider .swiper-button-prev:after,
.slider .swiper-button-next:after {
  font-size: var(--font-xl);
  color: var(--muted-color);
}

.slider .content {
  padding: 60px 80px;
  max-width: 700px;
  width: 100%;
  box-sizing: border-box;
  margin: 0 auto;
  position: relative;
  z-index: 2;
}

@media (max-width: 576px) {
  .slider .content {
    padding: 24px 20px;
  }
}

.slider .content a,
.slider .content h2,
.slider .content p {
  color: var(--default-color);
  text-shadow:
    -1px -1px 0 rgba(0, 0, 0, 0.55),
    1px -1px 0 rgba(0, 0, 0, 0.55),
    -1px 1px 0 rgba(0, 0, 0, 0.55),
    1px 1px 0 rgba(0, 0, 0, 0.55),
    0 2px 8px rgba(0, 0, 0, 0.4);
}

/*--------------------------------------------------------------
# Trending Category Section
--------------------------------------------------------------*/
.trending-category .post-entry {
  margin-bottom: 30px;
}

.trending-category .post-entry img {
  margin-bottom: 30px;
}

.trending-category .post-entry h2 {
  margin-bottom: 20px;
  font-size: var(--font-lg);
  font-weight: 600;
  line-height: 1.2;
}
.moderator-panel-page .panel-label {
  font-size: 1.1rem;
}
.moderator-panel-page .panel-page-title {
  font-size: 2.1rem;
}
.moderator-panel-page .panel-card-title {
  font-size: 1.3rem;
}
.moderator-panel-page .panel-btn-primary {
  font-size: 1.15rem;
}

.trending-category .post-entry h2 a {
  color: var(--heading-color);
}

.trending-category .post-entry h2 a:hover {
  text-decoration: underline;
}

/* The featured post sits one step above the other cards (--font-lg), not in a
   size of its own: the larger image is what marks it out, so the heading only
   has to lead them rather than outshout them. A viewport-scaled clamp() here
   put it at 32px on desktop, outside the type scale entirely, and long Greek
   titles then ran to four lines. */
.trending-category .post-entry.lg h2 {
  font-size: var(--font-xl);
  line-height: 1.25;
}

/* Cover images arrive at whatever ratio they were uploaded in, so both the
   featured slot and the cards fix a ratio and crop to fill. Without this the
   four cards in a row would each be a different height and the grid would
   never line up. */
.trending-category .featured-media {
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-base);
}

.trending-category .featured-media img {
  height: 100%;
  object-fit: cover;
  margin-bottom: 0;
}

.trending-category .custom-border {
  border-color: var(--border-color) !important;
}

@media (max-width: 768px) {
  .trending-category .custom-border {
    border: none !important;
  }
}

.trending-category .trending {
  border: 1px solid var(--border-color);
}

.trending-category .trending>h3 {
  color: var(--default-color);
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
}

.trending-category .trending .trending-post {
  padding: 0;
  margin: 0;
}

.trending-category .trending .trending-post li {
  padding: 0;
  margin: 0;
  list-style: none;
  display: block;
}

.trending-category .trending .trending-post li a {
  display: block;
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
  position: relative;
  overflow: hidden;
  z-index: var(--z-above);
}

.trending-category .trending .trending-post li a .number {
  position: absolute;
  z-index: var(--z-content);
  font-size: 5rem;
  left: -10px;
  top: -20px;
  font-weight: 700;
  font-family: var(--heading-font);
  color: var(--ghost-color);
}

.trending-category .trending .trending-post li a h3 {
  font-size: var(--font-md);
  color: var(--default-color);
  transition: 0.3s;
}

.trending-category .trending .trending-post li a .author {
  color: var(--muted-color);
  font-weight: 500;
}

.trending-category .trending .trending-post li a:hover h3 {
  color: var(--default-color);
  text-decoration: underline;
}

.trending-category .trending .trending-post li:last-child a {
  border-bottom: none;
}

/*--------------------------------------------------------------
# Teaser rows — a section's newest items on the landing page, as a way
# into the section rather than a listing of it.
--------------------------------------------------------------*/
.teaser-row {
  padding: var(--space-2xl) 0;
}

/* Alternating bands: the tinted one is full-bleed so the colour runs to the
   window edge while the cards stay on the container's grid.

   The tint has to be translucent. The page's backdrop is a fixed radial
   gradient on body::before that runs unbroken behind everything; an opaque
   band paints over it and cuts a hard horizontal stripe across it. A low-alpha
   wash darkens the band slightly while the gradient still reads through, so
   the row separates without breaking the backdrop. Its own edges are faded out
   for the same reason — a hard edge against a soft gradient looks like a seam. */
.teaser-row-shaded {
  background-image: linear-gradient(
      to bottom,
      transparent 0%,
      color-mix(in srgb, var(--default-color), transparent 96%) 12%,
      color-mix(in srgb, var(--default-color), transparent 96%) 88%,
      transparent 100%);
}

/* The rule under the heading is what marks the section, now that the row has
   no "see all" link sitting opposite the title. */
.teaser-row-head {
  margin-bottom: var(--space-lg);
  padding-bottom: var(--space-sm);
  border-bottom: 1px solid var(--border-color);
}

.teaser-row-title {
  margin: 0;
  font-size: var(--font-xl);
  font-weight: 600;
  color: var(--heading-color);
}

/* A section with fewer items than the row holds centres what it has rather
   than leaving a gap on the right. */
.teaser-row .row {
  justify-content: center;
}

/*--------------------------------------------------------------
# Announcements Section (standalone)
--------------------------------------------------------------*/
.announcements .trending {
  border: 1px solid var(--border-color);
}

.announcements .trending>h3 {
  color: var(--default-color);
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
}

.announcements .trending .trending-post {
  padding: 0;
  margin: 0;
}

.announcements .trending .trending-post li {
  padding: 0;
  margin: 0;
  list-style: none;
  display: block;
}

.announcements .trending .trending-post li a {
  display: block;
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
  position: relative;
  overflow: hidden;
  z-index: var(--z-above);
}

.announcements .trending .trending-post li a h3 {
  font-size: var(--font-md);
  color: var(--default-color);
  transition: 0.3s;
}

.announcements .trending .trending-post li a .author {
  color: var(--muted-color);
  font-weight: 500;
}

.announcements .trending .trending-post li a:hover h3 {
  color: var(--default-color);
  text-decoration: underline;
}

.announcements .trending .trending-post li:last-child a {
  border-bottom: none;
}

/* Image overlay */
/* `block`, not `inline-block`: an inline-level box sits on a text line and
   reserves room under the baseline for descenders, so the placeholder
   background below showed as a permanent strip beneath the photo rather than
   only while it loaded. `max-width: fit-content` shrink-wrapped the anchor to
   the image's intrinsic width for the same reason it was inline — neither is
   needed once the anchor is a block that its `width: 100%` image fills. */
.image-overlay-container {
  position: relative;
  display: block;
  overflow: hidden;
}

.image-loading-wrapper {
  position: relative;
  display: block;
  overflow: hidden;
  /* background-color: var(--bg-subtle); */
}

.image-overlay-container.image-loading-wrapper {
  display: block;
}

.image-loading-wrapper img {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0;
  transition: opacity var(--transition-fast) ease;
}

.image-loading-wrapper.is-loaded img {
  opacity: 1;
}

.image-loading-spinner {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 26px;
  height: 26px;
  margin-top: -13px;
  margin-left: -13px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--default-color), transparent 82%);
  border-top-color: var(--default-color);
  animation: image-loading-spin 0.7s linear infinite;
  z-index: var(--z-loader);
}

.image-loading-wrapper.is-loaded .image-loading-spinner {
  opacity: 0;
  visibility: hidden;
}

@keyframes image-loading-spin {
  to {
    transform: rotate(360deg);
  }
}

.image-overlay-container img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform var(--transition-fast) ease;
}

.image-overlay-container .image-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transition: var(--transition-fast) ease;
  pointer-events: none;
}

.image-overlay-container:hover img {
  transform: scale(1.05);
}

/*--------------------------------------------------------------
# Shared post-meta / author / post-list — used across all category sections
--------------------------------------------------------------*/
.post-meta {
  font-size: 11px;
  letter-spacing: 0.07rem;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--muted-color);
  margin-bottom: 10px;
}

.author .photo {
  margin-right: 10px;
}

.author .photo img {
  width: 40px;
  border-radius: var(--radius-full);
  margin-bottom: 0;
}

.author .name h3 {
  margin: 0;
  padding: 0;
  font-size: 15px;
  font-family: var(--default-font);
}

.post-list h2,
.post-list h2 a {
  color: var(--heading-color);
  margin-bottom: 20px;
  font-size: var(--font-lg);
  font-weight: 600;
  line-height: 1.2;
}

.post-list h2 a:hover {
  text-decoration: underline;
}

.post-list.lg h2 {
  font-size: 40px;
  line-height: 1;
}

/*--------------------------------------------------------------
# About Section
--------------------------------------------------------------*/
.about .content .who-we-are {
  text-transform: uppercase;
  margin-bottom: 15px;
  color: var(--muted-strong-color);
}

.about .content h3 {
  font-size: 2rem;
  font-weight: 700;
}

.about .content ul {
  list-style: none;
  padding: 0;
}

.about .content ul li {
  padding-bottom: 10px;
}

.about .content ul i {
  font-size: 1.25rem;
  margin-right: 4px;
  color: var(--accent-color);
}

.about .content p:last-child {
  margin-bottom: 0;
}

.about .content .read-more {
  font-family: var(--heading-font);
  font-weight: 500;
  font-size: var(--font-base);
  letter-spacing: 1px;
  padding: 12px 24px;
  border-radius: var(--radius-md);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.about .content .read-more i {
  font-size: var(--font-md);
  margin-left: 5px;
  line-height: 0;
  transition: 0.3s;
}

.about .content .read-more:hover {
  padding-right: 19px;
}

.about .content .read-more:hover i {
  margin-left: 10px;
}

/* The association photo is portrait, so at full column width it stands much
   taller than the intro text beside it and pushes the prose below the fold.
   The cap keeps the row balanced; it is centred because the capped image no
   longer fills its column. */
.about .about-images img {
  border-radius: 10px;
  max-height: 520px;
  width: auto;
  display: block;
  margin-inline: auto;
  box-shadow: var(--shadow-sm);
}

/* Stacked on narrow screens there is no text beside it to balance against, so
   the image takes the full width again and the cap only guards its height. */
@media (max-width: 991px) {
  .about .about-images img {
    max-height: 420px;
  }
}

/* The museum prose below the intro row reuses .history-article for its type,
   but not its measure: the 1000px cap the history page uses would centre the
   block inside the 1140px container and leave it narrower than the intro row
   above, so the two would not share an edge. Here the row above is the
   measure, and the prose takes the container's full width to match it. */
.about .history-article {
  max-width: none;
  margin-inline: 0;
}

/*--------------------------------------------------------------
# Museum History landing page
--------------------------------------------------------------*/
/* The index of history pages. The cards themselves are .gallery-card, shared
   with Activities and the gallery — what is left here is the intro line and
   the "Read more" link, which the shared card has no equivalent for. */
.history-index-intro {
  max-width: 620px;
  margin-inline: auto;
}

.history-index-more {
  margin-bottom: 0;
}

.history-index-link {
  display: inline-flex;
  align-items: center;
  color: var(--accent-color);
  font-weight: 600;
  text-decoration: none;
}

.history-index-link:hover {
  color: var(--accent-color);
  text-decoration: underline;
}

.history-index-link .bi {
  transition: transform 0.3s ease;
}

/* The arrow leans out on hovering anywhere on the card, not just the link —
   the whole card reads as the target, and .gallery-card already lifts on the
   same hover. */
.gallery-card:hover .history-index-link .bi {
  transform: translateX(4px);
}

/*--------------------------------------------------------------
# Museum History: back to the index
--------------------------------------------------------------*/
/* Sits above the page heading. Muted until hovered: it is a way back rather
   than the thing a visitor came to read, and it should not compete with the
   title directly below it. */
.history-back {
  margin-bottom: 1rem;
}

.history-back-link {
  display: inline-flex;
  align-items: center;
  font-size: 0.95rem;
  color: color-mix(in srgb, var(--default-color), transparent 35%);
  text-decoration: none;
  transition: color 0.3s;
}

.history-back-link:hover {
  color: var(--accent-color);
}

.history-back-link .bi {
  transition: transform 0.3s ease;
}

.history-back-link:hover .bi {
  transform: translateX(-3px);
}

/*--------------------------------------------------------------
# Museum History article
--------------------------------------------------------------*/
/* The article is narrower than its container: long justified prose is hard to
   track across a full 1140px, and this measure keeps lines readable even after
   a figure has been floated out of the column. */
.history-article {
  max-width: 1000px;
  margin-inline: auto;
}

.history-content {
  font-size: 1.05rem;
  line-height: 1.85;
  /* color: var(--text-emphasis-color); */
}

.history-content p {
  text-align: justify;
  hyphens: auto;
  margin-bottom: 1.15rem;
}

/* The opening paragraph is set slightly larger, which gives a long text an
   entry point without adding a separate intro field to the model. */
.history-content > p:first-of-type {
  font-size: 1.15rem;
  line-height: 1.8;
  color: var(--default-color);
}

.history-content p:last-child {
  margin-bottom: 0;
}

.history-content h3,
.history-content h4 {
  font-family: var(--heading-font);
  color: var(--heading-color);
  font-weight: 500;
  margin-top: 2rem;
  margin-bottom: .75rem;
}

/* A subhead squeezed into the gutter beside a floated figure wraps after two or
   three words and stops reading as a heading, so headings clear the left-hand
   figure and take the full measure.
   Two deliberate exceptions keep that from emptying the page: `clear: left`
   rather than `both`, so a heading may still sit beside the right-floated lead
   image (there is room for one there), and `:not(:first-child)`, because a
   section whose text opens with a heading would otherwise push its entire body
   below both figures and defeat the wrap before it starts. */
.history-content h3:not(:first-child),
.history-content h4:not(:first-child) {
  clear: left;
}

.history-content h3 {
  font-size: 1.5rem;
}

.history-content h4 {
  font-size: 1.25rem;
}

.history-content ul,
.history-content ol {
  padding-left: 1.25rem;
  margin-bottom: 1.15rem;
}

.history-content li {
  margin-bottom: .4rem;
}

.history-content blockquote {
  margin: 1.5rem 0;
  padding: .25rem 0 .25rem 1.25rem;
  border-left: 3px solid var(--accent-color);
  color: var(--muted-strong-color);
  font-style: italic;
}

.history-content a {
  color: var(--accent-color);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/*--------------------------------------------------------------
# Floated article figures
--------------------------------------------------------------*/
/* Up to two images per section wrap into the prose instead of sitting in a
   block beneath it. `shape-outside` lets justified text follow the card's
   rounded corners where supported, and is ignored harmlessly elsewhere. */
.history-figure {
  width: 40%;
  max-width: 420px;
  margin: .35rem 0 1.25rem;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md, 10px);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.history-figure:hover,
.history-figure:focus-within {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md, 0 6px 18px rgba(0, 0, 0, .12));
}

.history-figure-lead {
  float: right;
  margin-left: 2rem;
  shape-outside: inset(0 round 10px);
  shape-margin: 1.25rem;
}

/* The second image takes the opposite side, so a two-image section reads as a
   spread rather than one stacked column. It also starts lower, letting a few
   paragraphs run at full width between the two. */
/* `clear: both` is what makes this read as a spread rather than a vice: without
   it the two floats settle on the same first line and pinch the opening
   paragraph into a column a few words wide. Clearing drops this figure below
   the lead, so several paragraphs run at full width before the text wraps
   again — this time down the left-hand side. */
.history-figure-trail {
  float: left;
  clear: both;
  margin-right: 2rem;
  margin-top: 1.5rem;
  shape-outside: inset(0 round 10px);
  shape-margin: 1.25rem;
}

/* A figure the moderator placed by hand sits where she put it. `clear` and the
   top margin above exist to drop the *automatic* second image below the first;
   applied to a chosen one they would shove it down the page, away from the
   paragraph she anchored it to — which is the whole point of choosing. */
.history-figure-placed.history-figure-trail {
  clear: none;
  margin-top: .35rem;
}

/*--------------------------------------------------------------
# Prose deck: several placed figures floated as one
--------------------------------------------------------------*/
/* Two or more hand-placed photographs float as a single stack rather than as
   separate figures.

   Separate ones collide. A placed figure does not clear the figure before it
   (see `.history-figure-placed` above) because clearing would drop it away
   from the paragraph it was pinned to — so a pair anchored a paragraph or two
   apart floats up side by side and pinches the text between them into a
   column a few words wide. One float cannot collide with itself, so stacking
   sidesteps the geometry instead of tuning margins against it.

   The wrapper takes the float and the width that a lone figure would have; the
   cards inside give theirs up to it. */
.history-figure-deck {
  position: relative;
  width: 40%;
  max-width: 420px;
  margin: .35rem 0 1.25rem;
  /* The cards are sized from this box rather than from their own photographs,
     which is what makes them one deck of identical cards. Every card — the
     upright one in front included — is laid out against it explicitly, so no
     card takes its shape from its own crop.

     The room the fan and the count line need is margin, not padding. Padding
     would enlarge the box that `inset: 0` resolves against, so the cards
     behind came out wider and taller than the card in front, which is the
     mismatch this replaced: a front photograph visibly smaller than the one
     leaning behind it.

     The clearance is a length, not a percentage: a percentage margin resolves
     against the containing block — the article — not against this box, so 8%
     here was 8% of the full column and bore no relation to how far a card
     actually leans. How far it leans depends on the card's own size, which
     `--deck-lean` tracks. */
  --deck-lean: 2.25rem;
  margin-inline: var(--deck-lean);
  margin-bottom: 2.6rem;
  /* The card size, set once here. The height follows the width rather than
     whichever photograph happens to be in front, so every card agrees. */
  aspect-ratio: 4 / 3;
}

/* No `shape-outside` on either side, unlike a lone figure. A shape is computed
   from the element's box and ignores the rotation, so text would follow a
   straight upright edge and run under the fanned corners that stick out past
   it. The rectangular float box plus the side margins is the honest outline of
   a fan whose widest point is its top corners.

   These restate the 8% the wrapper reserves for the fan and add the gutter to
   the text on top of it. Setting `margin-left`/`margin-right` alone here would
   override that 8% — which is exactly what made the leaning cards swing over
   the paragraph beside them: the clearance the fan needed was being replaced
   by a plain 1.5rem gutter, so the corners had nothing to lean into. */
.history-figure-deck.history-figure-lead {
  float: right;
  /* Fan clearance plus a gutter on the text side; clearance alone outside. */
  margin-left: calc(var(--deck-lean) + 1.5rem);
  margin-right: var(--deck-lean);
}

.history-figure-deck.history-figure-trail {
  float: left;
  /* Like a single placed figure, this must not clear what came before it, or
     it would be shoved away from the paragraph it belongs beside. */
  clear: none;
  margin-right: calc(var(--deck-lean) + 1.5rem);
  margin-left: var(--deck-lean);
}

/* The cards stack on one spot. The wrapper owns the size and the float, so
   each card fills it rather than setting a width of its own.

   They pivot from just below the bottom edge, the way a hand of cards splays
   from the fist holding it: a rotation about the centre would swing the
   bottom corner out as far as the top and read as scattered rather than
   fanned. Keeping the pivot low means the bottoms stay gathered while the
   tops spread. */
.history-figure-deck .history-deck-card {
  position: absolute;
  inset: 0;
  width: 100%;
  max-width: none;
  margin: 0;
  transform-origin: 50% 115%;
}

/* The card in front stays upright — the fan opens behind the photograph being
   shown — but it is sized from the wrapper like every other card, not from its
   own photograph. It used to be `position: relative` so it could hold the
   stack's height open; the wrapper's own `aspect-ratio` does that now, which
   is what lets all the cards share one box. */
.history-figure-deck .history-deck-card:first-child {
  z-index: 4;
}

/* Each photograph is cropped to its card rather than setting the card's shape.
   This is the whole trick behind a deck of identical cards: `inset: 0` gives
   every card the wrapper's box, and `object-fit: cover` fills that box from
   the middle of the photograph, so a tall shot and a wide one come out the
   same rectangle.

   `aspect-ratio: auto` overrides the 4:3 the stylesheet puts on every history
   image — here the card's box decides, and the ratio is set once on the
   wrapper. Without this the image would keep its own 4:3 inside a box already
   shaped 4:3, and any rounding between the two showed up as a card that did
   not quite match its neighbours. */
.history-figure-deck .history-deck-card .history-figure-img {
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  object-fit: cover;
}

/* The fan proper. Cards alternate to either side of the upright leading one
   and lean further out as they go back, so the top edges spread into view
   while the bottoms stay gathered at the pivot. Each is a little dimmer,
   which does the work of depth without a shadow under every card.

   Four leaning cards is the limit: past that the angles would either crowd
   into each other or swing so wide that the fan stops reading as a stack.
   The rest sit exactly under the fourth, and the count line says how many
   are really there. */
.history-figure-deck .history-deck-card:nth-child(2) {
  z-index: 3;
  transform: rotate(5deg) scale(.985);
  filter: brightness(.975);
}

.history-figure-deck .history-deck-card:nth-child(3) {
  z-index: 2;
  transform: rotate(-5deg) scale(.985);
  filter: brightness(.95);
}

.history-figure-deck .history-deck-card:nth-child(4) {
  z-index: 1;
  transform: rotate(10deg) scale(.97);
  filter: brightness(.93);
}

.history-figure-deck .history-deck-card:nth-child(n + 5) {
  z-index: 0;
  transform: rotate(-10deg) scale(.97);
  filter: brightness(.91);
}

/* A deck shows no caption at all, not even on the front card.

   A caption belongs to one photograph, and a stack shows several — so a single
   caption under the front card reads as a label for the whole deck and
   miscaptions the rest. It also made the cards different heights, since only
   that one card carried it.

   Nothing is lost: the caption travels with its own photograph into the
   lightbox, which is where a visitor looking at one picture reads about it.
   The alt text is unaffected, so a screen reader still gets the caption for
   every card here. A lone figure and the plain grid keep their captions —
   there is only one photograph to describe in those. */
.history-figure-deck .history-figure-caption {
  display: none;
}

/* The stack lifts as one, rather than each card lifting out from under the
   pointer. Only the upright leading card carries the lift: adding a
   translate to a leaning card would mean restating its angle here, and the
   fan already reads as one object.

   `.history-figure`'s own hover lift is cancelled on every card, because a
   leaning card that gained `translateY(-3px)` would lose the rotation that
   rule replaces and snap upright under the pointer. The rotations are
   restated per card rather than dropped, so a hovered card keeps its angle. */
.history-figure-deck:hover .history-deck-card:first-child,
.history-figure-deck:focus-within .history-deck-card:first-child,
.history-figure-deck .history-deck-card:first-child:hover,
.history-figure-deck .history-deck-card:first-child:focus-within {
  transform: translateY(-3px);
}

.history-figure-deck .history-deck-card:nth-child(2):hover,
.history-figure-deck .history-deck-card:nth-child(2):focus-within {
  transform: rotate(5deg) scale(.985);
}

.history-figure-deck .history-deck-card:nth-child(3):hover,
.history-figure-deck .history-deck-card:nth-child(3):focus-within {
  transform: rotate(-5deg) scale(.985);
}

.history-figure-deck .history-deck-card:nth-child(4):hover,
.history-figure-deck .history-deck-card:nth-child(4):focus-within {
  transform: rotate(10deg) scale(.97);
}

.history-figure-deck .history-deck-card:nth-child(n + 5):hover,
.history-figure-deck .history-deck-card:nth-child(n + 5):focus-within {
  transform: rotate(-10deg) scale(.97);
}

/* Focus has to bring its card to the front: the
   outline is otherwise drawn behind an opaque card and the visitor sees it
   vanish. Only a parent selector can do this — the cards set `transform` and
   `filter`, each of which traps a descendant's z-index in its own stacking
   context.

   Straightening the focused card is deliberate here: it is about to open, so
   showing it square says which photograph that will be. It stays uncaptioned
   like the rest of the deck — revealing one would resize the card under the
   visitor's own focus, and the caption is a moment away in the lightbox.

   `:hover` on the rules above adds a pseudo-class, making them one step more
   specific than this selector, so a card both hovered and keyboard-focused
   would keep its lean and hide the focus ring behind the card in front. The
   `:hover` here matches that specificity, and the `:not(:hover)` variant
   covers focus arriving by keyboard with the pointer elsewhere. */
.history-figure-deck .history-deck-card:has(:focus-visible):hover,
.history-figure-deck .history-deck-card:has(:focus-visible):not(:hover) {
  z-index: 5;
  transform: none;
  filter: none;
}

/* Under the stack, in the margin left below it. `top: 100%` rather than
   `bottom: 0`: the wrapper's box is now exactly one card, so `bottom: 0` would
   print this over the photograph instead of beneath it. */
.history-figure-deck .history-deck-count {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: .5rem 0 0;
  text-align: center;
  font-size: .8rem;
  font-weight: 500;
  color: var(--muted-strong-color);
}

/* Full width: not a float at all, but a band spanning the column. `clear` here
   is doing the opposite job to the rule above — the band has to start below
   any float still running, or it would overlap one. */
.history-figure-full {
  float: none;
  clear: both;
  width: 100%;
  max-width: none;
  margin: 1.25rem 0;
}

/* The 4:3 crop suits a figure at 40% of the column; at full width it makes a
   letterbox tall enough to push the following text off the screen. */
.history-figure-full .history-figure-img {
  aspect-ratio: 16 / 9;
}

/* Several full-width photographs on one paragraph: a row of bands sharing the
   column rather than a deck. A stack exists to stop floats colliding, and
   bands do not float, so hiding all but one would only bury photographs.
   Three across, wrapping; two and four split evenly instead, so no row ends
   on a lone card beside two empty cells. */
.history-figure-row {
  clear: both;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin: 1.25rem 0;
}

.history-figure-row:has(> :nth-child(2):last-child),
.history-figure-row:has(> :nth-child(4):last-child) {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.history-figure-row > .history-figure-row-item {
  width: auto;
  max-width: none;
  margin: 0;
}

.history-figure-img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  cursor: zoom-in;
}

.history-figure-img:focus-visible {
  outline: 3px solid var(--accent-color);
  outline-offset: -3px;
}

.history-figure-caption {
  padding: .6rem .75rem;
  margin: 0;
  font-size: .85rem;
  line-height: 1.4;
  font-weight: 500;
  color: var(--muted-strong-color);
  text-align: center;
  border-top: 1px solid var(--border-color);
  background: var(--bg-wash);
}

/* Floats are out of flow, so without this a section whose text is shorter than
   its images would let the gallery, the divider or the next section overlap
   them. */
.history-float-clear {
  clear: both;
}

/* Tablet: the floats stay, but a 40% figure leaves too thin a column of
   justified text beside it, so the figures give up some width. */
@media (max-width: 991.98px) {
  .history-figure {
    width: 45%;
  }

  .history-figure-lead {
    margin-left: 1.5rem;
  }

  .history-figure-trail {
    margin-right: 1.5rem;
  }
}

/* Phone: a wrapped image would leave roughly twenty characters per line, so the
   floats are dropped and each figure becomes a full-width band — the lead above
   the prose, the trailing one below it. The article becomes a flex column only
   here, which is what lets `order` do that reshuffle; the DOM order is
   unchanged, so screen readers and the lightbox sequence still match. */
@media (max-width: 767.98px) {
  .history-article {
    display: flex;
    flex-direction: column;
  }

  /* A flex item defaults to `min-width: auto`, which lets a long word or URL
     push the column wider than the phone screen and send the whole page into
     horizontal scroll. Overriding it lets the text wrap inside the viewport. */
  .history-article > * {
    min-width: 0;
  }

  .history-figure,
  .history-figure-lead,
  .history-figure-trail,
  .history-figure-full {
    float: none;
    width: 100%;
    max-width: none;
    margin: 0 0 1.5rem;
    shape-outside: none;
  }

  /* The prose deck exists to stop two floats colliding, and at this width
     there are no floats to collide — so it unstacks into the same full-width
     bands every other figure becomes. Cards return to the flow, which also
     returns their captions: at 40% of a desktop column a stack saves space,
     but on a phone each photograph already spans the screen and hiding the
     ones behind would only bury them. */
  .history-figure-deck {
    width: 100%;
    max-width: none;
    /* The side room and the room below existed for the fanned corners and the
       count line; unstacked, nothing leans out and no count is drawn. */
    margin: 0;
    /* The cards are back in flow and size themselves, so the wrapper must not
       hold them to one card's height — the stack has become a column of
       full-width bands as tall as all of them together. */
    aspect-ratio: auto;
  }

  .history-figure-deck.history-figure-lead,
  .history-figure-deck.history-figure-trail {
    float: none;
    margin: 0;
    shape-outside: none;
  }

  .history-figure-deck .history-deck-card,
  .history-figure-deck .history-deck-card:first-child {
    position: relative;
    inset: auto;
    margin: 0 0 1.5rem;
    transform: none;
    filter: none;
  }

  .history-figure-deck .history-figure-caption {
    display: block;
  }

  /* Unstacked, each card sets its own height again, so the image takes its
     own crop back rather than filling a card it no longer shares. */
  .history-figure-deck .history-deck-card .history-figure-img {
    aspect-ratio: 4 / 3;
    height: auto;
  }

  /* The count described a stack that is no longer drawn. */
  .history-figure-deck .history-deck-count {
    display: none;
  }

  /* `order` reaches only the automatic figures, which are direct children of
     the article. An anchored one — full width or not — sits inside
     `.history-content`, so it is not a flex item here and stays in flow
     between the paragraphs it was anchored between, which is what a moderator
     who placed it there meant. */
  .history-figure-lead {
    order: -1;
  }

  /* At phone width every figure is already a full-width band, so the taller
     16:9 crop would only cost vertical space without changing the layout. */
  .history-figure-full .history-figure-img {
    aspect-ratio: 4 / 3;
  }

  /* Three across a phone is thumbnail size; two keeps each photograph
     readable without turning the row into a column as long as a deck. */
  .history-figure-row,
  .history-figure-row:has(> :nth-child(2):last-child),
  .history-figure-row:has(> :nth-child(4):last-child) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .75rem;
    margin: 0 0 1.5rem;
  }

  .history-content {
    order: 0;
    font-size: 1rem;
    line-height: 1.75;
  }

  .history-content > p:first-of-type {
    font-size: 1.05rem;
  }

  /* Justifying a narrow column opens rivers of whitespace between words;
     ragged-right is the more readable choice at this width. */
  .history-content p {
    text-align: left;
  }

  .history-figure-trail {
    order: 1;
    margin: 1.5rem 0 0;
  }

  .history-gallery {
    order: 2;
  }
}

/*--------------------------------------------------------------
# Overflow gallery (third image onward)
--------------------------------------------------------------*/
/* Images past the two wrapped into the prose sit in a centred grid below the
   article. A short final row stays centred rather than left-aligned
   (justify-content-center on the row). */
.history-gallery {
  margin-top: 2.5rem;
}

.history-card {
  display: flex;
  flex-direction: column;
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md, 10px);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast);
}

.history-card:hover,
.history-card:focus-within {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md, 0 6px 18px rgba(0, 0, 0, .12));
}

.history-card-img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  cursor: zoom-in;
}

.history-card-img:focus-visible {
  outline: 3px solid var(--accent-color);
  outline-offset: -3px;
}

.history-card-caption {
  padding: .6rem .75rem;
  margin: 0;
  font-size: .85rem;
  line-height: 1.35;
  font-weight: 500;
  color: var(--muted-strong-color);
  text-align: center;
  border-top: 1px solid var(--border-color);
  background: var(--bg-wash);
}

/* Separator between sections: a short centred accent rule rather than a
   full-width grey line, so a multi-section page reads as chapters of one
   article instead of unrelated blocks. */
.history-divider {
  width: min(180px, 40%);
  margin: 1rem auto 3.5rem;
  border: 0;
  border-top: 2px solid color-mix(in srgb, var(--accent-color), transparent 60%);
  opacity: 1;
}

/* Empty page: with no sections there is only a heading and one line of text,
   so the footer rides up and leaves a band of bare background beneath it.
   Holding the section open keeps the page filling the viewport until an
   editor adds content. Centred rather than top-aligned, so the notice sits in
   the space instead of clinging to the heading above it.

   40vh rather than a fixed pixel height because the header, page title and
   footer already account for the rest of the screen; a fixed value would
   overshoot on a laptop and undershoot on a tall monitor. */
.history-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 40vh;
}

/* How many photographs are in a prose deck — the one thing the fan cannot say.
   Under the stack, in the margin left below it. `top: 100%` rather than
   `bottom: 0`: the wrapper's box is exactly one card, so `bottom: 0` would
   print this over the photograph instead of beneath it. */
.history-deck-count {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin: 2.25rem 0 0;
  text-align: center;
  font-size: .85rem;
  font-weight: 500;
  color: var(--muted-strong-color);
}

/* The hover lift is decoration, not information — drop it when the visitor has
   asked the system for less motion. The fan itself stays: it is the layout,
   not an animation. */
@media (prefers-reduced-motion: reduce) {

  .history-figure,
  .history-card {
    transition: none;
  }

  .history-figure:hover,
  .history-figure:focus-within,
  .history-card:hover,
  .history-card:focus-within {
    transform: none;
  }

  /* The fan stays — the lean is the layout, not an animation — but the lift
     on the leading card goes. The leaning cards keep the angles set further
     up; nothing here overrides them, so they need no restating. */
  .history-figure-deck:hover .history-deck-card:first-child,
  .history-figure-deck:focus-within .history-deck-card:first-child,
  .history-figure-deck .history-deck-card:first-child:hover,
  .history-figure-deck .history-deck-card:first-child:focus-within {
    transform: none;
  }
}

/* Without `:has()` the deck cannot be made keyboard-accessible: focus lands on
   an image inside a card, and lifting that card out of the stack is something
   only a parent selector can do — each card sets `transform` and `filter`,
   each of which traps a descendant's z-index in its own stacking context, so
   no rule on the image can raise it above the card in front.

   In practice this matches no browser that can render the site: the colour
   system uses `color-mix()`, which shipped after `:has()` in every engine.
   It is here so the deck degrades to something correct rather than to
   something subtly broken. */
@supports not selector(:has(*)) {

  /* So rather than ship a deck that hides the focus ring, the deck inside the
     prose unstacks into ordinary placed figures. They may then collide as
     they did before — but a squeezed
     paragraph is a layout annoyance, whereas an invisible focus ring locks a
     keyboard visitor out of the photographs entirely. */
  .history-figure-deck {
    /* Nothing leans out once the cards are unstacked, so the room kept for
       the fanned corners and the count line would only narrow the
       photographs. The cards size themselves again, so the wrapper must stop
       holding them to one card's height. */
    margin-inline: 0;
    margin-bottom: 1.25rem;
    aspect-ratio: auto;
  }

  .history-figure-deck .history-deck-card,
  .history-figure-deck .history-deck-card:first-child {
    position: relative;
    inset: auto;
    margin: 0 0 1.25rem;
    transform: none;
    filter: none;
  }

  .history-figure-deck .history-figure-caption {
    display: block;
  }

  /* Each card sizes itself again, so the crop comes back — see the same pair
     of rules in the phone breakpoint above. */
  .history-figure-deck .history-deck-card .history-figure-img {
    aspect-ratio: 4 / 3;
    height: auto;
  }

  .history-figure-deck .history-deck-count {
    display: none;
  }
}

/*--------------------------------------------------------------
# Announcement / Event Detail
--------------------------------------------------------------*/
.announcement-hero {
  width: 100%;
  max-height: 420px;
  object-fit: cover;
}

/* "Booking open" pill, used in the homepage list and on event cards. */
.ann-badge-booking {
  background: var(--accent-color);
  color: var(--contrast-color);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .02em;
}

.event-panel {
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: 12px;
  padding: 1.25rem;
  box-shadow: var(--shadow-sm);
}

.event-panel-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--heading-color);
  margin: 0 0 .85rem;
}

.event-facts dt {
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-color);
  margin-top: .75rem;
}

.event-facts dt:first-child {
  margin-top: 0;
}

.event-facts dd {
  margin: .15rem 0 0;
  color: var(--default-color);
}

/* Honeypot: off-screen rather than display:none, since some bots skip
   hidden inputs but will still fill a visually-positioned one. */
.rsvp-hp {
  position: absolute !important;
  left: -9999px !important;
  width: 1px !important;
  height: 1px !important;
  opacity: 0 !important;
  pointer-events: none;
}

/* Sidebar announcement browser — jump between announcements without
   returning to the homepage. Fixed height so the panel can't push the
   booking form off-screen on an archive with many entries. */
.ann-browser-scroll {
  max-height: 420px;
  overflow-y: auto;
  padding-right: var(--space-sm);
}

.ann-browser-group {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted-color);
  margin: var(--space-md) 0 var(--space-sm);
}

.ann-browser-group:first-child {
  margin-top: 0;
}

.ann-browser-item {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  padding: .7rem .85rem;
  margin-bottom: var(--space-sm);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  /* Events carry an accent spine so they read as a different kind of
     item than plain notices at a glance. */
  border-left: 3px solid var(--border-color);
  border-radius: var(--radius-lg);
  text-decoration: none;
  color: var(--default-color);
  transition: transform var(--transition-fast), box-shadow var(--transition-fast),
              border-color var(--transition-fast);
}

.ann-browser-item:last-child {
  margin-bottom: 0;
}

.ann-browser-item.is-event {
  border-left-color: var(--accent-color);
}

.ann-browser-item.is-past {
  border-left-color: var(--muted-light-color);
}

.ann-browser-item.is-past .ann-browser-title {
  color: var(--muted-strong-color);
}

.ann-browser-item:hover,
.ann-browser-item:focus-visible {
  transform: translateX(2px);
  box-shadow: var(--shadow-sm);
  color: var(--default-color);
}

.ann-browser-item:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
}

.ann-browser-date,
.ann-browser-place {
  font-size: .78rem;
  color: var(--muted-color);
}

/* Activities documenting an event read as an outbound link, not a sibling
   announcement, so they get the accent treatment rather than a date spine. */
.ann-browser-item.is-activity {
  border-left-color: var(--accent-color);
}

.ann-browser-item.is-activity .ann-browser-place {
  color: var(--accent-color);
  font-weight: 600;
}

.ann-browser-flag {
  font-size: .72rem;
  font-weight: 600;
  color: var(--accent-color);
  margin-top: .15rem;
}

.ann-browser-title {
  font-weight: 600;
  color: var(--heading-color);
  line-height: 1.35;
}

.rsvp-success-icon {
  font-size: 3.5rem;
  line-height: 1;
  color: var(--accent-color);
}

/*--------------------------------------------------------------
# Team Section
--------------------------------------------------------------*/
.team .team-member {
  background-color: var(--surface-color);
  box-shadow: var(--shadow-sm);
  position: relative;
  border-radius: var(--radius-md);
  transition: var(--transition-base);
  padding: 30px;
  height: 100%;
}

@media (max-width: 576px) {
  .team .team-member {
    flex-direction: column;
    justify-content: center !important;
    align-items: center !important;
  }
}

.team .team-member .pic {
  overflow: hidden;
  width: 150px;
  aspect-ratio: 3 / 4;
  border-radius: var(--radius-base);
  flex-shrink: 0;
}

.team .team-member .pic img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: ease-in-out 0.3s;
}

.team .team-member:hover {
  transform: translateY(-10px);
}

.team .team-member .member-info {
  padding-left: 30px;
}

@media (max-width: 576px) {
  .team .team-member .member-info {
    padding: 30px 0 0 0;
    text-align: center;
  }
}

.team .team-member h4 {
  font-weight: 700;
  margin-bottom: 5px;
  font-size: var(--font-lg);
}

.team .team-member span {
  display: block;
  font-size: 15px;
  padding-bottom: 10px;
  position: relative;
  font-weight: 500;
}

.team .team-member span::after {
  content: "";
  position: absolute;
  display: block;
  width: 50px;
  height: 1px;
  background: var(--decorative-rule-color);
  bottom: 0;
  left: 0;
}

@media (max-width: 576px) {
  .team .team-member span::after {
    left: calc(50% - 25px);
  }
}

.team .team-member p {
  margin: 10px 0 0 0;
  font-size: var(--font-sm);
}

.team .team-member .social {
  margin-top: 12px;
  display: flex;
  align-items: center;
  justify-content: start;
  width: 100%;
}

@media (max-width: 576px) {
  .team .team-member .social {
    justify-content: center;
  }
}

.team .team-member .social a {
  background: var(--bg-subtle);
  transition: ease-in-out var(--transition-fast);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50px;
  width: 36px;
  height: 36px;
}

.team .team-member .social a i {
  color: var(--text-emphasis-color);
  font-size: var(--font-base);
  margin: 0 2px;
}

.team .team-member .social a:hover {
  background: var(--accent-color);
}

.team .team-member .social a:hover i {
  color: var(--contrast-color);
}

.team .team-member .social a+a {
  margin-left: 8px;
}

/*--------------------------------------------------------------
# Blog Details Section
--------------------------------------------------------------*/
.blog-details {
  padding-bottom: 30px;
}

.blog-details .article {
  background-color: var(--surface-color);
  padding: 30px;
  box-shadow: var(--shadow-md);
}

.blog-details .post-img {
  margin: -30px -30px 20px -30px;
  overflow: hidden;
}

.blog-details .title {
  color: var(--heading-color);
  font-size: 28px;
  font-weight: 700;
  padding: 0;
  margin: 30px 0;
}

.blog-details .content {
  margin-top: 20px;
}

.blog-details .content h3 {
  font-size: 22px;
  margin-top: 30px;
  font-weight: bold;
}

.blog-details .content blockquote {
  overflow: hidden;
  background-color: var(--ghost-color);
  padding: 60px;
  position: relative;
  text-align: center;
  margin: 20px 0;
}

.blog-details .content blockquote p {
  color: var(--default-color);
  line-height: 1.6;
  margin-bottom: 0;
  font-style: italic;
  font-weight: 500;
  font-size: 22px;
}

.blog-details .content blockquote:after {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 3px;
  background-color: var(--accent-color);
  margin-top: 20px;
  margin-bottom: 20px;
}

.blog-details .meta-top {
  margin-top: 20px;
  color: var(--muted-strong-color);
}

.blog-details .meta-top ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  align-items: center;
  padding: 0;
  margin: 0;
}

.blog-details .meta-top ul li+li {
  padding-left: 20px;
}

.blog-details .meta-top i {
  font-size: var(--font-base);
  margin-right: 8px;
  line-height: 0;
  color: var(--muted-strong-color);
}

.blog-details .meta-top a {
  color: var(--muted-strong-color);
  font-size: var(--font-sm);
  display: inline-block;
  line-height: 1;
}

.blog-details .meta-bottom {
  padding-top: 10px;
  border-top: 1px solid var(--border-color);
}

.blog-details .meta-bottom i {
  color: var(--muted-strong-color);
  display: inline;
}

.blog-details .meta-bottom a {
  color: var(--muted-strong-color);
  transition: 0.3s;
}

.blog-details .meta-bottom a:hover {
  color: var(--accent-color);
}

.blog-details .meta-bottom .cats {
  list-style: none;
  display: inline;
  padding: 0 20px 0 0;
  font-size: var(--font-sm);
}

.blog-details .meta-bottom .cats li {
  display: inline-block;
}

.blog-details .meta-bottom .tags {
  list-style: none;
  display: inline;
  padding: 0;
  font-size: var(--font-sm);
}

.blog-details .meta-bottom .tags li {
  display: inline-block;
}

.blog-details .meta-bottom .tags li+li::before {
  padding-right: 6px;
  color: var(--default-color);
  content: ",";
}

.blog-details .meta-bottom .share {
  font-size: var(--font-base);
}

.blog-details .meta-bottom .share i {
  padding-left: 5px;
}

/*--------------------------------------------------------------
# Blog Comments Section
--------------------------------------------------------------*/
.blog-comments {
  padding: 10px 0;
}

.blog-comments .comments-count {
  font-weight: bold;
}

.blog-comments .comment {
  margin-top: 30px;
  position: relative;
}

.blog-comments .comment .comment-img {
  margin-right: 14px;
}

.blog-comments .comment .comment-img img {
  width: 60px;
}

.blog-comments .comment h5 {
  font-size: var(--font-base);
  margin-bottom: 2px;
}

.blog-comments .comment h5 a {
  font-weight: bold;
  color: var(--default-color);
  transition: 0.3s;
}

.blog-comments .comment h5 a:hover {
  color: var(--accent-color);
}

.blog-comments .comment h5 .reply {
  padding-left: 10px;
  color: var(--text-emphasis-color);
}

.blog-comments .comment h5 .reply i {
  font-size: var(--font-lg);
}

.blog-comments .comment time {
  display: block;
  font-size: var(--font-sm);
  color: var(--muted-strong-color);
  margin-bottom: 5px;
}

.blog-comments .comment.comment-reply {
  padding-left: 40px;
}

/*--------------------------------------------------------------
# Comment Form Section
--------------------------------------------------------------*/
.comment-form {
  padding-top: 10px;
}

.comment-form form {
  background-color: var(--surface-color);
  margin-top: 30px;
  padding: 30px;
  box-shadow: var(--shadow-md);
}

.comment-form form h4 {
  font-weight: bold;
  font-size: 22px;
}

.comment-form form p {
  font-size: var(--font-sm);
}

.comment-form form input {
  background-color: var(--surface-color);
  color: var(--default-color);
  border: 1px solid var(--input-border-color);
  font-size: var(--font-sm);
  border-radius: 4px;
  padding: 10px 10px;
}

.comment-form form input:focus {
  color: var(--default-color);
  background-color: var(--surface-color);
  box-shadow: none;
  border-color: var(--accent-color);
}

.comment-form form input::placeholder {
  color: var(--muted-color);
}

.comment-form form textarea {
  background-color: var(--surface-color);
  color: var(--default-color);
  border: 1px solid var(--input-border-color);
  border-radius: 4px;
  padding: 10px 10px;
  font-size: var(--font-sm);
  height: 120px;
}

.comment-form form textarea:focus {
  color: var(--default-color);
  box-shadow: none;
  border-color: var(--accent-color);
  background-color: var(--surface-color);
}

.comment-form form textarea::placeholder {
  color: var(--muted-color);
}

.comment-form form .form-group {
  margin-bottom: 25px;
}

.comment-form form .btn-primary {
  padding: 10px 20px;
}

/* .comment-form form .btn-primary:hover {
 
} */

/*--------------------------------------------------------------
# Blog Posts Section
--------------------------------------------------------------*/
.blog-posts article {
  background-color: var(--surface-color);
  box-shadow: var(--shadow-sm);
  transition: 0.3s;
}

.blog-posts .post-img img {
  transition: 0.5s;
}

.blog-posts .post-date {
  background-color: var(--accent-color);
  color: var(--contrast-color);
  position: absolute;
  right: 0;
  bottom: 0;
  text-transform: uppercase;
  font-size: 13px;
  padding: 6px 12px;
  font-weight: 500;
}

.blog-posts .post-content {
  padding: 30px;
}

.blog-posts .post-title {
  font-size: var(--font-lg);
  color: var(--heading-color);
  font-weight: 700;
  transition: 0.3s;
  margin-bottom: 15px;
}

.blog-posts .meta i {
  font-size: var(--font-base);
  color: var(--accent-color);
}

.blog-posts .meta span {
  font-size: 15px;
  color: var(--muted-strong-color);
}

.blog-posts p {
  margin-top: 20px;
}

.blog-posts hr {
  color: var(--muted-soft-color);
  margin-bottom: 15px;
}

.blog-posts .readmore {
  display: flex;
  align-items: center;
  font-weight: 600;
  line-height: 1;
  transition: 0.3s;
  color: color-mix(in srgb, var(--heading-color), transparent 20%);
}

.blog-posts .readmore i {
  line-height: 0;
  margin-left: 6px;
  font-size: var(--font-base);
}

.blog-posts article:hover .post-title,
.blog-posts article:hover .readmore {
  color: var(--accent-color);
}

.blog-posts article:hover .post-img img {
  transform: scale(1.1);
}

/*--------------------------------------------------------------
# Blog Pagination Section
--------------------------------------------------------------*/
.blog-pagination {
  padding-top: 0;
  color: var(--muted-strong-color);
}

.blog-pagination ul {
  display: flex;
  padding: 0;
  margin: 0;
  list-style: none;
}

.blog-pagination li {
  margin: 0 5px;
  transition: 0.3s;
}

.blog-pagination li a {
  color: var(--muted-strong-color);
  padding: 7px 16px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.blog-pagination li a.active,
.blog-pagination li a:hover {
  background: var(--accent-color);
  color: var(--contrast-color);
}

.blog-pagination li a.active a,
.blog-pagination li a:hover a {
  color: var(--contrast-color);
}

/*--------------------------------------------------------------
# Contact Section
--------------------------------------------------------------*/
.contact .info-item+.info-item {
  margin-top: 40px;
}

.contact .info-item i {
  color: var(--contrast-color);
  background: var(--accent-color);
  font-size: var(--font-lg);
  width: 44px;
  height: 44px;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 4px;
  transition: all 0.3s ease-in-out;
  margin-right: 15px;
}

.contact .info-item h3 {
  padding: 0;
  font-size: var(--font-md);
  font-weight: 700;
  margin-bottom: 5px;
}

.contact .info-item p {
  padding: 0;
  margin-bottom: 0;
  font-size: var(--font-sm);
}

.contact .contact-form {
  height: 100%;
}

.contact .contact-form input[type=text],
.contact .contact-form input[type=email],
.contact .contact-form textarea {
  font-size: var(--font-sm);
  padding: 10px 15px;
  box-shadow: none;
  border-radius: 0;
  color: var(--default-color);
  background-color: color-mix(in srgb, var(--background-color), transparent 50%);
  border-color: var(--input-border-color);
}

.contact .contact-form input[type=text]:focus,
.contact .contact-form input[type=email]:focus,
.contact .contact-form textarea:focus {
  border-color: var(--accent-color);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-color), transparent 88%);
  background-color: #fff;
}

.contact .contact-form input[type=text]::placeholder,
.contact .contact-form input[type=email]::placeholder,
.contact .contact-form textarea::placeholder {
  color: var(--muted-light-color);
}

.contact .contact-form button[type=submit] {
  padding: 10px 30px;
}

/* .contact .contact-form button[type=submit]:hover {

} */

/*--------------------------------------------------------------
# Widgets
--------------------------------------------------------------*/
.widgets-container {
  margin: 40px 0 30px 0;
}

.widget-title {
  color: var(--heading-color);
  font-size: var(--font-lg);
  font-weight: 600;
  padding: 0 0 0 10px;
  margin: 0 0 20px 0;
  border-left: 4px solid var(--accent-color);
}

.widget-item {
  margin-bottom: 30px;
  background-color: var(--bg-wash);
  border: 1px solid var(--border-color);
  padding: 30px;
  border-radius: 5px;
}

.widget-item:last-child {
  margin-bottom: 0;
}

.blog-author-widget img {
  max-width: 120px;
  margin-right: 20px;
}

.blog-author-widget h4 {
  font-weight: 600;
  font-size: var(--font-xl);
  margin-bottom: 0px;
  padding: 0;
  color: var(--text-emphasis-color);
}

.blog-author-widget .social-links {
  margin: 5px 0;
}

.blog-author-widget .social-links a {
  color: var(--muted-soft-color);
  margin-right: 5px;
  font-size: var(--font-md);
}

.blog-author-widget .social-links a:hover {
  color: var(--accent-color);
}

.blog-author-widget p {
  font-style: italic;
  color: var(--text-strong-color);
  margin: 10px 0 0 0;
}

.search-widget form {
  background: var(--background-color);
  border: 1px solid var(--input-border-color);
  padding: 3px 10px;
  position: relative;
  border-radius: 50px;
  transition: 0.3s;
}

.search-widget form input[type=text] {
  border: 0;
  padding: 4px 10px;
  border-radius: 4px;
  width: calc(100% - 40px);
  background-color: var(--background-color);
  color: var(--default-color);
}

.search-widget form input[type=text]:focus {
  outline: none;
  /* focus ring handled by parent :focus-within */
}

.search-widget form button {
  background: none;
  color: var(--default-color);
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  border: 0;
  font-size: var(--font-base);
  padding: 0 16px;
  transition: 0.3s;
  line-height: 0;
}

.search-widget form button i {
  line-height: 0;
}

.search-widget form button:hover {
  color: var(--accent-color);
}

.search-widget form:is(:focus-within) {
  border-color: var(--accent-color);
}

.recent-posts-widget .post-item {
  display: flex;
  margin-bottom: 15px;
}

.recent-posts-widget .post-item:last-child {
  margin-bottom: 0;
}

.recent-posts-widget .post-item img {
  width: 80px;
  margin-right: 15px;
}

.recent-posts-widget .post-item h4 {
  font-size: 15px;
  font-weight: bold;
  margin-bottom: 5px;
}

.recent-posts-widget .post-item h4 a {
  color: var(--default-color);
  transition: 0.3s;
}

.recent-posts-widget .post-item h4 a:hover {
  color: var(--accent-color);
}

.recent-posts-widget .post-item time {
  display: block;
  font-style: italic;
  font-size: var(--font-sm);
  color: var(--muted-color);
}

.tags-widget ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.tags-widget ul li {
  display: inline-block;
}

.tags-widget ul a {
  background-color: var(--bg-subtle);
  color: var(--text-strong-color);
  border-radius: 50px;
  font-size: var(--font-sm);
  padding: 5px 15px;
  margin: 0 6px 8px 0;
  display: inline-block;
  transition: 0.3s;
}

.tags-widget ul a:hover {
  background: var(--accent-color);
  color: var(--contrast-color);
}

.tags-widget ul a span {
  padding-left: 5px;
  color: var(--muted-soft-color);
  font-size: var(--font-sm);
}

.blog-author-widget-2 img {
  max-width: 160px;
}

.blog-author-widget-2 h4 {
  font-weight: 600;
  font-size: var(--font-xl);
  margin: 15px 0 0 0;
  padding: 0;
  color: var(--text-emphasis-color);
}

.blog-author-widget-2 .social-links {
  margin: 5px 0;
}

.blog-author-widget-2 .social-links a {
  color: var(--muted-soft-color);
  margin: 0 3px;
  font-size: var(--font-md);
}

.blog-author-widget-2 .social-links a:hover {
  color: var(--accent-color);
}

.blog-author-widget-2 p {
  font-style: italic;
  color: var(--text-strong-color);
  margin: 10px 0 0 0;
}

/*--------------------------------------------------------------
# Gallery Page
--------------------------------------------------------------*/

/* Filtering swaps the grid over AJAX, so a category with only a couple of
   items would otherwise collapse the page and pull the footer up the screen
   mid-click. Reserving a viewport's worth of height keeps the footer put
   whatever the result count is. The sidebar is sticky and can be taller than
   a short result set, so this is a floor for the whole section, not the grid. */
.gallery-section {
  min-height: 100vh;
}

/* Sidebar */
.gallery-page aside.col-lg-3 {
  align-self: flex-start;
}

.gallery-sidebar {
  position: sticky;
  top: 80px;
}

.sidebar-label {
  display: block;
  font-family: var(--nav-font);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted-color);
  margin-bottom: 10px;
}

/* Collapsible sidebar sections (Categories / Sort).

   The toggle is a <button> so it is keyboard-operable, but it has to read as
   the plain label it replaced, hence the button reset. */
.sidebar-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
}

.sidebar-toggle-text {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

/* Active-selection hints shown while the panel is closed. */
.sidebar-toggle-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background-color: var(--accent-color);
  color: var(--contrast-color);
  font-size: 0.65rem;
  letter-spacing: 0;
}

.sidebar-toggle-value {
  color: var(--accent-color);
  font-weight: 600;
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  text-transform: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* .sidebar-toggle-badge sets display: inline-flex, which would otherwise win
   over the [hidden] attribute the JS toggles. */
.sidebar-toggle-badge[hidden],
.sidebar-toggle-value[hidden] {
  display: none;
}

.sidebar-toggle-icon {
  flex-shrink: 0;
  font-size: 0.8rem;
  transition: transform var(--transition-fast);
}

/* Bootstrap sets aria-expanded on the toggle itself, so the chevron can follow
   the panel state without any extra JS. */
.sidebar-toggle[aria-expanded="true"] .sidebar-toggle-icon {
  transform: rotate(180deg);
}

.sidebar-toggle:hover,
.sidebar-toggle:focus-visible {
  color: var(--accent-color);
}

.sidebar-toggle:focus {
  outline: none;
}

.sidebar-toggle:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 3px;
}

/* Desktop/tablet: no collapsing at all. The panel is forced open and the
   toggle degrades to a static label. !important is needed to beat Bootstrap's
   own .collapse { display: none } when the panel lacks .show. */
@media (min-width: 768px) {
  .sidebar-collapse {
    display: block !important;
    height: auto !important;
    visibility: visible !important;
  }

  .sidebar-toggle {
    cursor: default;
    pointer-events: none;
  }

  .sidebar-toggle-icon,
  .sidebar-toggle-badge,
  .sidebar-toggle-value {
    display: none;
  }
}

/* Phones and small tablets: the sections are stacked and usually collapsed, so
   the desktop spacing between them reads as dead space. Tighten the gaps and
   let the toggle's own padding provide the tap target instead of margins. */
@media (max-width: 767.98px) {

  /* The sidebar is a flex column here, so the 24px gap inherited from the
     tablet rules applies between every section. */
  .gallery-sidebar {
    gap: 4px !important;
    padding: 14px !important;
  }

  /* Each section is full width once stacked; flex-basis 220px would otherwise
     try to sit them side by side at wider phone sizes. */
  .gallery-filter,
  .gallery-sort {
    flex: 1 1 100% !important;
    margin-top: 0 !important;
  }

  .gallery-search {
    margin-bottom: 4px !important;
  }

  /* The label's bottom margin is spacing for an open panel; when the panel is
     closed it is pure gap between two headers. Move it onto the panel. */
  .sidebar-toggle {
    margin-bottom: 0;
    padding: 9px 0;
  }

  .sidebar-collapse.show {
    padding-bottom: 4px;
  }

  /* Separator between the two collapsed rows, so tightening the gap does not
     make them read as one block. */
  .gallery-sort .sidebar-toggle {
    border-top: 1px solid var(--border-color);
  }
}

/* Search */
.gallery-search .form-control {
  background-color: var(--surface-color);
  border: 1px solid var(--input-border-color);
  border-right: none;
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
  color: var(--default-color);
  font-size: 0.9rem;
  padding: 8px 12px;
}

.gallery-search .form-control:focus {
  box-shadow: none;
  border-color: var(--accent-color);
}

.gallery-search-btn {
  background-color: var(--accent-color);
  border: 1px solid var(--accent-color);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  color: var(--contrast-color);
  padding: 8px 14px;
  transition: background-color var(--transition-fast);
}

.gallery-search-btn:hover {
  background-color: var(--accent-hover);
  border-color: var(--accent-hover);
  color: var(--contrast-color);
}

.gallery-clear-btn {
  background-color: transparent;
  border: 1px solid var(--border-color);
  color: var(--muted-color);
  font-size: 0.82rem;
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  transition: background-color var(--transition-fast), color var(--transition-fast),
    border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.gallery-clear-btn:hover,
.gallery-clear-btn:focus,
.gallery-clear-btn:focus-visible,
.gallery-clear-btn:active,
.gallery-clear-btn:active:focus {
  background-color: transparent;
  border-color: var(--accent-color);
  color: var(--accent-color);
}

.gallery-clear-btn:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
  box-shadow: none;
}

.gallery-clear-btn:focus,
.gallery-clear-btn:active {
  box-shadow: none;
}

/* Filter list */
.filter-list {
  border-top: 1px solid var(--border-color);
}

.filter-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 9px 0;
  border-bottom: 1px solid var(--border-color);
  color: var(--default-color);
  font-size: 1.1rem;
  text-decoration: none;
  transition: color var(--transition-fast);
}

.filter-link:hover,
.filter-link.active {
  color: var(--accent-color);
}

.filter-link.active {
  font-weight: 600;
}

.filter-count {
  font-size: 0.78rem;
  color: var(--muted-color);
  background-color: var(--bg-subtle);
  border-radius: 20px;
  padding: 1px 8px;
  font-family: var(--nav-font);
}

.filter-link.active .filter-count,
.filter-link:hover .filter-count {
  background-color: var(--accent-faint);
  color: var(--accent-color);
}

/* Subcategory: indented under its parent */
.filter-item-sub .filter-link {
  margin-left: 20px;
  font-size: 1rem;
}

/* Results bar */
.gallery-results-bar {
  border-bottom: 1px solid var(--border-color);
  padding-bottom: 10px;
}

.results-count {
  font-family: var(--nav-font);
  font-size: 0.85rem;
  color: var(--muted-color);
}

.clear-filters {
  font-family: var(--nav-font);
  font-size: 0.82rem;
  color: var(--muted-color);
  text-decoration: none;
  transition: color var(--transition-fast);
}

.clear-filters:hover {
  color: var(--accent-color);
}

/* Cards */
.gallery-card {
  background-color: var(--surface-color);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: box-shadow var(--transition-fast), transform var(--transition-fast);
}

.gallery-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}

.gallery-card-img-wrap {
  display: block;
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
}

.gallery-card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.gallery-card:hover .gallery-card-img {
  transform: scale(1.04);
}

.gallery-card-img-placeholder {
  width: 100%;
  height: 100%;
  background-color: var(--bg-subtle);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted-color);
  font-size: 2.5rem;
}

.gallery-card-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  background-color: var(--accent-color);
  color: var(--contrast-color);
  font-family: var(--nav-font);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  padding: 3px 10px;
  border-radius: 20px;
}

.gallery-card-body {
  padding: 16px 18px 20px;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.gallery-card-title {
  font-size: 1.4rem;
  margin-bottom: 6px;
}

.gallery-card-title a {
  color: var(--heading-color);
  text-decoration: none;
  transition: color var(--transition-fast);
}

.gallery-card-title a:hover {
  color: var(--accent-color);
}

.gallery-card-meta {
  font-family: var(--nav-font);
  font-size: 0.78rem;
  color: var(--muted-color);
  margin-bottom: 8px;
}

.gallery-card-desc {
  font-size: 0.9rem;
  color: var(--muted-strong-color);
  margin: 0;
  line-height: 1.6;
}

/* Empty state */
.gallery-empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--muted-color);
}

.gallery-btn-reset {
  background-color: transparent;
  border: 1px solid var(--accent-color);
  color: var(--accent-color);
  border-radius: var(--radius-sm);
  padding: 7px 20px;
  font-family: var(--nav-font);
  font-size: 0.85rem;
  transition: all var(--transition-fast);
}

.gallery-btn-reset:hover {
  background-color: var(--accent-color);
  color: var(--contrast-color);
}

/* Pagination */
.gallery-pagination .page-link {
  color: var(--default-color);
  border-color: var(--border-color);
  background-color: var(--surface-color);
  font-family: var(--nav-font);
  font-size: 0.9rem;
  padding: 7px 14px;
  transition: all var(--transition-fast);
}

.gallery-pagination .page-link:hover,
.gallery-pagination .page-item.active .page-link {
  background-color: var(--accent-color);
  border-color: var(--accent-color);
  color: var(--contrast-color);
}

/* Loading overlay */
.gallery-loading-overlay {
  display: flex;
  position: absolute;
  inset: 0;
  z-index: var(--z-overlay);
  background-color: color-mix(in srgb, var(--background-color), transparent 15%);
  backdrop-filter: blur(2px);
  border-radius: var(--radius-md);
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.18s ease, visibility 0.18s ease;
}

.gallery-loading-overlay.is-active {
  opacity: 1;
  visibility: visible;
}

.gallery-spinner {
  display: flex;
  align-items: center;
  justify-content: center;
}

.gallery-spinner-ring {
  display: block;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 3px solid var(--accent-faint);
  border-top-color: var(--accent-color);
  animation: gallery-spin 0.75s linear infinite;
}

@keyframes gallery-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Infinite-scroll load-more indicator */
.gallery-load-more {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 20px 0 8px;
  color: var(--default-color);
  font-family: var(--nav-font);
  font-size: 0.9rem;
}

.gallery-load-more-text {
  opacity: 0.75;
}

.gallery-spinner-ring-sm {
  display: block;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--accent-faint);
  border-top-color: var(--accent-color);
  animation: gallery-spin 0.75s linear infinite;
  flex-shrink: 0;
}

/* ── Item detail page ── */
.item-detail-back {
  display: inline-flex;
  align-items: center;
  font-family: var(--nav-font);
  font-size: 0.88rem;
  color: var(--accent-color);
  text-decoration: none;
  transition: color var(--transition-fast);
}

.item-detail-back:hover {
  color: var(--accent-hover);
}

.item-detail-img-wrap {
  border-radius: var(--radius-md);
  overflow: hidden;
  background-color: var(--bg-subtle);
}

.item-detail-img {
  width: 100%;
  height: auto;
  display: block;
  object-fit: cover;
}

.item-detail-img-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 320px;
  font-size: 4rem;
  color: var(--muted-color);
}

.item-detail-badge {
  display: inline-block;
  background-color: var(--accent-color);
  color: var(--contrast-color);
  font-family: var(--nav-font);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 4px 12px;
  border-radius: 20px;
  margin-bottom: 12px;
}

.item-detail-title {
  font-family: var(--heading-font);
  font-size: 2rem;
  color: var(--heading-color);
  margin-bottom: 12px;
  line-height: 1.3;
}

.item-detail-meta {
  font-family: var(--nav-font);
  font-size: 0.9rem;
  color: var(--muted-color);
  margin-bottom: 20px;
}

.item-detail-desc {
  font-size: 1rem;
  line-height: 1.75;
  color: var(--default-color);
}

/* Responsive: sidebar becomes top bar on mobile */
@media (max-width: 991px) {
  .gallery-sidebar {
    position: static;
    display: flex;
    gap: 24px;
    flex-wrap: wrap;
    align-items: flex-start;
    background-color: var(--surface-color);
    border-radius: var(--radius-md);
    padding: 16px;
    box-shadow: var(--shadow-sm);
  }

  .gallery-search {
    flex: 1 1 220px;
    margin-bottom: 0 !important;
  }

  .gallery-filter {
    flex: 1 1 220px;
  }

  .gallery-sort {
    flex: 1 1 220px;
    margin-top: 0 !important;
  }

  .filter-list {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    border-top: none;
  }

  .filter-link {
    border-bottom: none;
    padding: 4px 12px;
    background-color: var(--bg-subtle);
    border-radius: 20px;
    font-size: 0.85rem;
  }

  .filter-link.active {
    background-color: var(--accent-faint);
    color: var(--accent-color);
  }

  .filter-count {
    display: none;
  }
}

/* ==========================================================================
   Moderator Panel
   ========================================================================== */

.moderator-panel-page .main { background: var(--bg-subtle); }

/* ── Layout ── */
.panel-section { padding: 2rem 0 4rem; min-height:60vh; }
.panel-page-title { font-size: 1.5rem; font-weight: 700; color: var(--heading-color); margin: 0; }

/* ── Sidebar nav ──
   Two columns from lg up; below that the sidebar collapses behind the
   "Sections" button and stacks above the content. */
.panel-layout { display: block; }
.panel-tab-content { padding-top: 1.5rem; min-width: 0; }

.panel-sidebar { margin-bottom: 1rem; }
.panel-nav-group + .panel-nav-group { margin-top: 1.25rem; }
.panel-nav-group-title {
  font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted-color); padding: 0 .75rem .35rem; opacity: .75;
}
.panel-nav-link {
  display: flex; align-items: center; gap: .6rem; width: 100%;
  padding: .5rem .75rem; border: none; border-radius: 8px;
  background: transparent; color: var(--default-color);
  font-size: .92rem; font-weight: 500; text-align: left;
  border-left: 3px solid transparent;
}
.panel-nav-link .bi { font-size: 1rem; color: var(--muted-color); flex-shrink: 0; }
.panel-nav-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.panel-nav-badge { font-size: .68rem; flex-shrink: 0; }
.panel-nav-link:hover:not(.active) { background: var(--bg-subtle); color: var(--heading-color); }
.panel-nav-link.active {
  background: var(--surface-color); color: var(--heading-color); font-weight: 600;
  border-left-color: var(--heading-color);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .06);
}
.panel-nav-link.active .bi { color: var(--heading-color); }

/* The panel is a dense workspace: tables, not prose. From lg up let it break
   out of container-lg's 1140px so the columns get the room they need, capped
   so it does not sprawl on an ultrawide display. */
@media (min-width: 992px) {
  .moderator-panel-page .panel-section > .container-lg {
    max-width: min(1600px, 100% - 3rem);
  }
  .panel-layout {
    display: grid;
    /* Size the sidebar to its widest label rather than a fixed width, so no
       nav item is ever clipped. Bounded so an unusually long translation can
       never crowd out the table beside it. */
    grid-template-columns: fit-content(22rem) minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
  }
  .panel-sidebar {
    position: sticky; top: 1.5rem; margin-bottom: 0;
    /* overflow-y alone would compute overflow-x to auto as well, which is what
       produced a horizontal scrollbar; clip the x-axis explicitly. */
    max-height: calc(100vh - 3rem); overflow-y: auto; overflow-x: hidden;
    padding: 1rem .5rem;
    background: var(--surface-color); border: 1px solid var(--border-color);
    border-radius: 12px; box-shadow: 0 1px 6px rgba(0, 0, 0, .05);
  }
  /* Labels set the column width here, so let them run to their natural size
     instead of truncating into the fixed track they used to share. */
  .panel-sidebar .panel-nav-text { overflow: visible; text-overflow: clip; }
  .panel-sidebar .panel-nav-link { width: auto; min-width: 13rem; }
  .panel-tab-content { padding-top: 0; }
}

/* ── Language tabs (bilingual CRUD modal fields) ── */
.panel-lang-tabs { border-bottom: 2px solid var(--decorative-rule-color); margin-bottom: 1rem; }
.panel-lang-tabs .nav-link {
  color: var(--muted-color); border: none; border-bottom: 3px solid transparent;
  margin-bottom: -2px; font-weight: 500; padding: .4rem .9rem; font-size: .9rem;
}
.panel-lang-tabs .nav-link.active { color: var(--heading-color); border-bottom-color: var(--heading-color); background: transparent; font-weight: 600; }
.panel-lang-tabs .nav-link:hover:not(.active) { color: var(--heading-color); border-bottom-color: var(--input-border-color); }

/* The page modal's Details / Content & photos / Map tabs: a level above the
   language tabs inside them, so boxed rather than underlined. */
.panel-section-tabs { border-bottom-color: var(--border-color); }
.panel-section-tabs .nav-link { color: var(--muted-color); font-weight: 500; }
.panel-section-tabs .nav-link:hover:not(.active) { color: var(--heading-color); border-color: transparent; }
.panel-section-tabs .nav-link.active {
  color: var(--heading-color); font-weight: 600;
  background: var(--surface-color); border-color: var(--border-color) var(--border-color) var(--surface-color);
}

/* ── Cards ── */
.panel-card {
  background: var(--surface-color); border-radius: 12px; padding: 1.5rem;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .07); border: 1px solid var(--border-color);
}
.panel-card-title {
  font-size: 1.05rem; font-weight: 600; color: var(--heading-color);
  margin-bottom: 1.25rem; padding-bottom: .75rem; border-bottom: 1px solid var(--bg-subtle);
}

/* ── Stat cards ──
   Compact horizontal tiles: the icon sits beside the figure rather than
   stacked above it, so ten counters read as one dense strip instead of
   three tall rows pushing the actual working area below the fold. */
.stat-card {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: .6rem;
  row-gap: 0;
  background: var(--surface-color);
  border-radius: var(--radius-lg);
  padding: .7rem .8rem;
  box-shadow: 0 1px 6px rgba(0, 0, 0, .07);
  border: 1px solid var(--border-color);
}

.stat-icon {
  grid-row: 1 / span 2;
  font-size: 1.15rem;
  line-height: 1;
  color: var(--accent-color);
  opacity: .85;
}

.stat-nums {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--heading-color);
  line-height: 1.1;
}

.stat-total {
  font-size: .8rem;
  color: var(--muted-light-color);
  font-weight: 400;
}

.stat-label {
  font-size: .72rem;
  color: var(--muted-color);
  line-height: 1.25;
}

.stat-card-alert .stat-icon,
.stat-card-alert .stat-nums { color: var(--color-error); }

/* ── Traffic / analytics ── */
.traffic-figure {
  background: var(--bg-wash);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  padding: .75rem .9rem;
  height: 100%;
}

.traffic-figure-value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--heading-color);
  line-height: 1.15;
}

.traffic-figure-label {
  font-size: .75rem;
  color: var(--muted-color);
  margin-top: .1rem;
}

.traffic-trend {
  font-size: .75rem;
  font-weight: 600;
  vertical-align: middle;
}

.traffic-trend.is-up { color: var(--color-success); }
.traffic-trend.is-down { color: var(--color-error); }

/* Chart.js needs a bounded parent to size against, or a responsive canvas
   grows on every resize event. */
.traffic-chart-wrap {
  position: relative;
  height: 230px;
}

.traffic-subtitle {
  font-size: .78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted-color);
  margin-bottom: .5rem;
}

.traffic-table td {
  padding: .35rem .5rem;
  font-size: .85rem;
  vertical-align: middle;
}

.traffic-table a {
  color: var(--default-color);
  text-decoration: none;
}

.traffic-table a:hover {
  color: var(--accent-color);
  text-decoration: underline;
}

/* ── Labels ── */
.panel-label {
  font-size: .85rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .05em; color: var(--muted-strong-color); margin-bottom: .3rem; display: block;
}

/* ── Buttons ── */
.panel-btn-primary { background: var(--default-color); border-color: var(--default-color); color: var(--contrast-color); font-size: 1rem; }
.panel-btn-primary:hover, .panel-btn-primary:focus { background: var(--heading-color); border-color: var(--heading-color); color: var(--contrast-color); }
.panel-btn-outline { border: 1px solid var(--heading-color); color: var(--heading-color); background: transparent; font-size: .9rem; }
.panel-btn-outline:hover { background: var(--heading-color); color: var(--contrast-color); }
.panel-btn-ghost-danger { border: 1px solid var(--color-error); color: var(--color-error); background: transparent; font-size: .9rem; }
.panel-btn-ghost-danger:hover { background: var(--color-error); color: var(--contrast-color); }

/* ── Icon buttons (table actions) ── */
.panel-icon-btn {
  background: transparent; border: 1px solid var(--border-color); color: var(--muted-strong-color);
  width: 30px; height: 30px; padding: 0; display: inline-flex;
  align-items: center; justify-content: center;
  border-radius: var(--radius-base); font-size: .875rem; margin-left: 4px;
  transition: all var(--transition-fast);
}
.panel-icon-btn:hover { background: var(--bg-subtle); color: var(--heading-color); border-color: var(--input-border-color); }
.panel-icon-btn-danger:hover { background: var(--color-error); color: var(--contrast-color); border-color: var(--color-error); }

/* ── Table search ── */
.panel-search { position: relative; flex: 1 1 200px; max-width: 320px; }
.panel-search-icon {
  position: absolute; left: 10px; top: 50%; transform: translateY(-50%);
  color: var(--muted-strong-color); font-size: .875rem; pointer-events: none;
}
.panel-search-input { padding-left: 30px; }
/* Chrome draws its own clear button on type=search; the icon is enough. */
.panel-search-input::-webkit-search-cancel-button { cursor: pointer; }

/* ── Badges ── */
.panel-badge-success { background: #d4edda; color: #155724; font-weight: 500; }
.panel-badge-muted   { background: #e9ecef; color: #6c757d; font-weight: 500; }

/* ── Unread message row ── */
.msg-unread td { font-weight: 600; }
.msg-unread td:first-child::before {
  content: '';
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--default-color);
  margin-right: .45rem;
  vertical-align: middle;
  margin-bottom: 2px;
}

/* ── Table ── */
.panel-table { font-size: 1rem; }
.panel-table thead th {
  font-size: .8rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted-color); font-weight: 600; background: var(--bg-wash);
  border-bottom: 1px solid var(--border-color); padding: .7rem 1rem;
}
.panel-table tbody tr { border-bottom: 1px solid var(--bg-subtle); }
.panel-table tbody tr:last-child { border-bottom: none; }
.panel-table tbody td { padding: .8rem 1rem; vertical-align: middle; color: var(--heading-color); }

/* The title cell opens the row's edit modal, the same as its pencil button.
   The class is what the click handler keys off, so the affordance and the
   behaviour stay defined together — an inline `cursor:pointer` used to mark
   these cells, which left nothing for the handler to match on but a column
   index that differs between tables that have a drag handle and tables
   that do not. */
.panel-title-cell { cursor: pointer; }

/* ── Thumbnails ── */
.panel-thumb {
  width: 38px; height: 38px; object-fit: cover;
  border-radius: var(--radius-base); flex-shrink: 0;
}
.panel-thumb-placeholder {
  width: 38px; height: 38px; border-radius: var(--radius-base);
  background: var(--bg-subtle); display: flex; align-items: center;
  justify-content: center; color: var(--muted-light-color); font-size: 1rem; flex-shrink: 0;
}

/* ── Profile photo ── */
.profile-photo-wrap {
  width: 170px; height: 170px; border-radius: 50%;
  overflow: hidden; border: 3px solid var(--decorative-rule-color);
}
.profile-photo { width: 100%; height: 100%; object-fit: cover; }
.profile-photo-placeholder {
  width: 100%; height: 100%; background: var(--bg-subtle);
  display: flex; align-items: center; justify-content: center;
  color: var(--input-border-color); font-size: 2.8rem;
}

/* ── Modal image preview ── */
.panel-img-preview {
  max-width: 500px; max-height: 500px; object-fit: cover;
  border-radius: var(--radius-base); border: 1px solid var(--decorative-rule-color);
}

/* ── Error alert inside modal ── */
.panel-form-errors { font-size: 1rem; }

/* ── Textareas ──
   Let the moderator drag longer fields taller. Initial height comes from each
   widget's own `rows` (2–6 across the panel forms), so a summary field stays
   compact while a long description starts roomy; the bounds only stop a drag
   from collapsing the field or running past the modal. */
.moderator-panel-page textarea {
  resize: vertical;
  min-height: 4.5rem;
  max-height: 40rem;
}

/* ── Bookings tab ── */
.booking-event + .booking-event {
  margin-top: .5rem;
}

.booking-event-head {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: .75rem;
  width: 100%;
  padding: .65rem .75rem;
  background: var(--bg-subtle);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  text-align: left;
  font-size: .9rem;
  color: var(--default-color);
}

.booking-event-head:hover {
  border-color: var(--input-border-color);
}

.booking-event-title {
  font-weight: 600;
  color: var(--heading-color);
  min-width: 0;
}

.booking-caret {
  font-size: .8rem;
  color: var(--muted-color);
}

.booking-event-when,
.booking-event-count {
  font-size: .82rem;
  white-space: nowrap;
}

.booking-event-body {
  padding: .85rem .75rem .25rem;
}

.booking-row {
  display: grid;
  grid-template-columns: 1fr auto auto minmax(9rem, auto) auto;
  align-items: center;
  gap: .75rem;
  padding: .6rem .25rem;
  border-bottom: 1px solid var(--bg-subtle);
}

.booking-row:last-child {
  border-bottom: none;
}

/* Cancelled bookings stay visible as a record but read as inactive. */
.booking-row-cancelled {
  opacity: .55;
}

.booking-row-cancelled .booking-who .fw-medium {
  text-decoration: line-through;
}

.booking-who {
  min-width: 0;
  overflow-wrap: anywhere;
}

@media (max-width: 767.98px) {
  .booking-event-head {
    grid-template-columns: auto 1fr;
    row-gap: .25rem;
  }
  .booking-event-when,
  .booking-event-count {
    grid-column: 2;
  }
  .booking-row {
    grid-template-columns: 1fr auto;
    row-gap: .4rem;
  }
  .booking-who {
    grid-column: 1 / -1;
  }
}

/* ── Sortable column headers ── */
.sortable-th { cursor: pointer; user-select: none; white-space: nowrap; }
.sortable-th:hover { color: var(--heading-color); }
.sort-icon { font-size: .75rem; opacity: .35; transition: opacity var(--transition-fast); vertical-align: middle; }
.sortable-th:hover .sort-icon { opacity: .7; }
.sortable-th.sort-asc  .sort-icon,
.sortable-th.sort-desc .sort-icon { opacity: 1; color: var(--heading-color); }

/* ── Activities section ── */

.activities-section{
  min-height: 60vh;
}

/* ── Activity image lightbox ── */
/* Tint and blur sit on .modal itself, not .modal-content: Chrome skips
   backdrop-filter inside an ancestor that is mid-fade or transformed, so the
   blur would only pop in after the animation. Bootstrap's own backdrop is
   turned off (data-bs-backdrop="false") so it doesn't stack on the tint. */
.lightbox-modal {
  background: rgba(0, 0, 0, .55);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .lightbox-modal { background: rgba(0, 0, 0, .85); }
}
@media (prefers-reduced-transparency: reduce) {
  .lightbox-modal { background: #212529; -webkit-backdrop-filter: none; backdrop-filter: none; }
}
.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(255,255,255,.15);
  color: #fff;
  font-size: 1.6rem;
  line-height: 1;
  padding: .4rem .7rem;
  border: none;
  border-radius: 6px;
  opacity: .35;
  transition: opacity .18s, background .18s;
  z-index: 10;
}
.lightbox-nav:hover,
.lightbox-nav:focus-visible { opacity: 1; background: rgba(255,255,255,.3); color: #fff; outline: none; }
.lightbox-nav.d-none-soft { visibility: hidden; pointer-events: none; }
.lightbox-nav-prev { left: 1rem; }
.lightbox-nav-next { right: 1rem; }
.lightbox-img-wrap { max-height: calc(100dvh - 120px); display: flex; align-items: center; justify-content: center; }
.lightbox-img-wrap img { max-height: calc(100dvh - 120px); max-width: 100%; object-fit: contain; }
.noselect { user-select: none; -webkit-user-select: none; pointer-events: none; }
/* ── Error pages (404) ── */
.error-section {
  min-height: 60vh;
  display: flex;
  align-items: center;
  padding: var(--space-2xl) 0;
}

.error-code {
  font-family: var(--heading-font);
  font-size: clamp(72px, 18vw, 140px);
  font-weight: 700;
  line-height: 1;
  margin-bottom: var(--space-md);
  color: var(--accent-color);
  /* The digits are decoration behind the real message, so keep them light. */
  opacity: .35;
  letter-spacing: .04em;
}

.error-title {
  font-family: var(--heading-font);
  font-size: clamp(24px, 4vw, 36px);
  font-weight: 400;
  color: var(--heading-color);
  margin-bottom: var(--space-md);
}

.error-text {
  color: var(--muted-strong-color);
  font-size: var(--font-md);
  max-width: 48ch;
  margin: 0 auto;
}

/* ── Panel on phones ── */
/* Moderators are beginners and some work from a phone, so the table action
   buttons get a real touch target rather than the 30px desktop icon size. */
@media (max-width: 767.98px) {
  .moderator-panel-page .panel-icon-btn {
    width: 44px;
    height: 44px;
    font-size: 1rem;
    margin-left: 2px;
  }
  .moderator-panel-page .panel-search {
    flex-basis: 100%;
    max-width: none;
  }
  /* A full-width primary action is easier to hit than one tucked in a corner. */
  .moderator-panel-page .panel-tab-content > .tab-pane > .d-flex > .panel-btn-primary {
    flex: 1 1 100%;
  }
}

/* ── Drag-to-reorder ── */
.reorder-th { width: 34px; }
.reorder-cell { width: 34px; padding-right: 0 !important; }
.drag-handle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; cursor: grab;
  color: var(--muted-strong-color); opacity: .5;
  transition: opacity var(--transition-fast), color var(--transition-fast);
  /* Stop a drag on touch from scrolling the page instead of moving the row. */
  touch-action: none;
}
.drag-handle:hover { opacity: 1; color: var(--heading-color); }
.drag-handle:active { cursor: grabbing; }
.row-drag-ghost { opacity: .4; background: var(--bg-subtle); }
/* While a search filter hides rows, reordering is paused — show it. */
.reorder-paused .drag-handle { opacity: .15; cursor: not-allowed; }
/* Exhibits: tick boxes and the bulk "Move to category" bar. */
.select-th, .select-cell { width: 36px; padding-right: 0 !important; }
.panel-table tr.row-selected > td { background: var(--bg-wash); }
.panel-bulk-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: .5rem .75rem;
  padding: .6rem .9rem; margin-bottom: .75rem;
  /* Opaque: the bar is sticky and rows scroll underneath it. */
  background: var(--surface-color); border: 1px solid var(--border-color);
  border-radius: .6rem; box-shadow: 0 2px 10px rgba(0, 0, 0, .08);
  position: sticky; top: .5rem; z-index: 5;
}
.panel-bulk-count { font-weight: 600; color: var(--heading-color); }
.panel-bulk-label { margin: 0; font-size: .85rem; color: var(--muted-strong-color); }
.panel-bulk-select { width: auto; min-width: 14rem; max-width: 100%; }
.panel-bulk-clear { margin-left: auto; }
@media (max-width: 575.98px) {
  .panel-bulk-select { flex: 1 1 100%; min-width: 0; }
  .panel-bulk-clear { margin-left: 0; }
}
/* Exhibits: handle plus a typed position, for lists too long to drag through. */
.reorder-th-numbered, .reorder-cell-numbered { width: 92px; }
.order-input {
  width: 58px; padding: .15rem .35rem; text-align: center;
  font-variant-numeric: tabular-nums; -moz-appearance: textfield;
}
.order-input::-webkit-outer-spin-button,
.order-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

@media (max-width: 767.98px) {
  /* Match the enlarged touch targets used by the row action buttons. */
  .drag-handle { width: 40px; height: 40px; font-size: 1.15rem; }
  .reorder-th, .reorder-cell { width: 42px; }
  .reorder-th-numbered, .reorder-cell-numbered { width: 104px; }
}

/* ── Drag-to-reorder: modal thumbnails ── */
/* A thumbnail grid has no spare column for a handle, so the thumb itself is the
   grip. The caption box below stays a normal text field — Sortable's `filter`
   excludes it, and resetting the cursor there says so before anyone tries. */
.panel-img-thumb { cursor: grab; touch-action: none; }
.panel-img-thumb:active { cursor: grabbing; }
.panel-img-thumb input,
.panel-img-thumb select,
.panel-img-thumb button { cursor: auto; touch-action: auto; }
.panel-img-thumb button { cursor: pointer; }
.panel-img-thumb select { cursor: pointer; }

/* The caption box under a thumbnail, in every modal that has a gallery.
   It used to inherit the thumb's 90px, which showed about a dozen characters
   of a caption that is a full sentence on the public page — the moderator was
   typing blind into a sliver. Like the anchor picker below, it sets the
   column's width instead of inheriting it, and the shared 160px keeps the two
   controls under one thumb the same width rather than stepping. */
.panel-img-caption {
  font-size: .75rem;
  padding: 3px 6px;
  width: 160px;
}

/* Where an image currently sits, under its thumbnail. It reports a position
   rather than setting one — the position is chosen by dragging the image onto
   the text — so it is styled as a status line, not as a control. */
.panel-img-anchor-badge {
  display: flex;
  align-items: center;
  gap: 2px;
  width: 160px;
  margin-top: 2px;
  font-size: .68rem;
  line-height: 1.3;
  color: var(--muted-strong-color);
}

.panel-img-anchor-badge > span {
  flex: 1;
  min-width: 0;
  /* One line: a paragraph's opening words are longer than the column, and the
     full text is on the element's title. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* In the text, as opposed to the grid below it. */
.panel-img-anchor-badge.is-placed {
  color: var(--text-emphasis-color);
  font-weight: 600;
}

/* Pointing at a paragraph the text no longer has. Worth saying plainly: the
   image silently drops to the grid on the public page, and without this she
   would have no way of knowing why. */
.panel-img-anchor-badge.is-missing {
  color: var(--bs-danger, #dc3545);
}

.panel-img-anchor-clear {
  flex: 0 0 auto;
  border: 0;
  border-radius: var(--radius-sm, 4px);
  background: transparent;
  color: inherit;
  font-size: .7rem;
  line-height: 1;
  padding: 2px 3px;
  cursor: pointer;
}

.panel-img-anchor-clear:hover {
  background: var(--bg-wash);
  color: var(--text-emphasis-color);
}

.panel-img-anchor-clear:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 1px;
}

/* The thumb column is sized by the controls under it, not by the 90px image,
   so the image stays its own size and sits centred over the wider box. */
.panel-img-thumb > .position-relative { align-self: center; }

/* The side an image takes beside its paragraph: left, right, full width, or
   left to the automatic alternation. Sits directly under the paragraph menu,
   because the two together are one decision — which paragraph, and where
   beside it. */
.panel-img-placement {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  width: 160px;
  margin-top: 2px;
}

/* The chosen side in words, under the icon buttons: the icons alone needed a
   hover to read. Its own line, so it never squeezes the buttons. */
.panel-img-placement-caption {
  flex: 0 0 100%;
  font-size: .68rem;
  line-height: 1.3;
  text-align: center;
  color: var(--muted-strong-color);
}

.panel-img-placement button {
  flex: 1;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 4px);
  background: var(--surface-color);
  color: var(--muted-strong-color);
  font-size: .7rem;
  line-height: 1.5;
  padding: 1px 0;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.panel-img-placement button:hover:not(:disabled) {
  color: var(--text-emphasis-color);
  border-color: var(--muted-strong-color);
}

.panel-img-placement button[aria-pressed="true"] {
  background: var(--accent-color);
  border-color: var(--accent-color);
  color: var(--contrast-color);
  font-weight: 600;
}

.panel-img-placement button:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 1px;
}

/* The strip is hidden outright when the photograph is not in the text — see
   `.panel-img-placement[hidden]` below. It used to be dimmed and left in
   place, on the reasoning that a control which greys is easier to follow than
   one that vanishes; that held while the strip was the only way to say
   anything about position, but it now sits beside a "Place in text" button
   that says what to do instead, so the greyed row was four more things to
   read past rather than a hint. The disabled state stays on the buttons
   themselves as a guard for assistive technology. */
.panel-img-placement button:disabled {
  cursor: default;
}

@media (prefers-reduced-motion: reduce) {
  .panel-img-placement button {
    transition: none;
  }
}

/* The thumbnail an image is being placed from, either dragged or clicked. */
.panel-img-thumb.is-dragging {
  opacity: .4;
}

.panel-img-thumb.is-pending-place {
  outline: 2px solid var(--accent-color);
  outline-offset: 2px;
  border-radius: 6px;
}

/* A brief flash after an image lands, so it is clear which one moved — the
   thumbnail does not change position, only what it reports. */
.panel-img-thumb.is-just-placed .panel-img-anchor-badge {
  animation: panel-placed-flash .9s ease-out;
}

@keyframes panel-placed-flash {
  from { background: color-mix(in srgb, var(--accent-color), transparent 55%); }
  to   { background: transparent; }
}

/* The one action offered on a photograph that is not in the text yet. A
   labelled button rather than a glyph: it is the entry point to placement, and
   it replaced a badge, a clear button and a four-glyph side strip that sat
   under every card whether or not they applied. Those still exist — they
   appear once the photograph has a position for them to describe. */
.panel-img-place-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .25rem;
  width: 160px;
  margin-top: 2px;
  padding: 3px 6px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 4px);
  background: var(--surface-color);
  color: var(--muted-strong-color);
  font-size: .7rem;
  line-height: 1.3;
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.panel-img-place-btn:hover {
  background: var(--bg-wash);
  color: var(--text-emphasis-color);
  border-color: var(--accent-color);
}

.panel-img-place-btn:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 1px;
}

.panel-img-place-btn[hidden] {
  display: none;
}

/* The chip and the side strip are the other half of that state: hidden until
   the photograph is actually in the text. */
.panel-img-anchor-badge[hidden],
.panel-img-placement[hidden] {
  display: none;
}

/* History cards have two drags: the photograph goes onto the text, the grip
   changes the order. So the card is no longer a grip as a whole, and each
   part says which drag it starts. */
#historyImagesList .panel-img-thumb,
#historyImagesList .panel-img-thumb:active {
  cursor: auto;
  touch-action: auto;
}

#historyImagesList .panel-img-thumb img {
  cursor: grab;
}

.panel-img-grip {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 16px;
  margin-bottom: 2px;
  border-radius: var(--radius-sm, 4px);
  color: var(--muted-strong-color);
  font-size: .9rem;
  line-height: 1;
  cursor: grab;
  touch-action: none;
  opacity: .85;
  transition: background var(--transition-fast), opacity var(--transition-fast);
}

.panel-img-grip:hover {
  opacity: 1;
  background: var(--bg-wash);
}

.panel-img-grip:active {
  cursor: grabbing;
}

/* "Delete this photograph?" laid over the thumbnail its ✕ belongs to. */
.panel-img-confirm {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 3px;
  padding: 4px;
  border-radius: 4px;
  /* Opaque: the ✕ underneath must not show through the question. */
  background: var(--surface-color);
  font-size: .68rem;
  line-height: 1.2;
  text-align: center;
  color: var(--text-emphasis-color);
  cursor: auto;
}

.panel-img-confirm > span {
  font-weight: 600;
}

.panel-img-confirm button {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 4px);
  padding: 1px 4px;
  font-size: .68rem;
  line-height: 1.4;
  cursor: pointer;
}

.panel-img-confirm .panel-img-confirm-yes {
  border-color: var(--bs-danger, #dc3545);
  background: var(--bs-danger, #dc3545);
  color: #fff;
}

.panel-img-confirm .panel-img-confirm-no {
  background: var(--surface-color);
  color: var(--text-emphasis-color);
}

.panel-img-confirm button:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 1px;
}

.panel-img-confirm button:disabled {
  opacity: .6;
  cursor: progress;
}

/* The three steps above a gallery that can be placed in the text. */
.panel-steps {
  list-style: none;
  counter-reset: panel-step;
  margin: 0 0 .4rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: .25rem;
  font-size: .78rem;
  line-height: 1.35;
  color: var(--muted-strong-color);
}

.panel-steps li {
  counter-increment: panel-step;
  display: flex;
  align-items: flex-start;
  gap: .4rem;
}

/* Number and icon together: the number gives the order, the icon matches
   the control the step is about. */
.panel-steps li::before {
  content: counter(panel-step);
  flex: 0 0 auto;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  background: var(--bg-wash);
  color: var(--text-emphasis-color);
  font-size: .68rem;
  font-weight: 700;
  line-height: 1.1rem;
  text-align: center;
}

.panel-steps li > i {
  flex: 0 0 auto;
  color: var(--accent-color);
}

@media (prefers-reduced-motion: reduce) {
  .panel-img-grip {
    transition: none;
  }
}

/* ── History edit window: preview, placeholder, language note ── */

/* The language tabs and the preview toggle on one line; the toggle wraps
   under the tabs when the column is narrow. */
.history-tabs-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: .5rem;
}

.history-preview-toggle {
  margin-bottom: .35rem;
  font-size: .78rem;
}

.history-preview-toggle[aria-pressed="true"] {
  background: var(--accent-color);
  border-color: var(--accent-color);
  color: var(--contrast-color);
}

/* While previewing, the preview stands where the editor was. */
#historyTextColumn.is-previewing .tab-content {
  display: none;
}

.history-preview {
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md, 8px);
  overflow: hidden;
}

.history-preview-bar {
  margin: 0;
  padding: .4rem .7rem;
  border-bottom: 1px solid var(--border-color);
  background: var(--bg-wash);
  font-size: .74rem;
  color: var(--muted-strong-color);
}

/* The page's own background, so the photographs and text read against what
   visitors see; scrolls on its own so the modal footer stays in reach. */
.history-preview-body {
  max-height: 62vh;
  min-height: 8rem;
  overflow-y: auto;
  padding: 1rem 1.1rem;
  background: var(--background-color);
  transition: opacity var(--transition-fast);
}

.history-preview-body.is-loading {
  opacity: .5;
}

/* Laid out at the article's width on the public page (see .history-article)
   and scaled down to the column. At the column's own ~600px, two floats
   squeezed the text between them into a sliver the real page never shows.
   JS keeps --preview-scale in step with the column. */
.history-preview-body .history-article {
  width: 1000px;
  max-width: none;
  zoom: var(--preview-scale, .6);
}

/* The page animates these in on scroll; inside the preview nothing starts
   that animation, so they would stay invisible. */
.history-preview-body [data-aos] {
  opacity: 1 !important;
  transform: none !important;
  transition: none !important;
}

/* Where the photographs will be, before the first save makes them possible. */
.panel-images-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .35rem;
  padding: 1.5rem 1rem;
  border: 2px dashed var(--border-color);
  border-radius: var(--radius-md, 8px);
  text-align: center;
  font-size: .8rem;
  color: var(--muted-strong-color);
}

.panel-images-placeholder > i {
  font-size: 1.6rem;
  color: var(--accent-color);
}

.panel-images-placeholder p {
  margin: 0;
}

.panel-images-placeholder .panel-images-placeholder-title {
  font-weight: 600;
  color: var(--text-emphasis-color);
}

.panel-images-placeholder .btn {
  margin-top: .35rem;
}

/* English and Greek have different paragraph counts while photographs are
   placed: worth reading, not an error. */
.panel-lang-mismatch {
  display: flex;
  align-items: flex-start;
  gap: .4rem;
  margin-bottom: .5rem;
  padding: .4rem .55rem;
  border-left: 3px solid var(--bs-warning, #ffc107);
  border-radius: var(--radius-sm, 4px);
  background: color-mix(in srgb, var(--bs-warning, #ffc107), transparent 85%);
  font-size: .74rem;
  line-height: 1.35;
  color: var(--text-emphasis-color);
}

.panel-lang-mismatch[hidden] {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  .history-preview-body {
    transition: none;
  }
}

/*--------------------------------------------------------------
# Dropping an image onto a paragraph
--------------------------------------------------------------*/
/* The targets are laid over the editor while a placement is in progress.
   CodeMirror owns the DOM inside itself, so drop rows are positioned on top of
   it rather than inserted between its lines, which it would overwrite on its
   next redraw. */
.history-content-field {
  position: relative;
}

/* The line above the drop targets saying what this step is. It carries the
   instructions that used to stand permanently above the gallery, where they
   described a mechanism she had not started using. */
.history-drop-head {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: .3rem .4rem .4rem;
  margin-bottom: 2px;
  border-bottom: 1px solid var(--border-color);
}

.history-drop-hint {
  margin: 0;
  font-size: .74rem;
  font-weight: 600;
  line-height: 1.35;
  color: var(--text-emphasis-color);
}

.history-drop-note {
  margin: 0;
  font-size: .68rem;
  line-height: 1.35;
  color: var(--muted-strong-color);
}

.history-drop-cancel {
  align-self: flex-start;
  margin-top: .15rem;
  padding: 2px 8px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 4px);
  background: var(--surface-color);
  color: var(--muted-strong-color);
  font-size: .68rem;
  cursor: pointer;
}

.history-drop-cancel:hover {
  background: var(--bg-wash);
  color: var(--text-emphasis-color);
}

.history-drop-cancel:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 1px;
}

.history-drop-overlay {
  position: absolute;
  /* Below the field's label, over the editor itself. */
  top: 1.9rem;
  left: 0;
  right: 0;
  bottom: 1.6rem;
  z-index: 5;
  padding: 4px;
  border: 2px dashed var(--accent-color);
  border-radius: var(--radius-md, 8px);
  /* Opaque: the editor's lines showed through between the rows as a second,
     ghostly copy of the paragraphs. */
  background: var(--surface-color);
}

.history-drop-overlay[hidden] {
  display: none;
}

/* What the overlay shows — the paragraph rows or a question — in a panel that
   sticks to the top of the visible part of the modal. The overlay is as tall
   as the text column and scrolls with the modal, so a photograph dragged from
   low in the list used to find the rows scrolled out of sight above it, with
   only the empty bottom of the overlay on screen. The overlay has no overflow
   of its own for the same reason: a scroll box between this panel and the
   modal body would become what it sticks to.

   The height is capped to roughly what the modal body shows (the viewport
   less the modal's header, footer and margins), so a long text scrolls inside
   the panel instead of running off the bottom of the screen. */
.history-drop-panel {
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: min(100%, calc(100dvh - 13rem));
  overflow-y: auto;
}

/* One paragraph: its text shown once, with the two sides an image can take
   beside it laid over the left and right halves. A faint rule down the middle
   says the row is two targets before the pointer finds out. */
.history-drop-row {
  position: relative;
  flex: 0 0 auto;
  border-radius: var(--radius-sm, 5px);
  background: var(--bg-wash);
}

.history-drop-row::after {
  content: "";
  position: absolute;
  top: 6px;
  bottom: 6px;
  left: 50%;
  border-left: 1px dashed var(--border-color);
  pointer-events: none;
}

.history-drop-para {
  display: flex;
  align-items: flex-start;
  gap: .35rem;
  padding: .35rem .5rem;
  color: var(--muted-strong-color);
  font-size: .74rem;
  line-height: 1.35;
  pointer-events: none;
}

.history-drop-num {
  flex: 0 0 auto;
  font-weight: 700;
  opacity: .75;
}

/* Two lines of the paragraph: enough to recognise it by its words, while a
   long paragraph still cannot push the later ones off the overlay. */
.history-drop-text {
  flex: 1;
  min-width: 0;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}

/* The targets. Transparent until the pointer (or a drag, or focus) is over
   one, when that half tints and names the side it gives. */
.history-drop-half {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  display: flex;
  align-items: center;
  padding: 0 .4rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm, 5px);
  background: transparent;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.history-drop-half[data-drop-side="left"] {
  left: 0;
  justify-content: flex-start;
}

.history-drop-half[data-drop-side="right"] {
  right: 0;
  justify-content: flex-end;
}

.history-drop-half:hover,
.history-drop-half.is-over {
  background: color-mix(in srgb, var(--accent-color), transparent 80%);
  border-color: var(--accent-color);
}

.history-drop-half:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: -2px;
}

.history-drop-side {
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--accent-color);
  color: var(--contrast-color);
  font-size: .68rem;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--transition-fast);
}

.history-drop-half:hover .history-drop-side,
.history-drop-half.is-over .history-drop-side,
.history-drop-half:focus-visible .history-drop-side {
  opacity: 1;
}

/* The pointer must not intercept the drop: the tag is decoration inside the
   button, and a dragover landing on it rather than the button itself would
   leave the target unhighlighted. */
.history-drop-half > span {
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .history-drop-half,
  .history-drop-side {
    transition: none;
  }

  .panel-img-thumb.is-just-placed .panel-img-anchor-badge {
    animation: none;
  }
}

@media (max-width: 575.98px) {
  /* Two columns still have to fit a phone's modal body, so the controls give
     the width back and the column falls to the image's own 90px. */
  .panel-img-thumb { width: 90px; }
  .panel-img-caption,
  .panel-img-anchor-badge,
  .panel-img-placement { width: 100%; max-width: 100%; }
}

/* A photograph that shares its paragraph is part of a stack, so its chip says
   so in the accent colour: it is the one thing on the card that describes how
   the page will draw it rather than where it sits. */
.panel-img-thumb.is-in-deck .panel-img-anchor-badge {
  color: var(--accent-color);
  font-weight: 600;
}

.panel-img-placement button[hidden] {
  display: none;
}

/* The line heading each group of photographs in a history page's list: the
   paragraph they sit on, or "Below the text". A full row of the wrapping
   list, so each group starts on a line of its own. */
.panel-img-group-label {
  flex: 0 0 100%;
  overflow: hidden;
  margin-top: .25rem;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--border-color);
  color: var(--muted-strong-color);
  font-size: .8rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panel-img-group-label:first-child {
  margin-top: 0;
}

.panel-img-group-label.is-missing {
  color: var(--bs-danger, #dc3545);
}

/* How many photographs already sit beside a paragraph, on its row, so that
   dropping onto it is never a surprise. */
.history-drop-count {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 0 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--accent-color), transparent 75%);
  color: var(--text-emphasis-color);
  font-size: .65rem;
  font-weight: 700;
}

/* The question asked when a drop would stack two photographs. It fills the
   overlay, so it is impossible to miss and nothing else can be dropped until
   it is answered. */
.history-deck-prompt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .4rem;
  padding: .75rem .6rem;
}

.history-deck-prompt-title {
  margin: 0;
  font-size: .85rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--text-emphasis-color);
}

.history-deck-prompt-body {
  margin: 0;
  font-size: .75rem;
  line-height: 1.35;
  color: var(--muted-strong-color);
}

.history-deck-prompt-choices {
  display: flex;
  gap: .5rem;
  margin: .25rem 0;
}

.history-deck-choice {
  min-width: 6.5rem;
  padding: .4rem .9rem;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm, 5px);
  background: var(--surface-color);
  color: var(--text-emphasis-color);
  font-size: .8rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition-fast), border-color var(--transition-fast);
}

.history-deck-choice:hover,
.history-deck-choice:focus-visible {
  background: color-mix(in srgb, var(--accent-color), transparent 72%);
  border-color: var(--accent-color);
}

.history-deck-choice:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: 1px;
}

/* The side she was aiming at when she dropped. A hint, not a default: nothing
   is applied until one of the two is pressed. */
.history-deck-choice.is-suggested {
  border-color: var(--accent-color);
}

@media (prefers-reduced-motion: reduce) {
  .history-deck-choice {
    transition: none;
  }
}

/* An image the moderator has ticked for removal, still on screen until they
   save — dimmed rather than hidden, so the choice stays reversible. */
.panel-img-pending-removal {
  opacity: .35;
  filter: grayscale(1);
}

/* ── Field hints ── */
/* One line under a field saying where the value shows up on the public site.
   The panel's users are museum staff, not web people, so the modals explain
   themselves rather than assuming the field name is self-evident. */
.panel-help {
  font-size: .78rem;
  line-height: 1.35;
  color: var(--muted-strong-color);
  margin-top: .25rem;
}
.panel-help:empty { display: none; }

/* ── Missing-translation warnings ── */
/* Shown under a field whose opposite-language twin is filled in, and counted
   on the language tab that holds them. Accent rather than red: a half-finished
   translation is a note to self, not an error -- the save is never blocked. */
.panel-i18n-warn {
  font-size: .78rem;
  line-height: 1.35;
  color: var(--accent-color);
  margin-top: .3rem;
  display: flex;
  align-items: baseline;
  gap: .1rem;
}

[data-i18n-missing] {
  border-color: var(--accent-color);
}


.panel-lang-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.15rem;
  height: 1.15rem;
  margin-left: .4rem;
  padding: 0 .3rem;
  border-radius: 999px;
  background: var(--accent-color);
  color: #fff;
  font-size: .7rem;
  font-weight: 600;
  line-height: 1;
  /* The tab label shifts as the badge appears and disappears; keeping it out
     of the baseline flow stops the row of tabs from jumping. */
  vertical-align: middle;
}

/* ── Row audit line ── */
/* "Edited by <name> · 3 days ago" under a row's title. Deliberately quieter
   and smaller than the title it follows: it is reference information staff
   glance at when two people share a tab, not something to read every row for.
   Sits outside the .fw-medium title element on purpose — the table sorter
   reads that element for its sort key, so keeping this out of it stops the
   editor's name from bleeding into a sort by title. */
.panel-row-meta {
  font-size: .75rem;
  line-height: 1.3;
  color: var(--muted-strong-color);
  margin-top: .15rem;
}

/* ── Language tab status dot ── */
/* English is optional here, so this reports rather than warns: a filled dot
   means that language has text, an outline means it is still empty. */
.lang-dot {
  display: inline-block;
  width: 7px; height: 7px;
  margin-left: .4rem;
  border-radius: 50%;
  border: 1px solid var(--muted-strong-color);
  background: transparent;
  vertical-align: middle;
  opacity: .55;
}
.lang-dot.is-filled {
  background: var(--color-success, #198754);
  border-color: var(--color-success, #198754);
  opacity: 1;
}

/* ── View-on-site link ── */
.btn-view-site { text-decoration: none; }

/* ── Image drop zone ── */
#itemImagesSection,
#activityImagesSection,
#historyImagesSection { border-radius: var(--radius-base); transition: background var(--transition-fast); }
.dropzone-active {
  background: var(--bg-subtle);
  outline: 2px dashed var(--color-accent, #6c757d);
  outline-offset: 4px;
}

/*--------------------------------------------------------------
# Rich text sizes
--------------------------------------------------------------*/
/* The only classes body copy may carry (richtext.SIZE_CLASSES). In em, so a
   size is relative to wherever the text is shown - a card, a modal, a page -
   and "Normal" is simply the surrounding text with no span. Larger stays
   below the h2 a moderator can also insert, so a sized line never competes
   with a heading. */
.rt-size-xs { font-size: .8em; }
.rt-size-sm { font-size: .9em; }
.rt-size-lg { font-size: 1.2em; }
.rt-size-xl { font-size: 1.4em; }

/*--------------------------------------------------------------
# Rich text editor (EasyMDE) - moderator panel only
--------------------------------------------------------------*/
/* EasyMDE ships its own light-only chrome. These rules re-point it at the
   panel's tokens so it follows the dark theme like every other control. */
.EasyMDEContainer .CodeMirror {
  background-color: var(--surface-color);
  color: var(--default-color);
  border: 1px solid var(--input-border-color);
  border-top: 0;
  border-radius: 0 0 var(--radius-sm, .375rem) var(--radius-sm, .375rem);
  font-family: inherit;
  font-size: .95rem;
}

/* A rich-text field's own textarea is hidden behind the EasyMDE container, so
   the [data-i18n-missing] border never shows; mark the editor's frame instead. */
[data-i18n-missing] + .EasyMDEContainer .CodeMirror {
  border-color: var(--accent-color);
}

.EasyMDEContainer .editor-toolbar {
  background-color: var(--bg-subtle);
  border: 1px solid var(--input-border-color);
  border-radius: var(--radius-sm, .375rem) var(--radius-sm, .375rem) 0 0;
  opacity: 1;
}

.EasyMDEContainer .editor-toolbar button {
  color: var(--default-color);
  border: 0;
}

.EasyMDEContainer .editor-toolbar button:hover,
.EasyMDEContainer .editor-toolbar button.active {
  background-color: var(--surface-color);
  border-radius: var(--radius-sm, .375rem);
}

/* The toolbar uses Bootstrap Icons, not EasyMDE's bundled Font Awesome, so
   the glyphs need the icon font declared explicitly. */
.EasyMDEContainer .editor-toolbar button.bi::before {
  font-family: 'bootstrap-icons', sans-serif;
}

.EasyMDEContainer .CodeMirror-cursor {
  border-left-color: var(--default-color);
}

.EasyMDEContainer .CodeMirror-selected {
  background-color: var(--bg-subtle);
}

/* Preview should look like the published page, not like the editor. */
.EasyMDEContainer .editor-preview,
.EasyMDEContainer .editor-preview-side {
  background-color: var(--surface-color);
  color: var(--default-color);
}

.panel-richtext-preview a {
  color: var(--accent-color);
}

/* The text-size dropdown. EasyMDE draws it with a hard-coded white
   background and a corner triangle, which disappears in the dark theme. */
.EasyMDEContainer .editor-toolbar .easymde-dropdown,
.EasyMDEContainer .editor-toolbar .easymde-dropdown:hover {
  background: none;
  border: 0;
}

.EasyMDEContainer .easymde-dropdown-content {
  background-color: var(--surface-color);
  border: 1px solid var(--input-border-color);
  border-radius: var(--radius-sm, .375rem);
  padding: .25rem;
  min-width: 8rem;
}

/* Each entry is shown at the size it applies (it carries the rt-size class
   itself), so the fixed toolbar button height has to give way. */
.EasyMDEContainer .easymde-dropdown-content button.rt-size-menu-item {
  width: 100%;
  height: auto;
  padding: .2rem .6rem;
  text-align: left;
  white-space: nowrap;
  line-height: 1.3;
}

/* A separator inherits the button colour and would otherwise vanish. */
.EasyMDEContainer .editor-toolbar i.separator {
  border-left: 1px solid var(--input-border-color);
  border-right: 0;
}

/*--------------------------------------------------------------
# Cookie Consent
--------------------------------------------------------------*/

/* A bar pinned to the bottom rather than a full-screen overlay: the site sets
   no cookies that need permission, so there is nothing to withhold the page
   for while the visitor decides. */
.site-notice {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1040;
  background-color: var(--surface-color);
  border-top: 1px solid var(--border-color);
  box-shadow: 0 -2px 16px rgba(0, 0, 0, 0.08);
  padding: 1rem 1.25rem;
}

.site-notice-dismissed {
  display: none;
}

.site-notice-inner {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}

.site-notice-text {
  flex: 1 1 22rem;
}

.site-notice-title {
  font-family: var(--heading-font);
  font-weight: 600;
  color: var(--heading-color);
  margin: 0 0 0.25rem;
}

.site-notice-body {
  margin: 0;
  font-size: 0.9rem;
  color: var(--text-strong-color);
}

.site-notice-link {
  color: var(--accent-color);
  text-decoration: underline;
  cursor: pointer;
}

.site-notice-actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Accept and reject share a size and weight on purpose: consent is not freely
   given if refusing is the visually harder option. */
.site-notice-btn {
  font-size: 0.875rem;
  padding: 0.5rem 1.5rem;
  border-radius: 4px;
  border: 1px solid var(--accent-color);
  white-space: nowrap;
}

.site-notice-btn-allow {
  background-color: var(--accent-color);
  color: var(--contrast-color);
}

.site-notice-btn-allow:hover {
  background-color: var(--accent-hover);
  color: var(--contrast-color);
}

.site-notice-btn-decline {
  background-color: transparent;
  color: var(--accent-color);
}

.site-notice-btn-decline:hover {
  background-color: var(--accent-faint);
  color: var(--accent-color);
}

@media (max-width: 575px) {
  .site-notice-actions {
    width: 100%;
  }

  .site-notice-btn {
    flex: 1 1 0;
  }
}

/* Placeholder shown in place of a third-party iframe until it is allowed. */
.embed-gate {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 1.5rem 1rem;
  background-color: var(--bg-subtle);
  border: 1px dashed var(--input-border-color);
  border-radius: 4px;
  text-align: center;
}

/* The map is not inside a Bootstrap .ratio, so its placeholder needs a height
   of its own — matching the iframe it replaces, to keep the page from jumping
   when the real map loads. */
.map-embed {
  height: 270px;
}

.map-embed iframe,
.map-embed .embed-gate {
  width: 100%;
  height: 100%;
}

.embed-gate-inner {
  max-width: 28rem;
}

.embed-gate-icon {
  font-size: 1.75rem;
  color: var(--muted-color);
  display: block;
  margin-bottom: 0.5rem;
}

.embed-gate-text {
  font-size: 0.85rem;
  color: var(--muted-strong-color);
  margin-bottom: 0.75rem;
}

.embed-gate-btn {
  border: 1px solid var(--accent-color);
  color: var(--accent-color);
  background-color: transparent;
  font-size: 0.8rem;
  border-radius: 4px;
}

.embed-gate-btn:hover {
  background-color: var(--accent-color);
  color: var(--contrast-color);
}

/* ── Panel help drawer ──
   Contextual guide, opened from the header and following whichever section is
   on screen. Slides in beside the edit modals rather than stacking on top of
   them, so the panel's backdrop and Escape handling stay unambiguous.

   Everything is expressed in the panel's own tokens, so the drawer follows the
   light and dark themes without a second set of rules. */
.panel-help-drawer {
  width: min(30rem, 92vw);
  background: var(--surface-color);
  color: var(--default-color);
  border-left: 1px solid var(--border-color);
}

.panel-help-drawer .offcanvas-header {
  border-bottom: 1px solid var(--border-color);
}

.panel-help-title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--heading-color);
  margin: 0;
}

.panel-help-heading {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--heading-color);
  margin: 0 0 1rem;
  padding-bottom: .6rem;
  border-bottom: 2px solid var(--accent-color);
}

.panel-help-sub {
  font-size: .8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--accent-color);
  margin: 1.5rem 0 .5rem;
}

.panel-help-lead {
  font-size: .95rem;
  line-height: 1.6;
  margin-bottom: .5rem;
}

.panel-help-list {
  padding-left: 1.1rem;
  margin-bottom: 0;
}

.panel-help-list li {
  font-size: .875rem;
  line-height: 1.55;
  margin-bottom: .5rem;
}

.panel-help-list code {
  font-size: .82em;
  padding: .1em .35em;
  border-radius: 3px;
  background: var(--accent-faint);
  color: var(--default-color);
}

/* The "worth knowing" block: the irreversible and the surprising. Marked with
   a rule rather than a colour alone, so it still reads as set apart for anyone
   who cannot distinguish the tint. */
.panel-help-warn {
  border-left: 3px solid var(--accent-color);
  background: var(--accent-faint);
  border-radius: 0 6px 6px 0;
  padding: .75rem 1rem .75rem 2rem;
  margin-left: 0;
}

.panel-help-btn {
  flex-shrink: 0;
}

/* ── Help drawer: button legend ──
   What the panel's icon-only controls do. Collapsed by default — it is what a
   novice needs at first and clutter once the icons are familiar — and sits
   above the per-section topics, since it applies to all of them. */
.panel-help-icons {
  border: 1px solid var(--border-color);
  border-radius: 8px;
  margin-bottom: 1.5rem;
  background: var(--bg-subtle, var(--accent-faint));
}

.panel-help-icons-summary {
  cursor: pointer;
  padding: .6rem .85rem;
  font-size: .85rem;
  font-weight: 600;
  color: var(--heading-color);
  list-style: none;
}

/* Replace the default disclosure marker with one that turns, so the control
   reads as expandable in both Safari and the rest. */
.panel-help-icons-summary::-webkit-details-marker {
  display: none;
}

.panel-help-icons-summary::after {
  content: "\f282";                 /* bi-chevron-down */
  font-family: "bootstrap-icons";
  float: right;
  font-size: .75rem;
  transition: transform .2s ease;
}

.panel-help-icons[open] > .panel-help-icons-summary::after {
  transform: rotate(180deg);
}

.panel-help-icons-summary:focus-visible {
  outline: 2px solid var(--accent-color);
  outline-offset: -2px;
}

/* Icon in its own column so the glyphs line up and the text blocks align,
   however long each description runs. */
.panel-help-icon-list {
  display: grid;
  grid-template-columns: 1.75rem 1fr;
  gap: .55rem .5rem;
  margin: 0;
  padding: .25rem .85rem .85rem;
}

.panel-help-icon-list dt {
  text-align: center;
  color: var(--accent-color);
  font-size: 1rem;
  line-height: 1.5;
}

.panel-help-icon-list dd {
  margin: 0;
  font-size: .85rem;
  line-height: 1.5;
}

.panel-help-icon-list dd strong {
  color: var(--heading-color);
}

/* ── Categories tab: two-level drag tree ──────────────────────────────────────
   Not a <table>: each level is its own Sortable list, and a <tbody> cannot
   nest inside another, so the rows are a stack of grid rows instead. The
   column widths below are what keep it reading as a table anyway — they match
   .panel-table's padding so the tab does not look foreign next to the others. */
.cat-tree-head,
.cat-row {
  display: grid;
  grid-template-columns: 42px 1fr 5.5rem 7rem;
  align-items: center;
  column-gap: .5rem;
}
.cat-tree-head {
  font-size: .8rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted-color); font-weight: 600; background: var(--bg-wash);
  border-bottom: 1px solid var(--border-color); padding: .7rem 1rem;
}
.cat-row { padding: .8rem 1rem; color: var(--heading-color); }
.cat-branch { border-bottom: 1px solid var(--bg-subtle); }
.cat-branch:last-child { border-bottom: none; }
.cat-col-count,
.cat-tree-head .cat-col-count { text-align: left; }
.cat-col-actions,
.cat-tree-head .cat-col-actions { text-align: right; }

/* Children sit visually inside their parent: indented, on a faint wash, and
   separated by hairlines rather than the heavier branch border. */
.cat-child-row { padding-left: 2.4rem; background: var(--bg-wash); }
.cat-children .cat-row + .cat-row { border-top: 1px solid var(--bg-subtle); }
.cat-children .cat-row:first-child { border-top: 1px solid var(--bg-subtle); }

/* An empty children list still has to be a drop target, so it keeps a small
   height instead of collapsing to nothing when a parent has no subcategories
   yet. Zero height would make the first subcategory impossible to drag in. */
.cat-children.is-empty { min-height: .55rem; }

/* Parent rows carry a "+ Subcategory" button at the end of the name cell, not
   in the actions column: parent and child rows are separate grids, so a wider
   actions cell on parents only would knock the columns out of line. */
.cat-parent-row .cat-col-name {
  display: flex; align-items: center; gap: .75rem;
}
.cat-name-block { min-width: 0; flex: 1 1 auto; }
.btn-add-subcat {
  flex: 0 0 auto; white-space: nowrap;
  font-size: .78rem; padding: .15rem .55rem;
}

/* Category modal, opened from "+ Subcategory": where the new row will go. */
.panel-subcat-target {
  padding: .6rem .8rem; margin-bottom: 1rem;
  background: var(--bg-wash); border-radius: .5rem;
  color: var(--muted-strong-color);
}
.panel-subcat-target strong { color: var(--heading-color); }

@media (max-width: 767.98px) {
  .cat-tree-head { display: none; }
  .cat-tree-head,
  .cat-row { grid-template-columns: 42px 1fr 3.5rem; }
  /* The actions wrap under the name rather than squeezing a fourth column. */
  .cat-col-actions { grid-column: 2 / -1; text-align: left; padding-top: .35rem; }
  .cat-child-row { padding-left: 1.4rem; }
}

/* ── Page maps ──
   The map closing a Museum History page, and its editor in the page modal.
   Leaflet's own stylesheet is loaded only where a map is drawn. */
.page-map-heading {
  font-size: 1.5rem;
  color: var(--heading-color);
  margin-bottom: 1rem;
}

.page-map,
.page-map-gate {
  height: 420px;
  border-radius: 4px;
}

.page-map {
  border: 1px solid var(--border-color);
  /* Leaflet panes sit at z-index 400+, above the sticky header otherwise. */
  position: relative;
  z-index: 0;
}

@media (max-width: 575px) {
  .page-map,
  .page-map-gate {
    height: 320px;
  }
}

/* "Use Ctrl + scroll to zoom" — shown over the map when a plain scroll or a
   one-finger swipe passes through it (page-map.js, cooperativeGestures).
   Clicks go through it, and it sits above Leaflet's panes and controls. */
.page-map-hint {
  position: absolute;
  inset: 0;
  z-index: 1001;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-family: var(--default-font);
  font-size: 1.1rem;
  font-weight: 600;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.page-map-hint.is-visible {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .page-map-hint {
    transition: none;
  }
}

/* The always-visible label beside each pin. */
.leaflet-tooltip.page-map-label {
  font-family: var(--default-font);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--heading-color);
  background: var(--surface-color);
  border: 1px solid var(--border-color);
  border-radius: 4px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
  padding: 2px 6px;
}

.leaflet-tooltip.page-map-label::before {
  display: none;
}

.leaflet-popup-content .page-map-popup-text {
  margin: 0.35rem 0 0;
  white-space: pre-line;
}

.page-map-list {
  list-style: none;
  padding: 0;
  margin: 1rem 0 0;
  font-size: 0.9rem;
}

.page-map-list li {
  padding: 0.2rem 0;
}

.page-map-list .bi {
  color: var(--accent-color);
  margin-right: 0.35rem;
}

.page-map-list-text {
  color: var(--muted-strong-color);
}

/* Panel editor */
.page-map-editor-map {
  height: 320px;
  border: 1px solid var(--border-color);
  border-radius: 4px;
  cursor: crosshair;
}

.page-map-pin {
  border: 1px solid var(--border-color);
  border-radius: 4px;
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.5rem;
  background: var(--surface-color);
}

.page-map-pin-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}

.page-map-pin-handle {
  cursor: grab;
  color: var(--muted-color);
}
