/* ===== Custom Properties ===== */
:root {
    --color-accent:  #9dff50;
    --color-bg:      #000000;
    --color-text:    #ffffff;
    --color-card-bg: rgba(80, 194, 255, 0.1);
    --color-border:  #9dff50;
    --font-main:     'Montserrat', sans-serif;
}

/* ===== Reset & Base ===== */
*, *::before, *::after { box-sizing: border-box; }

html {
    scroll-behavior: smooth;
    -webkit-text-size-adjust: 100%;
}

/* Sticky-footer scaffolding: body is a flex column tall enough to fill the
 * viewport. Children (top-strip, page content, footer, trailing script)
 * lay out top-to-bottom. The footer's margin-top: auto rule below grabs
 * any leftover vertical space when content is short, leaving the footer
 * pinned to the bottom edge. When content is taller than the viewport,
 * the body grows past 100vh and the margin collapses to 0, so the footer
 * naturally sits below the content. Sticky top-strip is unaffected — its
 * `position: sticky` works the same in a flex-column body. */
html, body { min-height: 100vh; }
/* Page chrome is light by default. The dark theme survives only on the
 * elements that opt in: .top-strip and .site-footer set their own dark
 * backgrounds, and the year-page hero/footer fill themselves explicitly.
 * Hardcoded values (not var(--color-bg)/--color-text) because those vars
 * still resolve to the dark palette and remain in use for header/footer. */
body {
    margin: 0;
    background-color: #f5f5f5;
    color: #1a1a1a;
    font-family: var(--font-main);
    line-height: 1.5;
    display: flex;
    flex-direction: column;
}
/* Push any direct-child footer (footer-simple.php and footer.php both
 * land as body children) to the bottom of the flex column. Trailing
 * <script> tags after the footer are zero-height flex items and don't
 * affect the visual position. */
body > footer { margin-top: auto; }

h1, h2, h3, h4, h5, h6 { margin: 0; }
p  { margin: 0; }
ol, ul { list-style: none; margin: 0; padding: 0; }
a  { color: inherit; text-decoration: inherit; }
img { display: block; max-width: 100%; height: auto; }
address { font-style: normal; }
button { cursor: pointer; border: none; background: transparent; font-family: inherit; }

.container {
    width: 100%;
    margin-left: auto;
    margin-right: auto;
}

@media (min-width: 640px)  { .container { max-width: 640px; } }
@media (min-width: 768px)  { .container { max-width: 768px; } }
@media (min-width: 1024px) { .container { max-width: 1024px; } }
@media (min-width: 1280px) { .container { max-width: 1280px; } }
@media (min-width: 1536px) { .container { max-width: 1536px; } }

/* ===== Top Strip ===== */
.top-strip {
    position: sticky;
    top: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 20px;
    padding: 0 20px;
    height: 44px;
    background: var(--color-bg);
    border-bottom: 1px solid rgba(255,255,255,0.1);
}
.top-strip__brand {
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--color-accent);
    text-decoration: none;
    letter-spacing: 0.08em;
    flex-shrink: 0;
}
.top-strip__brand span {
    color: #ffffff;
}

.top-strip__year {
    font-size: 0.75rem;
    font-weight: 400;
    font-style: italic;
    margin-left: 5px;
    letter-spacing: normal;
    color: #ffffff;
}

.top-strip__years { flex: 1; min-width: 0; overflow: hidden; }

/* Row wrappers exist so the markup can group items for the mobile two-row
 * layout. On desktop they're transparent to layout — children become
 * direct flex items of .top-strip exactly as before. */
.top-strip__row { display: contents; }

/* Explicit visual order: matches the original desktop layout
 * (brand → year → about×3 → search → lang). The DOM groups search next to
 * year/lang for the mobile row, but on desktop `order` rearranges them
 * back into the original sequence. Within each mobile row, items still
 * sort by `order`, which yields brand→year→search→lang on row 1 and the
 * three nav links left-to-right on row 2 — both per spec. */
.top-strip__brand   { order: 1; }
.year-dropdown      { order: 2; }
.top-strip__about   { order: 3; }
.top-strip__search  { order: 6; }
.top-strip__lang    { order: 7; }

/* ── Year list ──────────────────────────────────────── */
.year-list {
    display: flex;
    align-items: center;
    gap: 2px;
    list-style: none;
    margin: 0;
    padding: 0;
}
.year-list__item > a,
.year-list__group-btn {
    display: inline-block;
    padding: 3px 9px;
    border-radius: 4px;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--color-text);
    text-decoration: none;
    background: none;
    border: none;
    cursor: pointer;
    font-family: var(--font-main);
    white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}
.year-list__item > a:hover,
.year-list__group-btn:hover {
    background: rgba(255,255,255,0.08);
}
.year-list__item--active > a {
    color: var(--color-accent);
    font-weight: 700;
}
.year-list__item--empty > a {
    opacity: 0.3;
    pointer-events: none;
}
.year-list__group { display: contents; }
.year-list__group-items {
    display: none;
    list-style: none;
    margin: 0;
    padding: 0;
}
.year-list__group.is-expanded .year-list__group-items { display: contents; }
.year-list__group.is-expanded .year-list__group-btn   { display: none; }

/* ── Search ─────────────────────────────────────────── */
.top-strip__search {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}
.top-strip__search-input {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.75);
    border-radius: 4px;
    color: var(--color-text);
    font-family: var(--font-main);
    font-size: 0.8125rem;
    padding: 4px 10px;
    width: 150px;
    transition: border-color 0.2s, width 0.25s;
}
.top-strip__search-input::placeholder {
    color: rgba(255,255,255,0.75);
}
.top-strip__search-input:focus {
    outline: none;
    border-color: var(--color-accent);
    width: 210px;
}
.top-strip__search-btn {
    background: none;
    border: none;
    color: rgba(255,255,255,0.6);
    cursor: pointer;
    padding: 4px;
    line-height: 0;
    transition: color 0.15s;
}
.top-strip__search-btn:hover { color: var(--color-text); }

/* ── About link ─────────────────────────────────────── */
.top-strip__about {
    color: rgba(255,255,255,0.7);
    text-decoration: none;
    font-size: 0.8125rem;
    font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
    transition: color 0.15s;
}
.top-strip__about:hover { color: var(--color-text); }

/* ── Lang ───────────────────────────────────────────── */
.top-strip__lang {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8125rem;
    font-weight: 500;
    flex-shrink: 0;
}
.top-strip__lang-current { color: var(--color-accent); }
.top-strip__lang-switch {
    color: rgba(255,255,255,0.55);
    text-decoration: none;
    transition: color 0.15s;
}
.top-strip__lang-switch:hover { color: var(--color-text); }

/* ── Mobile ─────────────────────────────────────────── */
@media (max-width: 767px) {
    /* Two-row header on narrow viewports. .top-strip itself becomes
     * display: contents so its children (the two rows) escape its 80px-ish
     * containing block — row--main can then stick to the viewport across
     * the entire page scroll, not just within .top-strip's own height.
     * The .top-strip background, padding, height, sticky, etc. are all
     * declared on the row wrappers below instead. */
    .top-strip {
        display: contents;
    }
    .top-strip__row {
        display: flex;
        align-items: center;
        width: 100%;
        padding: 6px 12px;
        background: var(--color-bg);
        border-bottom: 1px solid rgba(255,255,255,0.1);
    }
    .top-strip__row--main {
        /* Sticky against the viewport (body is now the effective
         * containing block since .top-strip is display: contents). z-index
         * matches the desktop .top-strip value so the row stays above all
         * page content; the year/search dropdowns inherit this stacking
         * context and overlay correctly. */
        position: sticky;
        top: 0;
        z-index: 200;
        justify-content: space-between;
        gap: 10px;
    }
    .top-strip__row--nav {
        justify-content: space-around;
        gap: 6px;
        flex-wrap: wrap;
    }
    .top-strip__about { font-size: 0.8125rem; }

    /* "since 2010" subtitle takes ~70px next to the IT Sec logo — drop it
     * on mobile so the year, search, and lang have room on row 1. */
    .top-strip__year { display: none; }

    /* Search wrapper absorbs the remaining row width via flex: 1; the input
     * inside is always rendered in expanded state at width: 100%. No
     * tap-to-expand / icon-collapse — the input is a plain static element
     * at every width. Padding, background, border, placeholder, transition,
     * and focus-accent all inherit from the desktop rules above; only the
     * width adapts. The :focus override is required to suppress the
     * desktop focus rule's `width: 210px` jump. */
    .top-strip__search {
        flex: 1;
        min-width: 0;
    }
    .top-strip__search-input { width: 100%; }
    .top-strip__search-input:focus { width: 100%; }
}

/* ===== About page ===== */
.about-page { padding: 60px 20px; }
.about-page__inner { max-width: 860px; margin: 0 auto; }
.about-page__title { font-size: 2rem; font-weight: 700; margin-bottom: 32px; }
.about-page__body h2 { font-size: 1.125rem; font-weight: 600; margin: 28px 0 10px; }
.about-page__body p,
.about-page__body ul { line-height: 1.7; margin-bottom: 12px; }
.about-page__body ul { padding-left: 20px; }
.about-page__body li { margin-bottom: 4px; }
.about-page__body a { color: var(--color-accent); }

.about-page__editions { margin-top: 48px; }
.about-page__editions-title { font-size: 1.25rem; font-weight: 700; margin-bottom: 20px; }

