/*
 * Kleo site CSS - colours/type/measurements taken from the real,
 * currently-live kleo.org.uk stylesheet (read-only local mirror at
 * ~/Desktop/work/dev/wordpress/sites/kleo.org.uk/public/assets/css/
 * styles.css). Covers the Events pages plus, as of 2026-09-18, the
 * header/footer (see the "Header / Footer" section below). Homepage
 * layout/other pages are still the package's own generic default (see
 * CLAUDE.md's "Not yet done").
 *
 * Foco-Black/Foco-Light (MyFonts/Dalton Maag) - Tom confirmed 2026-09-18
 * this rebuild is covered by the existing licence, so the real webfont
 * files were copied from the legacy site's own public/assets/fonts/
 * into public/fonts/ here (same 4 formats each, eot/woff2/woff/ttf).
 * The legacy stylesheet's own @font-face src list is reproduced as-is
 * below - same files, same format fallback order.
 *
 * Content-wrapper horizontal padding (2026-09-28): the legacy site's
 * own `.inner` convention (max-width: 980px; margin: 0 auto;) carries
 * NO horizontal padding of its own - confirmed against its real
 * styles.css, including its own `.hero`/footer rules. This file's
 * equivalent wrapping containers (.diary, .event-detail, .kleo-footer,
 * .kleo-header__bar-inner, .kleo-nav .navbar-collapse, .kleo-subnav,
 * .home-upcoming, the banner's own .ck-content) had all picked up an
 * extra `20px` left/right on top of that centring, which live doesn't
 * have - removed for layout consistency with the real site. Left
 * untouched: padding on actual buttons/pills/cards (.diary-featured,
 * .diary-featured__link, .diary-filters button, event-card spacing)
 * - those aren't page-width containers, removing their padding would
 * just make them look broken, not more consistent with anything live
 * does.
 */

@font-face {
    font-family: 'Foco-Black';
    src: url('/fonts/2F50DD_0_0.eot');
    src: url('/fonts/2F50DD_0_0.eot?#iefix') format('embedded-opentype'),
         url('/fonts/2F50DD_0_0.woff2') format('woff2'),
         url('/fonts/2F50DD_0_0.woff') format('woff'),
         url('/fonts/2F50DD_0_0.ttf') format('truetype');
}

@font-face {
    font-family: 'Foco-Light';
    src: url('/fonts/2F50DD_1_0.eot');
    src: url('/fonts/2F50DD_1_0.eot?#iefix') format('embedded-opentype'),
         url('/fonts/2F50DD_1_0.woff2') format('woff2'),
         url('/fonts/2F50DD_1_0.woff') format('woff'),
         url('/fonts/2F50DD_1_0.ttf') format('truetype');
}

:root {
    --kleo-text: #4d4d4d;
    --kleo-heading: #58595b;
    --kleo-link: #ff5b00;
    --kleo-link-hover: #00adef;
    --kleo-bg-muted: #ebebeb;

    /* Brand accent colours - exact values from the legacy stylesheet's
       own .news-diary .button.filter.{kleo,kwf,kfm} rules (same colours
       that site's flag badges used). One brand per landing page here
       (see App\Entity\EventFields::getBrandSlug()), not a filter control
       the way the legacy shared diary needed. */
    --kleo-brand-kleo: #00adef;
    --kleo-brand-kwf: #a30060;
    --kleo-brand-kfm: #00a57f;
}

/* Every rem value in this file (12 of them, e.g. body's own 1.8rem
   below) was sized against the legacy stylesheet's own convention of
   1rem = 10px ("font-size: 18px; font-size: 1.8rem;" dual-declarations
   throughout its styles.css, an old px-fallback pattern that only
   works because it also sets `html { font-size: 62.5% }`). This file
   never carried that root rule over, so every rem value here was
   rendering at browser-default scale (1rem = 16px) instead - 60% too
   large sitewide, confirmed by comparing computed sizes against the
   real live site rather than assumed. Reproducing the legacy site's
   own 62.5% convention here is the fix, not converting every value to
   px individually. */
html {
    font-size: 62.5%;
}

body {
    font-family: 'Foco-Light', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 1.8rem;
    line-height: 1.25;
    color: var(--kleo-text);
    /* Reverted to plain white on request (2026-10-05) - supersedes the
       2026-09-29 change (below, kept for the record) that moved this to
       `--kleo-bg-muted` (`#ebebeb`, the same grey as the secondary nav)
       sitewide. `#sh-content-container`/`.kleo-subnav`/`.kleo-footer`'s
       own `--kleo-bg-muted` backgrounds (further down this file,
       deliberately untouched) still apply their own grey independently
       of this rule - only the page-wide `body` default changes here. */
    background-color: #fff;
}

/* Sticky footer (2026-09-29, on request) - standard flexbox pattern.
   The vendor package's own base.html.twig always wraps every page as
   `<body><div class="min-vh-100 {{ class_body }}"><header>...<div
   id="sh-content-container">...</div><footer>...</div></body>` -
   `.min-vh-100` is a plain Bootstrap utility (`min-height: 100vh`,
   already correct), targeted here via `body >` rather than that class
   alone since `class_body` also puts a second, page-specific class on
   the same element and `.min-vh-100` itself is a shared Bootstrap
   utility used elsewhere too, not safe to redefine globally. Making
   this wrapper a flex column and the content area `flex: 1 0 auto`
   (fills whatever space is left inside the 100vh wrapper on a short
   page, growing normally past 100vh on a tall one) pins the footer to
   the bottom of the screen on a short page without pinning it there on
   a tall one - the standard sticky-footer trade-off, not something a
   fixed pixel/vh value on the content area alone can do. */
body > div.min-vh-100 {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

/* Overrides the vendor package's own `#sh-content-container {
   min-height: 60vh }` (assets/frontend/styles/styles/frontend/
   _layout.scss) - that fixed 60vh spacer is what was pushing the
   footer down on short pages regardless of how much real content
   there was; `flex: 1 0 auto` replaces it with "grow to fill the
   wrapper's own remaining space" instead of a guessed fixed minimum.
   No `background-color` of its own any more - widened to `body` (on
   request, immediately after - see that rule's own comment) so the
   same default reaches every gap on the page, not just this element. */
#sh-content-container {
    min-height: 0;
    flex: 1 0 auto;
}

h1, h2, h3, h4, h5, h6 {
    font-family: 'Foco-Black', 'Arial Black', -apple-system, sans-serif;
    line-height: 1.25;
    margin: 0;
}

/* Tom, 2026-09-28: remove the vendor package's own default top/bottom
   padding on every content block. `.cc-content-container` is the
   generic wrapper `vendor/sevenhills/simpl-cms`'s own `cc_content.
   html.twig` (contentrowstart() macro) renders around EVERY content
   block on EVERY page (banner/text/collection/gallery/etc.) - its own
   `assets/frontend/styles/styles/frontend/_layout.scss` gives it
   `padding-top`/`padding-bottom: 2rem` as a generic, invented-for-that-
   pass default vertical rhythm between stacked blocks (see that
   package's own CLAUDE.md - "the spacing scale here is genuinely
   invented for this pass", unlike option_sets' own real production
   values). Overridden here rather than edited in vendor/ (never edit
   vendor/ directly - composer update would silently discard it).
   Doesn't touch ContentBlock's own real per-block margin-top/bottom
   option set (mt-default/mt-half/mt-double/mt-none, editable per block
   in the admin) - that's margin, this is padding, genuinely separate
   properties/mechanisms. */
.cc-content-container {
    padding-top: 0;
    padding-bottom: 0;
}

