/* neko13f2026 ("neko13") frontend template.
   Header/footer lifted from the "Horizone Blog" design mockup (Claude
   Design export, 2026-09-07) — classes below map 1:1 to that mockup's
   inline styles, just moved into a stylesheet per the same
   theme-is-a-folder convention the admin side uses (App\Support\Theme).
   Colors/copy are the mockup's placeholders, not final branding. */

* {
    box-sizing: border-box;
}

body.site {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    font-family: Helvetica, Arial, sans-serif;
    background: #fff;
    color: #1a1815;
    /* The closed mobile nav drawer sits at `right: calc(-1 * min(80vw,
       300px))` (see .site-header-collapse) so it can slide in via
       `right` instead of `transform` — needed for GTranslate's
       position:fixed popup to work (see header.php's comment on that).
       But unlike a transform-based offset, a `right`-based one still
       occupies real layout position outside the viewport, and browsers
       generally still count that toward the document's horizontal
       scrollable area even though the element is `position: fixed` —
       giving every single page a permanent, spurious bottom scrollbar
       reaching into empty space (Act's screenshot, Telegram
       2026-09-16, "เกือบทุกหน้า" — present site-wide since the header
       is shared). Clip it here rather than reverting to transform. */
    overflow-x: hidden;
}

.site a {
    text-decoration: none;
}

.site-header-inner,
.site-footer-inner,
.site-main {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
}

/* Header */

.site-header {
    /* Falls back to the mockup's plain-white look when Settings >
       General's "Frontend header background color" isn't set — see
       App\Support\FrontendTemplate::customCss(). Was `transparent`
       until the header became sticky below (Act's ask, Telegram
       2026-09-12): once it can sit on top of scrolled-under page
       content, it needs an opaque fallback or that content would show
       through underneath it. */
    background: var(--site-header-bg, #fff);
    /* Sticks to the top of the viewport while scrolling ("fixed...
       ติดอยู่ข้างบนตลอด", same ask) rather than scrolling away with the
       page. `sticky`, not `fixed`: it keeps the header's normal
       position in the page flow (no separate "push content down by
       the header's height" hack needed) while still reaching and
       staying at the top once scrolled that far. z-index keeps it
       above page content once something scrolls underneath it. */
    position: sticky;
    top: 0;
    z-index: 30;
}

.site-header-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    padding: 10px 16px 18px;
}

.site-header-left {
    display: flex;
    align-items: center;
    gap: 28px;
    flex-wrap: wrap;
}

.site-brand,
.site-footer-brand {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 700;
    color: #1a1815;
}

.site-brand {
    font-size: 19px;
}

.site-brand-mark {
    width: 24px;
    height: 24px;
    background: #1a1815;
    color: #fff;
    border-radius: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 13px;
    flex-shrink: 0;
}

.site-nav {
    display: flex;
    gap: 20px;
    flex-wrap: wrap;
}

.site-nav a {
    font-size: 14px;
    color: #4a4640;
}

.site-nav a:hover {
    color: #1a1815;
}

/* Demo-only "Home" dropdown (Design #1/2) — hover on pointer devices,
   :focus-within so a tap/click that focuses the button (its native
   behavior) also opens it on touch, with no JS needed either way. */
.site-nav-dropdown {
    position: relative;
}

.site-nav-dropdown-toggle {
    font: inherit;
    font-size: 14px;
    color: #4a4640;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
}

.site-nav-dropdown-toggle:hover {
    color: #1a1815;
}

.site-nav-dropdown-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 8px;
    background: #fff;
    border: 1px solid #e5e0d8;
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
    padding: 6px;
    min-width: 140px;
    z-index: 20;
}

.site-nav-dropdown:hover .site-nav-dropdown-menu,
.site-nav-dropdown:focus-within .site-nav-dropdown-menu {
    display: block;
}

.site-nav-dropdown-menu a {
    display: block;
    padding: 6px 10px;
    border-radius: 6px;
    white-space: nowrap;
}

.site-nav-dropdown-menu a:hover {
    background: #f3f1ee;
}