.about-editions { list-style: none; display: flex; flex-direction: column; gap: 10px; }
.about-editions__item {
    display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
    padding: 14px 18px;
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    transition: border-color 0.15s;
}
.about-editions__item:hover { border-color: var(--color-accent); }
.about-editions__link {
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
    flex: 1; text-decoration: none; color: inherit;
}
.about-editions__roman {
    font-size: 0.75rem; font-weight: 700; color: var(--color-accent);
    text-transform: uppercase; letter-spacing: .06em; flex-shrink: 0;
}
.about-editions__year {
    font-size: 1.0625rem; font-weight: 700; flex-shrink: 0;
}
.about-editions__title { flex: 1; font-size: 0.9375rem; }
.about-editions__city  { font-size: 0.8125rem; color: var(--color-accent); flex-shrink: 0; }
.about-editions__dates { font-size: 0.8125rem; opacity: 0.6; flex-shrink: 0; }
.about-editions__proc  {
    font-size: 0.8125rem; font-weight: 500; color: var(--color-accent);
    text-decoration: none; flex-shrink: 0;
    border: 1px solid var(--color-accent); border-radius: 4px; padding: 2px 8px;
}
.about-editions__proc:hover { background: var(--color-accent); color: #000; }

/* ===== Archive ===== */
.archive {
    padding: 60px 20px;
    max-width: 1280px;
    margin: 0 auto;
}

.archive__title {
    font-size: 2rem;
    font-weight: 500;
    margin-bottom: 48px;
}

.archive__grid {
    display: flex;
    flex-direction: column;
    gap: 24px;
}

.archive__card {
    border: 1px solid var(--color-border);
    border-radius: 1rem;
    padding: 24px;
    background: var(--color-card-bg);
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.archive__card-year {
    font-size: 2rem;
    font-weight: 700;
    color: var(--color-accent);
}

.archive__card-edition {
    font-size: 1rem;
    font-weight: 500;
}

.archive__card-city {
    font-size: 0.875rem;
    font-weight: 300;
}

.archive__card-links {
    display: flex;
    gap: 12px;
    margin-top: 12px;
    flex-wrap: wrap;
}

.archive__card-btn {
    display: inline-block;
    padding: 8px 20px;
    border-radius: 9999px;
    border: 1px solid var(--color-border);
    font-size: 0.875rem;
    color: var(--color-text);
    transition: background 0.2s;
}

.archive__card-btn:hover { background: rgba(80, 194, 255, 0.2); }

@media (min-width: 768px) {
    .archive__card { flex-direction: row; align-items: center; gap: 24px; }
    .archive__card-year { font-size: 2.5rem; min-width: 80px; }
    .archive__card-links { margin-top: 0; margin-left: auto; flex-shrink: 0; }
}

/* ===== Speaker / Person Page ===== */
.speaker-page {
    padding: 60px 20px;
    max-width: 900px;
    margin: 0 auto;
}

.speaker-page__photo {
    width: 160px;
    height: 160px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--color-border);
    margin-bottom: 24px;
}

.speaker-page__name {
    font-size: 2rem;
    font-weight: 700;
    color: var(--color-accent);
    margin-bottom: 8px;
}

.speaker-page__title {
    font-size: 1rem;
    font-weight: 300;
    margin-bottom: 16px;
}

.speaker-page__bio {
    font-size: 1rem;
    line-height: 1.8;
    margin-bottom: 32px;
}

.speaker-page__talks-title {
    font-size: 1.25rem;
    font-weight: 500;
    color: var(--color-accent);
    margin-bottom: 16px;
}

.speaker-page__talk {
    padding: 16px;
    border: 1px solid var(--color-border);
    border-radius: 0.75rem;
    margin-bottom: 12px;
    background: var(--color-card-bg);
}

.speaker-page__talk-conf {
    font-size: 0.75rem;
    color: var(--color-accent);
    margin-bottom: 4px;
}

.speaker-page__talk-title {
    font-size: 1rem;
    font-weight: 500;
}

/* ── Year Dropdown ── */
.year-dropdown {
    position: relative;
    display: inline-block;
}

.year-dropdown__btn {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border: 2px solid var(--color-accent);
    background: transparent;
    color: var(--color-accent);
    font-weight: 500;
    border-radius: 6px;
    cursor: pointer;
    transition: all 0.2s;
}

.year-dropdown__btn:hover {
    background: var(--color-accent);
    color: white;
}

.year-dropdown__btn[aria-expanded="true"] {
    background: var(--color-accent);
    color: white;
}

.year-dropdown__btn svg {
    width: 16px;
    height: 16px;
    transition: transform 0.2s;
}

.year-dropdown__btn[aria-expanded="true"] svg {
    transform: rotate(180deg);
}

.year-dropdown__list {
    position: absolute;
    top: 100%;
    left: 0;
    margin-top: 8px;
    background: white;
    border: 1px solid var(--color-border);
    border-radius: 6px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    list-style: none;
    padding: 0;
    min-width: 120px;
    max-height: 300px;
    overflow-y: auto;
    z-index: 100;
    /* Slim scrollbar tinted dark for the white dropdown background. */
    scrollbar-width: thin;
    scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
}
.year-dropdown__list::-webkit-scrollbar       { width: 6px; }
.year-dropdown__list::-webkit-scrollbar-track { background: transparent; }
.year-dropdown__list::-webkit-scrollbar-thumb {
    background: rgba(0, 0, 0, 0.2);
    border-radius: 3px;
}
.year-dropdown__list::-webkit-scrollbar-thumb:hover {
    background: rgba(0, 0, 0, 0.35);
}

.year-dropdown__item {
    padding: 0;
}

.year-dropdown__item a {
    color: rgba(0, 0, 0, 0.75);
    display: block;
    padding: 10px 16px;
    text-decoration: none;
    transition: background 0.2s;
}

.year-dropdown__item a:hover {
    background: var(--color-accent);
    color: white;
}

.year-dropdown__item--empty a {
    opacity: 0.5;
    cursor: not-allowed;
}

.year-dropdown__item--empty a:hover {
    background: transparent;
    color: var(--color-text);
}

.year-dropdown__item--active a {
    background: var(--color-accent);
    color: white;
    font-weight: 600;
}

/* ── Simple Footer (used by non-conference pages via footer-simple.php) ── */
.site-footer--simple {
    padding: 24px 0;
    border-top: 1px solid var(--color-border);
    background: var(--color-bg);
    color: var(--color-text);
}

.site-footer--simple .site-footer__inner {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 20px;
}

.site-footer--simple .site-footer__brand {
    flex-shrink: 0;
}

.site-footer--simple .site-footer__brand .hero__logo-text {
    font-size: 1.5rem;
    font-weight: 700;
    text-decoration: none;
    color: var(--color-text);
    transition: color 0.2s;
}

.site-footer--simple .site-footer__brand .hero__logo-text .hero__logo-accent {
    color: var(--color-accent);
}

.site-footer--simple .site-footer__brand .hero__logo-text:hover {
    color: var(--color-accent);
}

.site-footer--simple .site-footer__center {
    flex: 1;
    display: flex;
    justify-content: center;
}

.site-footer--simple .site-footer__nav-link {
    color: var(--color-text);
    text-decoration: none;
    transition: color 0.2s;
}

.site-footer--simple .site-footer__nav-link:hover {
    color: var(--color-accent);
}

.site-footer--simple .site-footer__lang {
    flex-shrink: 0;
}

.site-footer--simple .site-footer__lang a {
    color: var(--color-text);
    text-decoration: none;
    transition: color 0.2s;
    font-weight: 500;
}

.site-footer--simple .site-footer__lang a:hover {
    color: var(--color-accent);
}

/* ===== Top-strip live-suggest dropdown ===== */
.top-strip__search { position: relative; }
.top-strip__search-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    right: 50%;
    transform: translateX(50%);
    background: var(--color-bg);
    min-width: 400px;
    max-width: 480px;
    max-height: 70vh;
    /* Panel is a flex column with a scrollable list + sticky footer link.
     * overflow stays hidden here (scrolling moves to the inner list) so the
     * footer can sit outside the scroll viewport and stay pinned. */
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: #1b1b1b;
    border: 1px solid rgba(255,255,255,0.5);
    border-radius: 8px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.45);
    z-index: 300;
}
/* Without this, the `display: flex` above overrides the user-agent
 * stylesheet's `[hidden] { display: none }` rule — author stylesheets win
 * on equal specificity, so the JS-set `hidden` attribute alone has no
 * visible effect. Re-pinning `display: none` when [hidden] is set on the
 * panel restores the native behavior. */
.top-strip__search-dropdown[hidden] { display: none; }
.top-strip__search-list {
    flex: 1;
    overflow-y: auto;
    /* Flex children default to min-height: auto which prevents shrinking
     * below intrinsic content size. Override so the list actually scrolls
     * instead of pushing the footer below the dropdown's max-height. */
    min-height: 0;
    padding: 4px 0;
    /* Firefox slim scrollbar — thumb tinted to read on the dark dropdown
     * background, track transparent so the panel color shows through. */
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.2) transparent;
}
/* Webkit/Blink equivalent for the same panel. The 6px width matches the
 * Firefox `thin` rendering, the thumb brightens slightly on hover, and no
 * horizontal scrollbar is styled — content is expected to wrap (article
 * titles line-clamp to 2 lines, names rarely overflow on dropdown width). */
.top-strip__search-list::-webkit-scrollbar       { width: 6px; }
.top-strip__search-list::-webkit-scrollbar-track { background: transparent; }
.top-strip__search-list::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.2);
    border-radius: 3px;
}
.top-strip__search-list::-webkit-scrollbar-thumb:hover {
    background: rgba(255, 255, 255, 0.35);
}
.top-strip__search-empty {
    padding: 12px 14px;
    color: rgba(255,255,255,0.55);
    font-size: 0.875rem;
}
.top-strip__search-group-title {
    padding: 8px 14px 4px;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--color-accent);
}
/* Truncation hint appended when the DB total exceeds the dropdown cap, e.g.
 * "АВТОРИ (перші 10)". Lower-case, muted, normal weight to read as a
 * subordinate annotation rather than part of the section label. */
.top-strip__search-group-trunc {
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    color: rgba(255, 255, 255, 0.55);
    margin-left: 4px;
}
.top-strip__search-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 4px 14px;
    color: var(--color-text);
    text-decoration: none;
    border-bottom: 1px solid rgba(255,255,255,0.04);
}
.top-strip__search-item:hover { background: rgba(255,255,255,0.06); }
/* Up to 2 lines with ellipsis — articles whose titles wrap past a single
 * line use the second line; short titles (most authors, conferences) sit on
 * one line as before, since the clamp only kicks in when content overflows. */
.top-strip__search-item-title {
    font-size: 0.875rem;
    font-weight: 500;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 1.35;
}
.top-strip__search-item-sub   { font-size: 0.75rem; color: rgba(255,255,255,0.55); }
.top-strip__search-all {
    display: block;
    padding: 10px 14px;
    color: var(--color-accent);
    font-size: 0.8125rem;
    font-weight: 600;
    text-decoration: none;
    border-top: 1px solid rgba(255,255,255,0.25);
    /* Locked size — never shrinks when the list grows; always pinned to
     * the bottom of the dropdown panel. */
    flex-shrink: 0;
}
.top-strip__search-all:hover { background: rgba(255,255,255,0.06); }