/* `.cc-content` (2026-09-29, on request) - the actual content column
   inside `.cc-content-container` (`cc_content.html.twig`'s own markup:
   `.cc-content-container > .cc-content.cc-content--rows`). Its base
   vendor rule (`assets/frontend/styles/styles/frontend/_layout.scss`)
   is genuinely empty - a block's own "Content width" option set always
   adds one of six real modifier classes for a genuine, deliberate
   narrower/wider choice (`--w-100%`/`--w-three-quarters`/`--w-two-
   thirds`/`--w-half`/`--w-one-third`/`--w-one-quarter`), which this
   rule excludes and leaves untouched - or, when nothing's been chosen,
   `--w-default`/`--w-content` (Bootstrap's own, much wider `.container`
   default) or no modifier class at all, both of which this rule *does*
   override to 980px.

   Real gap found and fixed after the first version of this rule shipped
   ("does not seem to be applied on /kleo/blether-bothy"): that page's
   blocks carry `cc-content--w-default` (confirmed via curl - not every
   block on this site has the same modifier-or-none state the homepage's
   own blocks happened to have), and the original selector's broad
   `:not([class*="cc-content--w-"])` excluded ANY `--w-*` class
   indiscriminately, including `--w-default`/`--w-content` - exactly the
   "unset" state this rule is meant to apply to. Fixed by excluding only
   the six real, deliberate-choice modifiers by name instead of the
   whole `--w-*` family.

   A `:not(:has(.ci-content--banner))` hardcoded exclusion used to sit
   here too, added when the homepage hero's own Banner block was found
   getting squeezed to 980px by an earlier version of this rule -
   fixed the wrong way at the time: it excluded the block by *type*
   rather than respecting its own real, admin-editable "Content width"
   option (`ContentBlockType.php`'s `contentWidth` field, the exact
   same field every other block already earns this exclusion through).
   Removed 2026-09-29 (on request - "ensure the banner respects the
   content items display properties") - the homepage banner's own
   `content_width` was `'default'` (a real, existing value, carrying
   `cc-content--w-default` - see the `Real gap found...` note above,
   this is exactly the class that note's fix was written to still
   catch), explaining why it needed a type-based carve-out to stay
   full-bleed at all. Fixed at the data layer instead: the banner block
   now has `content_width = '100%'` (the real "Full" choice, same as
   any other block would use for this), so it earns the exclusion the
   same way every other full-width block does - via `--w-100\%` already
   being in this selector's own exclusion list, not a banner-specific
   hack. */
.cc-content:not(.cc-content--w-100\%):not(.cc-content--w-three-quarters):not(.cc-content--w-two-thirds):not(.cc-content--w-half):not(.cc-content--w-one-third):not(.cc-content--w-one-quarter) {
    max-width: 980px;
    margin: 0 auto;
}

/* On request (2026-09-29): remove `.cc-content`'s own horizontal
   padding at every width, mobile included - superseding the previous
   two entries here (a 5% mobile-only gutter, then a min-width:992px
   rule cancelling the small, pre-existing 7.5px Bootstrap `.container`
   gutter above that same breakpoint). Now that every content block's
   own "Content padding" option defaults to "Default" (2rem, on all four
   sides - see `content_block_defaults`/the DB backfill in
   `config/packages/simpl_cms.yaml`) rather than "None", real horizontal
   spacing is already provided at every viewport width by `.ci-content`
   itself (one level further in - `cc_content.html.twig`'s own
   `p-content-default` class), making a second, `.cc-content`-level
   mobile gutter redundant - removed rather than left stacking on top of
   it. No exclusion list needed (unlike the 980px max-width rule above)
   - the six genuine width-choice modifiers and the full-bleed Banner
   block never carried `.cc-content`'s own horizontal padding in the
   first place, so a blanket, no-media-query rule is a safe no-op for
   all of them. */
.cc-content {
    padding-left: 0;
    padding-right: 0;
}

h1 {
    color: var(--kleo-heading);
    font-size: 2.4rem;
}

h2 {
    color: #7f7f7f;
    font-size: 2.4rem;
}

/* Real, sitewide gap found on request (2026-09-28) - live's own global
   `a` rule sets `font-family: Foco-Black; font-size: 1.7rem` (confirmed
   via a direct computed-style check against a genuinely plain link on
   live, not assumed from the stylesheet text alone), never reproduced
   here - any link without its own more-specific override (this site's
   own "Contact us" being the one that got noticed) rendered in the
   inherited body font instead. Every other link on this site that
   deliberately differs (.kleo-nav a, .kleo-subnav a, .ci--text-content a,
   etc.) already has its own class-level override, which still wins
   over this element-level rule regardless of where in the cascade it
   sits - confirmed safe to add sitewide, not just patched per-element. */
a {
    color: var(--kleo-link);
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    font-size: 1.7rem;
    text-decoration: none;
    transition: color 0.1s ease-in-out;
}

a:hover {
    color: var(--kleo-link-hover);
}

/* Matches the legacy site's own global `strong { font-family: Foco-
   Black; }` rule exactly (2026-09-29, on request - "throughout the
   site", not just inside ordinary body copy) - unscoped there, so
   unscoped here too, same as the global `a` rule immediately above.
   Previously only applied inside `.ci--text-content` (an earlier,
   narrower pass) - real body copy elsewhere (event/news detail body
   text, etc.) already goes through that same class, but making this
   global removes the need to keep tracking every context individually,
   matching live's own simpler, unscoped rule. */
strong {
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
}

/* Event/news listing cards (templates/tpl_section/content_container/
   _event_card.html.twig/_news_card.html.twig) - same card shape as the
   legacy site's own a.list-item (290x420, white background, uppercase
   bold date, title/description stacked below the image) - see that
   stylesheet's own a.list-item/.news-diary/.flag rules, all read
   directly from live (2026-09-29, "bring the appearance... in line"),
   not guessed - real hex values/sizes throughout this block, and real
   colour/font values confirmed against live's own actual computed
   styles for the ones this project had previously only guessed at
   (title colour, title size - see below). */
.event-card {
    display: inline-flex;
    flex-direction: column;
    position: relative;
    width: 290px;
    max-width: 100%;
    background-color: #fff;
    color: var(--kleo-text);
    text-align: left;
    vertical-align: top;
    /* No margin any more (2026-09-29, on request - "apply that fix to
       all cards across the entire site") - every real grid this card
       renders inside (.home-teasers__cards, .diary-list, .sh-collection
       - see those rules below) is now a genuine flex container
       supplying its own spacing via `gap`, so a second, card-level
       margin isn't needed anywhere any more.
       padding-bottom (2026-09-29, on request) - the card's own last
       child (the description, or the title when there's no
       description) previously ran flush to the card's own bottom edge.
       Started at 1rem (matching the same inset every text element
       inside the card already uses horizontally), doubled to 2rem on
       a same-day follow-up request. */
    padding-bottom: 2rem;
}

.event-card:hover {
    color: var(--kleo-text);
}

.event-card__image {
    display: block;
    width: 100%;
    height: 190px;
    object-fit: cover;
}

/* "Flag" brand badge (2026-09-29, on request) - real assets copied
   verbatim from live's own /assets/img/ui/{winter-festival,farmers-
   market,kleo}-flag.png (a solid-colour ribbon graphic, real brand
   colour baked into the PNG itself - confirmed by opening the file, not
   assumed - the visible label text is real HTML, not part of the
   image). Positioned the same way live's own `.flag { position:
   absolute; top: 150px }` does - 150px down from the card's own top
   edge lands it over the lower portion of the 190px-tall image
   regardless of card type, matching live exactly. Previously,
   deliberately left out entirely ("each brand already has its own
   page, so which brand a card belongs to is already implied by which
   page it's on" - see the Events styling section above) - reversed on
   request now that /diary mixes all three brands again and every real
   card on live carries this regardless of which page it's on, not just
   cross-brand ones. */
.event-card__flag {
    position: absolute;
    top: 15rem;
    left: 0;
    width: 14.8rem;
    height: 3rem;
    display: block;
    color: #fff;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    font-size: 1.5rem;
    padding: 0.7rem 0 0 0.7rem;
    background-repeat: no-repeat;
    background-position: center;
}