.site-header-right {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.site-search {
    display: flex;
    align-items: center;
    gap: 8px;
    background: #f3f1ee;
    border-radius: 8px;
    padding: 9px 14px;
    min-width: 180px;
    font-size: 14px;
    color: #9a958f;
}

.site-search input {
    border: none;
    background: none;
    outline: none;
    font-size: 14px;
    font-family: inherit;
    color: #1a1815;
    flex: 1;
    min-width: 0;
    padding: 0;
}

.site-search input::placeholder {
    color: #9a958f;
}

.site-search button {
    border: none;
    background: none;
    padding: 0;
    margin-left: auto;
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    color: inherit;
}

.site-lang {
    font-size: 14px;
    color: #4a4640;
    display: flex;
    align-items: center;
    gap: 4px;
}

/* GTranslate's popup.js (Act's ask, Telegram 2026-09-16 — the default
   embed rendered as a plain unstyled blue browser link, "breaking" the
   header design) injects its own trigger link at runtime, after this
   stylesheet has already loaded, as either a class-based wrapper (no
   widget ID — most buyers) or an id-based one (buyer's own registered
   widget ID) — see App\Support\GTranslate::wrapperSelectorTarget().
   Cover both shapes; the [id^=] form is needed since the id itself is
   buyer-specific and can't be matched literally here. Its injected CSS
   doesn't set color/font-size on `.glink` itself (only vertical-align),
   so this doesn't need !important to win.

   Scoped to `.gt_switcher-popup` specifically, not just `.glink` — every
   row in the popup's own language list (`.gt_languages a`) also gets the
   `glink` class (see popup.js), so a bare `a.glink` selector here would
   win over GTranslate's own `.gt_white_content a { display: block; ...}`
   rule (higher specificity: two classes + the .gtranslate_wrapper
   ancestor beats their one class + one type selector, regardless of
   which stylesheet loaded later) and mangle every language option in the
   list, not just the header trigger — confirmed happening (Act's
   screenshot, Telegram 2026-09-16, the mobile globe-icon change below
   made every row in the popup show an identical unlabeled globe).
   `.gt_switcher-popup` is only ever on the trigger. */
.gtranslate_wrapper a.gt_switcher-popup.glink,
[id^="gt-wrapper-"] a.gt_switcher-popup.glink {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-family: inherit;
    color: #4a4640;
}

.gtranslate_wrapper a.gt_switcher-popup.glink:hover,
[id^="gt-wrapper-"] a.gt_switcher-popup.glink:hover {
    color: #1a1815;
}

.gtranslate_wrapper a.gt_switcher-popup.glink img,
[id^="gt-wrapper-"] a.gt_switcher-popup.glink img {
    border-radius: 2px;
}

/* Mobile nav (Act's ask, Telegram 2026-09-16): a right-side slide-in
   drawer below the breakpoint, rather than the nav/search/language row
   wrapping awkwardly onto extra lines. Right side specifically (not
   left) so the toggle sits under a right-handed thumb's natural reach
   while holding the phone.
   .site-header-collapse wraps .site-nav + .site-search (language stays
   outside it — see header.php's comment on why) and is `display:
   contents` above the breakpoint — it has no box of its own there, so
   .site-nav/.site-search are direct flex children of .site-header-inner
   exactly as if this wrapper didn't exist, and desktop's layout is
   byte-for-byte the same as before it was added (nav right after the
   brand, search + language grouped at the far right via the auto
   margin below). */
.site-header-inner {
    justify-content: flex-start;
    gap: 28px;
}

.site-header-collapse {
    display: contents;
}

.site-search {
    margin-left: auto;
}

.site-nav-toggle,
.site-nav-drawer-close {
    display: none;
}

.site-nav-backdrop {
    display: none;
}

@media (max-width: 760px) {
    .site-nav-toggle {
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 5px;
        width: 36px;
        height: 36px;
        padding: 0;
        border: none;
        background: none;
        cursor: pointer;
        flex-shrink: 0;
    }

    .site-nav-toggle-bar {
        display: block;
        width: 22px;
        height: 2px;
        background: #1a1815;
        border-radius: 1px;
        transition: transform 0.15s ease, opacity 0.15s ease;
    }

    .site-header.is-menu-open .site-nav-toggle-bar:nth-child(1) {
        transform: translateY(7px) rotate(45deg);
    }

    .site-header.is-menu-open .site-nav-toggle-bar:nth-child(2) {
        opacity: 0;
    }

    .site-header.is-menu-open .site-nav-toggle-bar:nth-child(3) {
        transform: translateY(-7px) rotate(-45deg);
    }

    /* Overrides the desktop `display: contents` — becomes a real,
       fixed-position drawer instead of dissolving into the header row.
       Slides via `right`, not `transform` (a `transform` on a
       `position: fixed` element like this one is itself unusual, but
       more importantly a `transform` here would make it a new
       containing block for any `position: fixed` descendant it
       contains — moot now that search/language live outside it, but
       keep the `right`-based slide regardless; see header.php's comment
       for the GTranslate history that led here). */
    .site-header-collapse {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 20px;
        position: fixed;
        top: 0;
        right: calc(-1 * min(80vw, 300px));
        height: 100vh;
        height: 100dvh;
        width: min(80vw, 300px);
        background: #fff;
        padding: 24px 20px;
        box-shadow: -8px 0 24px rgba(0, 0, 0, 0.15);
        transition: right 0.25s ease;
        z-index: 1000;
        overflow-y: auto;
    }

    .site-header.is-menu-open .site-header-collapse {
        right: 0;
    }

    .site-nav-drawer-close {
        display: flex;
        align-self: flex-end;
        border: none;
        background: none;
        font-size: 26px;
        line-height: 1;
        color: #1a1815;
        cursor: pointer;
        padding: 0;
    }

    .site-nav {
        flex-direction: column;
        align-items: flex-start;
        gap: 16px;
        width: 100%;
    }

    /* Cancels the desktop auto-margin — inside the drawer's column flex
       layout that would otherwise pull search to the cross-axis (right)
       edge instead of lining up flush left under the nav links. */
    .site-search {
        margin-left: 0;
        width: 100%;
    }

    /* z-index here must stay BELOW .site-header's own z-index (30), not
       above it. .site-header is `position: sticky` with z-index:30,
       which makes it a stacking context — z-index only ever compares
       within the same stacking context, so .site-header-collapse's
       z-index:1000 only wins against *its own* siblings inside that
       context, never against something outside .site-header entirely.
       This backdrop is a sibling of <header>, not a descendant, so a
       z-index above 30 here doesn't just dim the page — it paints over
       .site-header as a whole (search/language included, not just the
       drawer), matching exactly what Act saw (Telegram 2026-09-16):
       language unresponsive and the drawer itself washed-out grey while
       open. 25 sits above ordinary page content (nothing else in this
       stylesheet goes above z-index:2) and below the header. */
    .site-nav-backdrop {
        display: none;
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.4);
        z-index: 25;
    }

    .site-header.is-menu-open ~ .site-nav-backdrop {
        display: block;
    }

    /* Row order independent of DOM order — brand, language, and the
       toggle share the one always-visible row (Act's ask, Telegram
       2026-09-16: search moved into the drawer specifically so this row
       wouldn't be left half-empty; language sits just before the
       hamburger, which stays flush at the far-right edge). */
    .site-header-left {
        order: 1;
    }

    /* .site-header-inner's own `gap: 28px` (desktop's brand-nav spacing)
       otherwise also applies between language and the toggle here —
       with the flag/name hidden down to just a globe icon (below) that
       read as an odd, too-wide gap (Act's ask, Telegram 2026-09-16).
       Shrinking the container's gap doesn't affect the brand-to-language
       distance, since that's dominated by the auto margin below, not by
       this minimum. */
    .site-header-inner {
        gap: 10px;
    }

    .site-header-lang {
        order: 2;
        margin-left: auto;
    }

    /* Globe icon only — no flag/language name/dropdown arrow (Act's ask,
       Telegram 2026-09-16: the flag+text made this the most eye-catching
       thing in the row). Hides GTranslate's own injected img+spans
       (the language name and the ▼ arrow are each their own <span> — see
       popup.js's widget_code) and shows a plain globe via ::before
       instead; same treatment for the pre-configuration fallback. Only
       hides the *display*, not the widget — the link/click target and
       full popup behavior underneath are untouched.

       Scoped to `.gt_switcher-popup` (the trigger only) same as above —
       a bare `a.glink` here hid the flag/name on every row of the
       popup's own language list too, since those share the `glink`
       class, leaving a list of identical unlabeled globes with no way
       to tell the options apart (confirmed, Act's screenshot, Telegram
       2026-09-16). */
    .gtranslate_wrapper a.gt_switcher-popup.glink img,
    [id^="gt-wrapper-"] a.gt_switcher-popup.glink img,
    .gtranslate_wrapper a.gt_switcher-popup.glink span,
    [id^="gt-wrapper-"] a.gt_switcher-popup.glink span,
    .site-lang-label {
        display: none;
    }

    .gtranslate_wrapper a.gt_switcher-popup.glink::before,
    [id^="gt-wrapper-"] a.gt_switcher-popup.glink::before {
        content: "\1F310";
        font-size: 18px;
        line-height: 1;
    }

    .site-nav-toggle {
        order: 3;
    }
}

.site-login-link {
    font-size: 14px;
    color: #4a4640;
}

.site-login-link:hover {
    color: #1a1815;
}

.site-signup-btn {
    background: #1a1815;
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 10px 18px;
    font-size: 14px;
    cursor: pointer;
    display: inline-block;
}

.site-signup-btn:hover {
    opacity: 0.9;
}

.site-brand-logo {
    /* Buyer-configurable (Settings > General "Header logo height", Act's
       ask, Telegram 2026-09-12 — some logos only look right at a
       different size) — see App\Support\FrontendTemplate::customCss(). */
    height: var(--site-header-logo-height, 32px);
    display: block;
}

.site-footer-brand .site-brand-logo {
    /* Buyer-configurable (Settings > General "Footer logo height", Act's
       ask, Telegram 2026-09-15 — same reasoning as the header one) —
       independent variable/fallback, not tied to the header's setting. */
    height: var(--site-footer-logo-height, 28px);
}

/* Main */