/* ===== Handle page (author + article landings) ===== */
.handle-page { padding: 40px 20px; max-width: 900px; margin: 0 auto; }
.handle-page__head { display: flex; gap: 24px; align-items: flex-start; margin-bottom: 24px; flex-wrap: wrap; }
.handle-page__photo { width: 160px; height: 160px; border-radius: 50%; object-fit: cover; border: 2px solid var(--color-border); flex-shrink: 0; }
.handle-page__name { font-size: 2rem; font-weight: 700; color: var(--color-accent); margin-bottom: 4px; }
.handle-page__role,
.handle-page__affiliation,
.handle-page__country { font-size: 0.9375rem; line-height: 1.5; opacity: 0.85; }
.handle-page__links { display: flex; gap: 12px; margin-top: 12px; list-style: none; flex-wrap: wrap; }
.handle-page__links a { color: var(--color-accent); text-decoration: none; font-size: 0.875rem; }
.handle-page__links a:hover { text-decoration: underline; }
.handle-page__title { font-size: 1.75rem; font-weight: 700; line-height: 1.3; margin-bottom: 12px; }
.handle-page__authors,
.handle-page__supervisors { font-size: 1rem; line-height: 1.6; margin-bottom: 8px; }
.handle-page__authors a,
.handle-page__supervisors a { color: var(--color-accent); text-decoration: none; }
.handle-page__authors a:hover,
.handle-page__supervisors a:hover { text-decoration: underline; }
.handle-page__meta { display: grid; grid-template-columns: auto 1fr; gap: 6px 16px; margin: 20px 0; font-size: 0.9375rem; }
.handle-page__meta dt { font-weight: 600; color: var(--color-accent); }
.handle-page__meta a { color: inherit; text-decoration: underline; }
.handle-page__abstract { margin: 24px 0; }
.handle-page__abstract p { line-height: 1.7; }
.handle-page__keywords { margin: 12px 0 20px; font-size: 0.9375rem; opacity: 0.85; }
.handle-page__pdf { margin: 24px 0; }
.handle-page__pdf-btn {
    display: inline-block;
    padding: 10px 22px;
    border-radius: 9999px;
    background: var(--color-accent);
    color: #000;
    font-weight: 600;
    text-decoration: none;
}
.handle-page__pdf-btn:hover { opacity: 0.85; }
.handle-page__id {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin-top: 24px;
    padding: 12px 14px;
    background: var(--color-card-bg);
    border: 1px solid var(--color-border);
    border-radius: 8px;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.875rem;
}
.handle-page__id-label { font-family: var(--font-main); font-weight: 600; color: var(--color-accent); }
.handle-page__copy {
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text);
    padding: 4px 10px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.75rem;
    margin-left: auto;
}
.handle-page__copy:hover { background: rgba(255,255,255,0.06); }
.handle-page__bio { margin: 16px 0; line-height: 1.7; }
.handle-page__section { margin-top: 32px; }
.handle-page__section-title { font-size: 1.125rem; font-weight: 600; color: var(--color-accent); margin-bottom: 12px; }
.handle-page__list { list-style: none; display: flex; flex-direction: column; gap: 6px; }
.handle-page__list a { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap; padding: 8px 12px; border-radius: 6px; background: #e4e4e4; color: inherit; text-decoration: none; }
.handle-page__list a:hover { border-color: var(--color-accent); }
.handle-page__list-title { flex: 1; font-size: 0.9375rem; }
.handle-page__list-meta  { font-size: 0.8125rem; opacity: 0.6; }

/* ── Handle pages: light theme ──────────────────────────────────────────
 * Scoped to <main class="main-content handle-theme-light"> on both the
 * author and article handle branches. Overrides --color-bg / --color-text
 * locally so the existing var(--color-text), var(--color-card-bg) etc.
 * rules cascade automatically. Site header + footer stay dark — they're
 * outside the scoped main. Don't touch :root.
 */
.handle-theme-light {
    --color-bg:   #f5f5f5;
    --color-text: #1a1a1a;
    background: var(--color-bg);
    color: var(--color-text);
}
/* Strip the per-element opacity fades from the previous white-on-dark pass
 * so muted text reads as full-strength dark on the light background. */
.handle-theme-light .handle-page__role,
.handle-theme-light .handle-page__affiliation,
.handle-theme-light .handle-page__country,
.handle-theme-light .handle-page__list-meta,
.handle-theme-light .handle-page__keywords { opacity: 1; }
/* Article-handle author/supervisor inline links: the dark-theme rules force
 * accent green text. On the light theme those need to be regular dark links
 * with the accent reserved for hover. The .handle-page__pdf-btn button is
 * intentionally not included — it stays a green pill with black text. */
.handle-theme-light .handle-page__authors a,
.handle-theme-light .handle-page__supervisors a { color: var(--color-text); }
.handle-theme-light .handle-page__authors a:hover,
.handle-theme-light .handle-page__supervisors a:hover { color: var(--color-accent); }

/* Two-column header: name block left, identifiers/links right.
 * gap matches the rest of the page's rhythm; align-items: start so a
 * long name in the left column doesn't stretch the right column rows. */
.handle-page--author .handle-page__head {
    display: grid;
    grid-template-columns: 6fr 4fr;
    gap: 32px;
    align-items: start;
    flex-wrap: initial;
}
.handle-page--author .handle-page__head-left  { min-width: 0; }
.handle-page--author .handle-page__head-right {
    display: flex; flex-direction: column; gap: 8px;
    font-size: 0.9375rem; line-height: 1.5;
    min-width: 0;
}
.handle-page--author .handle-page__head-right .handle-page__id-row {
    display: flex; flex-wrap: wrap; align-items: baseline;
    gap: 6px; margin: 0;
}
/* Identifier value chip — same pill shape as the participation year chips,
 * applied to both span (non-linked, e.g. the page's own handle) and anchor
 * (linked, e.g. ORCID / Scholar / Scopus / АСКБ). Hover only applies to
 * the anchor variant so the static handle ID doesn't appear interactive. */
.handle-page__id-chip {
    display: inline-block;
    padding: 2px 10px;
    background: #e4e4e4;
    border-radius: 999px;
    color: var(--color-text);
    text-decoration: none;
    /* Explicit font so the chip renders the same in the article-handle id
     * strip (whose parent forces monospace) and in the author-page right
     * column (which inherits the body sans-serif). */
    font-family: var(--font-main);
    font-size: 0.875rem;
    font-weight: 500;
    word-break: break-all;
    transition: color .15s, background .15s;
}
a.handle-page__id-chip:hover {
    color: var(--color-accent);
    background: #d4d4d4;
}
/* Right-column labels: fixed 100px column so the chips line up across
 * every row, and the colon separates label from value cleanly. */
.handle-page--author .handle-page__head-label { width: 120px; font-weight: 600; color: var(--color-text); }

/* Year sub-heading inside the Articles section. Smaller than the page-level
 * Статті heading (h2) but tabular — sits flush with the cards below. */
.handle-page--author .handle-page__year-heading {
    font-size: 1rem;
    font-weight: 600;
    margin: 18px 0 6px;
    color: var(--color-text);
}
.handle-page--author .handle-page__year-heading:first-child { margin-top: 0; }
.handle-page--author .handle-page__section > .handle-page__list { margin-bottom: 0; }

/* Per-row badge for non-author roles (supervisor). Author rows render no
 * badge — the section heading already implies "by this person". */
.handle-page--author .handle-page__role-badge {
    font-size: 0.75rem;
    padding: 2px 8px;
    border: 1px solid var(--color-border);
    border-radius: 999px;
    color: var(--color-accent);
    align-self: center;
}

/* Participation section: flat rows — role label on the left ending with a
 * colon, conference items as chips on the right. No card frame; the chips
 * carry the visual weight. Fixed-ish left column so rows align; mobile
 * collapses to a stack with the role label above its chip row. */
.handle-page--author .handle-page__participation {
    display: flex; flex-direction: column; gap: 10px;
    margin: 0;
    margin-top: 12px;
}
.handle-page--author .handle-page__participation-row {
    display: grid;
    grid-template-columns: 240px 1fr;
    gap: 16px;
    align-items: baseline;
}
.handle-page--author .handle-page__participation-role {
    font-weight: 600;
    color: var(--color-accent);
    margin: 0;
}
.handle-page--author .handle-page__participation-years {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
}
/* Conference chip — darker fill than the light page bg so it reads as a
 * tappable element; hover shifts text to accent. Pill shape matches
 * .handle-page__role-badge so the two tap-target shapes on the page read
 * as a family. */
.handle-page--author .handle-page__year-chip {
    display: inline-block;
    padding: 2px 10px;
    background: #e4e4e4;
    border-radius: 999px;
    color: var(--color-text);
    text-decoration: none;
    font-size: 0.875rem;
    white-space: nowrap;
    transition: color .15s, background .15s;
}
.handle-page--author .handle-page__year-chip:hover {    
    background: #d4d4d4;
}

@media (max-width: 720px) {
    .handle-page--author .handle-page__participation-row {
        grid-template-columns: 1fr;
        gap: 4px;
    }
}

/* Narrow viewports: stack the columns so the right column's labels don't
 * get crushed. 720px is where 7fr / 3fr leaves the right column under
 * ~200px wide — too tight for "Google Scholar" + label on one line. */
@media (max-width: 720px) {
    .handle-page--author .handle-page__head {
        grid-template-columns: 1fr;
        gap: 16px;
    }
}

/* ── Handle pages: heading colors ──────────────────────────────────────
 * Headings on these two pages are bound to var(--color-accent) globally,
 * which becomes unreadable when a conference's accent shifts to a bright
 * tone (e.g. neon green on the #f5f5f5 light bg). Pin them to the body
 * text color instead so they always pass against the light background.
 * Accent is preserved for marker badges, hover affordances, and the PDF
 * CTA — pop-of-color uses, not primary text.
 * Scoped via .handle-theme-light so other pages keep their accent
 * treatment. Placed last so it wins specificity ties against the
 * earlier .handle-page--author scoped rules. */
.handle-theme-light .handle-page__name,
.handle-theme-light .handle-page__title,
.handle-theme-light .handle-page__section-title,
.handle-theme-light .handle-page__participation-role,
.handle-theme-light .handle-page__meta dt,
.handle-theme-light .handle-page__id-label { color: var(--color-text); }

/* Articles list rows: number column on the left, card on the right. The
 * card (the <a>) keeps its existing styling — the number sits outside it
 * so "card layout stays as-is" per the spec. Year sub-headings remain
 * full-width siblings of the <ul>, so the number column only aligns with
 * the cards, not with the year header above. */
.handle-page__list-item {
    display: flex;
    align-items: baseline;
    gap: 10px;
}
.handle-page__list-item > a { flex: 1; min-width: 0; }
.handle-page__list-num {
    flex: 0 0 36px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #6b6b6b;
    font-size: 0.875rem;
}

/* Section heading bar — dark fill that matches the site header / footer
 * background. Inside .handle-theme-light the local --color-bg is the light
 * page bg, so #000 is hardcoded here with a pointer to the :root variable
 * it mirrors. Bar spans the section's content width (block h2 inside
 * .handle-page__inner — same width as the cards/rows below). margin: 0 +
 * border-radius: 0 keeps it flush; the h1 page title and h3 year
 * sub-headings are untouched. Overrides the white-text-on-light-bg color
 * from the earlier headings-color rule (same specificity, later in file). */
.handle-theme-light .handle-page__section-title {
    background: #c7c7c7; /* same as .top-strip's var(--color-bg) at :root */
    color: black;
    font-size: 1.25rem;
    font-weight: 600;
    padding: 14px 16px;
    margin: 0;
    border-radius: 0;
}

/* ── Author profile redesign ─────────────────────────────────────────────
 * Academic-profile (ORCID / Crossref / ResearchGate) style:
 *   1. Profile card on the light grey page bg — white-ish fill, subtle
 *      border, photo + identity on top, identifier rows below a divider.
 *   2. Section headings use .handle-page__section-heading (plain h2, no
 *      dark bar). The .handle-page__section-title dark-bar rule above
 *      stays — it still applies to the article handle page's "Анотація"
 *      heading.
 *   3. Articles list switches from cards to a 48px + 1fr grid with year
 *      sub-headings spanning both columns and a thin row separator.
 * Only the author handle page is in scope — selectors are anchored to
 * .handle-page--author. */

.handle-page--author .handle-page__profile {
    background: #ffffff;
    border: 1px solid #e4e4e4;
    border-radius: 8px;
    padding: 24px 28px;
    margin-bottom: 32px;
}
.handle-page--author .handle-page__profile-identity {
    display: grid;
    grid-template-columns: 96px 1fr;
    gap: 24px;
    align-items: center;
}
.handle-page--author .handle-page__profile-photo {
    width: 96px; height: 96px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid #e4e4e4;
}
.handle-page--author .handle-page__profile-photo--placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #eeeeee;
    color: #888888;
    font-size: 1.625rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: .02em;
}
.handle-page--author .handle-page__profile-text { min-width: 0; }
.handle-page--author .handle-page__profile-name {
    font-size: 1.375rem;
    font-weight: 500;
    line-height: 1.3;
    color: var(--color-text);
    margin: 0 0 4px 0;
}
.handle-page--author .handle-page__profile-position {
    font-size: 0.9375rem;
    color: #555;
    margin: 0;
    line-height: 1.4;
}
.handle-page--author .handle-page__profile-affil {
    font-size: 0.8125rem;
    color: #777;
    margin: 6px 0 0 0;
}

