/* ============================================================
   Newsvik — Theme stylesheet
   ------------------------------------------------------------
   Single source of truth for the public-facing theme: palette
   (light + dark), site container width, header, layout grid,
   widget rendering, and mobile responsiveness.

   Color philosophy: cool slate-based neutrals — no loud reds
   or oranges. Links pick up a subtle blue. Active states use a
   light gray chip (#bebebe) for consistency with the existing
   layout-toggle look.

   Light/dark switch:
     <html data-theme="light">  (default)
     <html data-theme="dark">   (user picks dark)
   The theme toggle in the header writes this attribute and
   mirrors it into localStorage (newsvik_theme) so the choice
   survives reloads.
   ============================================================ */

:root,
:root[data-theme="light"] {
    --bg:               #f1f5f9;   /* page background */
    --bg-elev:          #ffffff;   /* cards / header / dropdowns */
    --bg-sub:           #f8fafc;   /* subtle inset (search input, etc.) */
    --text:             #1e293b;   /* primary text */
    --text-muted:       #64748b;   /* secondary text / meta */
    --text-dim:         #94a3b8;   /* tertiary / placeholder */
    --border:           #e2e8f0;   /* hairline borders */
    --border-strong:    #cbd5e1;
    --link:             #2563eb;   /* hyperlinks (admin chrome / non-news) */
    --link-hover:       #1d4ed8;
    --news-link:        #337ab7;   /* news titles — kept distinct from --link
                                      because publishers expect a familiar
                                      "news blue" tone on aggregated headlines. */
    --news-link-hover:  #125a99;
    --accent:           #475569;   /* slate-600 — primary button */
    --accent-hover:     #334155;
    --accent-soft:      #e2e8f0;   /* hover bg for ghost buttons */
    --shadow:           0 1px 3px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
    --shadow-lg:        0 10px 30px rgba(15, 23, 42, 0.10), 0 4px 8px rgba(15, 23, 42, 0.04);
    --radius:           8px;
    --radius-lg:        12px;
    --header-h:         62px;
    --header-h-shrunk:  48px;       /* compact state when the page is scrolled */
    --container-max:    1200px;
}

:root[data-theme="dark"] {
    --bg:               #0f172a;
    --bg-elev:          #1e293b;
    --bg-sub:           #0b1220;
    --text:             #e2e8f0;
    --text-muted:       #94a3b8;
    --text-dim:         #64748b;
    --border:           #334155;
    --border-strong:    #475569;
    --link:             #60a5fa;
    --link-hover:       #93c5fd;
    --news-link:        #7eb5dd;   /* lifted from #337ab7 for AA contrast on dark surfaces */
    --news-link-hover:  #a8d0eb;
    --accent:           #cbd5e1;
    --accent-hover:     #f1f5f9;
    --accent-soft:      #1e293b;
    --shadow:           0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-lg:        0 12px 30px rgba(0, 0, 0, 0.5), 0 4px 10px rgba(0, 0, 0, 0.3);
}

/* Animation timing — shared across the scroll-shrink choreography so the
   header and the secondary bar move in lockstep. */
:root { --header-ease: 220ms ease; }

/* ---------- reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
    margin: 0;
    background: var(--bg);
    color: var(--text);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    font-size: 15px;
    line-height: 1.5;
}
a { color: var(--link); text-decoration: none; }
a:hover { color: var(--link-hover); text-decoration: underline; }
img { max-width: 100%; height: auto; }

/* Universal container — every centered band inside the page uses this. */
.site-container {
    max-width: var(--container-max);
    margin: 0 auto;
    padding: 0 16px;
    width: 100%;
}

/* ============================================================
   Header (sticky, full-bleed background, content centered)
   ------------------------------------------------------------
   Two states:
     normal   — .site-header               (header-h = 62px)
     shrunk   — .site-header.is-scrolled   (header-h-shrunk = 48px)
   The shrunk class is toggled by JS in _header.php on window scroll.
   Logo, search input, icon buttons all interpolate to smaller sizes
   over --header-ease so the transition is smooth. The secondary bar
   below the header rides along via the same easing on its `top:`.
   ============================================================ */
