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

body {
    font-family: 'Segoe UI', Arial, sans-serif;
    color: #222;
    min-height: 100vh;
    background-color: #1a1a2e;
}

/* Painted as a fixed layer pinned below the header (not on body's own background)
   so it's sized against the actual page area, not the full viewport height
   including the strip the header sits on top of. Stretched to fill that area
   exactly (100% 100%, not "contain") — no letterboxing, aspect ratio not kept. */
body::before {
    content: "";
    position: fixed;
    top: 60px; /* header height */
    left: 0;
    right: 0;
    bottom: 0;
    z-index: -1;
    background:
        linear-gradient(rgba(245, 245, 245, 0.05), rgba(245, 245, 245, 0.05)) center / cover no-repeat,
        url('/wallpaper-369e28c108f88ef2f4d4b67557c96da3.png') center / 100% 100% no-repeat;
}

/* ===== Header ===== */
/* At least 60px tall; on a narrow screen (or zoomed in) it grows and wraps rather than letting
   the title spill out of it. */
header {
    background: #1a1a2e;
    color: white;
    min-height: 60px;
    padding: 0.4rem 1.5rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 1rem;
    position: sticky;
    top: 0;
    z-index: 50;
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}

header h1 { font-size: 1.2rem; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
header h1 a,
header h1 a:visited { color: inherit; text-decoration: none; }


.admin-link,
.admin-link:visited {
    margin-left: auto;
    color: inherit;
    text-decoration: none;
    font-size: 0.85rem;
    padding: 0.5rem 0.4rem;   /* a bigger target than the word alone */
}
.admin-link:hover { color: white; }

/* The help link (fragments/header :: help-link): a round "?" and its label ("Help", "Admin guide"),
   at the right-hand end, after Admin if any. Only the "?" on a narrow screen. */
.help-link,
.help-link:visited {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: inherit;
    font-size: 0.85rem;
    text-decoration: none;
    padding: 0.35rem 0.4rem;
}
/* The same blue as the First/Previous/Next/Last buttons (.browse-nav, .nav-bar). */
.help-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: #0066cc;
    color: white;
    font-size: 0.9rem;
    font-weight: 700;
    line-height: 1;
}
.help-link:hover { color: white; }
.help-link:hover .help-icon,
.help-link:focus-visible .help-icon { background: #0052a3; }
.admin-link + .help-link { margin-left: 0; }
/* Windows contrast themes would drop the circle's blue, leaving a bare "?" (and "i" in the viewer). */
@media (forced-colors: active) {
    .help-icon,
    .modal-toolbar .info-btn { forced-color-adjust: none; }
}
@media (max-width: 600px) {
    /* Hidden from sight only, so a screen reader still names the link. */
    .help-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%);
                  white-space: nowrap; }
}

/* DEBUG_MODE=true only: a red debug icon at the header's right-hand end (after Admin and ?, if any). */
.debug-mode-badge { margin-left: auto; display: flex; color: #e53935; cursor: help; }
.admin-link + .debug-mode-badge,
.help-link + .debug-mode-badge { margin-left: 0; }

/* ===== Main layout ===== */
/* 1640px: 8 columns of 190px cards with 8px gaps (1576px) inside the 1.5rem side padding. */
main { padding: 1.2rem 1.5rem 5.5rem; max-width: 1640px; margin: 0 auto; }

/* ===== Search bar ===== */
/* Wraps, so on a narrow screen (or zoomed in) the two dropdowns go under the box instead of off
   the side of the page; below 700px each takes a whole row. */
.search-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1.2rem;
}