/* Identifier rows below the in-card divider. Three-column grid keeps the
 * icon, label, and value cleanly aligned across rows. Scoped to
 * .handle-theme-light so the rules apply on both the author profile card
 * AND the article page's identifier block — same look, one source. */
.handle-page--author .handle-page__profile-identifiers,
.handle-page--article .handle-page__article-identifiers {
    margin-top: 20px;
    padding-top: 18px;
    border-top: 1px solid #e8e8e8;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.handle-theme-light .handle-page__id-line {
    display: grid;
    /* 120px label column accommodates "Конференція" (the widest UA label),
     * "PDF статті", and "Article PDF". Shorter labels (Handle, ORCID,
     * Scopus, Scholar, АСКБ/ACSP, Year, Section, Pages) get extra
     * breathing room — acceptable trade for consistent vertical alignment
     * of the value column across all rows on both author and article
     * pages. */
    grid-template-columns: 20px 120px 1fr;
    gap: 12px;
    align-items: center;
    font-size: 0.875rem;
}
.handle-theme-light .handle-page__id-icon {
    width: 18px; height: 18px;
    color: #777;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.handle-theme-light .handle-page__id-icon svg { width: 100%; height: 100%; display: block; }
.handle-theme-light .handle-page__id-key { color: #555; }
.handle-theme-light .handle-page__id-val {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    color: var(--color-text);
    word-break: break-all;
    text-decoration: none;
}
.handle-theme-light .handle-page__id-val::after {
    content: '→';
    display: none;
    padding-left: 12px;
}
.handle-theme-light a.handle-page__id-val:hover {
    font-weight: 700;
    text-decoration: underline;
}
.handle-theme-light a.handle-page__id-val:hover::after {
    display: inline-block;
}
/* External-link identifier rows (e.g. Proceedings) embed a literal ↗ in
 * the link text to signal "opens elsewhere". Suppress the hover → glyph
 * so the two affordances don't double up. */
.handle-theme-light .handle-page__id-line--external a.handle-page__id-val:hover::after {
    display: none;
}

/* Участь + Статті wrappers — same white-card styling as the profile card
 * above so the page reads as three stacked panels: identity, participation,
 * articles. Scoped to .handle-page--author so the article handle page's
 * .handle-page__section (if it ever uses this class) stays untouched. */
.handle-page--author .handle-page__section {
    background: #ffffff;
    border: 1px solid #e4e4e4;
    border-radius: 8px;
    padding: 24px 28px;
    margin-top: 0;
    margin-bottom: 32px;
}

/* Plain section heading — used by both Участь and Статті on the author
 * page. No dark bar; the dark bar is article-handle-only. margin-top: 0
 * because the card's 24px padding already provides the breathing room. */
.handle-page--author .handle-page__section-heading {
    font-size: 1.125rem;
    font-weight: 500;
    color: var(--color-text);
    margin: 0 0 12px 0;
}

/* Participation rebalance: 180px role column (per spec), muted/smaller
 * label. Overrides the earlier .handle-page--author .handle-page__participation-*
 * rules thanks to source order (same specificity, later wins). */
.handle-page--author .handle-page__participation-row {
    grid-template-columns: 180px 1fr;
}
.handle-page--author .handle-page__participation-role {
    color: #666;
    font-size: 0.8125rem;
    font-weight: 400;
}

/* Articles — grid replacement for the old <ul>/<li> cards. Year sub-
 * headings span both columns; number + title rows share a thin bottom
 * border. No card frame, no individual row backgrounds. */
/* Author profile articles list — outer is a block list so year headings
 * sit cleanly between rows. Each row is its own 2-column grid (num |
 * title) with a row-level border so the line spans both columns evenly. */
.handle-page--author .handle-page__articles { display: block; }
.handle-page--author .handle-page__articles-year {
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--color-text);
    margin: 18px 0 4px 0;
}
.handle-page--author .handle-page__articles-year:first-child { margin-top: 0; }
.handle-page--author .handle-page__articles-row {
    display: grid;
    grid-template-columns: 48px 1fr;
    column-gap: 16px;
    align-items: baseline;
    padding: 10px 0;
    border-bottom: 1px solid #e8e8e8;
    color: var(--color-text);
    text-decoration: none;
}
.handle-page--author .handle-page__articles-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #888;
    font-size: 0.875rem;
}
.handle-page--author .handle-page__articles-title {
    color: var(--color-text);
    font-size: 0.9375rem;
    line-height: 1.5;
}
/* Shared hover treatment for "row of links" lists — author profile articles
 * list and both search-results sections. The `<a>` is now the row wrapper,
 * so hover triggers on the row and the visual change applies to the inner
 * title/name span. Base state: arrow hidden, slid left. Hover: weight
 * bumps to 500 and the arrow fades + slides in. font-weight isn't
 * animatable without a variable font, but the transition declaration is
 * harmless and keeps the rule self-contained. */
.handle-page--author .handle-page__articles-title,
.handle-page--search .search-page__authors-name,
.handle-page--search .search-page__articles-title {
    transition: font-weight 0.15s ease;
}
.handle-page--author .handle-page__articles-title::after,
.handle-page--search .search-page__authors-name::after,
.handle-page--search .search-page__articles-title::after {
    content: '→';
    display: inline-block;
    padding-left: 8px;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
}
.handle-page--author .handle-page__articles-row:hover .handle-page__articles-title,
.handle-page--search .search-page__authors-row:hover .search-page__authors-name,
.handle-page--search .search-page__articles-row:hover .search-page__articles-title {
    font-weight: 500;
}
.handle-page--author .handle-page__articles-row:hover .handle-page__articles-title::after,
.handle-page--search .search-page__authors-row:hover .search-page__authors-name::after,
.handle-page--search .search-page__articles-row:hover .search-page__articles-title::after {
    opacity: 1;
    transform: translateX(0);
}
.handle-page--author .handle-page__articles-role {
    font-size: 0.75rem;
    color: #888;
    margin-left: 4px;
}

/* Mobile stack: photo over identity, single-column identifier rows,
 * participation role label above its chips (already handled by the
 * earlier @media rule on .handle-page__participation-row). */
@media (max-width: 720px) {
    .handle-page--author .handle-page__profile { padding: 20px 18px; }
    .handle-page--author .handle-page__profile-identity {
        grid-template-columns: 1fr;
        justify-items: center;
        text-align: center;
        gap: 16px;
    }
    .handle-page--author .handle-page__id-line {
        grid-template-columns: 20px auto 1fr;
        gap: 8px;
    }
    .handle-page--author .handle-page__articles { column-gap: 10px; }
    .handle-page--author .handle-page__articles { grid-template-columns: 36px 1fr; }
}

/* ── Article handle page ───────────────────────────────────────────────
 * Three stacked white cards (article info, abstract, cite) followed by an
 * embedded PDF iframe in a fourth tight-padding card. Visual language
 * mirrors the author profile page so the reader recognizes the pattern. */

/* Shared card chrome — same five properties as .handle-page--author's
 * .handle-page__profile / .handle-page__section. Generic so the article
 * page (and any future panel) can opt in by adding .handle-page__card. */
.handle-theme-light .handle-page__card {
    background: #ffffff;
    border: 1px solid #e4e4e4;
    border-radius: 8px;
    padding: 24px 28px;
    margin-bottom: 32px;
}