.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background: var(--bg-elev);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow);
    transition: box-shadow var(--header-ease);
}
.site-header.is-scrolled {
    box-shadow: var(--shadow-lg);   /* a touch heavier so it reads as "stuck" */
}
.header-inner {
    display: flex;
    align-items: center;
    gap: 14px;
    height: var(--header-h);
    transition: height var(--header-ease);
}
.site-header.is-scrolled .header-inner { height: var(--header-h-shrunk); }

.brand {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text);
    text-decoration: none;
    font-weight: 700;
    font-size: 1.25rem;
    flex-shrink: 0;
    transition: font-size var(--header-ease);
}
.brand:hover { text-decoration: none; color: var(--text); }
.brand img {
    height: 28px;
    width: auto;
    transition: height var(--header-ease);
}
.site-header.is-scrolled .brand     { font-size: 1.05rem; }
.site-header.is-scrolled .brand img { height: 22px; }

/* Global search — sits in the middle, expands. */
.global-search {
    position: relative;
    flex: 1;
    max-width: 540px;
    margin: 0 auto;
}
.global-search input {
    width: 100%;
    height: 38px;
    padding: 0 14px 0 38px;
    background: var(--bg-sub);
    border: 1px solid var(--border);
    border-radius: 999px;
    color: var(--text);
    font: inherit;
    font-size: 0.92rem;
    transition: border-color 0.15s, background 0.15s, height var(--header-ease), font-size var(--header-ease);
}
.site-header.is-scrolled .global-search input {
    height: 32px;
    font-size: 0.88rem;
}
.global-search input:focus {
    outline: none;
    border-color: var(--accent);
    background: var(--bg-elev);
}
.global-search::before {
    content: "";
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    width: 16px;
    height: 16px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3-3'/%3E%3C/svg%3E") center/contain no-repeat;
    pointer-events: none;
}

/* Primary menu (top-level + dropdowns) */
.primary-menu {
    display: flex;
    align-items: center;
    gap: 4px;
}
.primary-menu .menu-item { position: relative; }
.primary-menu .menu-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 8px 12px;
    border-radius: 6px;
    color: var(--text);
    font-size: 0.92rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
}
.primary-menu .menu-link:hover {
    background: var(--accent-soft);
    color: var(--text);
    text-decoration: none;
}
.primary-menu .menu-item.has-children > .menu-link::after {
    content: "";
    width: 10px;
    height: 10px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat;
    margin-left: 2px;
}
.primary-menu .submenu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 180px;
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 6px;
    display: none;
    z-index: 60;
}
.primary-menu .menu-item:hover > .submenu,
.primary-menu .menu-item:focus-within > .submenu {
    display: block;
}
.primary-menu .submenu .menu-link {
    display: block;
    padding: 8px 12px;
    border-radius: 4px;
    font-size: 0.88rem;
}

/* Header right-side icons (theme toggle, etc.) */
.header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}
.icon-btn {
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    color: var(--text-muted);
    cursor: pointer;
    transition: background 0.15s, color 0.15s, width var(--header-ease), height var(--header-ease);
}
.site-header.is-scrolled .icon-btn { width: 32px; height: 32px; }
.icon-btn:hover {
    background: var(--accent-soft);
    color: var(--text);
}
.icon-btn svg { width: 18px; height: 18px; }
.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* ============================================================
   Image toggle — lets visitors hide every news/feed thumbnail
   site-wide (saves bandwidth, gives a text-only reading mode).
   State lives on <html data-images="off"> via the boot script in
   _header.php (localStorage key: newsvik_images, values yes|no).
   Article body images are intentionally NOT in the selector list —
   editorial article content is treated as part of the story, not
   thumbnailware.
   ============================================================ */
.image-toggle .icon-img-on  { display: block; }
.image-toggle .icon-img-off { display: none; }
:root[data-images="off"] .image-toggle .icon-img-on  { display: none; }
:root[data-images="off"] .image-toggle .icon-img-off { display: block; }