.site-main {
    /* flex: 1 0 auto (paired with body.site's display:flex/column above)
       is the actual "stick to bottom" fix — pushes the footer down to
       the viewport's bottom edge on short pages instead of it floating
       right under a short page's content (Ricky's screenshot, Telegram
       2026-09-09). min-height stays as a floor under that. */
    flex: 1 0 auto;
    padding: 16px;
    min-height: 240px;
}

/* Shared layout helpers — any page's sub-header band (breadcrumb bar,
   dark hero band, etc.) that should span edge-to-edge like .site-header/
   .site-footer already do, instead of being capped at 1200px like
   ordinary .site-main content (Ricky's ask, Telegram 2026-09-09, first
   raised on Contact Us, then reused as-is for Events/FAQ). */

.full-bleed {
    width: 100vw;
    margin-left: calc(50% - 50vw);
}

/* Inner wrapper for a .full-bleed band — keeps its actual content
   aligned to the same 1200px/16px-padding column as .site-header-inner
   ("เนื้อหาก็ตรงกับ logo จนถึงภาษา"), rather than touching the viewport edge. */
.band-inner {
    max-width: 1200px;
    margin: 0 auto;
    padding-left: 16px;
    padding-right: 16px;
}

.breadcrumb-bar {
    background: #f3f1ee;
}

.breadcrumb-bar-inner {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14px;
    padding-top: 22px;
    padding-bottom: 22px;
}

.breadcrumb-bar a {
    color: #6a655e;
}

.breadcrumb-bar span:not(.breadcrumb-current) {
    color: #9a958f;
}

.breadcrumb-current {
    color: #1a1815;
    font-weight: 600;
}

/* Dark variant — sits inside a dark full-bleed band (e.g. .contact-hero)
   instead of having its own #f3f1ee background. */
.breadcrumb-bar-dark {
    background: transparent;
}

.breadcrumb-bar-dark.breadcrumb-bar-inner {
    padding-top: 0;
    padding-bottom: 10px;
}

.breadcrumb-bar-dark a {
    color: rgba(255, 255, 255, 0.6);
}

.breadcrumb-bar-dark span:not(.breadcrumb-current) {
    color: rgba(255, 255, 255, 0.4);
}

.breadcrumb-bar-dark .breadcrumb-current {
    color: #fff;
}

/* Generic page content — public /p/{slug} pages with no bespoke design
   of their own (About Us, Privacy Policy, etc.), plus the single Event
   page and the intro blurb on Blog/Events/FAQ's index pages, all of
   which reuse .content-page(-body) already. Previously unstyled ("no
   real design exists yet"); this is Act's "About Us" mockup (Telegram,
   2026-09-10), meant as the shared theme for this kind of page in
   general — not an About-Us-only style. The mockup's hero photo, stats
   grid, and CTA banner aren't here: they're fixed "Horizone" example
   content with no admin field behind them, and a Page row is
   deliberately just a title + rich-text body (see App\Models\Page). */

.content-page {
    max-width: 840px;
    margin: 0 auto;
    padding: 40px 0 8px;
}

.content-page h1 {
    font-size: 34px;
    margin: 0 0 10px;
    font-weight: 700;
}

.content-page-updated {
    font-size: 14px;
    color: #9a958f;
    margin: 0 0 32px;
}

.content-page-body {
    font-size: 16px;
    line-height: 1.75;
    color: #3a3630;
}

.content-page-body p {
    margin: 0 0 24px;
}

.content-page-body h2 {
    font-size: 22px;
    font-weight: 700;
    margin: 36px 0 14px;
    color: #1a1815;
}

.content-page-body ul,
.content-page-body ol {
    margin: 0 0 24px;
    padding-left: 22px;
}

.content-page-body li {
    margin-bottom: 10px;
}

.content-page-body img {
    max-width: 100%;
    border-radius: 12px;
}

/* Hero (homepage only — Views/frontend/home/hero.php) */

.hero {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    border-radius: 16px;
    overflow: hidden;
    color: #fff;
}

/* One slide per hero_banners row (App\Models\HeroBanner::activeForFrontend()) —
   stacked absolutely, only .hero-slide-active shown, JS in hero.php
   toggles which one. A single slide (no carousel controls in that
   case) still gets this treatment for a consistent DOM either way. */
.hero-slide {
    position: absolute;
    inset: 0;
    display: block;
    color: inherit;
    text-decoration: none;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.5s ease;
}

.hero-slide-active {
    opacity: 1;
    visibility: visible;
}

.hero-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.hero-author {
    position: absolute;
    top: 20px;
    right: 20px;
    display: flex;
    align-items: center;
    gap: 10px;
    background: rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(4px);
    border-radius: 30px;
    padding: 6px 14px 6px 6px;
    z-index: 1;
}

.hero-author-avatar {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.25);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    font-weight: 600;
    flex-shrink: 0;
}

.hero-author-avatar-img {
    object-fit: cover;
}

.hero-author-name {
    font-weight: 600;
    font-size: 13px;
}

.hero-author-meta {
    opacity: 0.85;
    font-size: 12px;
}

/* Content position variants (Settings > Hero Banner > Content position) —
   the block itself is always a flex column so align-items can control
   text alignment along with the anchor corner. */
.hero-content {
    position: absolute;
    max-width: 480px;
    display: flex;
    flex-direction: column;
    z-index: 1;
}

.hero-content-bottom-left .hero-content {
    left: 24px;
    bottom: 24px;
    align-items: flex-start;
    text-align: left;
}

.hero-content-bottom-right .hero-content {
    right: 24px;
    bottom: 24px;
    align-items: flex-end;
    text-align: right;
}

.hero-content-top-left .hero-content {
    left: 24px;
    top: 24px;
    align-items: flex-start;
    text-align: left;
}

.hero-content-top-right .hero-content {
    right: 24px;
    top: 24px;
    align-items: flex-end;
    text-align: right;
}

.hero-content-center .hero-content {
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    align-items: center;
    text-align: center;
    max-width: 560px;
}

.hero-badge {
    background: rgba(255, 255, 255, 0.9);
    color: #1a1815;
    font-size: 12px;
    font-weight: 600;
    padding: 5px 12px;
    border-radius: 20px;
    display: inline-block;
    margin-bottom: 12px;
}

.hero-title {
    color: #fff;
    font-size: clamp(24px, 3vw, 34px);
    margin: 0 0 8px;
    font-weight: 700;
}

.hero-desc {
    color: rgba(255, 255, 255, 0.9);
    font-size: 14px;
    margin: 0;
    line-height: 1.5;
}

/* Carousel-wide, not per-slide — a stable spot regardless of which
   corner the active slide's content sits in. */
.hero-dots {
    position: absolute;
    left: 50%;
    bottom: 16px;
    transform: translateX(-50%);
    z-index: 2;
    display: flex;
    gap: 6px;
}

.hero-dot {
    width: 5px;
    height: 5px;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.5);
    cursor: pointer;
}

.hero-dot-active {
    width: 16px;
    background: #fff;
}

/* Design #3's hero (Act's ask, Telegram 2026-09-16, from a ChatGPT-made
   ad image he liked) — home/hero-with-latest.php wraps the same .hero
   carousel (unchanged) plus this sidebar. Grid, not flex: `align-items:
   stretch` (grid's default) makes both columns match the hero's own
   height (set by its aspect-ratio), which is what makes the sidebar's
   last item's bottom land flush with the hero's bottom edge — Act's
   "bottom เสมอกัน" spec — via space-between below, not a fixed height. */