.handle-page--article .handle-page__article-title {
    font-size: 1.375rem;
    font-weight: 500;
    line-height: 1.3;
    color: var(--color-text);
    margin: 0 0 4px 0;
}
/* Opposite-language title under the H1: same font but smaller and muted.
 * Hidden entirely when the alt language column is empty (template-level). */
.handle-page--article .handle-page__article-title-alt {
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.35;
    color: #666;
    margin: 0 0 4px 0;
}
/* Conference year line under the title block — small muted link to the
 * year page. Helps a reader spot the conference at a glance without
 * scanning down to the identifiers list. Adjacent margins collapse with
 * the alt-title's bottom margin so the gap above stays consistent
 * whether or not the alt title renders. */
.handle-page--article .handle-page__article-title-year {
    margin: 4px 0 18px 0;
    font-size: 0.8125rem;
    color: #777;
}
.handle-page--article .handle-page__article-title-year a {
    color: inherit;
    text-decoration: none;
}
.handle-page--article .handle-page__article-title-year a:hover {
    color: var(--color-accent);
    text-decoration: underline;
}
/* Authors and supervisors as vertical stacks: each contributor is its own
 * name + affiliation block. Gap between blocks gives the list visual rhythm
 * without commas. */
.handle-page--article .handle-page__article-authors,
.handle-page--article .handle-page__article-supervisors {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 12px 0 6px 0;
}
.handle-page--article .handle-page__article-supervisors {
    margin-top: 18px;
}
.handle-page--article .handle-page__article-author {
    line-height: 1.4;
}
/* Numbered author rows: 36px num column + 1fr body. Baseline alignment so
 * the number sits with the author name (top row), not centered against the
 * name+affiliation stack. Mirrors the .handle-page__list-num styling on the
 * author profile's article list. Only authors get this — supervisors keep
 * the non-numbered block layout above. */
.handle-page--article .handle-page__article-author--numbered {
    display: grid;
    grid-template-columns: 36px 1fr;
    column-gap: 12px;
    align-items: baseline;
}
.handle-page--article .handle-page__article-author-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #6b6b6b;
    font-size: 0.875rem;
}
.handle-page--article .handle-page__article-author-body { min-width: 0; }
/* Author name = link, matches the .handle-page__id-val hover treatment so a
 * reader trained on the identifier rows recognizes the same affordance:
 * bold + underline + a → glyph that fades in on hover. */
.handle-page--article .handle-page__article-author-name {
    color: var(--color-text);
    text-decoration: none;
    font-size: 0.9375rem;
    font-weight: 500;
}
.handle-page--article .handle-page__article-author-name::after {
    content: '→';
    display: none;
    padding-left: 8px;
}
.handle-page--article a.handle-page__article-author-name:hover {
    font-weight: 700;
    text-decoration: underline;
}
.handle-page--article a.handle-page__article-author-name:hover::after {
    display: inline-block;
}
/* Affiliation rendered on its own line under the name — muted, smaller, no
 * link styling. */
.handle-page--article .handle-page__article-author-aff {
    color: #777;
    font-size: 0.8125rem;
    margin-top: 2px;
    line-height: 1.4;
}
.handle-page--article .handle-page__article-supervisors-label {
    color: #777;
    font-weight: 600;
    font-size: 0.8125rem;
    margin: 0 0 4px 0;
    text-transform: none;
}

/* Card heading used for Abstract + Cite sections — same size/weight as
 * the author page's section heading, no dark bar. */
.handle-page--article .handle-page__card-heading {
    font-size: 1.125rem;
    font-weight: 500;
    color: var(--color-text);
    margin: 0 0 12px 0;
}

.handle-page--article .handle-page__abstract-body {
    line-height: 1.7;
    margin: 0 0 12px 0;
}
.handle-page--article .handle-page__keywords-line {
    font-size: 0.875rem;
    color: #555;
    margin: 12px 0 0 0;
}
.handle-page--article .handle-page__keywords-label {
    color: #777;
    font-weight: 600;
}

/* Cite block: APA citation as a flowing paragraph, BibTeX as a tight
 * monospaced pre. The pre uses the same #f5f5f5-ish fill as the page bg
 * so it reads as code-quote inside the white card, with a soft border. */
.handle-page--article .handle-page__cite-apa {
    font-size: 0.9375rem;
    line-height: 1.6;
    margin: 0 0 16px 0;
    color: var(--color-text);
}
.handle-page--article .handle-page__cite-bibtex {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    line-height: 1.5;
    background: #f5f5f5;
    border: 1px solid #e4e4e4;
    border-radius: 4px;
    padding: 12px 14px;
    margin: 0;
    white-space: pre;
    overflow-x: auto;
    /* max-width pin so the pre never pushes the card past the viewport on
     * narrow screens; long BibTeX lines scroll horizontally inside the pre
     * (overflow-x: auto) rather than dragging the entire page sideways. */
    max-width: 100%;
}

/* PDF iframe wrapper — same card chrome, tighter padding so the iframe
 * nearly fills the card. The iframe owns its own scrolling via the
 * browser's built-in PDF viewer; we just give it a fixed height. */
.handle-page--article .handle-page__card--pdf {
    padding: 12px;
}
.handle-page--article .handle-page__pdf-frame {
    display: block;
    width: 100%;
    height: 600px;
    border: 0;
    border-radius: 4px;
}

/* ── Handle pages: mobile content fit ────────────────────────────────
 * On narrow viewports the .handle-page wrapper's 40px/20px padding plus
 * the card's 24px/28px padding eats roughly 96px of horizontal space —
 * enough to push BibTeX lines and 2-col grids past the viewport on a
 * 375px screen. Tighten everything here so the cards span the available
 * width with symmetric padding and the inner blocks stay inside the
 * card. Threshold 600px sits just above iPhone-Plus widths and well
 * below tablet portrait, so the desktop layout is unaffected. */
@media (max-width: 600px) {
    .handle-page { padding: 20px 12px; }
    .handle-theme-light .handle-page__card { padding: 16px; }
    /* Identifier rows drop the fixed 120px label column for an auto-
     * sized one so the value column gets the freed pixels. */
    .handle-theme-light .handle-page__id-line {
        grid-template-columns: 18px auto 1fr;
        gap: 8px;
    }
    /* PDF card keeps its tight inner padding but matches the others. */
    .handle-page--article .handle-page__card--pdf { padding: 8px; }
    /* Iframe shrinks to a more phone-friendly height — the desktop 600px
     * dominates a small viewport and hides the surrounding context. */
    .handle-page--article .handle-page__pdf-frame { height: 70vh; min-height: 360px; }
    /* Article author rows: tighten the number column so the 36px gutter
     * doesn't eat the name column on narrow widths. */
    .handle-page--article .handle-page__article-author--numbered {
        grid-template-columns: 28px 1fr;
        column-gap: 8px;
    }
}

/* ── Search results page ─────────────────────────────────────────────────
 * Reuses the .handle-page / .handle-theme-light / .handle-page__card
 * chrome from the handle pages; the rules below add the search-specific
 * bits: form layout, summary line, and the numbered grid rows for the
 * Authors / Articles result lists. */

/* Search box: input takes the row, submit button at the right. flex-wrap
 * so the button drops to its own line on very narrow viewports. */
.handle-page--search .search-page__form {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
}
.handle-page--search .search-page__input {
    flex: 1;
    min-width: 0;
    padding: 10px 14px;
    font-size: 0.9375rem;
    font-family: var(--font-main);
    color: var(--color-text);
    background: #ffffff;
    border: 1px solid #d4d4d4;
    border-radius: 6px;
    outline: none;
}
.handle-page--search .search-page__input:focus { border-color: var(--color-accent); }
.handle-page--search .search-page__submit {
    padding: 10px 18px;
    font-size: 0.9375rem;
    font-weight: 500;
    color: #000;
    background: var(--color-accent);
    border: 0;
    border-radius: 6px;
    cursor: pointer;
}
.handle-page--search .search-page__submit:hover { opacity: 0.9; }

/* Summary + hint share the same muted styling — small label under the
 * search input. */
.handle-page--search .search-page__summary,
.handle-page--search .search-page__hint {
    margin: 12px 0 0;
    font-size: 0.875rem;
    color: #666;
}

/* Card heading on the Authors / Articles cards — H2 with the result count
 * inlined as a muted, smaller suffix. Same heading size as the article-
 * handle page's card headings; the count uses em units so it scales with
 * the heading font-size. */
.handle-page--search .search-section__heading {
    font-size: 1.125rem;
    font-weight: 500;
    color: var(--color-text);
    margin: 0 0 12px 0;
}
.handle-page--search .search-section__count {
    color: #888;
    font-size: 0.85em;
    font-weight: 400;
    margin-left: 0.5em;
    font-variant-numeric: tabular-nums;
}

/* "Nothing found" message rendered only when both sections would be empty.
 * Centered, muted, with vertical padding so it doesn't feel cramped next
 * to the search input card above. */
.handle-page--search .search-page__no-results {
    text-align: center;
    color: #666;
    font-size: 0.9375rem;
    padding: 24px 0;
}

/* Authors result list — outer is a flat block, each row is a 2-column
 * grid (num | name). Row container holds the border so the rule under
 * each row spans both columns evenly. */
.handle-page--search .search-page__authors { display: block; }
.handle-page--search .search-page__authors-row {
    display: grid;
    grid-template-columns: 48px 1fr;
    column-gap: 16px;
    align-items: baseline;
    padding: 10px 0;
    border-bottom: 1px solid #e8e8e8;
    color: var(--color-text);
    text-decoration: none;
}
.handle-page--search .search-page__authors-row:last-child { border-bottom: none; }
.handle-page--search .search-page__authors-name {
    color: var(--color-text);
    font-size: 0.9375rem;
    line-height: 1.5;
}

/* Articles result list — 2-column row grid (num | content). Content cell
 * stacks the title on top and a muted "{year} · author1, author2" meta
 * line below. Year is part of the meta line, not its own column. */