.search-bar input {
    flex: 1 1 16rem;
    min-width: 0;
    padding: 0.65rem 1rem;
    font-size: 1.05rem;
    border: 2px solid #ccc;
    border-radius: 6px;
    /* Transparent, not none: a Windows contrast theme colours it in, so focus still shows there. */
    outline: 3px solid transparent;
    outline-offset: 2px;
    transition: border-color 0.2s;
}
.search-bar input:focus { border-color: #0066cc; }
/* The keyboard-focus yellow of the thumbnails (.card:focus-visible). */
.search-bar input:focus-visible,
.category-filter:focus-visible { outline-color: #ffd54f; }

/* Category filter — sits inline in .search-bar, between the input and the spinner. */
.category-filter {
    min-width: 0;
    max-width: 100%;
    padding: 0.65rem 0.9rem;
    font-size: 1rem;
    color: #333;
    background: white;
    border: 2px solid #ccc;
    border-radius: 6px;
    outline: 3px solid transparent;
    outline-offset: 2px;
    cursor: pointer;
    transition: border-color 0.2s;
}
.category-filter:focus { border-color: #0066cc; }

/* "Collection" / "Category", before their dropdowns. */
.filter-label {
    color: #f0f0f0;
    font-size: 0.95rem;
    font-weight: 600;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
    margin-left: 0.5rem;
}

.spinner { font-size: 1rem; }

/* Under the search box, always shown: how to search (index.html, the box's aria-describedby). */
.search-hint {
    flex: 1 1 100%;
    margin: 0;
    font-size: 0.9rem;
    color: #f0f0f0;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}

/* ===== Image grid ===== */
.image-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* ===== Thumbnail card ===== */
.card {
    background: white;
    border: 2px solid #e0e0e0;
    border-radius: 6px;
    padding: 3px;
    width: 190px;   /* the 180px-wide thumbnail box + padding + border: the card fits the image */
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s, background 0.15s;
    text-align: center;
    /* When focus scrolls a card into view, keep it clear of the sticky header above and the pager
       and footer fixed at the bottom, so a focused card is never hidden under them. */
    scroll-margin: 5rem 0 6rem;
}

.card:hover {
    border-color: #0066cc;
    box-shadow: 0 2px 8px rgba(0,102,204,0.2);
}

/* Keyboard focus: a thick yellow outline, standing out from the dark wallpaper and from a mouse
   hover's blue border. An outline (not a box-shadow) so Windows' contrast themes still draw it. */
.card:focus-visible {
    outline: 4px solid #ffd54f;
    outline-offset: 3px;
}

/* The image open in the viewer. Bright amber, twice the old 4px blue ring, which was hard to see
   against the dark blue wallpaper; above its neighbours so the ring isn't drawn under them. */
.card.active {
    border-color: #ffb300;
    background: #fff4d6;
    box-shadow: 0 0 0 8px #ffb300, 0 4px 18px rgba(255, 179, 0, 0.6);
    transform: scale(1.05);
    position: relative;
    z-index: 1;
    /* Invisible normally; in a Windows contrast theme, which drops box-shadows, it's the highlight. */
    outline: 4px solid transparent;
}

.card img {
    /* A 3:2 box, the shape of a 35mm slide or negative and most prints, so a landscape photo
       isn't letterboxed above and below as it was in the old 128px square. Keep the two sizes
       in step with app.thumbnail.max-px (the longest edge), results.html's width/height and
       app.js measureCard's stand-in. */
    width: 180px;
    height: 120px;
    object-fit: contain;
    display: block;
    border-radius: 3px;
    background: #fafafa;
}

/* ===== No results ===== */
/* On a dark panel of their own: straight on the wallpaper photo, grey text was too faint to read. */
.no-results,
.loading {
    color: #f0f0f0;
    background: rgba(26, 26, 46, 0.9);
    padding: 0.75rem 1rem;
    border-radius: 6px;
    font-size: 1rem;
}

/* ===== Browse-all pagination ===== */
.browse-nav {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.75rem;
    padding: 0.75rem 1.25rem;
    background: white;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0,0,0,0.15);
    width: fit-content;
    max-width: calc(100vw - 2rem);
    flex-wrap: wrap;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 1rem;
    margin: 0 auto;
    z-index: 60;
}
.browse-nav:empty { display: none; }

.browse-nav button {
    padding: 0.5rem 1rem;
    font-size: 0.9rem;
    border: none;
    border-radius: 6px;
    background: #0066cc;
    color: white;
    cursor: pointer;
}
.browse-nav button:hover:not(:disabled) { background: #0052a3; }
.browse-nav button:disabled {
    background: #ddd;
    color: #555;
    cursor: not-allowed;
}


/* ===== Thumbnail description tooltip ===== */
.thumb-tooltip {
    position: fixed;
    z-index: 300;
    max-width: 320px;
    padding: 0.55rem 0.8rem;
    background: #1a1a2e;
    color: white;
    font-size: 0.95rem;
    line-height: 1.35;
    border-radius: 6px;
    box-shadow: 0 4px 14px rgba(0,0,0,0.35);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease;
}
.thumb-tooltip.visible { opacity: 1; visibility: visible; }

/* ===== Modal ===== */
#modal-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,0.65);
    z-index: 400;
    justify-content: center;
    align-items: center;
}
#modal-backdrop.open { display: flex; }

#modal {
    background: white;
    border-radius: 10px;
    padding: 1.5rem;
    max-width: 480px;
    width: 92%;
    max-height: 90vh;
    overflow-y: auto;
    position: relative;
    box-shadow: 0 8px 32px rgba(0,0,0,0.4);
}

/* The image viewer always fits the screen: a fixed-height column (95% of the visible
   viewport — dvh excludes mobile browser toolbars, vh is the fallback) where the caption
   and nav bar keep their natural size and #image-frame takes whatever height is left.
   The picture is scaled down (never up) to fit that space in both directions, so the
   nav buttons are never pushed below the fold on a short screen. Extra top padding
   keeps the close/fullscreen buttons clear of the picture.
   Selectors here are deliberately weaker than the #image-frame:fullscreen rules
   below, so native fullscreen is unaffected. */
/* Focused on opening (app.js), for screen readers; it's obvious enough without an outline. */
#modal:focus { outline: none; }
#modal.image-modal {
    width: 95vw;
    max-width: 1600px;
    height: 95vh;
    height: 95dvh;
    max-height: 95vh;
    max-height: 95dvh;
    display: flex;
    flex-direction: column;
    padding: 3rem 1rem 1rem;
}
.image-modal #image-frame {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 0.75rem;
}
.image-modal .full-image {
    max-width: 100%;
    max-height: 100%;
    margin: 0;
}
.image-modal #modal-description,
.image-modal .nav-bar { flex: none; }