.event-card__flag--kwf { background-image: url('/img/ui/flags/winter-festival-flag.png'); }
.event-card__flag--kfm { background-image: url('/img/ui/flags/farmers-market-flag.png'); }
.event-card__flag--kleo { background-image: url('/img/ui/flags/kleo-flag.png'); }

.event-card__date {
    display: block;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    text-transform: uppercase;
    font-weight: bold;
    color: var(--kleo-heading);
    margin-left: 1rem;
    padding: 1rem 0;
}

.event-card__title {
    display: block;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    /* 2.4rem/#7f7f7f (was a guessed 1.8rem/#000) - confirmed against
       live's own real, generic `h2` rule, which every card title reads
       through there too (no more specific override exists on live for
       this). */
    font-size: 2.4rem;
    color: #7f7f7f;
    margin: 0 1rem;
}

.event-card__description {
    display: block;
    font-size: 1.8rem;
    color: var(--kleo-text);
    margin: 4px 1rem 0;
}

/* Gallery-vs-video icon (2026-09-29, on request - "as with the live
   site"). First tried live's own literal mechanism verbatim - an
   absolutely-positioned bottom-right background-image on the whole
   card, plus live's own matching fixed 295px card height (without
   which the icon has nowhere to sit but directly over the title text
   on a short-titled card - confirmed live via a real collision report,
   "Festive market nov 2023"). Correctly rejected on a follow-up
   request: live's fixed height only works there because literally
   every card on live has one (420px base, 295px for gallery/youtube) -
   this site's own cards were a deliberate, considered exception to
   that (content-driven height throughout, so Producer's own shorter
   cards - also a different fixed height on live - aren't stretched to
   match, see the card-appearance section above). Bolting a fixed
   height onto just these two modifier classes reintroduced exactly the
   inconsistency that earlier decision avoided - cards on the same grid
   at different heights, with dead space reserved purely so an
   overlaid icon wouldn't collide with text it was sitting on top of in
   the first place.

   Fixed properly instead: a real icon image in its own container,
   placed in normal document flow AFTER the title (see
   cc_card_galleryentry.html.twig's own `.event-card__icon` div) rather
   than absolutely positioned over it - nothing to collide with, no
   fixed height needed anywhere. */
.event-card__icon {
    display: block;
    text-align: right;
    padding: 4px 1rem 0;
}

.event-card__icon img {
    display: inline-block;
    vertical-align: middle;
}

/* Per-brand text tinting removed sitewide (2026-09-28, full-comparison
   follow-up) - checked directly against the real legacy stylesheet
   rather than assumed: the ONLY two places live ever uses a per-brand
   colour are the `.button.filter.{kleo,kwf,kfm}` diary filter pills
   (kept, see `.diary-filters` below) and the `.flag.{kwf,kfm,kleo}`
   badge icons (deliberately not reproduced, see the Events styling
   section of CLAUDE.md) - `.event-card__date`/meta labels/headings are
   always the same plain colour regardless of brand on live, confirmed
   via computed-style checks against real KLEO/KWF/KFM pages. This
   `.page--{brand}-events .event-card__date` rule (and its three
   siblings elsewhere in this file) was an invented embellishment from
   an earlier session, never checked against live - removed, the base
   `.event-card__date` rule above already has the correct plain colour. */

/* Event detail page (templates/event/show.html.twig) - the legacy
   site's own diary_article_item.html.twig laid these fields out as
   plain labelled rows ("Venue: ...", "Ticket price: ...", "Event
   organiser: ..."), styled via p.additional-event-info - reproduced
   here as a <dl> instead (same visual result, better markup for
   label/value pairs) using the same uppercase-bold-label convention. */
.event-detail {
    max-width: 980px;
    margin: 0 auto;
    padding: 30px 0;
}

/* Real left/right-edge misalignment found on request (2026-10-05, on
   request - "Intro content should be padded left and right as with
   other content") - confirmed via a real CDP measurement before
   guessing which side was actually wrong: the event's own body/intro
   text (ordinary zone content, `.ci-content.p-content-default`)
   already correctly carries the sitewide-standard 20px left/right
   inset every other page's own content uses - it was this header
   (title/image/meta table, hardcoded in templates/event/show.html.twig,
   outside the zone-content padding mechanism entirely) that had none
   at all, sitting flush against `.event-detail`'s own edge while the
   text below it sat inset by 20px - a real, visible misalignment, not
   a missing feature on the text's own side. `2rem` matches
   `$cc-padding-default`'s own real compiled value (20px at this site's
   62.5% root convention) exactly, rather than a separately-invented
   pixel value. */
.event-detail__header {
    padding: 0 2rem;
}

.event-detail__header h1 {
    /* Matches the legacy site's own .headline h2, .ck h2 rule (an
       event's title there is an <h2>, not an <h1>, but the same
       magenta/size treatment clearly applies to "this page's own
       title" regardless of tag - confirmed against a real live event
       page before matching it). */
    color: #a30060;
    font-size: 4rem;
    margin-bottom: 20px;
}

.event-detail__image {
    display: block;
    width: 100%;
    max-width: 600px;
    height: auto;
    margin-bottom: 20px;
}

.event-detail__meta {
    margin: 0 0 30px;
}

.event-detail__meta-row {
    display: flex;
    gap: 10px;
    padding: 6px 0;
    border-bottom: 1px solid var(--kleo-bg-muted);
}

.event-detail__meta-row dt {
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    text-transform: uppercase;
    font-weight: bold;
    color: var(--kleo-heading);
    min-width: 140px;
}

.event-detail__meta-row dd {
    margin: 0;
    color: #7f7f7f;
}

/* Per-brand tinting removed here too - see the same note above
   `.event-card__date`'s own rule for the full reasoning. Confirmed via
   a direct computed-style check against a real live event page: the
   meta labels (Venue/Ticket price/Organiser) are plain grey
   (`--kleo-heading`, matching the base `.event-detail__meta-row dt`
   rule above) regardless of brand, never tinted. */

/* Header / Footer (templates/header/default_header.html.twig,
   templates/footer/default_footer.html.twig) - same three-tier header
   layout and dark footer bar as the legacy site's own styles.css
   (.banner/.nav-primary/footer rules there), adapted to this site's
   real DOM (Bootstrap navbar/collapse markup, not the legacy's own
   checkbox-toggle hack - same visual result, the toggle mechanism
   itself comes free from frontend.js). Selector names below are this
   site's own (kleo-header__*, not .banner/.nav-primary) - not a
   like-for-like class rename, a fresh header built to match the same
   look. */

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
}

.skip-link:focus {
    left: 0;
    z-index: 1000;
    background: #fff;
    padding: 10px;
}

.kleo-header__bar {
    background-color: var(--kleo-heading);
    padding: 11px 0;
}