.handle-page--search .search-page__articles { display: block; }
.handle-page--search .search-page__articles-row {
    display: grid;
    grid-template-columns: 48px 1fr;
    column-gap: 16px;
    align-items: baseline;
    padding: 10px 0;
    border-bottom: 1px solid #e8e8e8;
    color: var(--color-text);
    text-decoration: none;
}
.handle-page--search .search-page__articles-row:last-child { border-bottom: none; }
.handle-page--search .search-page__articles-content {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.handle-page--search .search-page__articles-title {
    color: var(--color-text);
    font-size: 0.9375rem;
    line-height: 1.5;
}
.handle-page--search .search-page__articles-meta {
    color: #777;
    font-size: 0.8125rem;
    line-height: 1.4;
}

/* Number column shared by both row grids — tight, right-aligned, muted. */
.handle-page--search .search-page__num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #6b6b6b;
    font-size: 0.875rem;
}

/* Narrow viewports: tighten the number column gutter to match the
 * handle-page mobile rules. Both rows are 2-col on mobile and desktop —
 * the year is part of the meta line so no column drops out. */
@media (max-width: 600px) {
    .handle-page--search .search-page__authors-row,
    .handle-page--search .search-page__articles-row {
        grid-template-columns: 36px 1fr;
        column-gap: 10px;
    }
}

/* ── Authors list page ──────────────────────────────────────────────────
 * Filter card on top (heading + search input + three chip rows), responsive
 * card grid below. Lives under .handle-theme-light to inherit the light bg
 * + dark text + white card styling from the handle-page rules. */

/* Shared filter chrome between the authors and articles list pages — the
 * heading, search input/submit, filter chip rows, chips, counter, and
 * empty-state card all render identically on both. List-row markup
 * differs (.authors-list vs .articles-list) so the result rows live in
 * their own page-scoped rules below. */

/* Page heading inside the filter card — sized between the search h1 and
 * the section heading; weight stays at 500 to match the rest of the light
 * theme. Reusing the search-page font sizing keeps visual rhythm. */
.handle-page--authors .authors-page__title,
.handle-page--articles .authors-page__title {
    font-size: 1.5rem;
    font-weight: 500;
    color: var(--color-text);
    margin: 0 0 16px 0;
}

/* Search form — mirrors the search page input + submit pairing so the two
 * pages feel like siblings. */
.handle-page--authors .authors-page__form,
.handle-page--articles .authors-page__form {
    display: flex;
    gap: 8px;
    margin: 0 0 16px 0;
}
.handle-page--authors .authors-page__input,
.handle-page--articles .authors-page__input {
    flex: 1;
    min-width: 0;
    padding: 10px 14px;
    border: 1px solid #d0d0d0;
    border-radius: 6px;
    font: inherit;
    color: var(--color-text);
    background: #fff;
}
.handle-page--authors .authors-page__input:focus,
.handle-page--articles .authors-page__input:focus { outline: none; border-color: var(--color-accent); }
.handle-page--authors .authors-page__submit,
.handle-page--articles .authors-page__submit {
    padding: 10px 18px;
    border: none;
    border-radius: 6px;
    background: var(--color-accent);
    color: #000;
    font: inherit;
    font-weight: 500;
    cursor: pointer;
}
.handle-page--authors .authors-page__submit:hover,
.handle-page--articles .authors-page__submit:hover { opacity: 0.9; }

/* Filter row — label sits to the left of the horizontally-scrollable chip
 * strip on desktop. The label is muted and small so the chips dominate. */
.handle-page--authors .authors-filter-row,
.handle-page--articles .authors-filter-row {
    display: grid;
    grid-template-columns: 140px 1fr;
    align-items: start;
    gap: 12px;
    padding: 10px 0;
    border-top: 1px solid #ececec;
}
.handle-page--authors .authors-filter-row:first-of-type,
.handle-page--articles .authors-filter-row:first-of-type { border-top: none; }
.handle-page--authors .authors-filter-row__label,
.handle-page--articles .authors-filter-row__label {
    color: #6b6b6b;
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding-top: 6px;
}

/* Chip strip — no-wrap so the row stays a single visual line; horizontal
 * scroll on overflow (kicks in mainly on phones with the long letter row).
 * The hidden scrollbar keeps it from looking technical. */