:root[data-images="off"] .fc-thumb,
:root[data-images="off"] .feed-list-item img,
:root[data-images="off"] .sr-thumb {
    display: none !important;
}
/* When images are hidden, the .fc-entry rows no longer need the
   thumb-sized gap — collapse padding so titles align cleanly.
   Triangle bullets get added so each entry still reads as a list
   item (mirrors the .fc-entry-no-img treatment already used by the
   server when image_path is empty). */
:root[data-images="off"] .fc-entry {
    padding: 8px 6px;
}
:root[data-images="off"] .fc-entry:not(.fc-entry-no-img)::before {
    content: '\25B8';
    color: #605d5d;
    margin-right: 1px;
    font-size: 20px;
}
:root[data-images="off"] .feed-list-item {
    padding: 14px;
}
:root[data-images="off"] .feed-list-item:not(.fl-no-img)::before {
    content: '\25B8';
    color: #605d5d;
    font-size: 20px;
    margin-right: 1px;
    flex-shrink: 0;
}
/* Search-result equivalent: when the visitor (or admin) toggles images off,
   results that DID have a thumbnail get the same bullet treatment as the
   ones that natively didn't, so the list stays visually uniform. */
:root[data-images="off"] .search-result {
    padding: 14px;
}
:root[data-images="off"] .search-result:not(.sr-no-img)::before {
    content: '\25B8';
    color: #605d5d;
    font-size: 20px;
    margin-right: 1px;
    flex-shrink: 0;
}

.hamburger {
    display: none;     /* shown only on mobile */
}

/* ============================================================
   Secondary menu strip — sits glued under the header, shares the
   sticky stack so it scrolls with the page header. Visually quieter
   than the primary menu so the eye lands on the brand+search first.
   ============================================================ */
.secondary-menu-bar {
    /* Non-sticky: scrolls away with the page. Used to be position:sticky
       glued under .site-header, but the user wanted to see it as a static
       strip below the header. The sibling-scroll-shrink rule that adjusted
       its `top:` is removed too — it had nothing to anchor against once the
       bar stopped being position:sticky. */
    background: var(--bg-sub);
    border-bottom: 1px solid var(--border);
}
.secondary-menu-bar .secondary-menu-inner {
    display: flex;
    align-items: center;
    justify-content: center;     /* center the menu within the container */
    min-height: 32px;            /* slimmer strip — was 40px */
    /* overflow:visible (default) is essential here — any non-visible value
       creates a clipping context that hides the absolutely-positioned
       .submenu dropdowns instead of letting them escape downward. */
}
/* The inner element renderPrimaryMenu emits is <nav class="secondary-menu">,
   a block-level element that contains the .menu-item children. Making the
   nav itself a flex container — and center-justifying — gives the
   row-of-buttons-that-grows-from-the-middle look. */
.secondary-menu-bar .secondary-menu {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;                   /* enough room for the separator pseudo to
                                    breathe without crowding the labels */
    flex-wrap: wrap;
}
.secondary-menu-bar .menu-item { position: relative; flex-shrink: 0; }
/* Vertical separator between adjacent top-level items — small slate line
   centered in the gap, never on the first item. Submenu items inside the
   dropdown skip this (they live in a different .menu-item context). */