.kleo-header__bar-inner {
    max-width: 980px;
    margin: 0 auto;
    /* Facebook icon on the left, "Contact us" on the right - matches
       live's own layout (`#contact { float: right }` there); flexbox
       here instead of a float, consistent with how the rest of this
       site's own CSS is written. */
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.kleo-header__bar-inner img {
    vertical-align: middle;
}

/* Matches the legacy site's own mobile behaviour: its `.inner` class
   (which the top bar's own <nav> carries there) picks up a 5% side
   margin below 990px (`@media max-width: 990px { .inner { width: 90%;
   margin: 0 5%; } }`) - this site's own equivalent `.kleo-header__bar-
   inner` never had that, so "Contact us" sat flush against the very
   edge of the screen on mobile (confirmed via a real DevTools Protocol
   measurement - live's own right edge sits ~19px in from the edge at
   375px width, this site's sat at the literal edge). Scoped to this one
   element, not a sitewide `.inner`-style mobile margin pass - the
   generic "ordinary content has no width constraint on mobile" gap is
   already tracked separately (see CLAUDE.md's "Content-wrapper
   horizontal padding removed" section) and out of scope here. */
@media screen and (max-width: 991.98px) {
    .kleo-header__bar-inner {
        margin: 0 5%;
    }
}

/* Matches the legacy site's own `#contact` rule exactly (colour, size,
   icon) - added once a real Contact page existed to link to (see
   CLAUDE.md's "Header and footer" section for why this was originally
   left out, and the full-site-audit section for when the real page was
   added). No hover-colour override, matching live: `#contact`'s own id
   selector there outranks the generic `a:hover` rule, so the text stays
   white on hover rather than picking up this site's usual link-hover
   colour. */
.kleo-header__contact {
    color: #fff;
    height: 24px;
    line-height: 24px;
    padding-left: 30px;
    background: url('/img/ui/contact.png') no-repeat center left;
    font-size: 1.7rem;
}

.kleo-header__contact:hover {
    color: #fff;
}

.kleo-header__brand {
    text-align: center;
    padding: 20px 0;
}

.kleo-header__logo {
    /* Real horizontal-overflow bug found via mobile screenshot
       (2026-09-28): an inline-flex element sizes to its own content by
       default and has no `max-width` here, so on a narrow viewport the
       full "Kinross-shire Local Events Organisation" text ran straight
       past the edge of the screen instead of wrapping - `.kleo-header__
       brand`'s own `text-align: center` only positions this element,
       it doesn't constrain its width. `max-width: 100%` lets the flex
       item shrink to the viewport, `flex-wrap: wrap` then lets the
       (still `inline-flex`) logo image and text stack/wrap instead of
       forcing one unbroken row. */
    display: inline-flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 12px;
    max-width: 100%;
    color: var(--kleo-heading);
}

.kleo-header__logo:hover {
    color: var(--kleo-heading);
}

.kleo-header__logo span {
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    text-transform: uppercase;
    /* Was 1.8rem (18px) - confirmed via a real DevTools Protocol
       computed-style check against live that its own `.banner-logo`
       (an <h1>, inheriting the generic `h1` rule's own `font-size:
       2.4rem`, not something `.banner h1` sets itself) renders at 24px/
       32px line-height, not 18px - this site's own explicit 1.8rem was
       a guess from the original header-building session, never checked
       against the real computed value. */
    font-size: 2.4rem;
    line-height: 3.2rem;
}

.kleo-nav {
    /* `border-top`/Bootstrap's own default `.navbar` padding (`padding:
       var(--bs-navbar-padding-y) var(--bs-navbar-padding-x)`, 0.5rem
       top/bottom) - confirmed via a real DevTools Protocol computed-
       style check that live's own nav has neither (0px border, 0px
       padding both here) - both removed. */
    background-color: #fff;
    padding: 0;
}

.kleo-nav .navbar-collapse {
    /* Not 980px like the header bar/footer/page content above - the 7
       real primary nav items (Home/KLEO/Kinross Winter Festival/Kinross
       Farmers' Market/Diary/Get Involved/Gallery) genuinely don't fit
       in that width at this font-size/padding - confirmed by testing at
       a 2000px viewport with the old max-width still in place, which
       still wrapped, since the constraint was on this container, not
       the viewport. `none` rather than a guessed fixed number: adapts
       automatically if a nav item is ever renamed/added, rather than
       silently wrapping again the next time site content changes. The
       header/logo above isn't tied to the 980px column either (centred
       via plain text-align, no max-width of its own) - only the dark
       top bar and the page content below actually use that width, so
       this doesn't break any alignment that existed before. */
    max-width: none;
    margin: 0 auto;
    /* This is the element Bootstrap actually makes `display: flex` and
       full-width (`.navbar-expand-lg .navbar-collapse{display:flex
       !important}`, confirmed in the vendor's own compiled CSS) - its
       one child (the <ul> below) is a flex item with no `flex-grow` of
       its own, so it only ever takes up exactly as much width as its
       own content needs. `justify-content: center` on the <ul> itself
       (below) was therefore centering the nav items *within a box
       already exactly their own width* - a no-op, confirmed visually
       (the whole nav sat flush against the left edge instead of the
       centre, at every width tested). Centering has to happen here,
       one level up, on the box that's actually as wide as the page. */
    justify-content: center;
}

.kleo-nav ul {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
}

.kleo-nav li {
    margin: 0;
}

.kleo-nav a {
    display: block;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    color: #4c4c4c;
    padding: 10px 24px 2px;
    border-bottom: 8px solid #fff;
}

.kleo-nav a:hover,
.kleo-nav li.current a {
    color: #000;
    border-bottom: 8px solid #ffb000;
}

.kleo-nav__toggle {
    /* Real bug found via mobile screenshot (2026-09-28): `margin: 10px
       auto` centres the button within `.kleo-nav`'s own flex row
       (Bootstrap's `.navbar` is `display: flex; justify-content:
       space-between` by default - with only this one child visible on
       mobile, an auto margin on BOTH sides overrides that and centres
       it mid-header, floating with nothing on either side). The legacy
       site's own equivalent (`nav label { float: right; }`) always
       pins its hamburger to the right edge - matched here by an auto
       margin on the left only, which pushes this one flex item as far
       right as the row allows instead of centring it. */
    display: none;
    margin: 10px 0 10px auto;
    border: 1px solid var(--kleo-bg-muted);
    background: #fff;
    padding: 6px 10px;
}

/* 991.98px, not 767px - a real, separate bug found while checking the
   max-width fix above at a few in-between viewport widths: Bootstrap's
   own bundled `.navbar-expand-lg` (frontend.css) switches at exactly
   992px, hiding `.navbar-collapse` below that (Bootstrap's own base
   `.collapse:not(.show) { display: none }`) regardless of anything in
   this file. This media query's old 767px boundary only started
   showing the toggle button below THAT width - leaving a genuine dead
   zone from 768px to 991px where neither the toggle button nor the nav
   itself was visible at all. 991.98px matches Bootstrap's own
   convention for this exact boundary (avoids a 1px gap right at 992px
   on fractional-pixel-ratio displays), not a round number picked at
   random. */
@media screen and (max-width: 991.98px) {
    .kleo-nav__toggle {
        display: block;
    }

    .kleo-nav .navbar-collapse {
        display: none;
    }

    .kleo-nav .navbar-collapse.show {
        display: block;
    }

    .kleo-nav ul {
        flex-direction: column;
        text-align: center;
    }

    .kleo-nav a {
        border-bottom: 1px solid var(--kleo-bg-muted);
        padding: 14px 8px;
    }
}

.kleo-footer {
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    font-size: 1.5rem;
    color: #fff;
    background-color: var(--kleo-heading);
    text-align: center;
    padding: 26px 0;
    /* On request (2026-09-29): space between the page content above and
       the footer bar - previously butted directly against each other. */
    margin-top: 40px;
}

.kleo-footer__nav {
    margin-bottom: 10px;
}

/* Real colour mismatch found on request (2026-09-28) - a footer link
   was guessed at white here (matching the footer's own plain-text
   colour) but a direct computed-style check against live shows its
   real "Privacy and terms of use" link is genuinely orange (rgb(255,
   91, 0) - the site's ordinary link colour, inherited from the global
   `a` rule above, not something the footer overrides). Removed the
   incorrect override entirely rather than hardcoding the colour, so it
   correctly tracks the same `--kleo-link`/hover colours every other
   plain link on the site already does. */
.kleo-footer__nav a {
    margin: 0 10px;
}

/* Real size mismatch found via the systematic computed-style audit
   (2026-09-28) - the copyright line had a guessed 1.3rem (13px) of its
   own; live's real text has no override at all and just inherits
   `.kleo-footer`'s own 1.5rem (15px), confirmed via computed style.
   Removed the override rather than hardcoding 1.5rem again, so it stays
   correct automatically if the footer's own base size ever changes. */
.kleo-footer__copyright {
    margin: 0;
}

/* Homepage (templates/home/show.html.twig) - hero banner text + the
   "Upcoming events" teaser. The banner block's own background photo/
   gradient overlay is already handled by the vendor's own
   cc_content_item_banner.html.twig (inline styles) - this just makes
   the heading/credit text inside it legible (white, centred, large,
   matching the legacy site's own .hero h1/p) and gives the block a
   real hero height, since a CSS background-image has no inherent
   height of its own. */
.ci-content--banner {
    /* 410px/flex-centred text matches the legacy .hero rule's own
       height (410px, padding-top: 90px there - flex-centring gets a
       visually equivalent result without depending on this block's
       exact text length the way a fixed padding-top would). */
    min-height: 410px;
    display: flex;
    align-items: center;
}

.ci-content--banner .ck-content {
    width: 100%;
    text-align: center;
    color: #fff;
    padding: 40px 0;
}

.ci-content--banner .ck-content h1 {
    color: #fff;
    font-size: 7rem;
    text-transform: uppercase;
    margin-bottom: 10px;
}

.ci-content--banner .ck-content p {
    color: #fff;
    font-size: 5rem;
    margin: 0;
}

/* Real horizontal-overflow bug found via mobile screenshot (2026-09-28)
   - matches the legacy site's own `.hero h1`/`.hero p` responsive
   breakpoints (its `styles.css`, `@media max-width: 990px`), never
   reproduced here: at a narrow viewport, 7rem/5rem hero text ran well
   past the edge of the screen with nothing shrinking it. */
@media screen and (max-width: 991.98px) {
    .ci-content--banner .ck-content h1 {
        font-size: 4rem;
    }

    .ci-content--banner .ck-content p {
        font-size: 2.4rem;
    }
}

/* Ordinary page content's own <h1> (e.g. the homepage's "Welcome") -
   matches the legacy site's own `.main h1, .news h1, .diary h1` rule
   (same magenta, same 60px) rather than the generic dark-grey `h1`
   rule above, which is for page/section titles outside a Text block
   (e.g. this site's own header/nav chrome has no h1 of its own to
   collide with this). */
.cc-zone--content .ci--text-content h1 {
    color: #a30060;
    font-size: 6rem;
}

/* CSS full-pass (2026-09-28) - a real, previously-flagged-but-not-fixed
   gap: an ordinary Text block (e.g. the homepage's own "Welcome" copy,
   "About KLEO" on /kleo, the Get Involved intro) has NO width
   constraint of its own anywhere in this package's vendor CSS (checked
   directly - vendor/sevenhills/simpl-cms's own frontend.css only sets
   padding on .cc-content-container/.cc-zone, never a max-width) - it
   runs genuinely full-viewport-width, where the legacy site always
   wraps this in a max-width: 980px `.inner`. Scoped to
   `.ci-content-container--text` specifically (the content_type-specific
   wrapper `cc_content.html.twig` already emits per block, `content_type
   = 'text'` for an ordinary Text block) rather than every
   `.cc-content-container` sitewide, so this doesn't also squeeze the
   homepage's own full-bleed hero Banner block or a brand page's event
   Collection-block grid - neither of those was reported broken and
   both are already deliberately full-width/flex-wrapping. */
.ci-content-container--text {
    max-width: 980px;
    margin: 0 auto;
}

/* Query container for .sh-collection's own 3-vs-2-per-row `@container`
   rule below - same reasoning/same real browser constraint as `.diary`/
   `.home-teasers__row`'s own identical additions (see those rules' own
   comments): has to be a real ancestor of the grid, not the grid
   itself. `.ci-content` is the one shared wrapper every Collection
   block's own `.sh-collection` grid already renders directly inside
   (`cc_content_item_collection.html.twig`, vendor) - a single rule here
   covers every brand's own listing page, not one per page. Applying
   `container-type: inline-size` sitewide to every content block's own
   `.ci-content` (not just Collection ones) is safe/inert for every
   other block type - it only ever takes effect where a real
   `@container` rule actually targets it, which nothing but this one
   does today. */
.ci-content {
    container-type: inline-size;
}

/* Same CSS full-pass - ordinary body-copy links/bold text inside a Text
   block weren't reproducing the legacy site's own global `a`/`strong`
   rules (Foco-Black, links at 1.7rem) - e.g. the Winter Festival page's
   real migrated programme links, or "hires equipment" on /kleo, were
   rendering in the generic Foco-Light body font instead. Scoped to
   `.ci--text-content` (not a sitewide `a`/`strong` override) so this
   doesn't touch any of this site's own already-correct, more specific
   nav/card/button link styling (.kleo-nav a, .event-card, .kleo-subnav
   a, .diary-featured__link, etc.). */
.ci--text-content a {
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    font-size: 1.7rem;
}

/* `strong` styling is now a global rule (see the base `a`/`strong`
   type rules near the top of this file) - no longer needed here. */

/* The "larger" CKEditor style (config/packages/fos_ckeditor.yaml's own
   `cc_styles`, outputs `<div class="cc_intro">`) had never had a real
   CSS rule at all before this - Tom asked for it to replicate the
   homepage hero's own subtitle text ("Events & activities in a vibrant
   community"), confirmed via live's real markup/stylesheet
   (`.hero p { font-size: 50px/5rem; line-height: 1; color: #fff }`,
   `@media max-width: 990px { .hero p { font-size: 30px/3rem } }`) -
   `cc_intro` has no equivalent class on live at all (grepped its real
   stylesheet - `.main .inner.intro` is a different, unrelated
   full-width-wrapper class, not a text style), so this is a genuinely
   new mapping, not a rename of an existing live rule.

   Size/line-height reproduced exactly; `color`/`max-width: 60%`
   deliberately NOT carried over - both are specific to the hero's own
   photo-overlay layout (white text needs a dark photo behind it to
   stay legible; the 60% cap exists so the text doesn't run under the
   hero's own absolutely-positioned "What's on?" button), not
   intrinsic to what "larger" text looks like wherever an editor
   applies it in ordinary page content - it inherits the surrounding
   text's own colour instead, same as every other `cc_styles` entry. */
.ci--text-content .cc_intro {
    font-size: 5rem;
    line-height: 1;
}

@media screen and (max-width: 991.98px) {
    .ci--text-content .cc_intro {
        font-size: 3rem;
    }
}

/* Full-comparison pass (2026-09-28) - the real hero images added to Get
   Involved/Equipment Hire/Blether Bothy (see FixStaticPageHeadingsCommand)
   match the legacy site's own `.headline img { float: left; margin-
   right: 30px }` - reproduced here, scoped to an image immediately
   following the page's own `<h1>` (`h1 + img` - matches exactly how
   these three pages' real markup is ordered) rather than every image
   in a Text block, so this doesn't float an image appearing later in
   some other page's own body copy - live's own rule was scoped the
   same way (the `.headline` wrapper class on the hero image
   specifically, not a generic `article img`). */
.ci--text-content h1 + img {
    float: left;
    margin: 0 30px 20px 0;
}

/* News + Diary, stacked as full-width rows - matches the legacy
   homepage's own `.news-diary` row (two `<section>`s, News then Diary,
   in one `.inner` row - confirmed via a real DevTools Protocol rect
   measurement against live, not assumed: both sections share the exact
   same left edge and full width, News on top). Corrected 2026-09-28
   (full-comparison follow-up) from an earlier, wrong side-by-side
   `.home-teasers__col` layout - `.home-teasers__row` replaces it.
   Renamed from the original events-only `.home-upcoming` once the News
   teaser was added alongside it. */
.home-teasers {
    background-color: var(--kleo-bg-muted);
    padding: 40px 0;
}

.home-teasers__inner {
    max-width: 980px;
    margin: 0 auto;
    /* On request (2026-09-29): same horizontal padding as an ordinary
       content block's own "Content padding: Default" option
       (`p-content-default`, `.ci-content` - see `content_block_defaults`
       in config/packages/simpl_cms.yaml) - 2rem, the exact value
       `$cc-padding-default` compiles to. News/Diary sit outside the
       `.cc-zone`/`.ci-content` chain entirely (their own dedicated
       `.home-teasers` section, not a content block), so they never
       picked this up automatically the way ordinary page content now
       does. */
    padding-left: 2rem;
    padding-right: 2rem;
}

.home-teasers__row + .home-teasers__row {
    margin-top: 40px;
}

/* Query container for .home-teasers__cards's own 3-vs-2-per-row
   `@container` rule below - same reasoning/same real browser
   constraint as `.diary`'s own identical addition (see that rule's own
   comment): has to be a real ancestor, not the grid itself. No
   horizontal padding of its own on this element, so its content-box
   width already matches `.home-teasers__cards`'s own available width. */
.home-teasers__row {
    container-type: inline-size;
}

/* Real heading bug, same follow-up: live's real "News"/"Diary" headings
   are genuine `<h1>` tags (confirmed via computed style - color
   rgb(163,0,96)/60px, matching `.main h1`/`.news h1`/`.diary h1` -  the
   same magenta/60px treatment as "Welcome" and every other page's own
   h1, not the grey/24px `<h2>` this template originally guessed at).
   Scoped to `.home-teasers h1` rather than relying on the generic
   `.cc-zone--content .ci--text-content h1` rule, since these two
   headings sit outside that zone's own DOM. */
.home-teasers h1 {
    color: #a30060;
    font-size: 6rem;
    margin-bottom: 20px;
}

.home-teasers__row-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
}