.hero-with-latest {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 24px;
}

.hero-latest-posts {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}

.hero-latest-posts-title {
    font-size: 20px;
    font-weight: 700;
    margin: 0 0 4px;
}

.hero-latest-posts-list {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    flex: 1;
}

.hero-latest-post-item {
    display: block;
    padding: 12px 0;
    border-bottom: 1px solid #e5e0d8;
    color: inherit;
}

.hero-latest-post-item:last-child {
    border-bottom: none;
}

.hero-latest-post-title {
    display: block;
    font-size: 15px;
    font-weight: 600;
    color: #1a1815;
    margin-bottom: 4px;
}

.hero-latest-post-item:hover .hero-latest-post-title {
    color: var(--color-primary, #2563eb);
}

/* Not in the reference ad image (Act's ask, Telegram 2026-09-16) — he
   saw the plain title+date result and asked for a summary line anyway,
   same 2-line clamp as .blog-card-excerpt. */
.hero-latest-post-summary {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 13px;
    color: #6a655e;
    line-height: 1.5;
    margin-bottom: 6px;
}

.hero-latest-post-date {
    display: block;
    font-size: 13px;
    color: #6a655e;
}

@media (max-width: 900px) {
    .hero-with-latest {
        grid-template-columns: minmax(0, 1fr);
    }

    .hero-latest-posts {
        justify-content: flex-start;
    }

    .hero-latest-posts-list {
        flex: none;
        gap: 4px;
    }
}

.site-placeholder {
    padding: 80px 16px;
    text-align: center;
    color: #9a958f;
    font-size: 15px;
}

/* 404 page (Views/frontend/404.php) */

.not-found {
    text-align: center;
    padding: 64px 16px;
    color: #1a1815;
}

.not-found-svg {
    width: 160px;
    height: 128px;
    color: #c9c5be;
    margin-bottom: 8px;
}

.not-found-code {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.08em;
    color: #9a958f;
    margin-bottom: 8px;
}

.not-found-title {
    font-size: 24px;
    font-weight: 700;
    margin: 0 0 8px;
}

.not-found-desc {
    font-size: 14px;
    color: #6a655e;
    margin: 0 0 24px;
}

/* Footer */

.site-footer {
    /* Same var/fallback approach as .site-header above, default matches
       the mockup's dark footer. */
    background: var(--site-footer-bg, #1a1815);
    color: #fff;
}

.site-footer-inner {
    padding: 40px 16px 24px;
}

.site-footer-top {
    display: grid;
    grid-template-columns: 1.6fr 1fr 1fr 1.4fr;
    gap: 32px;
    padding-bottom: 32px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.site-footer-brand {
    font-size: 18px;
    color: #fff;
    margin-bottom: 12px;
}

.site-footer-brand .site-brand-mark {
    background: #fff;
    color: #1a1815;
}

.site-footer-about-text {
    max-width: 280px;
}

.site-footer-about-text p {
    font-size: 13px;
    color: rgba(255, 255, 255, 0.6);
    line-height: 1.6;
    margin: 0;
}

.site-footer-about-text a {
    color: rgba(255, 255, 255, 0.85);
    text-decoration: underline;
}

.site-footer-col-title {
    font-weight: 600;
    font-size: 14px;
    margin-bottom: 14px;
}

.site-footer-col a {
    display: block;
    font-size: 13px;
    color: rgba(255, 255, 255, 0.7);
    margin-bottom: 10px;
}

.site-footer-col a:hover {
    color: #fff;
}

.site-footer-social {
    display: flex;
    gap: 10px;
}

.site-footer-social a {
    width: 30px;
    height: 30px;
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
}

.site-footer-social a:hover {
    background: rgba(255, 255, 255, 0.1);
}

.site-footer-social svg {
    width: 15px;
    height: 15px;
}

.site-footer-bottom {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-top: 20px;
    font-size: 13px;
    color: rgba(255, 255, 255, 0.55);
    flex-wrap: wrap;
    gap: 10px;
}

.site-footer-legal {
    display: flex;
    gap: 20px;
}

.site-footer-legal a {
    color: inherit;
}

.site-footer-legal a:hover {
    text-decoration: underline;
}

@media (max-width: 720px) {
    .site-footer-top {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    }
}

@media (max-width: 480px) {
    .site-footer-top {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Blog section (homepage only — Views/frontend/home/blog-section.php + partials/blog-card.php) */

.blog-section {
    padding: 48px 0 24px;
}

/* Homepage "Featured Posts" row (Act's ask, Telegram 2026-09-16) — sits
   between the hero and whatever comes next on every home design.
   Reuses .blog-section-title and .blog-grid/.blog-card-* as-is, same
   spacing rhythm as .blog-section above. */
.featured-posts-section {
    padding: 32px 0 24px;
}

.blog-section-title {
    font-size: 32px;
    margin: 0 0 8px;
    font-weight: 700;
}

.blog-section-subtitle {
    font-size: 15px;
    color: #6a655e;
    margin: 0 0 28px;
}

/* Horizontal scroll, not a hard cutoff — Ricky's mobile concern
   (Telegram, 2026-09-07): capping at 4 tabs keeps this short, but a
   narrow phone plus long category names could still overflow, so
   nothing gets hidden/unreachable, it just scrolls. */
.blog-tabs {
    display: flex;
    align-items: center;
    gap: 26px;
    margin-bottom: 28px;
    overflow-x: auto;
    white-space: nowrap;
    -webkit-overflow-scrolling: touch;
}

.blog-tab {
    font-size: 14px;
    color: #6a655e;
    padding-bottom: 4px;
    flex-shrink: 0;
}

.blog-tab-active {
    font-weight: 700;
    color: #1a1815;
    border-bottom: 2px solid #1a1815;
}

.blog-tab-more {
    color: #9a958f;
    margin-left: auto;
}

.blog-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
}

@media (max-width: 860px) {
    .blog-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 560px) {
    .blog-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Blog index (public, /p/{blog-index-slug} — Views/frontend/blog/index.php).
   Distinct from .blog-section above (the homepage teaser) — this is
   the dedicated listing page, with its own sidebar category list
   instead of horizontal tabs. Design ref: Act's "Blog (index).dc.html"
   mockup, Telegram 2026-09-10. Reuses .blog-grid/.blog-card-* as-is. */

.blog-index {
    max-width: 1200px;
    margin: 0 auto;
    padding: 40px 16px 56px;
}

.blog-index-intro {
    max-width: 640px;
    margin-bottom: 8px;
}

.blog-index-layout {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 40px;
    align-items: start;
    margin-top: 28px;
}

@media (max-width: 760px) {
    .blog-index-layout {
        grid-template-columns: minmax(0, 1fr);
    }
}

.blog-index-sidebar {
    display: flex;
    flex-direction: column;
    gap: 6px;
    position: sticky;
    top: 16px;
}

@media (max-width: 760px) {
    .blog-index-sidebar {
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
    }
}

.blog-index-cat {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 10px;
    font-size: 14px;
    color: #1a1815;
}

.blog-index-cat-active {
    background: #1a1815;
    color: #fff;
    font-weight: 600;
}

.blog-index-cat-count {
    font-size: 12px;
    color: #9a958f;
}

.blog-index-cat-active .blog-index-cat-count {
    color: rgba(255, 255, 255, 0.6);
}

.blog-index-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 24px;
}

.blog-index-result-count {
    font-size: 14px;
    color: #9a958f;
}

.blog-index-sort {
    font-size: 14px;
    color: #4a4640;
}

.blog-index-sort select {
    border: 1px solid #e5e2dd;
    border-radius: 8px;
    padding: 8px 14px;
    margin-left: 8px;
    font-size: 14px;
    font-family: inherit;
    color: #4a4640;
    background: #fff;
    cursor: pointer;
}

.blog-index-pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 8px;
    margin-top: 44px;
}

.blog-index-page-btn {
    width: 36px;
    height: 36px;
    border: 1px solid #e5e2dd;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    color: #4a4640;
}

.blog-index-page-btn-current {
    background: #1a1815;
    border-color: #1a1815;
    color: #fff;
}

.blog-index-page-btn-disabled {
    color: #c9c5be;
}

.blog-index-page-label {
    font-size: 14px;
    color: #6a655e;
    margin: 0 4px;
}

.blog-card-media {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;
    border-radius: 12px;
    overflow: hidden;
    margin-bottom: 14px;
}

.blog-card-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.blog-card-media-placeholder {
    position: absolute;
    inset: 0;
    display: block;
    background: linear-gradient(135deg, #e5e2dd, #c9c5be);
}

.blog-card-category {
    position: absolute;
    top: 14px;
    left: 14px;
    background: rgba(255, 255, 255, 0.92);
    color: #1a1815;
    font-size: 11px;
    font-weight: 600;
    padding: 5px 12px;
    border-radius: 20px;
}

/*
 * Same badge, not absolutely positioned (Act's report, Telegram
 * 2026-09-10: the badge was overlapping the title text in home-v2/v3's
 * hero/featured captions) — .blog-card-category's absolute positioning
 * is relative to its nearest positioned ancestor, which in those two
 * spots is the caption box itself (already position:absolute for the
 * image-overlay effect), landing the badge on top of the title instead
 * of above it in normal flow. Same fix shape as .event-card-category's
 * existing "own rule so it can be a plain flex child" comment above —
 * also fixes events/show.php's category badge, which had the same bug
 * for an unrelated reason (no positioned ancestor there at all, so it
 * was positioned against the page rather than inline before the h1).
 */
.blog-card-category-inline {
    display: inline-block;
    background: rgba(255, 255, 255, 0.92);
    color: #1a1815;
    font-size: 11px;
    font-weight: 600;
    padding: 5px 12px;
    border-radius: 20px;
}

.blog-card-meta {
    font-size: 13px;
    color: #9a958f;
    margin-bottom: 8px;
}

.blog-card-title {
    font-size: 18px;
    font-weight: 700;
    margin: 0 0 8px;
    line-height: 1.35;
}

.blog-card-title a {
    color: #1a1815;
}

.blog-card-excerpt {
    font-size: 14px;
    color: #6a655e;
    line-height: 1.55;
    margin: 0 0 14px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.blog-card-author {
    display: flex;
    align-items: center;
    gap: 8px;
}

.blog-card-author-avatar {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.blog-card-author-avatar-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #eef0f4;
    color: #6a655e;
    font-size: 11px;
    font-weight: 600;
}

.blog-card-author-name {
    font-size: 13px;
    color: #4a4640;
}

.blog-section-footer {
    display: flex;
    justify-content: center;
    margin-top: 40px;
}

/* Upcoming Events section (homepage only — Views/frontend/home/events-section.php + partials/event-card.php) */

.events-section {
    padding: 24px 0 48px;
}

.events-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 24px;
}

@media (max-width: 860px) {
    .events-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 560px) {
    .events-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.event-card {
    background: #f3f1ee;
    border-radius: 16px;
    overflow: hidden;
}

.event-card-media {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
}

.event-card-media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/*
 * Wrapper owns the corner position and stacks the date/category badges
 * with a fixed gap via flexbox — a fixed pixel `top` on the category
 * badge itself (previous approach) had to guess the date badge's
 * rendered height, and that guess broke at other card widths since the
 * image is aspect-ratio-based (Ricky's screenshot, Telegram 2026-09-09:
 * the category ended up looking like it drifted toward the middle of
 * the image). Stacking as a flex group keeps the gap correct at any size.
 */
.event-card-badges {
    position: absolute;
    top: 14px;
    left: 14px;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
}

.event-card-date {
    background: #fff;
    border-radius: 10px;
    padding: 8px 12px;
    text-align: center;
    line-height: 1.1;
}

.event-card-date-month {
    display: block;
    font-size: 11px;
    font-weight: 600;
    color: #e05a2b;
    letter-spacing: 0.03em;
}

.event-card-date-day {
    display: block;
    font-size: 18px;
    font-weight: 700;
    color: #1a1815;
}

/* Own rule rather than reusing .blog-card-category so it can be a plain flex child here instead of absolutely positioned. */
.event-card-category {
    background: rgba(255, 255, 255, 0.92);
    color: #1a1815;
    font-size: 11px;
    font-weight: 600;
    padding: 5px 12px;
    border-radius: 20px;
}

.event-card-body {
    padding: 20px;
}

.event-card-title {
    font-size: 17px;
    font-weight: 700;
    margin: 0 0 10px;
    line-height: 1.35;
}

.event-card-title a {
    color: #1a1815;
}

/* Location line (Act's ask, Telegram 2026-09-16, matching a reference
   ad image — "📍 Bangkok, Thailand") — only renders at all when the
   event has a location and/or country set, see event-card.php. */
.event-card-location {
    font-size: 13px;
    color: #4a4640;
    margin: 0 0 10px;
}

.event-card-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.event-card-time {
    font-size: 13px;
    color: #4a4640;
}

.event-card-details {
    font-size: 13px;
    font-weight: 600;
    text-decoration: underline;
    color: #1a1815;
}

/* Frequently Asked Questions section (homepage only — Views/frontend/home/faq-section.php) */

.faq-section {
    display: grid;
    grid-template-columns: 1fr 1.4fr;
    gap: 48px;
    padding: 0 0 48px;
}

@media (max-width: 760px) {
    .faq-section {
        grid-template-columns: minmax(0, 1fr);
        gap: 20px;
    }
}

.faq-section-intro .blog-section-title,
.faq-section-intro .blog-section-subtitle {
    margin-bottom: 0;
}

.faq-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.faq-list .faq-item {
    border: 1px solid #e5e2dd;
    border-radius: 12px;
    padding: 18px 20px;
}

.faq-list .faq-item-question {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    text-align: left;
    color: inherit;
    cursor: pointer;
}

.faq-list .faq-item-question span:first-child {
    font-size: 15px;
    font-weight: 600;
}

.faq-list .faq-item-icon {
    font-size: 18px;
    flex-shrink: 0;
    color: #4a4640;
}

.faq-list .faq-item-answer {
    display: none;
    font-size: 14px;
    color: #6a655e;
    line-height: 1.6;
    margin-top: 14px;
}

.faq-list .faq-item-answer p:first-child {
    margin-top: 0;
}

.faq-list .faq-item-answer p:last-child {
    margin-bottom: 0;
}

.faq-list .faq-item-open .faq-item-answer {
    display: block;
}

/* Blog post detail (Views/frontend/blog/show.php) — Ricky's design
   reference (Telegram, 2026-09-08). Same color palette/type scale as
   the blog card/section rules above, just sized up for a page-level
   article rather than a grid card. Single column for now — a sidebar
   ("column ด้านข้างน่าสนใจ... แค่เพิ่มกริดอีกอัน") is a later, separate
   card per Ricky, this is deliberately just the main column so adding
   one later is a plain grid-template-columns change, not a rewrite. */

.blog-post {
    /* No max-width of its own (Ricky's ask, Telegram 2026-09-08 — the
       content/image stopped well short of the site's actual right
       edge, leaving dead space, since there's no sidebar yet to fill
       it) — .site-main, its parent (layout.php), already caps the
       page at 1200px and centers it; this just fills that. Same
       wrapper a future sidebar grid column slots into later, no
       further width change needed then. Not a readability change to
       the text itself — still governed by .blog-post-summary/
       .blog-post-body's own font-size/line-height. */
    padding: 48px 0 64px;
}

.blog-post-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: #f3f1ee;
    color: #4a4640;
    font-size: 13px;
    font-weight: 600;
    padding: 8px 16px;
    border-radius: 20px;
    margin-bottom: 24px;
}

.blog-post-back:hover {
    background: #e5e2dd;
}

.blog-post-date {
    font-size: 13px;
    color: #9a958f;
    margin-bottom: 12px;
}

.blog-post-title {
    font-size: 36px;
    font-weight: 700;
    line-height: 1.2;
    margin: 0 0 16px;
}

.blog-post-summary {
    font-size: 16px;
    color: #6a655e;
    line-height: 1.6;
    margin: 0 0 24px;
}

.blog-post-author {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 32px;
}

.blog-post-author-avatar {
    width: 44px;
    height: 44px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
}

.blog-post-author-avatar-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #eef0f4;
    color: #6a655e;
    font-size: 15px;
    font-weight: 600;
}

.blog-post-author-name {
    font-size: 14px;
    font-weight: 700;
    color: #1a1815;
}

.blog-post-author-position {
    font-size: 13px;
    color: #9a958f;
}

.blog-post-feature {
    width: 100%;
    max-height: 480px;
    object-fit: cover;
    border-radius: 16px;
    display: block;
    margin-bottom: 32px;
}

.blog-post-body {
    font-size: 16px;
    line-height: 1.75;
    color: #2a2722;
}

.blog-post-body img {
    max-width: 100%;
    border-radius: 12px;
}

/* "Share this" row (Act's ask, Telegram 2026-09-10) — Views/frontend/blog/show.php and events/show.php, both via App\Support\ShareButtons. */
.share-buttons {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 32px 0;
    padding-top: 24px;
    border-top: 1px solid #e5e2dd;
}

.share-buttons-label {
    font-size: 13px;
    font-weight: 600;
    color: #6a655e;
}

.share-button {
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    color: #1a1815;
    background: #fff;
    border: 1px solid #e5e2dd;
    border-radius: 20px;
    padding: 6px 16px;
    cursor: pointer;
}

/* Ad Spaces (Views/frontend/partials/ad-space.php) — a small, optional
   banner slot; the partial renders nothing at all when no ad space is
   configured/enabled for that page+position, so this never has to
   account for an empty state. Deliberately no max-height or crop
   (Act's ask, Telegram 2026-09-15 — "we don't control size, we let it
   free, just don't let width exceed the design"): whatever aspect
   ratio the uploaded image has is shown as-is, just never wider than
   the page content. */

.ad-space {
    padding: 24px 0;
    text-align: center;
}

.ad-space img {
    max-width: 100%;
    height: auto;
    border-radius: 6px;
}

/* Events index (public, /p/{events-index-slug} — Views/frontend/events/index.php) */

.events-intro {
    padding: 24px 0 8px;
}

/* Events page hero (Act's ask, Telegram 2026-09-16, from a ChatGPT-made
   ad image he liked) — replaces the old .events-calendar-section
   pairing (calendar+agenda side by side) with hero-highlight+calendar
   instead; .events-agenda moved to its own full-width section right
   after (see events/index.php's comment for why). Hero wider than the
   calendar (1.6fr vs 1fr), matching the reference image's proportions —
   opposite of the old 1fr/1.3fr calendar/agenda split this replaced. */
.events-hero-section {
    display: grid;
    grid-template-columns: 1.6fr 1fr;
    gap: 40px;
    align-items: stretch;
    padding: 24px 0 40px;
}

.events-hero-highlight {
    position: relative;
    display: block;
    border-radius: 16px;
    overflow: hidden;
    color: #fff;
    min-height: 320px;
    background: #1a1815;
}

.events-hero-highlight-photo {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.events-hero-highlight-content {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    gap: 8px;
    padding: 32px;
    /* Same reasoning as .hero-content's own gradient (this template's
       hero carousel) — guarantees the white text below stays readable
       regardless of the photo's own colors. */
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.15) 60%, transparent 100%);
}

.events-hero-highlight-eyebrow {
    font-size: 13px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    opacity: 0.85;
}

.events-hero-highlight-title {
    font-size: 32px;
    font-weight: 700;
    margin: 0;
    line-height: 1.2;
}

.events-hero-highlight-desc {
    font-size: 15px;
    margin: 0;
    opacity: 0.9;
    max-width: 46ch;
}

.events-hero-highlight-meta {
    font-size: 13px;
    opacity: 0.85;
}

.events-agenda {
    padding: 0 0 40px;
}

@media (max-width: 900px) {
    .events-hero-section {
        grid-template-columns: minmax(0, 1fr);
    }

    .events-hero-highlight {
        min-height: 260px;
    }
}

.events-calendar {
    border: 1px solid #e5e2dd;
    border-radius: 16px;
    padding: 22px;
}

.events-calendar-nav {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 18px;
}

.events-calendar-nav-btn {
    width: 32px;
    height: 32px;
    border: 1px solid #e5e2dd;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #1a1815;
}

.events-calendar-month-label {
    font-size: 16px;
    font-weight: 700;
}

.events-calendar-weekdays,
.events-calendar-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 4px;
}

.events-calendar-weekdays {
    margin-bottom: 6px;
}

.events-calendar-weekday {
    text-align: center;
    font-size: 12px;
    color: #9a958f;
    font-weight: 600;
    padding: 6px 0;
}

.events-calendar-day {
    aspect-ratio: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    border-radius: 10px;
    font-size: 13px;
    color: #1a1815;
}

.events-calendar-day-empty {
    visibility: hidden;
}

.events-calendar-day-today {
    box-shadow: inset 0 0 0 1px #e5e2dd;
}

.events-calendar-day-selected {
    background: #1a1815;
    color: #fff;
    font-weight: 700;
}

.events-calendar-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #e05a2b;
}