/* Info, Full screen and Close, in one row at the top right (index.html's .modal-toolbar). */
.modal-toolbar {
    position: absolute;
    top: 0.6rem;
    right: 0.6rem;
    z-index: 3;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
.modal-toolbar button {
    -webkit-appearance: none;
    appearance: none;
    box-sizing: border-box;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: #e8eaee;
    color: #333;
    line-height: 1;
    cursor: pointer;
}
.modal-toolbar button:hover { background: #d4d8de; color: #111; }
.modal-toolbar button:focus-visible { outline: 3px solid #0066cc; outline-offset: 2px; }
.modal-toolbar svg { display: block; width: 1.1rem; height: 1.1rem; }
.modal-close { font: 1.5rem/1 Arial, Helvetica, sans-serif; }

/* 4x zoom and Sharpen: on/off pills, filled blue when on (aria-pressed). */
.modal-toolbar .toolbar-toggle {
    width: auto;
    padding: 0 0.8rem;
    border-radius: 999px;
    font: 600 0.85rem/1 'Segoe UI', Arial, sans-serif;
}
.modal-toolbar .toolbar-toggle[aria-pressed="true"] { background: #0066cc; color: white; }
.modal-toolbar .toolbar-toggle[aria-pressed="true"]:hover { background: #0052a3; color: white; }

/* The Sharpen option, on the photo and, much stronger, on the magnifier (in full screen as well). */
#image-frame.sharpen .full-image { filter: url(#sharpen-filter) contrast(1.06); }
#image-frame.sharpen .magnifier  { filter: url(#sharpen-filter-strong) contrast(1.08); }
.svg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Info button, left of the fullscreen button: a white "i" on a blue circle (the nav buttons' blue). */
.modal-toolbar .info-btn {
    background: #0066cc;
    color: white;
    font: italic bold 1.05rem/1 Georgia, "Times New Roman", serif;
}
.modal-toolbar .info-btn:hover,
.modal-toolbar .info-btn[aria-expanded="true"] { background: #0052a3; color: white; }

/* The Info panel: a small box under the buttons, over the top-right of the picture. */
.info-panel {
    position: absolute;
    top: 3rem;
    right: 0.75rem;
    z-index: 2;
    max-width: min(22rem, calc(100% - 1.5rem));
    padding: 0.6rem 0.9rem;
    background: white;
    border: 1px solid #ccc;
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.25);
    font-size: 0.85rem;
}
.info-panel[hidden] { display: none; }
.info-panel dl,
.footer-info-panel dl { margin: 0; }
/* The labels in the Info buttons' blue (7:1 on white), so they stand out from the values. */
.info-panel dt,
.footer-info-panel dt {
    font-weight: bold;
    font-size: 0.8rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: #0052a3;
    border-bottom: 1px solid #cfe0f3;
    margin-bottom: 0.1rem;
}
.info-panel dd,
.footer-info-panel dd { margin: 0 0 0.45rem; overflow-wrap: anywhere; }
.info-panel dd:last-child,
.footer-info-panel dd:last-child { margin-bottom: 0; }

/* ===== Full image viewer ===== */
.full-image {
    display: block;
    max-width: 100%;
    max-height: 600px;
    object-fit: contain;
    margin: 0 auto 1rem;
    border-radius: 4px;
    cursor: zoom-in;
}
.full-image.magnifying { cursor: none; }

/* Native fullscreen (triggered by #fullscreen-btn) is requested on #image-frame
   rather than .full-image directly — the browser only renders the fullscreened
   element plus its descendants, and .magnifier is a sibling of .full-image, so
   fullscreening .full-image alone would leave the loupe unable to show. */
#image-frame:fullscreen,
#image-frame:-webkit-full-screen {
    width: 100vw;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #000;
}
#image-frame:fullscreen .full-image,
#image-frame:-webkit-full-screen .full-image {
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    margin: 0;
    cursor: zoom-in;
}

/* Shown in place of .full-image when it fails to load (e.g. a transient hiccup
   reading from a network-mounted input dir) — see the modal-image 'error' handler
   in index.html. */
.image-error {
    display: none;
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding: 2.5rem 1rem;
    color: #666;
    text-align: center;
}
/* Why it failed (filled in by app.js's explainLoadError) — can name a long file path. */
.image-error-detail {
    max-width: 40em;
    margin: 0;
    font-size: 0.9rem;
    color: #444;
    overflow-wrap: anywhere;
}
#image-frame.load-error .full-image { display: none; }
#image-frame.load-error .image-error { display: flex; }

#image-error-retry {
    padding: 0.35rem 0.9rem;
    border-radius: 6px;
    border: 1px solid #ccc;
    background: #f4f4f4;
    cursor: pointer;
}
#image-error-retry:hover { background: #e8e8e8; }

/* Magnifying-glass loupe that follows the cursor over .full-image — see the
   mousemove handler in index.html for how its background is positioned. */
.magnifier {
    display: none;
    position: fixed;
    width: 300px;    /* MAG_SIZE in app.js */
    height: 300px;
    border-radius: 50%;
    border: 3px solid #fff;
    box-shadow: 0 4px 16px rgba(0,0,0,0.45), inset 0 0 0 1px rgba(0,0,0,0.15);
    background-repeat: no-repeat;
    background-color: #000;
    pointer-events: none;
    z-index: 500;
}
.magnifier.visible { display: block; }

/* ===== Navigation bar ===== */
.nav-bar {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.nav-bar button {
    padding: 0.55rem 1.1rem;
    background: #0066cc;
    color: white;
    border: none;
    border-radius: 5px;
    font-size: 0.95rem;
    cursor: pointer;
    min-width: 90px;
}

.nav-bar button:hover:not(:disabled):not([aria-disabled="true"])  { background: #0052a3; }
/* aria-disabled, not disabled (app.js): a disabled button would drop the keyboard focus on it. */
.nav-bar button:disabled,
.nav-bar button[aria-disabled="true"] {
    background: #ddd;
    color: #555;
    cursor: not-allowed;
}

.nav-label {
    font-size: 0.85rem;
    color: #555;
    padding: 0 0.5rem;
    flex: 1;
    text-align: center;
    /* Wraps rather than being cut off at a large text size. */
    overflow-wrap: anywhere;
}

.image-caption {
    text-align: center;
    font-size: 0.8rem;
    font-weight: 600;
    color: #1a1a2e;
}

#modal-description {
    text-align: center;
    font-size: 1.1rem;
    font-weight: 600;
    color: #1a1a2e;
    background: #f2f6fc;
    border-left: 4px solid #0066cc;
    border-radius: 4px;
    padding: 0.7rem 1rem;
    margin-bottom: 1rem;
}

/* ===== Error / success messages ===== */
.error   { color: #cc0000; font-size: 0.9rem; margin-top: 0.5rem; }
.success { color: #007700; font-size: 0.9rem; margin-top: 0.5rem; }

/* ===== Footer ===== */
.site-footer {
    position: fixed;
    left: 0.75rem;
    bottom: 0.5rem;
    font-size: 0.8rem;
    color: white;
    /* A dark band behind it, so it can be read over any part of the photo. */
    background: rgba(26, 26, 46, 0.8);
    padding: 0.15rem 0.5rem;
    border-radius: 4px;
    /* Above the pager (60), so the info panel above the "i" is never hidden under its buttons; the footer lets clicks
       through everywhere but the "i", so it covers nothing. Below the viewer (400) and the thumbnail tooltip (300). */
    z-index: 61;
    pointer-events: none;
}

/* The footer's "i": the viewer's Info button, smaller. The footer lets clicks through to the page; the "i" and its
   panel take them. */
.footer-info {
    position: relative;
    display: inline-block;
    margin-left: 0.35rem;
    vertical-align: middle;
    pointer-events: auto;
}
.footer-info-btn {
    width: 1.3rem;
    height: 1.3rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: #0066cc;
    color: white;
    font: italic bold 0.85rem/1 Georgia, "Times New Roman", serif;
    cursor: help;
}
.footer-info-btn:hover,
.footer-info:focus-within .footer-info-btn { background: #0052a3; }
.footer-info-btn:focus-visible { outline: 4px solid #ffd54f; outline-offset: 2px; }
/* The panel above it, shown while the pointer is over the "i" or the panel, or the "i" has the focus. It stays a
   quarter of a second after the pointer leaves, so the pointer can cross onto it (e.g. to tap the number). */
.footer-info-panel {
    position: absolute;
    bottom: calc(100% + 0.4rem);
    left: 0;
    z-index: 41;
    min-width: 13rem;
    padding: 0.6rem 0.9rem;
    background: white;
    color: #222;
    border: 1px solid #ccc;
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(0,0,0,0.25);
    padding-right: 2.6rem;   /* room for the copy button, top right */
    font-size: 0.85rem;
    text-align: left;
    white-space: nowrap;
    visibility: hidden;
    transition: visibility 0s linear 0.25s;
}
.footer-info:hover .footer-info-panel,
.footer-info:focus-within .footer-info-panel { visibility: visible; transition-delay: 0s; }
/* Its copy button: the usual two-sheets icon, a green tick for 2 s once copied (red if it couldn't). */
.footer-copy-btn {
    position: absolute;
    top: 0.4rem;
    right: 0.4rem;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 1px solid #cfe0f3;
    border-radius: 4px;
    background: white;
    color: #0052a3;
    cursor: pointer;
}
.footer-copy-btn:hover { background: #e8f1fb; }
.footer-copy-btn:focus-visible { outline: 4px solid #ffd54f; outline-offset: 1px; }
.footer-copy-btn .icon-done { display: none; }
.footer-copy-btn.copied .icon-copy { display: none; }
.footer-copy-btn.copied .icon-done { display: block; }
.footer-copy-btn.copied { color: #007700; border-color: #007700; }
.footer-copy-btn.copy-failed { color: #cc0000; border-color: #cc0000; }

/* ===== Narrow screens (a phone, or a window zoomed in) ===== */
/* Below 700px the pager and footer stop floating over the bottom of the page and follow the
   thumbnails instead, so neither covers the other or a thumbnail; the dropdowns get a row each. */
@media (max-width: 700px) {
    header { padding: 0.4rem 1rem; }
    header h1 { font-size: 1rem; }
    main { padding: 1rem 1rem 1rem; }
    .search-bar input,
    .search-bar .category-filter { flex: 1 1 100%; }
    .filter-label { flex: 1 1 100%; margin: 0.25rem 0 -0.25rem; }
    .browse-nav { position: static; margin: 1rem auto 0; }
    .site-footer { position: static; display: block; padding: 1rem; }
}

/* ===== Windows contrast themes ===== */
/* They keep background images, so text would sit straight on the wallpaper photo: drop it. */
@media (forced-colors: active) {
    body::before { display: none; }
}

/* ===== Reduced motion (an operating-system setting) ===== */
/* No zoom on the viewer's highlighted thumbnail and no fades or slides. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { transition: none !important; animation: none !important; }
    .card.active { transform: none; }
}

/* ===== Screen-reader-only text ===== */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* ===== HTMX indicator ===== */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator,
.htmx-request.htmx-indicator { display: inline; }