.home-teasers__row-header h1 {
    margin-bottom: 0;
}

/* On request (2026-09-29): the rightmost card in each row wasn't flush
   with the container's own right edge. First tried flexbox (`flex-wrap`
   + `gap` + `justify-content: space-between`) - fixed the flush-edge
   problem (checked the real numbers: 3 fixed-290px cards + 2x20px gaps
   only fill 910px of the ~940-980px actually available, a genuine
   shortfall plain `gap` alone can't close) but introduced a real,
   different regression once widened to "all cards across the entire
   site" and checked against every real page, not just the two originally
   fixed: flexbox's `justify-content` distributes space independently
   *per wrapped line*, so a genuinely incomplete final row (found live -
   /gallery has 23 cards, 3 per row, a real trailing row of exactly 2)
   got spread across the FULL row width same as a complete one - two
   cards pinned to the far left and far right with a large, empty,
   clearly-unintentional-looking gap between them, confirmed via a real
   screenshot, not just guessed as a theoretical edge case.

   Fixed properly with CSS Grid instead of a flexbox patch - Grid's
   columns are real, shared tracks defined ONCE for the whole grid, not
   re-computed per row the way flex's per-line justify-content is.
   `repeat(auto-fill, 290px)` (not a hardcoded `repeat(3, ...)`) means
   the column count adapts automatically to however many 290px cards
   actually fit the container's own current width, responsive reflow
   included, rather than assuming "3 per row" is a fixed constant
   anywhere.

   `justify-content` on that shared track set went through three real
   states, not settled on first try. (1) `space-between` (matching the
   original "flush right edge" ask) correctly fixed 3-per-row and left
   an incomplete last row of 2 sensibly left-aligned (see above) - but
   reported back as looking wrong at the *responsive* 2-per-row case
   (the viewport narrow enough that `auto-fill` itself only computes 2
   columns, not 3-with-a-short-last-row): `space-between` doesn't know
   the difference between "an incomplete row" and "this is just how many
   columns fit now" - it pins EVERY row's 2 cards to the two far edges
   with a large gap between them, at every row, not just a trailing one.
   (2) Switched to `justify-content: center` unconditionally - fixed
   2-per-row (centres the whole set of tracks as one block, with only
   the explicit `gap` between items, no stretching to fill) but this
   itself was then reported as a regression at 3-per-row, which was
   never supposed to change at all - its own flush left/right edges no
   longer lined up with `.home-teasers`'s own "News" heading/"What's
   on?" button beside it. (3) Fixed properly by making the two states
   conditional on the grid's own real width instead of picking one
   value for all cases - see the `container-type`/`@container` rules
   themselves, directly below, for how.

   Every real card grid funnels through one of exactly three containers
   (checked via a full template grep, not assumed): this teaser,
   `.diary-list` (`/diary`), and `.sh-collection` (vendor's own shared
   Collection-block wrapper - every brand's own Events/News page,
   Gallery, Producers, all render through this one class). `.event-card`
   itself lost its own base `margin` entirely once this covered every
   real usage - a second, card-level margin alongside this `gap` was
   never needed once nothing was left relying on it. */
