/* site.css — everything this site adds on top of Bootstrap.
 *
 * Replaces the old stylesheet.css and bss-overrides.css, which between them
 * carried about two hundred lines for form controls, dropdowns, validation
 * states and an input group that appear nowhere in the markup, plus eight
 * utilities that only restated what Bootstrap already says.
 *
 * The shape of the file:
 *
 *   1. tokens      one place for the fonts and sizes
 *   2. inheritance set on body and the heading group, then left alone
 *   3. layout      sections, hero, banner
 *   4. components  navbar, cards, buttons
 *   5. motion      view transitions, reduced-motion
 *
 * The rule of thumb throughout: declare a thing once, at the highest element
 * that should have it, and let the cascade carry it down. The old file set
 * font-family: 'Titillium Web' on five separate selectors and Jost on six
 * more, so changing a typeface meant finding all eleven.
 */

/* ---------- 1. tokens ---------- */

:root,
[data-bs-theme="light"] {
    /* Bootstrap reads these two for the body, so setting them here is what
       makes the body font inherit everywhere instead of being repeated. */
    --bs-body-font-family: "Titillium Web", system-ui, -apple-system, "Segoe UI", sans-serif;
    --bs-body-font-weight: 300;

    --font-display: Jost, var(--bs-body-font-family);
    --font-body: var(--bs-body-font-family);

    --weight-body: 300;
    --weight-display: 600;

    /* Headings.
    
       This has to be stated, not inherited. Bootstrap sets h1-h6 to 500, and
       the old site only ever loaded Jost at 700, 800 and 900 — so there was no
       500 to use and the browser fell back to 700. The headings were bold by
       accident of which files were loaded.
    
       Self-hosting the fonts made a real 500 available for the first time,
       Bootstrap got the weight it asked for, and every title on the site went
       lighter. Saying 700 outright keeps the look and stops it depending on
       which weights happen to be downloaded. */
    --weight-heading: 700;

    --size-body: 1.1em;
    --size-caption: .875rem;

    /* Section rhythm: one value, used by .section and .mb-8 alike. */
    --space-section: 6rem;
    --space-section-lg: 7.5rem;

    --banner-height-sm: 40vh;
    --banner-height-md: 60vh;
    --banner-height-lg: 70vh;

    /* What shows in the instant before the banner is decoded — a dark tone
       rather than white, so that moment reads as part of the picture rather
       than as a flash. The darkening of the picture itself is a brightness
       filter on the background layer, not a colour here. */
    --banner-base: #2b2f33;

    --hero-size-sm: 100px;
    --hero-size-md: 160px;
    --hero-size-lg: 200px;
}

/* ---------- 2. inheritance ---------- */

/* Set once on the body; every paragraph, list, table cell and form control
   below it inherits. Nothing else needs to name the body font again. */
body {
    font-family: var(--font-body);
    font-weight: var(--weight-body);
}

p {
    font-size: var(--size-body);
    margin: 0;
}

/* One rule for the display face rather than six. The sizes differ per level,
   so only those are stated separately below. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--font-display);
    font-weight: var(--weight-heading);
}

h1 { font-size: clamp(24px, 9vw, 120px); margin: 0; }
h2 { font-size: 2.25em; }
h3 { font-size: clamp(16px, 2vw, 24px); }
h4 { font-size: 1.5em; margin: 0; }
h5 { font-size: 1em; }
h6 { font-size: 76px; }

.caption {
    font-size: var(--size-caption);
}

/* Form controls do not inherit the page font by default — this is the one
   place the body font has to be named again, and it covers all of them. */
input,
select,
textarea,
button {
    font-family: inherit;
}

/* ---------- 3. layout ---------- */

.section {
    margin-bottom: var(--space-section);
}

/* The only utility the design adds that Bootstrap has no equivalent of. */
.mb-8 {
    margin-bottom: var(--space-section-lg) !important;
}

/* The banner behind a page title.
 *
 * The background image is put here by the server; CustomParallax then moves it
 * onto a layer of its own and blurs that. The blur must never be applied to
 * this element: it would blur the heading sitting on top of it as well.
 *
 * Only the height changes between breakpoints, so only the height is repeated.
 * The old file restated width and z-index in all three. */
.parallax {
    position: relative;
    width: 100%;
    height: var(--banner-height-sm);
    overflow: hidden;
    background-color: var(--banner-base);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;

    /* Required, not cosmetic.

       The script moves the picture onto a child layer at z-index -1. A child
       with a negative z-index paints behind its parent's background unless the
       parent is a stacking context of its own — so the moment this element was
       given a background colour, that colour covered the photograph and the
       banner showed as a plain dark block.

       isolation makes this element a stacking context, which puts the layer
       back above the colour and still below the heading. */
    isolation: isolate;
}