.events-calendar-day-selected .events-calendar-dot {
    background: #fff;
}

.events-agenda-label {
    font-size: 14px;
    color: #9a958f;
    margin-bottom: 16px;
}

.events-agenda-empty {
    border: 1px solid #e5e2dd;
    border-radius: 12px;
    padding: 24px;
    text-align: center;
    color: #9a958f;
    font-size: 14px;
}

.events-agenda-item {
    display: flex;
    gap: 16px;
    border: 1px solid #e5e2dd;
    border-radius: 12px;
    padding: 16px;
    margin-bottom: 12px;
    color: #1a1815;
}

.events-agenda-item-date {
    background: #f3f1ee;
    border-radius: 10px;
    padding: 10px 14px;
    text-align: center;
    line-height: 1.1;
    flex-shrink: 0;
    height: fit-content;
}

.events-agenda-item-month {
    font-size: 11px;
    font-weight: 600;
    color: #e05a2b;
    letter-spacing: 0.03em;
}

.events-agenda-item-day {
    font-size: 18px;
    font-weight: 700;
}

.events-agenda-item-category {
    font-size: 13px;
    color: #9a958f;
    margin-bottom: 6px;
}

.events-agenda-item-title {
    font-size: 16px;
    font-weight: 700;
    margin: 0 0 6px;
}