.home-teasers__cards,
.diary-list,
.sh-collection {
    display: grid;
    grid-template-columns: repeat(auto-fill, 290px);
    justify-content: space-between;
    gap: 20px;
}

/* `.sh-collection-intro` (2026-10-05) - the vendor's own `cc_content_item_
   collection.html.twig` already renders a Collection block's "Intro"
   CKEditor field (if an editor fills one in) directly above the card
   grid, wrapped in this class - previously unstyled anywhere on this
   site, since no real Collection block had ever used it. Used now for
   the brand hub pages' own real "News"/"Diary" headings (see CLAUDE.md
   - these replaced a bespoke controller/template pair with ordinary,
   admin-editable Collection blocks, each with its own real intro text
   doing the heading's job instead of a hardcoded <h1> in a site-owned
   template). `h1` styled to match every other real section heading on
   this site (`.home-teasers h1`, `.cc-zone--content .ci--text-content
   h1` - same magenta/60px values, not a separately-invented size), and
   `.btn-pill` (the CKEditor "button" style, already matching `.button`
   exactly - see that style's own CLAUDE.md section) given a touch of
   top margin so it doesn't sit flush against the heading above it. */
.sh-collection-intro h1 {
    color: #a30060;
    font-size: 6rem;
    margin-bottom: 20px;
}

.sh-collection-intro .btn-pill {
    margin-top: 10px;
}

/* Real regression reported same day: switching this rule's own
   `justify-content` to `center` (see the entry above) also moved the
   3-per-row case, which was never supposed to change - its own flush
   left/right edges no longer lined up with the "News" heading/"What's
   on?" button beside it. `justify-content` can only ever be one value
   at a time, and a plain viewport `@media` query would have to
   separately guess the exact breakpoint for each of this rule's three
   different real contexts (this teaser's own padding, `.diary`'s,
   `.ci-content`'s) - fragile, and wrong the moment any of those
   paddings change independently.

   `@container` instead responds to the grid's own real, current width
   directly - correct in all three contexts with one query, no guessed
   pixel breakpoint copied three times. Confirmed via an isolated test
   page before trusting it in the real site, not assumed: an element
   querying its OWN width for its OWN `justify-content` silently never
   matched in this browser (self-referencing container queries aren't
   supported here the way descendant ones are) - `container-type:
   inline-size` has to sit on a real ANCESTOR of the grid instead
   (`.home-teasers__row`/`.diary`/`.ci-content`, each right above this
   entry - see their own comments), with this rule targeting the grid
   as a descendant of whichever one applies.

   910px = 3 cards at 290px + 2 gaps at 20px (3*290 + 2*20) - the exact
   width below which a third column genuinely can't fit any more and
   `auto-fill` itself drops to 2. Only below that point does the
   "centred, consistent gap" fix from the entry above apply - at 3-per-
   row (910px+) `justify-content` stays the original `space-between`
   from before that fix, so the flush left/right edges this was
   reported to have broken are back to lining up with `.home-teasers`'s
   own "News" heading/"What's on?" button exactly as they did before. */
@container (max-width: 909.98px) {
    .home-teasers__cards,
    .diary-list,
    .sh-collection {
        justify-content: center;
    }
}