/* There is no darkening overlay element. The darkening is a brightness filter
 * on the picture itself, applied on the background layer next to the blur that
 * is already there — see CustomParallax. One layer instead of two, and nothing
 * sitting between the photograph and the words.
 *
 * How dark is set per location and per page in the admin, and reaches the
 * script as data-dim on the banner. */

@media (min-width: 576px) { .parallax { height: var(--banner-height-md); } }
@media (min-width: 992px) { .parallax { height: var(--banner-height-lg); } }

/* The hero text sits above both the background layer the script inserts at
   z-index -1 and the tint at z-index 0. */
.parallax > .row {
    position: relative;
    z-index: 1;
}

/* The map, when no key is configured — on localhost, where the key's referrer
   restriction means Google would answer 403. Same footprint as the embed, so
   the page reads the same here as it does live. */
.map-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 600px;
    border-radius: .375rem;
    background: var(--banner-base);
    color: #fff;
    text-decoration: none;
}

.map-placeholder-inner {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    text-align: center;
}

.map-placeholder:hover {
    color: #fff;
    text-decoration: underline;
}

/* The small fossil that overlaps the bottom edge of the banner. Again, only
   the size changes across breakpoints. */
#hero-image {
    position: relative;
    z-index: 2;
    width: var(--hero-size-sm);
    height: var(--hero-size-sm);
    margin-top: -3em;
    margin-bottom: 1em;
}

@media (min-width: 768px) {
    #hero-image {
        width: var(--hero-size-md);
        height: var(--hero-size-md);
        margin-top: -5em;
    }
}

@media (min-width: 992px) {
    #hero-image {
        width: var(--hero-size-lg);
        height: var(--hero-size-lg);
    }
}

/* ---------- 4. components ---------- */

.navbar {
    transition: opacity .4s ease, visibility .4s ease;
    opacity: 1;
    visibility: visible;
}

.navbar.hidden {
    opacity: 0;
    visibility: hidden;
}

.brand-name {
    padding-top: 11px;
}

.globe-icon {
    margin-top: 2.5px;
    margin-right: 4px;
}

/* The language switcher: plain links, so it works without JavaScript and a
   crawler can follow each one to that language's version of the page. */
.language-nav {
    margin: 0;
    padding: 0;
    list-style: none;
}

.language-nav .language-link {
    color: var(--bs-light-bg-subtle, #cfd3d8);
    font-size: .82rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    text-decoration: none;
}

.language-nav .language-link:hover,
.language-nav .language-link:focus-visible {
    color: #fff;
    text-decoration: underline;
}

.language-nav .language-link.active {
    color: #fff;
    font-weight: 700;
}

.btn {
    min-width: 7em;
    height: 2.5em;
    font-size: 1.1em;
    font-weight: var(--weight-display);
}

.zoom-hover {
    transition: transform .25s ease;
}

.zoom-hover:hover {
    transform: scale(1.05);
}

/* Cards the country filter has hidden. [hidden] alone loses to the display
   the grid sets, so it is stated outright. */
.location-card[hidden] {
    display: none !important;
}

/* The footer carries the site's navigation — there is no menu anywhere else —
   so its links need to look like links on hover without shouting in the
   resting state. */
.footer-link:hover,
.footer-link:focus-visible {
    text-decoration: underline !important;
    color: #fff !important;
}

#footer-nav h2 {
    font-size: var(--size-caption);
    letter-spacing: .06em;
    opacity: .75;
}

/* ---------- 5. motion ---------- */

/* There is deliberately no cross-document view transition here.
 *
 * It was tried, and it is the wrong tool for this site: a language change does
 * not navigate at all any more — the switcher replaces the page's contents in
 * place — and on the navigations that remain, a cross-fade of the banner is
 * just the banner fading, which is exactly what this page was asked not to do.
 * Nothing about the top of the page should ever appear to move or dissolve.
 *
 * The only motion left is on things a reader asks for: a card under the
 * pointer, and the navbar hiding as you scroll. */

@media (prefers-reduced-motion: reduce) {
    .zoom-hover,
    .navbar {
        transition: none;
    }

    .zoom-hover:hover {
        transform: none;
    }
}

/* The location you are already on, shown in its own grid only when the country
   filter asks for a country it is the only one of. It is not a link, so it is
   marked as the one you are reading rather than looking like a dead card. */
.location-card-here .card-image {
    opacity: .75;
}
.location-card-here .card-text1 {
    color: var(--muted, #6c757d);
}