.secondary-menu-bar .secondary-menu > .menu-item + .menu-item::before {
    content: "";
    position: absolute;
    left: -6px;
    top: 25%;
    bottom: 25%;
    width: 1px;
    background: var(--border-strong);
    pointer-events: none;
}
.secondary-menu-bar .menu-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 5px 10px;           /* tighter vertical padding for the slimmer bar */
    color: var(--text-muted);
    font-size: 0.86rem;
    font-weight: 500;
    text-decoration: none;
    border-radius: 6px;
    white-space: nowrap;
}
.secondary-menu-bar .menu-link:hover {
    color: var(--text);
    background: var(--bg-elev);
    text-decoration: none;
}
.secondary-menu-bar .menu-item.has-children > .menu-link::after {
    content: "";
    width: 9px; height: 9px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") center/contain no-repeat;
    margin-left: 2px;
}
.secondary-menu-bar .submenu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 180px;
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 6px;
    display: none;
    z-index: 60;
}
.secondary-menu-bar .menu-item:hover > .submenu,
.secondary-menu-bar .menu-item:focus-within > .submenu { display: block; }
.secondary-menu-bar .submenu .menu-link {
    display: block;
    padding: 8px 12px;
    border-radius: 4px;
    font-size: 0.86rem;
    color: var(--text);
    /* Override the bar's hover (which uses var(--bg-elev) — white-on-white in
       the dropdown). Use the muted slate hover for visible contrast. */
}
.secondary-menu-bar .submenu .menu-link:hover {
    background: var(--accent-soft);
    color: var(--text);
    text-decoration: none;
}
@media (max-width: 860px) {
    .secondary-menu-bar { display: none; }   /* both menus collapse into the drawer */
}

/* ============================================================
   Per-page "User Description" — a "Details" toggle pinned to the right of the
   secondary menu bar, and the collapsible HTML panel it reveals. The toggle is
   absolutely positioned so the centered menu nav stays centered. Hidden by
   default via the [hidden] attribute on the panel.
   ============================================================ */