/* Generic button component - matches the legacy site's own `button,
   .button, input[type=submit]` rule exactly. Never built as a reusable
   class until now (full-comparison pass, 2026-09-28) - the Diary
   teaser's own real "What's on?" button is the first thing on this site
   to need it, but any future one can reuse this class directly rather
   than each inventing its own button styling.

   `.btn-pill` added to the same selector (2026-09-29, on request - "can
   the button style please replicate buttons elsewhere on the site") -
   `btn-pill` is the class CKEditor's own "button" Styles-dropdown entry
   (config/packages/fos_ckeditor.yaml's `cc_styles`) outputs onto an
   `<a>`, and it had never had any CSS at all before this (confirmed via
   grep), rendering as a plain unstyled link. Added directly to this
   rule's own selector list, not duplicated as a second copy - the two
   are meant to look identical, so one rule keeping them in sync is
   correct, not two that could independently drift the way the earlier
   per-brand-tinting bug did (see CLAUDE.md's own "systemic... tinting
   bug" section) - a future change to this site's real button styling
   updates both at once automatically. */
.button,
.btn-pill {
    display: inline-block;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    color: #fff;
    text-align: center;
    background-color: var(--kleo-link);
    cursor: pointer;
    border: 0 none;
    text-decoration: none;
    font-size: 1.8rem;
    line-height: 1;
    padding: 1.2rem 3rem 0.7rem;
}

/* Matches live exactly - `.button:hover { color: #ffffff; }` only, no
   background change (this rule's whole job is stopping the generic
   `a:hover` colour swap from applying here, not adding a new effect). */
.button:hover,
.btn-pill:hover {
    color: #fff;
}

/* Secondary nav row (App\Controller\FrontendController::getSecondaryNav(),
   rendered in templates/header/default_header.html.twig) - matches the
   legacy site's own `.headline nav a` rule (centred, divider between
   items, plain black text) rather than the bolder/coloured primary nav
   above it. */
.kleo-subnav {
    background-color: var(--kleo-bg-muted);
    text-align: center;
}

.kleo-subnav__inner {
    max-width: 980px;
    margin: 0 auto;
}

/* On request (2026-09-29): no text-colour hover, a yellow underline
   matching the primary nav's own `.kleo-nav a:hover`/`li.current`
   treatment instead (same 8px `#ffb000` border, same "also shown when
   this item is the current page" idea - see `current` on `item` above,
   set in FrontendController::getSecondaryNav()).

   Vertical dividers between items reinstated (2026-10-05, on request -
   "as with the live site") - the original divider rule (this same
   selector) was removed on an earlier, separate request the same day
   this underline treatment was added ("remove... the left/right
   dividers... the underline itself is enough separation"); re-checked
   live's own real stylesheet this time rather than reconstructing from
   memory - its `.headline nav a` rule genuinely does carry both a
   divider AND the same plain-black/no-hover-colour treatment already
   matched here, so this isn't a contradiction of that earlier call,
   just a correction of it.

   First attempt (a plain `border-right` on the `<a>` itself) was a real
   regression, caught via a real screenshot and fixed same day ("those
   dividers look very off") - live's own link has almost no vertical
   padding (`padding: 2px 10px 0 10px`), so its own `border-right` only
   ever spans a slim, text-height line. This link's own box is much
   taller (12px/8px padding plus an 8px `border-bottom` permanently
   reserved for the amber-underline mechanic, a treatment live doesn't
   have at all) - a plain `border-right` on it stretched the whole way
   down through that reserved space, reading as a tall, heavy bar
   filling almost the entire subnav row rather than a slim divider next
   to the text. Fixed with a `::after` pseudo-element instead, sized and
   centred independently of the link's own padding/border-bottom. */
.kleo-subnav a {
    display: inline-block;
    position: relative;
    color: #000;
    font-family: 'Foco-Light', -apple-system, sans-serif;
    font-size: 1.9rem;
    /* padding-top = 1.5x padding-bottom (12px = 1.5 x 8px), on request. */
    padding: 12px 10px 8px;
    border-bottom: 8px solid transparent;
}

.kleo-subnav a:not(:last-of-type)::after {
    content: '';
    position: absolute;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    width: 1px;
    height: 1.9rem;
    background-color: #000;
}

.kleo-subnav a:hover,
.kleo-subnav a.current {
    color: #000;
    border-bottom-color: #ffb000;
}

/* Diary page (templates/diary/show.html.twig) - headline event box,
   brand filter pills, and the event grid (reuses .event-card, styled
   already above). */
.diary {
    max-width: 980px;
    margin: 0 auto;
    padding: 30px 0;
    /* Query container for .diary-list's own 3-vs-2-per-row `@container`
       rule (see that rule's own comment) - has to sit on a real
       ANCESTOR of the grid, not the grid itself (confirmed the hard
       way, via an isolated test page: a container querying its own
       width for its own `justify-content` silently never matches in
       this browser - self-referencing container queries aren't
       supported here the way descendant ones are). No horizontal
       padding of its own, so this element's content-box width already
       equals `.diary-list`'s own available width exactly. */
    container-type: inline-size;
}

.diary > h1 {
    color: #a30060;
    font-size: 6rem;
    margin-bottom: 20px;
}

/* `background-color: var(--kleo-bg-muted)` removed (2026-10-05, real bug
   report - "I've set the content background color for the headline
   event... but this is not showing correctly"). Root cause: this grey
   was a hardcoded stylesheet rule on `.diary-featured` itself, a
   descendant *inside* the content block's own `.ci-content` wrapper (the
   element the admin's real "Content background colour" field actually
   sets, as an inline style, via ContentBlockType's own contentBgColor -
   confirmed that field IS being applied correctly) - `.diary-featured`'s
   own opaque background simply painted over it, so no admin colour
   choice could ever show through on the headline-event specific block.
   Checked live's own real stylesheet before just deleting it, not
   assumed: `.headline article` (the real per-brand headline-event box)
   is `background-color: #ffffff` - white, never grey - a genuine,
   previously-unchecked mismatch (the grey here was carried over from
   this page's own earlier, separately-built Diary-page box, never
   verified against live's own real per-brand equivalent). Removing it
   outright fixes both real contexts at once: the Diary page's own
   cross-brand box now shows the page's own white background (matching
   live exactly), and the brand hub pages' own specific-block version now
   genuinely respects whatever "Content background colour" an editor
   picks via the admin, white included. */
.diary-featured {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    padding: 20px;
}

/* On request (2026-10-05, same day as the flexbox wrapping fix above) -
   "On mobile, needs to move beneath image": below this site's own
   standard mobile breakpoint (991.98px, matching the nav/header/hero
   text switches elsewhere in this file), the image and body no longer
   sit side-by-side at all - `flex-direction: column` stacks them in
   their real DOM order (image, then body) instead of relying on
   `flex-wrap` to decide when they're too cramped to share a row. The
   image's own `max-width: 300px` stays as-is rather than stretching
   full-width here - a deliberate, modest size that still reads clearly
   on a phone screen without needing a second, mobile-specific value. */
@media screen and (max-width: 991.98px) {
    .diary-featured {
        flex-direction: column;
    }
}

/* Matches live's own real `.headline.home/.news h1` + `.line-center`
   pair exactly (2026-10-05, on request - "style the 'Headline event'
   text, as with the live site") - confirmed via live's real stylesheet,
   not guessed: a real `<h1>` (not just a styled `<span>`, which this
   previously was) centred, uppercase, 2.4rem, the same light blue this
   project's own `--kleo-link-hover` already happened to match exactly
   (`#00adef`), with a full-width horizontal rule running behind it
   (`:after`, absolutely positioned, `z-index: -1`) and the text itself
   sitting on a white patch (`__label-text`, `z-index: 2` via the parent
   `h1`'s own stacking context) that breaks the line - the classic
   "text interrupting a divider" effect, not reproducible with the
   previous plain uppercase/letter-spaced label alone. */