.events-agenda-item-time {
    font-size: 13px;
    color: #4a4640;
}

@media (max-width: 720px) {
    .events-calendar-section {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* FAQ index (public, /p/{faq-index-slug} — Views/frontend/faq/index.php) */

.faq-intro {
    padding: 48px 0 40px;
    text-align: center;
}

.faq-intro .blog-section-title,
.faq-intro .blog-section-subtitle {
    text-align: center;
}

.faq-search {
    max-width: 480px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    background: #f3f1ee;
    border-radius: 10px;
    padding: 4px 4px 4px 16px;
}

.faq-search input {
    flex: 1;
    min-width: 0;
    border: none;
    background: transparent;
    font-size: 14px;
    font-family: inherit;
    padding: 10px 0;
    color: #1a1815;
}

.faq-search input:focus {
    outline: none;
}

.faq-search button {
    border: none;
    background: transparent;
    font-size: 15px;
    padding: 8px 12px;
    cursor: pointer;
    color: #4a4640;
}

.faq-body {
    display: grid;
    grid-template-columns: 260px 1fr;
    gap: 40px;
    align-items: start;
    padding: 0 0 56px;
}

.faq-categories {
    display: flex;
    flex-direction: column;
    gap: 6px;
    position: sticky;
    top: 16px;
}

.faq-category {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 14px;
    border-radius: 10px;
    font-size: 14px;
    color: #1a1815;
}

.faq-category-active {
    background: #1a1815;
    color: #fff;
    font-weight: 600;
}

.faq-category-count {
    font-size: 12px;
    color: #9a958f;
}

.faq-category-active .faq-category-count {
    color: rgba(255, 255, 255, 0.6);
}

.faq-active-label {
    font-size: 20px;
    font-weight: 700;
    margin: 0 0 20px;
}

.faq-accordion {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.faq-accordion .faq-item {
    border: 1px solid #e5e2dd;
    border-radius: 12px;
    padding: 18px 20px;
}

.faq-accordion .faq-item-question {
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

/* Native <summary> marker replaced with a +/− that flips with [open], same visual language as the mockup's toggle icon. */
.faq-accordion .faq-item-question::-webkit-details-marker {
    display: none;
}

.faq-accordion .faq-item-question::after {
    content: '+';
    font-size: 18px;
    color: #4a4640;
    flex-shrink: 0;
}

.faq-accordion .faq-item[open] .faq-item-question::after {
    content: '\2212';
}

.faq-accordion .faq-item-answer {
    font-size: 14px;
    color: #6a655e;
    line-height: 1.6;
    margin-top: 14px;
}

.faq-accordion .faq-item-answer p:first-child {
    margin-top: 0;
}

.faq-cta {
    background: #1a1815;
    border-radius: 16px;
    text-align: center;
    color: #fff;
    padding: 44px 32px;
    margin-bottom: 56px;
}

.faq-cta-title {
    font-size: 22px;
    margin: 0 0 8px;
    font-weight: 700;
}

.faq-cta-subtitle {
    font-size: 14px;
    color: rgba(255, 255, 255, 0.7);
    margin: 0 0 20px;
}

.faq-cta-button {
    display: inline-flex;
    background: #fff;
    color: #1a1815;
    border-radius: 8px;
    padding: 12px 24px;
    font-size: 14px;
    font-weight: 600;
}

@media (max-width: 720px) {
    .faq-body {
        grid-template-columns: minmax(0, 1fr);
    }

    .faq-categories {
        position: static;
        flex-direction: row;
        flex-wrap: wrap;
    }
}

/* Contact Us (both designs — Views/frontend/contact/with-form.php, no-form.php) */

.contact-hero {
    background: #1a1815;
    margin-bottom: 24px;
}

.contact-hero-inner {
    padding-top: 36px;
    padding-bottom: 36px;
}

.contact-hero-title {
    color: #fff;
    font-size: clamp(26px, 4vw, 38px);
    font-weight: 700;
    margin: 0;
}

.contact-heading {
    font-size: 32px;
    margin: 0 0 8px;
    font-weight: 700;
}

.contact-subheading {
    font-size: 15px;
    color: #6a655e;
    margin: 0 0 32px;
}

.contact-with-form {
    display: grid;
    grid-template-columns: 1.2fr 1fr;
    gap: 56px;
    padding: 24px 0 56px;
}

.contact-alert {
    border-radius: 8px;
    padding: 14px 16px;
    font-size: 14px;
    margin-bottom: 20px;
}

.contact-alert-success {
    background: #ecfdf3;
    color: #065f46;
}

.contact-alert-error {
    background: #fef3f2;
    color: #991b1b;
}

.contact-form {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.contact-form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.contact-form-field label {
    font-size: 13px;
    font-weight: 600;
    display: block;
    margin-bottom: 8px;
}

.contact-form-field input,
.contact-form-field select,
.contact-form-field textarea {
    width: 100%;
    box-sizing: border-box;
    border: 1px solid #e5e2dd;
    border-radius: 8px;
    padding: 12px 14px;
    font-size: 14px;
    font-family: inherit;
    background: #fff;
    color: #1a1815;
}

.contact-form-field textarea {
    resize: vertical;
}

.contact-form-submit {
    background: #1a1815;
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 13px 24px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    align-self: flex-start;
    width: auto;
}

.contact-details-col {
    display: flex;
    flex-direction: column;
    gap: 28px;
}

.contact-details-heading {
    font-size: 20px;
    margin: 0 0 18px;
    font-weight: 700;
}

.contact-details-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.contact-detail-label {
    font-size: 13px;
    color: #9a958f;
    margin-bottom: 2px;
}

.contact-detail-value {
    font-size: 14px;
}

.contact-map-frame {
    position: relative;
    width: 100%;
    border-radius: 16px;
    overflow: hidden;
}

.contact-map-frame img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.contact-map-frame-4-3 {
    aspect-ratio: 4 / 3;
}

.contact-map-frame-16-6 {
    aspect-ratio: 16 / 6;
}

.contact-map-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    font-weight: 600;
    margin-top: 14px;
    text-decoration: underline;
    color: #1a1815;
}

.contact-map-overlay-link {
    position: absolute;
    left: 24px;
    bottom: 24px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: #fff;
    color: #1a1815;
    font-size: 14px;
    font-weight: 600;
    padding: 12px 20px;
    border-radius: 30px;
    text-decoration: none;
}

.contact-no-form {
    padding: 0 0 56px;
}

.contact-detail-cards {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px;
    margin-bottom: 40px;
}

.contact-detail-card {
    background: #f3f1ee;
    border-radius: 16px;
    padding: 26px 22px;
}

.contact-detail-card .contact-detail-label {
    margin: 14px 0 4px;
}

.contact-detail-card .contact-detail-value {
    font-size: 15px;
    font-weight: 600;
    line-height: 1.5;
}

@media (max-width: 720px) {
    .contact-with-form {
        grid-template-columns: minmax(0, 1fr);
    }

    .contact-form-row {
        grid-template-columns: minmax(0, 1fr);
    }

    .contact-detail-cards {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Shared button used by more than one homepage design's ad-slot
   placeholders (see Vikunja card #104) — .editorial-btn-light is meant
   for a dark background, .editorial-btn-outline for a light one. */
.editorial-btn {
    display: inline-flex;
    align-items: center;
    border-radius: 8px;
    padding: 14px 26px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
}

.editorial-btn-outline {
    background: transparent;
    color: #1a1815;
    border: 1px solid #e5e2dd;
}

.editorial-btn-light {
    background: #fff;
    color: #1a1815;
    border: none;
    padding: 11px 22px;
}

/* Shared "section title + View all" header row and its meta line,
   used by more than one homepage design. */
.blog-section-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 28px;
}

.blog-section-header .blog-section-title {
    margin: 0;
}

.blog-section-link {
    font-size: 14px;
    font-weight: 600;
    text-decoration: underline;
    color: #1a1815;
    white-space: nowrap;
}

.editorial-blog-side-meta {
    font-size: 12px;
    color: #9a958f;
    margin-bottom: 4px;
}

/* Home v4 "Magazine" (public /, when settings.home_design = 2 —
   Views/frontend/home-v4.php — still slot 2, only what's behind it
   changed). Design ref: Act's "Home v4 (Magazine).dc.html" mockup,
   Telegram 2026-09-12, replacing the old "Editorial" design that used
   to live here. Shares .blog-section-title/.blog-section-header/
   .blog-card-*/.events-*/.faq-*/.editorial-btn/.editorial-blog-side-meta
   with the other homepage designs; only the magazine-* classes below
   are new. */

.home-v4 {
    padding: 32px 0 8px;
}

.magazine-layout {
    display: grid;
    grid-template-columns: 2.2fr 1fr;
    gap: 40px;
    align-items: start;
    /* .home-v4's own padding (32px 0 8px) only spaces the *outside* of
       the whole design — nothing separated the hero carousel from this
       section right under it (Act's ask, Telegram 2026-09-16). Scoped
       here rather than on the shared .hero class since that partial is
       reused by every home design, not just this one (Design #2). */
    margin-top: 32px;
    padding-bottom: 56px;
}

@media (max-width: 900px) {
    .magazine-layout {
        grid-template-columns: minmax(0, 1fr);
    }
}

.magazine-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px;
}

@media (max-width: 560px) {
    .magazine-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.magazine-sidebar {
    display: flex;
    flex-direction: column;
    gap: 36px;
}

.magazine-widget-title {
    font-size: 16px;
    font-weight: 700;
    margin: 0 0 16px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.magazine-suggested-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.magazine-suggested-item {
    display: flex;
    gap: 12px;
    color: inherit;
}

.magazine-suggested-thumb {
    position: relative;
    width: 64px;
    height: 64px;
    flex-shrink: 0;
    border-radius: 10px;
    overflow: hidden;
    display: block;
}

.magazine-suggested-thumb img,
.magazine-suggested-thumb .blog-card-media-placeholder {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.magazine-suggested-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.magazine-suggested-title {
    font-size: 14px;
    font-weight: 700;
    line-height: 1.35;
    color: #1a1815;
}

.magazine-categories-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.magazine-category-link {
    font-size: 13px;
    background: #f3f1ee;
    border-radius: 8px;
    padding: 8px 14px;
    display: flex;
    align-items: center;
    gap: 6px;
    color: #1a1815;
}

.magazine-category-count {
    color: #9a958f;
}

.magazine-newsletter {
    background: #f3f1ee;
    border-radius: 14px;
    padding: 24px;
}

/* Shared newsletter signup form (Act's ask, Telegram 2026-09-12) —
   used by both Home #1 (.home-newsletter-band, full-width) and the
   Magazine design (.magazine-newsletter, sidebar box). Defaults to a
   dark button since the Magazine sidebar box is light — Home #1's own
   dark band overrides it back to light below, same idea as the old
   editorial-btn/editorial-btn-light split. */
.newsletter-form {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
}

.newsletter-form input[type="email"] {
    flex: 1;
    min-width: 160px;
    border: 1px solid #e5e2dd;
    border-radius: 8px;
    padding: 11px 14px;
    font-size: 14px;
    font-family: inherit;
}

.newsletter-form button {
    background: #1a1815;
    color: #fff;
    border: none;
    border-radius: 8px;
    padding: 11px 20px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
}

.newsletter-flash {
    font-size: 13px;
    padding: 10px 14px;
    border-radius: 8px;
    margin-bottom: 12px;
}

.newsletter-flash-success {
    background: #ecfdf3;
    color: #065f46;
}

.newsletter-flash-error {
    background: #fef2f2;
    color: #991b1b;
}

/* Home #1's own newsletter band (Act's ask, Telegram 2026-09-12) — a
   new full-width closing section, since Design #1 never had an
   ad-slot/promo area to repurpose the way the Magazine design's
   sidebar box did. Dark, matching the site's other bold full-width
   bands (e.g. the footer) — its .newsletter-form button is overridden
   light below so it still shows up against this dark background,
   same idea as the old editorial-btn/editorial-btn-light split. */
.home-newsletter-band {
    background: #1a1815;
    border-radius: 16px;
    padding: 40px 32px;
    margin: 0 0 40px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
}

.home-newsletter-band-copy h2 {
    color: #fff;
    font-size: clamp(20px, 3vw, 26px);
    font-weight: 700;
    margin: 0 0 6px;
}

.home-newsletter-band-copy p {
    color: rgba(255, 255, 255, 0.65);
    font-size: 14px;
    margin: 0;
}

.home-newsletter-band .newsletter-form {
    flex: 1 1 320px;
    max-width: 420px;
}

.home-newsletter-band .newsletter-form input[type="email"] {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.2);
    color: #fff;
}

.home-newsletter-band .newsletter-form input[type="email"]::placeholder {
    color: rgba(255, 255, 255, 0.5);
}

.home-newsletter-band .newsletter-form button {
    background: #fff;
    color: #1a1815;
}

/* Site search results (public /search — Views/frontend/search.php).
   Design ref: Act's ask, Telegram 2026-09-10 — reuses .blog-section-
   title/.blog-grid/.events-grid/blog-card/event-card as-is, no new
   card design. */

.search-results {
    max-width: 1200px;
    margin: 0 auto;
    padding: 40px 16px 56px;
}

.search-section {
    margin-top: 40px;
}

.search-faq-hint {
    margin-top: 48px;
    padding-top: 24px;
    border-top: 1px solid #e5e2dd;
    font-size: 14px;
    color: #6a655e;
}