.handle-page--authors .authors-chips,
.handle-page--articles .authors-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    min-width: 0;
}
.handle-page--authors .authors-chip,
.handle-page--articles .authors-chip {
    display: inline-block;
    padding: 4px 10px;
    border: 1px solid #d0d0d0;
    border-radius: 999px;
    background: #fff;
    color: var(--color-text);
    font: inherit;
    font-size: 0.8125rem;
    line-height: 1.4;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.handle-page--authors .authors-chip:hover,
.handle-page--articles .authors-chip:hover { border-color: #999; }
.handle-page--authors .authors-chip--active,
.handle-page--articles .authors-chip--active {
    background: var(--color-text);
    border-color: var(--color-text);
    color: #f5f5f5;
}

/* Results counter — small text between the filter card and the grid. */
.handle-page--authors .authors-page__counter,
.handle-page--articles .authors-page__counter {
    color: #6b6b6b;
    font-size: 0.875rem;
    margin: 0 0 16px 0;
    padding: 0 4px;
}

/* Empty-state card — same chrome as a regular card, centered content. */
.handle-page--authors .authors-empty,
.handle-page--articles .authors-empty {
    text-align: center;
}
.handle-page--authors .authors-empty__msg,
.handle-page--articles .authors-empty__msg {
    color: #6b6b6b;
    font-size: 0.9375rem;
    margin: 0 0 12px 0;
}
.handle-page--authors .authors-empty__reset,
.handle-page--articles .authors-empty__reset {
    padding: 8px 18px;
    border: 1px solid var(--color-text);
    border-radius: 6px;
    background: transparent;
    color: var(--color-text);
    font: inherit;
    font-size: 0.875rem;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
}
.handle-page--authors .authors-empty__reset:hover,
.handle-page--articles .authors-empty__reset:hover {
    background: var(--color-text);
    color: #f5f5f5;
}

/* Author list — flat numbered rows. Row container holds the border-bottom
 * so the line under each row spans both columns evenly regardless of how
 * tall the content cell (name + optional affiliation) grows. Cells inside
 * the row have no borders of their own. */
.handle-page--authors .authors-list { display: block; }
.handle-page--authors .authors-list__row {
    display: grid;
    grid-template-columns: 48px 1fr;
    column-gap: 16px;
    align-items: baseline;
    padding: 10px 0;
    border-bottom: 1px solid #e8e8e8;
    color: var(--color-text);
    text-decoration: none;
    transition: font-weight 0.15s ease;
}
.handle-page--authors .authors-list__row:last-child { border-bottom: none; }
.handle-page--authors .authors-list__num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #6b6b6b;
    font-size: 0.875rem;
}
.handle-page--authors .authors-list__content {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
/* Name + counter sit on the same baseline row inside the content cell.
 * Counter is `margin-left: auto`'d to the right edge so a long name
 * pushes against it and wraps naturally before the counter is dislodged.
 * align-items: baseline keeps the counter on the name's text baseline,
 * not the bottom of a wrapped multi-line name. */
.handle-page--authors .authors-list__name-row {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 12px;
    row-gap: 2px;
    min-width: 0;
}
.handle-page--authors .authors-list__name {
    font-size: 0.9375rem;
    line-height: 1.4;
    font-weight: 400;
    transition: font-weight 0.15s ease;
    flex: 1 1 auto;
    min-width: 0;
}
.handle-page--authors .authors-list__count {
    color: #555;
    font-size: 0.8125rem;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    margin-left: auto;
    flex-shrink: 0;
}
.handle-page--authors .authors-list__name::after {
    content: '→';
    display: inline-block;
    padding-left: 6px;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
}
.handle-page--authors .authors-list__row:hover .authors-list__name { font-weight: 500; }
.handle-page--authors .authors-list__row:hover .authors-list__name::after {
    opacity: 1;
    transform: translateX(0);
}
/* Affiliation — muted second line under the name. */
.handle-page--authors .authors-list__aff {
    color: #777;
    font-size: 0.8125rem;
    line-height: 1.4;
}

/* Mobile: chip rows stack their label above the strip (label column drops),
 * and the strip becomes horizontally scrollable for long letter / conf rows
 * so the card height stays predictable instead of wrapping into 4-5 lines.
 * The number column tightens to match the .search-page mobile gutter. */
@media (max-width: 720px) {
    .handle-page--authors .authors-filter-row,
    .handle-page--articles .authors-filter-row {
        grid-template-columns: 1fr;
        gap: 6px;
    }
    .handle-page--authors .authors-filter-row__label,
    .handle-page--articles .authors-filter-row__label { padding-top: 0; }
    .handle-page--authors .authors-chips,
    .handle-page--articles .authors-chips {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: thin;
        -webkit-overflow-scrolling: touch;
        padding-bottom: 4px;
    }
    .handle-page--authors .authors-chip,
    .handle-page--articles .authors-chip { flex-shrink: 0; }
    .handle-page--authors .authors-list__row {
        grid-template-columns: 36px 1fr;
        column-gap: 10px;
    }
    .handle-page--articles .articles-list__row {
        grid-template-columns: 36px 1fr;
        column-gap: 10px;
    }
}

/* Sort row — shared between the articles and authors list pages. Sits
 * between the filter card and the results counter. Two pill buttons +
 * a muted label. The active button is filled dark; the inactive button
 * is outlined. Each button shows its own direction arrow (↑/↓) which
 * updates in place when the active button is toggled. The label
 * collapses on narrow screens. */
.list-sort {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 16px 0;
    padding: 0 4px;
}
.list-sort__label {
    color: #6b6b6b;
    font-size: 0.875rem;
    margin-right: 4px;
}
.list-sort__btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 14px;
    border: 1px solid #d0d0d0;
    border-radius: 999px;
    background: #fff;
    color: var(--color-text);
    font: inherit;
    font-size: 0.875rem;
    line-height: 1.3;
    cursor: pointer;
    transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.list-sort__btn:hover { border-color: #999; }
.list-sort__btn--active {
    background: var(--color-text);
    border-color: var(--color-text);
    color: #f5f5f5;
}
.list-sort__arrow {
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

@media (max-width: 480px) {
    .list-sort__label { display: none; }
}

/* ── Articles list page ─────────────────────────────────────────────────
 * Two-column row (num | content). Content stacks the title on top and a
 * muted "{year} · author1, author2" meta line below — year is no longer
 * a separate column. Row container holds the bottom border so the line
 * under each row spans both columns evenly. */
.handle-page--articles .articles-list { display: block; }
.handle-page--articles .articles-list__row {
    display: grid;
    grid-template-columns: 48px 1fr;
    column-gap: 16px;
    align-items: baseline;
    padding: 10px 0;
    border-bottom: 1px solid #e8e8e8;
    color: var(--color-text);
    text-decoration: none;
}
.handle-page--articles .articles-list__row:last-child { border-bottom: none; }
.handle-page--articles .articles-list__num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #6b6b6b;
    font-size: 0.875rem;
}
.handle-page--articles .articles-list__content {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.handle-page--articles .articles-list__title {
    font-size: 0.9375rem;
    line-height: 1.4;
    font-weight: 400;
    transition: font-weight 0.15s ease;
}
.handle-page--articles .articles-list__title::after {
    content: '→';
    display: inline-block;
    padding-left: 6px;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
}
.handle-page--articles .articles-list__row:hover .articles-list__title { font-weight: 500; }
.handle-page--articles .articles-list__row:hover .articles-list__title::after {
    opacity: 1;
    transform: translateX(0);
}
.handle-page--articles .articles-list__meta {
    color: #777;
    font-size: 0.8125rem;
    line-height: 1.4;
}

/* ── About page ─────────────────────────────────────────────────────────
 * Card-based static page. Intro card folds in description, top topics
 * and geography paragraphs. Organizers + partners are DB-driven lists.
 * Contacts is email-only. Editions list rows link to /{lang}/{year}/. */

.handle-page--about .about-page__title {
    font-size: 1.5rem;
    font-weight: 500;
    color: var(--color-text);
    margin: 0 0 12px 0;
}
.handle-page--about .about-page__intro {
    color: var(--color-text);
    font-size: 1rem;
    line-height: 1.55;
    margin: 0 0 12px 0;
}
.handle-page--about .about-page__intro:last-child { margin-bottom: 0; }
.handle-page--about .about-page__geo { margin-top: 16px; }

/* Section heading (H2) — plain dark text, no accent bar. Sub-heading (H3)
 * sits inside a section to label a subsection like "Основні теми". */
.handle-page--about .about-section__heading {
    font-size: 1.125rem;
    font-weight: 600;
    color: var(--color-text);
    margin: 0 0 12px 0;
}
.handle-page--about .about-section__sub {
    font-size: 0.875rem;
    font-weight: 600;
    color: #555;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: 18px 0 10px 0;
}

/* Top topics — list with an inline SVG check icon as the bullet. Each
 * row has a slight indent + comfortable line-height. The trailing
 * "and others" line sits below the list as muted normal text. */
.handle-page--about .about-topics {
    list-style: none;
    margin: 0 0 8px 0;
    padding: 0;
    color: var(--color-text);
}
.handle-page--about .about-topics__item {
    display: flex;
    /* Centre-align so the larger icon sits visually centred with the
     * topic text instead of dangling below the baseline. */
    align-items: center;
    gap: 12px;
    padding: 4px 0;
    line-height: 1.5;
}
.handle-page--about .about-topics__icon {
    flex-shrink: 0;
    /* Dark icon at 2× the original size — reads as a structured bullet
     * rather than decoration. align-self: center on the flex item keeps
     * it visually centred with the first line of the topic text. */
    color: var(--color-text);
    width: 36px;
    height: 36px;
    align-self: center;
}
.handle-page--about .about-topics__suffix {
    color: #777;
    font-size: 0.9375rem;
    font-style: italic;
    margin: 4px 0 0 0;
}

/* Flag icon — 120×90 with a subtle border so light-coloured flags
 * (Poland, Japan) don't blend into the card background. Placeholder
 * version has the same footprint but stays transparent, keeping row
 * baselines aligned when a country isn't in the ISO map. */
.handle-page--about .about-flag {
    display: block;
    width: 120px;
    height: 90px;
    object-fit: cover;
    border: 0.5px solid #ddd;
    margin: 0 auto;
    flex-shrink: 0;
}
.handle-page--about .about-flag--placeholder {
    border-color: transparent;
}

/* Country cell grid — flag on top, name centred below. Wraps freely so
 * the row collapses to fewer columns on narrow viewports. Per-cell
 * width is capped so long names wrap into two lines rather than push
 * neighbouring cells apart. */
.handle-page--about .about-country-row {
    display: flex;
    flex-wrap: wrap;
    gap: 20px 28px;
    margin: 12px 0 4px 0;
    justify-content: center;
}
.handle-page--about .about-country-cell {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    width: 140px;
}
.handle-page--about .about-country-cell__name {
    font-size: 0.875rem;
    line-height: 1.3;
    text-align: center;
    color: var(--color-text);
}

/* Organizers + partners — 3-column responsive grid of cards. auto-fit
 * with a 220px minmax gives 3 cols on desktop, 2 on tablet, 1 on phone
 * without per-breakpoint rules. Each card is logo-on-top + centred name
 * below; the whole card is the clickable surface when website_url is
 * present, else it falls back to an inert <div> with the same chrome. */
.handle-page--about .about-orgs-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
}
/* Each tile is a solid dark fill against the white wrapping card. Logo
 * sits on a white square so light-coloured marks remain visible against
 * the dark backdrop; the placeholder uses the same white square with a
 * muted icon so cards without logos still read as labelled tiles. */
.handle-page--about .about-org-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 12px;
    padding: 20px 16px;
    background: #8e8e8e;
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 8px;
    color: #ffffff;
    text-align: center;
    text-decoration: none;
    transition: background 0.15s, border-color 0.15s;
}
a.about-org-card:hover {
    background: #252525;
    border-color: rgba(255, 255, 255, 0.18);
}
.handle-page--about .about-org-card__logo {
    width: 80px;
    height: 80px;
    object-fit: contain;
    flex-shrink: 0;
    background: #8e8e8e;
    padding: 8px;
    border-radius: 4px;
    transition: background 0.15s, border-color 0.15s;
}
a.about-org-card:hover .about-org-card__logo {
    background: #252525;
}
/* Logo-less cards render a generic icon directly on the dark card —
 * white icon, no white square backing — so the tile reads as
 * "placeholder" rather than "missing image". */
.handle-page--about .about-org-card__logo--placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: #ffffff;
    background: transparent;
    padding: 0;
}
.handle-page--about .about-org-card__logo--placeholder svg {
    width: 56px;
    height: 56px;
}
.handle-page--about .about-org-card__name {
    font-size: 0.875rem;
    line-height: 1.4;
    font-weight: 500;
    color: #ffffff;
}

/* Contacts card — short paragraph + a single prominent email link.
 * The link itself uses the shared .about-email-link style defined below. */
.handle-page--about .about-contact-email {
    margin: 12px 0 0 0;
    font-size: 1.0625rem;
}

/* Shared email link styling for any itsec.bit@gmail.com link on the
 * About page (Contacts card + CTA card). Default state: underlined,
 * inherits the surrounding text colour (dark on the white Contacts card,
 * white on the dark CTA card), normal weight. Hover: underline drops,
 * weight bumps to 600, an arrow fades + slides in from the left. Colour
 * stays inherited so the rule works against both light and dark backdrops. */
.handle-page--about .about-email-link {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    font-weight: 400;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: font-weight 0.15s ease;
}
.handle-page--about .about-email-link::after {
    content: '→';
    display: inline-block;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
}
.handle-page--about .about-email-link:hover {
    text-decoration: none;
    color: inherit;
    font-weight: 600;
}
.handle-page--about .about-email-link:hover::after {
    opacity: 1;
    transform: translateX(0);
}

/* Editions list — each row holds two siblings: the main `<a>` covering
 * Roman + year + loc + dates, and an optional separate proceedings link
 * at the right. The main link gets the shared weight-bump + arrow hover.
 * The wrapper itself isn't clickable so the inner proceedings link can
 * receive its own click without nested-anchor issues. */
.handle-page--about .about-editions {
    display: flex;
    flex-direction: column;
}
.handle-page--about .about-editions__row {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px;
    padding: 10px 0;
    border-bottom: 1px solid #e8e8e8;
    line-height: 1.4;
}
.handle-page--about .about-editions__row:last-child { border-bottom: none; }
/* Editions link is a 3-column grid: Roman | year | locblock (loc+dates).
 * The locblock stacks city/country on the top line with the date range
 * below in muted smaller text. The PDF link is a sibling of the link
 * inside the row wrapper; flex pushes it to the right edge. */
.handle-page--about .about-editions__link {
    flex: 1;
    min-width: 0;
    display: grid;
    grid-template-columns: 50px 70px 1fr;
    align-items: baseline;
    column-gap: 12px;
    color: var(--color-text);
    text-decoration: none;
    font-size: 0.9375rem;
    transition: font-weight 0.15s ease;
}
.handle-page--about .about-editions__link:hover { font-weight: 500; }
.handle-page--about .about-editions__roman {
    font-weight: 600;
    color: var(--color-text);
    font-variant-numeric: tabular-nums;
}
.handle-page--about .about-editions__year {
    color: #555;
    font-variant-numeric: tabular-nums;
}
.handle-page--about .about-editions__locblock {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}
.handle-page--about .about-editions__loc {
    color: var(--color-text);
    transition: font-weight 0.15s ease;
}
.handle-page--about .about-editions__loc::after {
    content: '→';
    display: inline-block;
    padding-left: 6px;
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 0.15s ease, transform 0.15s ease;
}
.handle-page--about .about-editions__link:hover .about-editions__loc::after {
    opacity: 1;
    transform: translateX(0);
}
.handle-page--about .about-editions__dates {
    color: #888;
    font-size: 0.8125rem;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.handle-page--about .about-editions__proc {
    color: #555;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 2px 8px;
    border: 1px solid #d0d0d0;
    border-radius: 4px;
    letter-spacing: 0.04em;
    text-decoration: none;
    flex-shrink: 0;
}
.handle-page--about .about-editions__proc:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
}

/* Invitation CTA card — solid dark fill with full-white text for
 * legibility. Centred copy + a single prominent email link styled via
 * the shared .about-email-link rule (underline → weight 600 + arrow on
 * hover). Overrides the white .handle-page__card chrome scoped under
 * .handle-theme-light so this single card stands out. */
.handle-theme-light .handle-page__card.about-cta {
    background: #1a1a1a;
    border-color: transparent;
    color: #ffffff;
    padding: 48px 32px;
    text-align: center;
}
.handle-page--about .about-cta__heading {
    font-size: 1.75rem;
    font-weight: 500;
    color: #ffffff;
    margin: 0 0 16px 0;
}
.handle-page--about .about-cta__body {
    font-size: 1rem;
    line-height: 1.55;
    color: #ffffff;
    margin: 0 auto 16px auto;
    max-width: 64ch;
}
.handle-page--about .about-cta__lead-in {
    font-size: 1rem;
    color: #ffffff;
    margin: 0 auto 18px auto;
}
/* Email is the only CTA — render larger than body so it visually leads. */
.handle-page--about .about-cta__email {
    font-size: 1.25rem;
}

/* Year-page header organizer logos — explicit height cap that doesn't
 * depend on the Tailwind bundle (only .h-6 and .h-16 are compiled in,
 * so utility classes like h-12 / md:h-16 silently no-op). Smaller on
 * mobile so the logo row stays compact above the section nav; larger
 * on tablet+ to match the historical desktop look. width: auto keeps
 * each logo's natural aspect ratio (the ДУІКТ wordmark is ~2.34:1). */
.year-header__logo {
    height: 40px;
    width: auto;
    display: block;
}
@media (min-width: 768px) {
    .year-header__logo { height: 56px; }
}
@media (min-width: 1024px) {
    .year-header__logo { height: 64px; }
}

/* Year-page section nav (Контрольні дати / Теми конференції / …). Hand-
 * rolled responsive gaps + sizing because the precompiled Tailwind
 * bundle lacks gap-x-*, gap-y-*, breakpoint-prefixed gaps, and
 * whitespace-nowrap. flex-wrap lets the 5 links break onto multiple
 * rows on mobile; whitespace-nowrap on each link keeps multi-word
 * labels like "Контрольні дати" intact (whole link wraps as a unit). */
.year-header__nav {
    display: flex;
    flex-wrap: wrap;
    column-gap: 16px;
    row-gap: 8px;
    color: #ffffff;
    font-size: 0.875rem;          /* text-sm baseline for mobile tap targets */
}
.year-header__nav a {
    color: #ffffff;
    white-space: nowrap;
}
@media (min-width: 768px) {
    .year-header__nav {
        column-gap: 8px;
        row-gap: 4px;
        font-size: 0.75rem;       /* text-xs at md+ — matches the historical look */
    }
}
@media (min-width: 1024px) {
    .year-header__nav { font-size: 0.875rem; }
}
@media (min-width: 1280px) {
    .year-header__nav {
        column-gap: 16px;
        justify-content: flex-end;
        font-size: 1rem;          /* text-base at xl+ */
    }
}
@media (min-width: 1536px) {
    .year-header__nav { column-gap: 40px; }
}

/* Wrapper around the same nav in the year-page footer. The nav class is
 * shared with the header for visual consistency; this wrapper just
 * centres it horizontally inside the footer column at lg+. On smaller
 * viewports the wrapper is a no-op and the nav flows naturally. */
.year-footer__nav-wrap {
    display: flex;
}
@media (min-width: 1024px) {
    .year-footer__nav-wrap { justify-content: center; }
    /* Inside the footer, the shared nav should centre its items rather
     * than right-align them (the header version pins them flush right). */
    .year-footer__nav-wrap .year-header__nav { justify-content: center; }
}

/* ── Year-page footer partners ──────────────────────────────────────────
 * Single flex-wrap row — the browser handles per-row item count via
 * per-item flex-basis breakpoints below. No PHP-side chunking; new
 * partners just slot in. A trailing partial row (e.g. 6 items → 5 + 1)
 * stays centred via justify-content: center. */
.footer-partners__list {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: flex-start;
    gap: 24px 32px;
    margin-top: 20px;
}
/* Default (desktop ≥1024px): 5 items per row with the 32px column gap
 * subtracted from the basis. max-width caps long-name partners from
 * stretching past a comfortable cell width. text-align: center handles
 * both text-mode (<p>) and logo-mode (<a><img></a>) — inline <img>
 * children centre inside the parent via the same rule. */
.footer-partners__item {
    flex: 0 0 calc((100% - 4 * 32px) / 5);
    max-width: 200px;
    text-align: center;
    margin: 0;
}
.footer-partners__item img {
    max-width: 100%;
    height: auto;
}
@media (max-width: 1023px) {
    .footer-partners__item {
        flex: 0 0 calc((100% - 2 * 32px) / 3);
    }
}
@media (max-width: 639px) {
    .footer-partners__list { gap: 16px; }
    .footer-partners__item {
        flex: 0 0 calc((100% - 2 * 16px) / 3);
        font-size: 13px;
    }
}

/* ── Public edit-request form on handle pages ───────────────────────────
 * Collapsed by default; expands when the visitor clicks "Suggest an edit"
 * (native <details>/<summary>). Stays inside .handle-theme-light so it
 * inherits the white-card-on-light-grey rhythm. */
.handle-page .edit-request { margin-top: 24px; }

.handle-page .edit-request__flash {
    padding: 12px 16px;
    border-radius: 6px;
    margin: 0 0 16px 0;
    font-size: 0.9375rem;
    line-height: 1.4;
}
.handle-page .edit-request__flash--success {
    background: #e8f4ea;
    color: #2c5e35;
    border: 1px solid #b9dfc0;
}
.handle-page .edit-request__flash--error {
    background: #fde8e6;
    color: #a51b13;
    border: 1px solid #f0c4bf;
}

.handle-page .edit-request__details {
    background: #e0e0e0;
    border: 1px solid #c3c1c1;
    border-radius: 8px;
    padding: 16px 20px;
    padding-bottom: 0px;
}
.handle-page .edit-request__summary {
    cursor: pointer;
    font-weight: 500;
    font-size: 0.9375rem;
    color: var(--color-text);
    /* Strip the default marker; we add an arrow via ::before that
     * rotates when the details element is open. */
    list-style: none;
    padding-bottom: 12px;
}
.handle-page .edit-request__summary::-webkit-details-marker { display: none; }
.handle-page .edit-request__summary::before {
    content: '▸';
    display: inline-block;
    margin-right: 8px;
    color: #888;
    transition: transform 0.15s;
}
.handle-page .edit-request__details[open] .edit-request__summary::before {
    transform: rotate(90deg);
}

.handle-page .edit-request__body { margin-top: 16px; }
.handle-page .edit-request__intro {
    color: #555;
    font-size: 0.875rem;
    line-height: 1.5;
    margin: 0 0 16px 0;
}
.handle-page .edit-request__form {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

/* Per-field row. Label spans the full width; under it sits a 1fr 1fr
 * grid with the current value on the left (muted, read-only) and the
 * editable input on the right. The .edit-request-row--single variant
 * skips the grid for email + notes rows which don't have a "current
 * value" side. */
.handle-page .edit-request-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.handle-page .edit-request__label {
    font-size: 0.8125rem;
    font-weight: 500;
    color: #555;
}
.handle-page .edit-request-row__cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
    align-items: start;
}
.handle-page .edit-request-row__col {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.handle-page .edit-request-row__caption {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #888;
}
.handle-page .edit-request-row__current {
    padding: 8px 12px;
    background: #f5f5f5;
    border-radius: 6px;
    color: #555;
    font-size: 0.9375rem;
    line-height: 1.4;
    min-height: 38px;
    display: flex;
    align-items: center;
    word-break: break-word;
}
.handle-page .edit-request-row__current--empty { color: #aaa; }
/* Photo cell variant — shrinks the box around the thumbnail so the
 * 96px image doesn't sit on a wide pale strip. */
.handle-page .edit-request-row__current--photo {
    padding: 6px;
    background: #f5f5f5;
    min-height: 96px;
    justify-content: center;
}
.handle-page .edit-request-row__photo {
    width: 96px;
    height: 96px;
    object-fit: cover;
    border-radius: 50%;
    border: 1px solid #ddd;
    display: block;
}
/* File input row — no extra borders/padding so the native picker UI
 * isn't doubly framed. */
.handle-page .edit-request__input--file {
    padding: 0;
    border: 0;
    background: transparent;
    font-size: 0.875rem;
}
.handle-page .edit-request-row__current-empty {
    color: #aaa;
    font-style: italic;
}

.handle-page .edit-request__input {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #d0d0d0;
    border-radius: 6px;
    font: inherit;
    font-size: 0.9375rem;
    color: var(--color-text);
    background: #fff;
}
.handle-page .edit-request__input:focus {
    outline: none;
    border-color: var(--color-accent);
}
.handle-page .edit-request__hint {
    color: #888;
    font-size: 0.75rem;
}
/* Header block — title + intro paragraph above the field rows. Mirrors
 * the footer's chrome (same padding, same negative horizontal margins,
 * same background tint, same 2px gray separator) so the two blocks
 * read as matching bookends around the data fields. Negative side
 * margins break out of the parent .edit-request__details 20px padding
 * so the band spans the full card width edge-to-edge. */
.handle-page .edit-request__header {
    padding: 24px 20px;
    margin: 0 -20px 24px -20px;
    border-bottom: 2px solid #d0d0d0;
    background: #fafafa;
}
.handle-page .edit-request__heading {
    font-size: 1.375rem;
    font-weight: 500;
    color: #1a1a1a;
    margin: 0 0 8px 0;
    line-height: 1.3;
}
.handle-page .edit-request__intro {
    color: #666;
    font-size: 0.875rem;
    line-height: 1.5;
    margin: 0;
}

/* Footer block — submitter-contact field + primary submit action.
 * Top border + slight gray tint so the submit zone stands out clearly
 * from the data fields above. */
.handle-page .edit-request__footer {
    padding: 24px 20px 24px 20px;
    margin: 24px -20px 0 -20px;
    border-top: 2px solid #d0d0d0;
    background: #fafafa;
    border-radius: 0 0 6px 6px;
    
}
.handle-page .edit-request__email-block { margin-bottom: 20px; }
.handle-page .edit-request__actions { margin-top: 0; }
.handle-page .edit-request__submit {
    padding: 14px 28px;
    border: none;
    border-radius: 6px;
    background: var(--color-accent);
    color: #1a1a1a;
    font: inherit;
    font-weight: 500;
    font-size: 1rem;
    cursor: pointer;
    transition: filter 0.12s;
}
.handle-page .edit-request__submit:hover { filter: brightness(0.95); }

/* Mobile: stack the two columns vertically with their captions, so the
 * read-only Current row sits above the editable Proposed input. */
@media (max-width: 767px) {
    .handle-page .edit-request-row__cols {
        grid-template-columns: 1fr;
        gap: 8px;
    }
}