.diary-featured__label {
    display: block;
    width: 100%;
    position: relative;
    z-index: 2;
    text-align: center;
    text-transform: uppercase;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    color: var(--kleo-link-hover);
    font-size: 2.4rem;
    margin: 0;
}

.diary-featured__label:after {
    content: '';
    position: absolute;
    top: 50%;
    left: 0;
    right: 0;
    border-top: 1px solid #e6e7e8;
    z-index: -1;
}

.diary-featured__label-text {
    display: inline-block;
    padding: 0 10px;
    background: #fff;
}

.diary-featured__image {
    width: 100%;
    max-width: 300px;
    height: auto;
    display: block;
}

/* Real bug found/fixed on request (2026-10-05 - "Headline event text
   needs to be to the right of the image at .../kinross-farmers-market")
   - a classic flexbox gotcha, confirmed via a real CDP measurement
   before guessing: this wasn't an image-sizing issue (both brands'
   images measured identically, 300x197 rendered either way).

   First fix tried, confirmed via the same CDP measurement NOT to work:
   `min-width: 0` alone. That's the usual fix for a flex item refusing
   to shrink *within an already-assigned line*, but it doesn't touch the
   earlier *line-breaking* decision itself - flexbox decides whether an
   item fits on the current line using its hypothetical (hashtag
   max-content) size, computed from its own unconstrained content width,
   before any shrinking is applied. `h2`'s own 4rem text ("Kinross
   Farmer's Market 24 October" is long enough to trigger this; "Ten
   Minute Tales" on the Winter Festival page wasn't) gave the body a
   huge hypothetical width, which alone was enough to push it onto a new
   line regardless of min-width.

   Real fix: `flex: 1 1 0%` gives the item an explicit, non-content-
   derived flex-basis of 0 - the line-breaking algorithm now sees "wants
   0, can grow" instead of "wants however wide its unwrapped text is",
   so it correctly stays on the image's own row and grows to fill the
   remaining space, with the `h2` text wrapping normally inside whatever
   width that ends up being. `min-width: 0` kept alongside it (now
   actually doing its originally-intended job, not fixing the real bug
   alone). */
.diary-featured__body {
    flex: 1 1 0%;
    min-width: 0;
}

.diary-featured__body h2 {
    color: #a30060;
    font-size: 4rem;
    margin-bottom: 10px;
}

.diary-featured__body time {
    display: block;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    color: var(--kleo-heading);
    margin-bottom: 10px;
}

.diary-featured__link {
    display: inline-block;
    background-color: var(--kleo-link);
    color: #fff;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    padding: 10px 20px;
}

.diary-featured__link:hover {
    color: #fff;
    background-color: var(--kleo-link-hover);
}

/* Per-brand tinting removed here too - see the note above
   `.event-card__date`'s own rule. Confirmed via a direct computed-style
   check against live's real Diary page: the "Headline event" label is
   always the fixed blue `--kleo-link-hover` (matching the base
   `.diary-featured__label` rule above), and the featured event's own
   title is always the fixed magenta `#a30060` (matching the base
   `.diary-featured__body h2` rule above) - a real Farmers' Market
   headline event still showed the magenta title, not KFM's green. */

.diary-filters {
    margin-bottom: 20px;
}

.diary-filters button {
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    color: #fff;
    background-color: #7f7f7f;
    border: 0;
    padding: 10px 20px;
    margin: 0 10px 10px 0;
    cursor: pointer;
}

.diary-filters button.is-active {
    background-color: var(--kleo-link);
}

.diary-filters button[data-filter="kleo"].is-active { background-color: var(--kleo-brand-kleo); }
.diary-filters button[data-filter="kwf"].is-active { background-color: var(--kleo-brand-kwf); }
.diary-filters button[data-filter="kfm"].is-active { background-color: var(--kleo-brand-kfm); }

/* `.diary-list` itself is now styled alongside `.home-teasers__cards`/
   `.sh-collection` (see that shared rule's own comment, above) - kept
   here only if it ever needs a rule of its own again. */

/* Gallery entry detail page (templates/gallery-entry/show.html.twig) -
   the photo grid itself (.ci-gallery) is styled by the vendor's own
   frontend.css, nothing needed here for that. */
.gallery-entry {
    max-width: 980px;
    margin: 0 auto;
    padding: 30px 0;
}

.gallery-entry > h1 {
    color: #a30060;
    font-size: 6rem;
    margin-bottom: 20px;
}

.gallery-entry__video {
    margin-bottom: 20px;
}

/* News detail page (templates/news/show.html.twig). */
.news-detail {
    max-width: 980px;
    margin: 0 auto;
    padding: 30px 0;
}

/* Same real left/right-edge misalignment already fixed on the event
   detail page (2026-10-05, on request - "Similarly with news items" -
   see `.event-detail__header`'s own comment for the full reasoning):
   the body text below already carries the sitewide-standard 20px inset
   via `.ci-content.p-content-default`, this header (title/image/date)
   didn't - same `2rem` value, same fix. */
.news-detail__header {
    padding: 0 2rem;
}

.news-detail h1 {
    color: #a30060;
    font-size: 6rem;
    margin-bottom: 20px;
}

/* Per-brand tinting removed here too - see the note above
   `.event-card__date`'s own rule. Confirmed via a direct computed-style
   check against a real Farmers' Market news article on live (a real
   test, not the Winter Festival case where the brand colour and the
   generic magenta happen to be identical): the title is still plain
   magenta `#a30060` (matching the base `.news-detail h1` rule above),
   not KFM's own green. */

.news-detail__image {
    display: block;
    width: 100%;
    max-width: 600px;
    height: auto;
    margin-bottom: 20px;
}

.news-detail__date {
    display: block;
    font-family: 'Foco-Black', 'Arial Black', sans-serif;
    text-transform: uppercase;
    font-weight: bold;
    color: var(--kleo-heading);
    margin-bottom: 20px;
}

/* Repository content block (a "downloads list", e.g. Equipment Hire's
   real PDFs - see CLAUDE.md) - `.ci-repository` itself had no CSS at
   all on this site until now (the vendor template's own generic inline
   SVG download-arrow icon was rendering completely unstyled). The
   `<h2>` the vendor template now also renders (the block's own real
   "Title" field, a genuine rendering gap fixed the same day - see
   CLAUDE.md) needs no CSS of its own - it already matches live's real
   `section.uploads h2` exactly via the sitewide `h1,h2,h3.../h2` rules
   (Foco-Black, #7f7f7f, 2.4rem), confirmed before assuming so.

   Icon: live's own real equivalent (`section.uploads a`) uses a real
   image asset (`/assets/img/ui/download-image.png`, copied here
   verbatim - a 25x28px red document-with-arrow icon), not a generic
   inline SVG - on request ("add the icon for each downloadable, as on
   [live]"), the vendor's own SVG is hidden and replaced with that real
   asset as a background-image on the same `.ci-repository__icon` span,
   sized to the real file's own real dimensions rather than a guessed
   box. */
.ci-repository__icon svg {
    display: none;
}

/* On request (2026-10-05, same day) - "Icon should come before the
   document title, both horizontally centered" (matching live's own
   real layout: `section.uploads a { background: url(...) center left
   no-repeat; padding-left: 35px; }` - the icon pinned before the text,
   vertically centred against it). The vendor template's own markup
   order is fixed (icon last, inside `.ci-repository__content` alongside
   title/filesize) - rather than editing that shared vendor file just to
   reorder three `<span>`s for one site's own layout preference, this is
   done entirely with flexbox here: `.ci-repository__content` becomes a
   centred flex row, and `order: -1` moves the icon to the visual front
   without touching the underlying markup/DOM order at all. */
.ci-repository__content {
    display: flex;
    align-items: center;
    gap: 10px;
}

.ci-repository__icon {
    display: inline-block;
    order: -1;
    flex-shrink: 0;
    width: 25px;
    height: 28px;
    background: url('/img/ui/download-image.png') center / contain no-repeat;
}