.secondary-menu-bar .secondary-menu-inner { position: relative; }
.secondary-desc-toggle {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: 6px;
    color: var(--text-muted);
    cursor: pointer;
    padding: 3px 9px;
    font-size: 0.78rem;
    line-height: 1;
}
.secondary-desc-toggle:hover {
    color: var(--text);
    background: var(--bg-elev);
    border-color: var(--border-strong);
}
.secondary-desc-toggle.is-open {
    color: var(--text);
    background: var(--bg-elev);
    border-color: var(--news-link, #c00);
}
.secondary-desc-label { font-weight: 600; }
@media (max-width: 560px) { .secondary-desc-label { display: none; } }  /* icon-only on tiny screens */

.page-desc-panel { background: var(--bg-elev); border-bottom: 1px solid var(--border); }
.page-desc-panel[hidden] { display: none; }
.page-desc-inner {
    padding: 16px 0 20px;
    color: var(--text);
    line-height: 1.7;
    font-size: 0.95rem;
}
.page-desc-inner img { max-width: 100%; height: auto; border-radius: 6px; }
.page-desc-inner h1, .page-desc-inner h2, .page-desc-inner h3, .page-desc-inner h4 { color: var(--text); margin: 16px 0 8px; line-height: 1.3; }
.page-desc-inner p { margin: 0 0 12px; }
.page-desc-inner ul, .page-desc-inner ol { margin: 0 0 12px; padding-left: 22px; }
.page-desc-inner a { color: var(--news-link, #c00); }
.page-desc-inner table { border-collapse: collapse; max-width: 100%; }
.page-desc-inner td, .page-desc-inner th { border: 1px solid var(--border); padding: 6px 10px; }

/* ============================================================
   Below-navbar widget area (full-width band, content 1200)
   ============================================================ */
.below-navbar {
    background: var(--bg);
    padding: 14px 0;
}
.below-navbar:empty,
.below-navbar .site-container:empty { display: none; }
.below-navbar .widget {
    margin: 0;
}

/* ============================================================
   Page grid — 2-column (category/language) or 3-column (feed/article/page)
   ============================================================ */
.page-grid {
    display: grid;
    gap: 12px;                /* matches inter-widget vertical gap so the
                                 horizontal seam doesn't look bigger than the
                                 vertical one — visually balanced. */
    padding: 4px 0 40px;      /* tighter top so the breadcrumb sits closer to
                                 the header / below-navbar band. Bottom stays
                                 generous so the footer doesn't crowd the
                                 last cards. */
    align-items: start;
}
.page-grid-2col {
    grid-template-columns: 210px minmax(0, 1fr);
}
.page-grid-3col {
    grid-template-columns: 210px minmax(0, 1fr) 190px;
}
/* Used when ONLY the right sidebar has widgets — main expands to the left. */
.page-grid-2col-right {
    grid-template-columns: minmax(0, 1fr) 190px;
}
.page-grid-1col {
    grid-template-columns: minmax(0, 1fr);
}
/* Sidebars: slimmer than before. The width reduction lands in main automatically
   because the grid template adds up to less than container width, so main's
   1fr expands. The total page width is still <= --container-max. */
.sidebar { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.main-area { min-width: 0; }   /* prevent grid item from overflowing */

/* ---- Floating (sticky-on-scroll) sidebar widgets ----
   A widget marked "Float on scroll" in the admin gets .widget-float. It sticks
   below the (sticky) header once scrolled to, and stays visible. For that to
   have room, the SIDEBAR it lives in must be as tall as the row — but the grid
   uses align-items:start, so the column is normally only as tall as its content.
   _footer.php's JS adds .has-float to such a sidebar (→ align-self:stretch) and
   sets each floating widget's `top` so MULTIPLE float widgets stack instead of
   overlapping. The top below is a CSS fallback for the single-widget / no-JS case. */
.sidebar.has-float { align-self: stretch; }
.widget-float { position: sticky; top: calc(var(--header-h-shrunk) + 10px); z-index: 5; }
@media (max-width: 960px) {
    /* Single-column layout — a sticky sidebar widget would cover the article. */
    .widget-float { position: static; top: auto; }
    .sidebar.has-float { align-self: start; }
}

/* ---- "Popular in 24 hours" widget ----
   text-align:left is set explicitly so the widget reads cleanly even in the
   below-navbar band (whose .widget-body is center-aligned for ads). */
.pop-list { list-style: none; margin: 0; padding: 0; text-align: left; }
.pop-item { border-bottom: 1px solid var(--border); }
.pop-item:last-child { border-bottom: 0; }
.pop-link { display: flex; gap: 10px; padding: 10px 2px; text-decoration: none; color: inherit; align-items: flex-start; text-align: left; }
.pop-link:hover { background: var(--accent-soft); }
.pop-thumb { width: 64px; height: 46px; object-fit: cover; border-radius: 6px; flex-shrink: 0; background: var(--border); }
/* No-thumbnail items (admin "show images" off, or item without an image) get the
   site's ▸ arrow bullet — same marker the feed lists use. The visitor "hide
   images" toggle adds the bullet to thumbed items too (and hides the thumb). */
.pop-link.pop-no-img::before,
:root[data-images="off"] .pop-link:not(.pop-no-img)::before {
    content: '\25B8';
    color: var(--text-dim);
    font-size: 15px;
    line-height: 1.5;
    flex-shrink: 0;
    margin-right: 2px;
}
:root[data-images="off"] .pop-thumb { display: none; }
.pop-body { min-width: 0; flex: 1; }
.pop-title { display: block; font-size: 0.88rem; line-height: 1.35; color: var(--news-link); }
.pop-link:hover .pop-title { color: var(--news-link-hover); text-decoration: underline; }
.pop-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 5px; font-size: 0.72rem; color: var(--text-dim); line-height: 1.3; }
.pop-sep { color: var(--border-strong); }
.pop-source { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
.pop-feed-icon { width: 14px; height: 14px; border-radius: 2px; object-fit: contain; flex-shrink: 0; }
.pop-clicks { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; color: var(--text-muted); white-space: nowrap; }
.pop-eye { vertical-align: middle; }
.pop-empty { color: var(--text-dim); font-size: 0.85rem; font-style: italic; padding: 6px 2px; text-align: left; }

/* ---- Lazy-load images (optional, toggled in Admin -> System -> Caching) ----
   While an image is waiting to scroll into view it shows the placeholder (set
   as its src by the footer JS) over a neutral background; the real image fades
   in on load. */
.lazy-pending { background: var(--bg-sub); }
img.lazy-loaded { animation: lazy-fade 0.35s ease; }
@keyframes lazy-fade { from { opacity: 0.4; } to { opacity: 1; } }

/* ---- "More from this source" widget (sibling feeds of the current feed page) ---- */
.src-feeds-head { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); padding: 2px 2px 9px; }
.src-feeds-list { list-style: none; margin: 0; padding: 0; }
.src-feeds-item { border-bottom: 1px solid var(--border); }
.src-feeds-item:last-child { border-bottom: 0; }
.src-feeds-item a,
.src-feeds-item > span { display: block; padding: 9px 10px; font-size: 0.9rem; line-height: 1.35; text-decoration: none; }
.src-feeds-item a { color: var(--news-link); }
.src-feeds-item a:hover { background: var(--accent-soft); color: var(--news-link-hover); }
/* Current page — highlighted, non-clickable */
.src-feeds-item.src-current > span {
    background: var(--accent-soft);
    color: var(--text);
    font-weight: 700;
    border-left: 3px solid var(--news-link, #c00);
    padding-left: 9px;
    cursor: default;
}

/* ---- "Latest Articles" widget (newest CMS posts, auto/manual scope) ----
   Shares the visual language of the Popular widget so a sidebar stacking both
   reads consistently. text-align:left for the below-navbar (centered) band. */
.lat-list { list-style: none; margin: 0; padding: 0; text-align: left; }
.lat-item { border-bottom: 1px solid var(--border); }
.lat-item:last-child { border-bottom: 0; }
.lat-link { display: flex; gap: 10px; padding: 10px 2px; text-decoration: none; color: inherit; align-items: flex-start; text-align: left; }
.lat-link:hover { background: var(--accent-soft); }
.lat-thumb { width: 64px; height: 46px; object-fit: cover; border-radius: 6px; flex-shrink: 0; background: var(--border); }
.lat-link.lat-no-img::before,
:root[data-images="off"] .lat-link:not(.lat-no-img)::before {
    content: '\25B8';
    color: var(--text-dim);
    font-size: 15px;
    line-height: 1.5;
    flex-shrink: 0;
    margin-right: 2px;
}
:root[data-images="off"] .lat-thumb { display: none; }
.lat-body { min-width: 0; flex: 1; }
.lat-title { display: block; font-size: 0.88rem; line-height: 1.35; color: var(--news-link); }
.lat-link:hover .lat-title { color: var(--news-link-hover); text-decoration: underline; }
.lat-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 5px; font-size: 0.72rem; color: var(--text-dim); line-height: 1.3; }
.lat-sep { color: var(--border-strong); }
.lat-cat { font-weight: 600; color: var(--text-muted); }
.lat-empty { color: var(--text-dim); font-size: 0.85rem; font-style: italic; padding: 6px 2px; text-align: left; }

/* Note: we used to have .sidebar:empty { display: none } here, but CSS Grid
   keeps the column slot allocated even when an item is display:none — and
   the auto-flow then puts the main element into the (240px) empty slot,
   making main super narrow. The fix lives in PHP: callers buffer the widget
   output and skip the <aside> entirely (and pick a narrower grid class) when
   the area is empty. So we no longer need a CSS-side hide. */
@media (max-width: 960px) {
    .page-grid-2col, .page-grid-2col-right, .page-grid-3col, .page-grid-1col {
        grid-template-columns: minmax(0, 1fr);
    }
    /* Mobile reading order: the DOM is [sidebar-left → main → sidebar-right]
       so desktop CSS Grid can place columns left-to-right, but on a narrow
       single-column stack that order means visitors scroll past sidebar
       widgets before reaching the article/feed body. Use grid `order` to
       move main to the top, then right sidebar, then left sidebar —
       matches admin preference and "below_navbar" widgets (rendered by
       _header.php, outside this grid) still appear first naturally. */
    .page-grid > .main-area     { order: 1; }
    .page-grid > .sidebar-right { order: 2; }
    .page-grid > .sidebar-left  { order: 3; }
}

/* ============================================================
   Widget rendering — light card with title bar
   ============================================================ */
.widget {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    box-shadow: var(--shadow);
}
.widget-title {
    padding: 10px 14px;
    background: var(--bg-sub);
    border-bottom: 1px solid var(--border);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.widget-body {
    padding: 14px;
    font-size: 0.92rem;
    color: var(--text);
    word-break: break-word;
}
.widget-body img { max-width: 100%; height: auto; border-radius: 6px; }

/* Below-navbar widgets are usually ad-shaped — center them and let them
   breathe without the title-bar chrome. */
.below-navbar .widget {
    background: transparent;
    border: 1px dashed var(--border-strong);
    box-shadow: none;
}
.below-navbar .widget-title { display: none; }
.below-navbar .widget-body { text-align: center; padding: 10px; }

/* Mid-feed inline widgets — placed between cards in the feed-cards grid.
   Behaviour is intentionally different per column layout:
     • 1-col / 2-col → ALWAYS span full row (`grid-column: 1 / -1`). In 2-col
                       this means the widget body is visually centered with
                       breathing room on both sides instead of sticking to
                       one side as a single cell.
     • 3-col         → fit the remaining empty cells in the row
                       (`grid-column: auto / -1`). E.g. after card 2 the
                       widget snaps into column 3 so no gap is visible.
   The `.fc-cols-3` selector below is more specific (4 vs 3 class hits) so it
   wins over the default. PHP renders the grid with `fc-cols-3` by default,
   matching the server-side default column count — no flash before JS init. */
.feed-cards-grid .widget.is-inline {
    grid-column: 1 / -1;
    background: transparent;
    border: 1px dashed var(--border-strong);
    box-shadow: none;
}
.feed-cards-grid.fc-cols-3 .widget.is-inline {
    grid-column: auto / -1;
}
.feed-cards-grid .widget.is-inline .widget-title { display: none; }
.feed-cards-grid .widget.is-inline .widget-body { text-align: center; padding: 10px; }

/* ============================================================
   Main-area content card
   ============================================================ */
.content-card {
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 22px;
    box-shadow: var(--shadow);
}

/* ============================================================
   Footer
   ============================================================ */
.site-footer {
    margin-top: 30px;
    padding: 20px 0 0;
    color: var(--text-muted);
    font-size: 0.85rem;
    border-top: 1px solid var(--border);
    background: var(--bg-elev);
}
.site-footer .social-links a {
    color: var(--accent);
    margin: 0 8px;
    font-weight: 500;
}
.site-footer .footer-base {
    text-align: center;
    padding: 18px 0 26px;
}

/* Footer widget zone — two side-by-side widgets on top, one full-width
   underneath. Renders nothing when there are no footer widgets active. */
.footer-widget-zone {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    padding: 8px 0 18px;
}
.footer-widget-zone .footer-area-full {
    grid-column: 1 / -1;       /* span across the 2-col band */
}
.footer-widget-zone .widget {
    background: var(--bg-sub);
}
.footer-widget-zone:empty { display: none; }
@media (max-width: 760px) {
    .footer-widget-zone { grid-template-columns: 1fr; }
    .footer-widget-zone .footer-area-full { grid-column: 1; }
}

/* ============================================================
   Search results page
   ============================================================ */
.search-result {
    display: flex;
    gap: 12px;
    padding: 12px;
    background: var(--bg-elev);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    text-decoration: none;
    color: inherit;
    transition: box-shadow 0.15s, border-color 0.15s;
}
.search-result:hover {
    box-shadow: var(--shadow-lg);
    border-color: var(--border-strong);
    text-decoration: none;
}
.search-result img.sr-thumb {
    width: 110px; height: 76px;
    object-fit: cover;
    border-radius: 6px;
    background: var(--bg-sub);
    flex-shrink: 0;
}
.search-result.sr-no-img { padding: 14px; }
/* Matching triangle bullet for image-less search results — same style used
   by feed cards and the single-feed page so the "no image" affordance reads
   consistently across every list surface. */
.search-result.sr-no-img::before {
    content: '\25B8';
    color: #605d5d;
    font-size: 20px;
    margin-right: 1px;
    flex-shrink: 0;
}
.search-result .sr-body { min-width: 0; flex: 1; }
.search-result .sr-title { font-size: 0.95rem; color: var(--news-link); line-height: 1.4; font-weight: 500; }
.search-result:hover .sr-title { color: var(--news-link-hover); }
.search-result .sr-meta {
    margin-top: 6px;
    font-size: 0.78rem;
    color: var(--text-muted);
    display: inline-flex; align-items: center; gap: 6px;
    flex-wrap: wrap;
}
.search-result .sr-meta .sr-dot { width: 3px; height: 3px; background: var(--text-dim); border-radius: 50%; display: inline-block; }
.search-result .sr-meta img.sr-feed-icon {
    width: 16px; height: 16px;
    border-radius: 3px;
    object-fit: contain;
    background: var(--bg-sub);
}
.search-result .sr-meta .sr-feed-name { font-weight: 600; color: var(--text); }

.search-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    margin-top: 16px;
}
@media (max-width: 1050px) {
    .search-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 700px) {
    .search-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   Mobile: hamburger + drawer
   ============================================================ */
@media (max-width: 860px) {
    .global-search { max-width: none; }
    .primary-menu { display: none; }
    .hamburger {
        display: inline-flex;
        align-items: center; justify-content: center;
        width: 38px; height: 38px;
        background: transparent;
        border: 1px solid transparent;
        border-radius: 8px;
        color: var(--text);
        cursor: pointer;
    }
    .hamburger:hover { background: var(--accent-soft); }
    .hamburger svg { width: 22px; height: 22px; }

    /* Drawer that slides in from the left */
    body.has-drawer-open { overflow: hidden; }
    .drawer-scrim {
        position: fixed; inset: 0;
        background: rgba(15, 23, 42, 0.45);
        z-index: 70;
        display: none;
    }
    body.has-drawer-open .drawer-scrim { display: block; }
    .nav-drawer {
        position: fixed;
        top: 0; left: 0; bottom: 0;
        width: 280px;
        background: var(--bg-elev);
        z-index: 80;
        transform: translateX(-100%);
        transition: transform 0.22s ease-out;
        display: flex;
        flex-direction: column;
        box-shadow: var(--shadow-lg);
    }
    body.has-drawer-open .nav-drawer { transform: translateX(0); }
    .nav-drawer-head {
        padding: 12px 14px;
        border-bottom: 1px solid var(--border);
        display: flex; align-items: center; justify-content: space-between;
    }
    .nav-drawer-head strong { font-size: 1rem; }
    .nav-drawer ul {
        list-style: none; padding: 8px 0; margin: 0;
        overflow-y: auto;
    }
    .nav-drawer ul ul { padding-left: 14px; }
    .nav-drawer a {
        display: block;
        padding: 10px 16px;
        color: var(--text);
        font-size: 0.95rem;
    }
    .nav-drawer a:hover { background: var(--accent-soft); text-decoration: none; }
    /* "Page Details" entry in the drawer — opens the description panel. Styled
       to read like a drawer link but reset from <button> defaults. Border-top
       separates it from the menu list above. */
    .drawer-desc-link {
        display: flex;
        align-items: center;
        gap: 8px;
        width: 100%;
        text-align: left;
        padding: 12px 16px;
        margin-top: 4px;
        background: transparent;
        border: 0;
        border-top: 1px solid var(--border);
        color: var(--text);
        font-size: 0.95rem;
        font-weight: 600;
        font-family: inherit;
        cursor: pointer;
    }
    .drawer-desc-link:hover { background: var(--accent-soft); }
    .drawer-desc-link svg { color: var(--text-muted); flex-shrink: 0; }
}

@media (min-width: 861px) {
    .drawer-scrim, .nav-drawer { display: none !important; }
}

/* ============================================================
   Generic helpers — let pages drop their own inline styles
   gradually and use these instead.
   ============================================================ */
.btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: var(--accent);
    color: #fff;
    border: 0;
    border-radius: 6px;
    cursor: pointer;
    font: inherit;
    font-weight: 500;
    text-decoration: none;
}
.btn-primary:hover { background: var(--accent-hover); color: #fff; }
