/*
Theme Name:         TSP
Theme URI:          https://www.alexjordan.co.uk
Description:        TSP, a bespoke WordPress Theme for The Skateparks Project by Alex Jordan.
Version:            2.0.10
Author:             Alex Jordan
Author URI:         https://www.alexjordan.co.uk
*/

/* CSS Document */

/*----------------------------------------------------------------------------*/
/* Fonts                                                                      */
/*                                                                            */
/* Source Sans 3, the current release of what was Source Sans Pro. Variable   */
/* rather than static: one 161KB file covers every weight from 200 to 900,    */
/* where the four static weights this theme uses would total 602KB.           */
/*                                                                            */
/* The italic file is declared but only downloaded on pages that actually     */
/* render italic text, so it costs nothing elsewhere.                         */
/*----------------------------------------------------------------------------*/

@font-face {
	font-family: 'Source Sans 3';
	font-style: normal;
	font-weight: 200 900;
	font-display: swap;
	src: url('assets/fonts/source-sans-3/SourceSans3VF-Upright.otf.woff2') format('woff2');
}

@font-face {
	font-family: 'Source Sans 3';
	font-style: italic;
	font-weight: 200 900;
	font-display: swap;
	src: url('assets/fonts/source-sans-3/SourceSans3VF-Italic.otf.woff2') format('woff2');
}

/*----------------------------------------------------------------------------*/
/* Reset                                                                      */
/*                                                                            */
/* Resets are applied by scope rather than by a fixed element list, so newly  */
/* introduced elements are covered without maintenance.                       */
/*----------------------------------------------------------------------------*/
 
/* --- Box model ------------------------------------------------------------ */
 
html { box-sizing: border-box; }
*, *::before, *::after { box-sizing: inherit; }
 
/* Inheriting rather than setting border-box directly lets a third-party
   widget opt its own subtree back to content-box with a single rule. */
 
/* --- Margin & padding ----------------------------------------------------- */
 
* { margin: 0; padding: 0; }
 
/* --- Document ------------------------------------------------------------- */
 
html {
	/* Stops iOS Safari inflating text when a phone rotates to landscape. */
	-webkit-text-size-adjust: 100%;
}
 
body {
	min-width: 320px;
	text-rendering: optimizeSpeed;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}
 
/* --- Sectioning ----------------------------------------------------------- */
 
article, aside, details, figcaption, figure, footer,
header, hgroup, main, menu, nav, section {
	display: block;
}
 
/* --- Hidden --------------------------------------------------------------- */
 
/* The UA stylesheet hides [hidden] elements, but an author rule beats the UA
   origin regardless of specificity, so the sectioning rule above and the media
   rule below both re-show anything carrying the attribute. That is why
   main.hidden in theme.js has never hidden anything, and why three components
   in the search panel each carry their own [hidden] patch.

   !important rather than leaning on the attribute selector's specificity:
   (0,1,0) does beat the type selectors, but not a class rule such as
   .search-busy{display:flex}. This settles it for every component, present and
   future. hidden states that the element is not in the document right now, so
   nothing should be overriding it. */
[hidden] { display: none !important; }
 
/* --- Typography ----------------------------------------------------------- */
 
/* Headings inherit the body font so the h1–h6 rules later in the stylesheet
   are the single source of size and weight. Without this they carry browser
   defaults, and any heading whose weight is not explicitly set renders bold. */
h1, h2, h3, h4, h5, h6 {
	font: inherit;
	text-wrap: balance;
}
 
/* Avoids a single orphaned word on the last line. Ignored where unsupported. */
p, li, figcaption {
	text-wrap: pretty;
}
 
b, strong { font-weight: bold; }
i, em { font-style: italic; }
 
a {
	color: inherit;
	text-decoration: none;
}
 
blockquote, q { quotes: none; }
blockquote::before, blockquote::after,
q::before, q::after { content: none; }
 
/* --- Lists ---------------------------------------------------------------- */
 
/* Scoped to navigation and UI lists so that prose lists keep their markers.
   Safari drops list semantics from any list with list-style: none, and stops
   announcing "list, N items". Add role="list" where that count is useful for
   deciding whether to read on — the county index, for example. Navigation
   lists are a destination hunt rather than a decision, so they are left as
   they are. */
nav ol, nav ul,
#header ul, #footer ul, .navigation ul, .tabs ul, .gallery ul {
	list-style: none;
}
 
/* --- Media ---------------------------------------------------------------- */
 
img, picture, video, canvas, svg, iframe, embed, object {
	display: block;
	max-width: 100%;
}
 
img, video { height: auto; }
 
/* --- Forms ---------------------------------------------------------------- */
 
/* Form controls take the browser's system font unless told otherwise. */
input, button, textarea, select {
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	border-radius: 0;
}
 
button {
	cursor: pointer;
	/* Safari centres button text without this. */
	text-align: inherit;
}
 
textarea { resize: vertical; }
 
/* Suppresses Firefox's red glow on invalid fields. */
:invalid { box-shadow: none; }
 
/* --- Tables --------------------------------------------------------------- */
 
table {
	border-collapse: collapse;
	border-spacing: 0;
}
 
/* Header cells default to bold and centred; inherit instead so table styling
   is governed in one place. */
th {
	font-weight: inherit;
	text-align: inherit;
}
 
/* --- Focus ---------------------------------------------------------------- */
 
/* :focus-visible shows the ring for keyboard navigation and suppresses it for
   pointer clicks. Removing focus indication entirely fails WCAG 2.4.7 and
   leaves icon buttons unreachable for keyboard users. */
:focus-visible {
	outline: 2px solid var(--teal);
	outline-offset: 2px;
}
 
:focus:not(:focus-visible) { outline: none; }
 
/* --- Motion --------------------------------------------------------------- */
 
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* Suppress transitions for a frame. Used when an accordion breakpoint is
   crossed and the panel would otherwise animate as though a button had been
   pressed. !important because it has to beat the transition declared on the
   panel and on its list, wherever those rules happen to sit. */
.no-transition {transition:none !important;}

/*----------------------------------------------------------------------------*/
/* Default Styles
/*----------------------------------------------------------------------------*/

body {
    font-family: 'Source Sans 3', 'Source Sans Pro', system-ui, sans-serif;
	font-size:1rem;
	line-height:1.5rem;
	font-weight:400;
	color:rgb(74,74,73);
    min-width:320px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5, h6 {margin:0 0 20px 0;}
h1 {font-weight: bold;margin:0 0 30px 0;font-size:36px;line-height:45px;}
h2 {font-size:36px;line-height:41px;}
h3, h4, h5, h6 {font-size:16px;line-height:26px;}

p, span, a {font-size:1.2rem;line-height:1.6rem;color:#333;}

p {margin:0 0 1.25rem 0;}

/* Prose measure
   ----------------------------------------------------------------------------
   .wysiwyg is editor output — the WYSIWYG layout on page.php and the park
   finder, the content blocks on a news article, and the description at the top
   of a park profile. Its track runs to ~966px beside a sidebar and wider on the
   finder, past a comfortable line length.

   The cap sits on the prose block itself, not on .content or .wrap, so images,
   galleries, tab panels, pull quotes and the news hero keep the full column.
   Left-aligned, matching the site's float-left flow; ~46rem is close to 75
   characters at the 1.2rem body size. */

.wysiwyg {max-width:46rem;}

/* Prose lists
   ----------------------------------------------------------------------------
   Editor output only — .wysiwyg on page, parkfinder, news and park profiles,
   plus the FAQ answers. UI lists are excluded because they set their own box.

   The reset zeroes padding globally. With list-style-position at its default
   of outside, that leaves the marker rendering in the margin area beyond the
   content box, where it sits flush to the container edge or is clipped away.

   padding-left rather than margin-left: padding keeps the marker inside the
   box, so a two- or three-digit ordered marker still has room. margin would
   push it out past the container.

   li is absent from the p, span, a rule above, so without the size declared
   here a list renders smaller and lighter than the paragraph it follows. */

.wysiwyg ul,
.wysiwyg ol,
.faq .answer ul,
.faq .answer ol,
.sp-attributes ul,
.amenities ul {margin:0 0 1.25rem 0;padding:0 0 0 1.75rem;}

  .wysiwyg li,
  .faq .answer li,
  .sp-attributes li,
  .amenities li {font-size:1.2rem;line-height:1.6rem;color:#333;margin:0 0 0.5rem 0;}

  /* A nested list belongs to the item above it, so it takes the indent but not
     a fresh block of space — no margin-top, per the site convention. */

  .wysiwyg li > ul,
  .wysiwyg li > ol,
  .faq .answer li > ul,
  .faq .answer li > ol {margin:0;}

a{text-decoration:none;color:#333;cursor:pointer;}
a:hover{color:#333;text-decoration:none;}

/*----------------------------------------------------------------------------*/
/* Structure
/*----------------------------------------------------------------------------*/

.wrap{float:left;width:100%;}
.cont{display:flow-root;width:100%;min-width:320px;max-width:1366px;margin:0 auto;padding:0 30px;}

.flex{display:flex;}
.sidebar{flex: 0 0 300px;}
.content {flex:none;display:block;float:left;width:100%;}

/* Content and sidebar
   ----------------------------------------------------------------------------
   The shared two-column layout: the news article now, the park profile and
   park template when they move across. Grid rather than flex, because the
   column widths are a decision belonging to the container, and because a flex
   row cannot collapse to one column without redeclaring every child.

   One column until 1001px, the same breakpoint the card grids use. Above it
   the sidebar takes a fixed track and the content takes what is left.

   minmax(0, 1fr) rather than 1fr: a grid item's automatic minimum size is its
   content, so one wide table, <pre> or unbroken URL would push the content
   track past its share and squeeze the sidebar. The 0 floor removes that.

   Float does not apply to grid items, so .content's float:left above is
   computed away here and needs no override. */

.layout {
  display:grid;
  grid-template-columns:1fr;
  gap:40px;
  margin:0 0 50px 0;
}

@media screen and (min-width: 1001px){

  .layout {grid-template-columns:minmax(0, 1fr) 300px;}

}

/* 404 has no sidebar, so no .layout wrapper to carry the space the shared
   two-column templates get below their content. An error page is short, so it
   gets a deliberately generous gap to keep it from butting up against the
   footer. */
body.error404 .content {margin:0 0 100px 0;}

.column-left {float:left;width:50%;}
.column-right {float:right;width:50%;}
.column-left .container {float:right;width:100%;max-width:683px;padding:0 0 0 30px;}
.column-right .container {float:left;width:100%;max-width:683px;padding:0 30px 0 150px;}

main {width:100%;background:#FFF;padding:0;}
main > .cont > .wrap {background:#FFF;}

/* overflow:hidden propagates to the viewport and locks scrolling in place.
   position:fixed would collapse body to the viewport and lose the scroll
   position, jumping the page to the top. */
.noscroll {overflow:hidden;}

/* Available to assistive technology and keyboard focus, but not painted. */
.visually-hidden {position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;}

/* Skip link
   ----------------------------------------------------------------------------
   First in the tab order, so a keyboard user is not walked through the header
   and menu on every page. It shares .visually-hidden rather than repeating it,
   and only the focused state is defined here.

   It stays out of flow in both states, which matters more than it looks: body
   is a grid whose four rows are all explicitly assigned, so a flow-level child
   would be auto-placed into an implicit fifth row and appear below the footer.
   Absolutely and fixed positioned children of a grid container take no part in
   placement, so it cannot disturb the rows.

   :focus rather than :focus-visible, because the link is unpainted until
   focused — focus arriving any other way would leave it holding focus while
   still invisible. */

.skip-link:focus {
  position:fixed;
  top:0;
  left:0;
  z-index:10000;
  width:auto;
  height:auto;
  margin:0;
  padding:12px 20px;
  overflow:visible;
  clip-path:none;
  background:var(--teal);
  color:#FFF;
  font-size:1.2rem;
  line-height:1.6rem;
  border-bottom-right-radius:8px;
}

  /* The global ring is teal, invisible on this background. Same treatment as
     the search submit and the footer links. */
  .skip-link:focus-visible {outline-color:#FFF;outline-offset:-4px;}

/* theme.js sets #main inert while the menu overlay is open and hidden while
   search results are showing. Focus sent to either fails silently, so the link
   goes with it rather than sitting in the tab order as a dead control.
   syncMainReachable() maintains the class. */
body.main-unreachable .skip-link {display:none;}

:root {
  --header-h: 83px;

  /* rgb(0,161,156) was 3.19:1 against white and failed 1.4.3 for anything
     under 24px. The scale now starts one step down. Each token is at least
     4.5:1 on white and 4:1 on the #EFEFEF search panel, so any of the three
     can carry small text in either direction. */
  --teal:        rgb(0, 130, 125);  /* 4.68:1 — default */
  --teal-dark:   rgb(0, 110, 106);  /* 6.11:1 — hover, current page */
  --teal-darker: rgb(0,  94,  91);  /* 7.63:1 — hover for fills on grey */
}

body {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-rows: auto auto 1fr auto;
}

#header     { grid-row: 1; }
#searchform { grid-row: 2; }
#main       { grid-row: 3; }
#footer     { grid-row: 4; }

/* Tall enough: header leaves the flow, content passes beneath it */
@media (min-height: 600px) {
  html {scroll-padding-top: calc(var(--header-h) + 1rem);}
  #header { position: fixed; top: 0; right: 0; left: 0; z-index: 100; }
  body { padding-top: var(--header-h); }
  [id] { scroll-margin-top: calc(var(--header-h) + 1rem); }
}


/*----------------------------------------------------------------------------*/
/* header
/*----------------------------------------------------------------------------*/

#header {height:83px;width:100%;border-top:var(--teal) 3px solid;background:#FFF;-webkit-box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.24);-moz-box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.24);box-shadow: 0px 2px 8px 0px rgba(0,0,0,0.24);z-index:9999;}

#header .header-content {padding:5px 0;text-align:center;}

/* Header Menu */

#header nav {display:none;float:right;height:32px;margin:0;padding:19px 0;}

/* Below 900px the same markup becomes a full-height overlay, opened and closed
   by the one button. overscroll-behavior stops scrolling past the end of the
   menu from chaining to the page underneath. */
#header nav.is-open {display:block;position:fixed;top:var(--header-h);right:0;bottom:0;left:0;height:auto;float:none;padding:0 30px;background:#FFF;z-index:998;overflow-y:auto;overscroll-behavior:contain;}

#header nav.is-open ul {height:auto;padding:6px 0;}
#header nav.is-open ul > li {display:block;padding:0;border-bottom:#EEE 1px solid;}
#header nav.is-open ul > li:first-child {border-top:#EEE 1px solid;}
#header nav.is-open ul > li a {display:block;padding:15px 0;text-align:left;}

/* Pins the header while the overlay is open, so the close button stays
   reachable and the overlay's top offset stays correct on short viewports
   where the header is not otherwise fixed. */
body.noscroll #header {position:fixed;top:0;right:0;left:0;}
#header ul {list-style:none;margin:0;height:32px;}
#header ul > li {display:inline-block;padding:0 15px;}
#header ul > li a {font-size:22px;line-height:32px;color:rgb(74,74,73);transition: color, 0.3s;}
#header ul > li a:hover {color:var(--teal-dark);}
#header ul > li > a[aria-current="page"] {color:var(--teal-dark);border-bottom:var(--teal-dark) 2px solid;padding-bottom:4px;}
#header nav.is-open ul > li > a[aria-current="page"] {border-bottom:none;border-left:var(--teal-dark) 4px solid;padding-left:12px;}


/* Search Button */

#search {float:right;width:48px;height:48px;padding:12px;margin:11px 0;border-radius:5px;background:var(--teal);transition:background,0.3s;z-index:99999;position:relative;}

#search:hover,
#search.is-open {background:rgb(74,74,73);}

#search .icon-close {display:none;}
#search.is-open .icon-search {display:none;}
#search.is-open .icon-close {display:block;}


#header .logo,
#header .logo img {width:70px;height:70px;display:inline-block;}
#header .logo a {display:block;width:70px;height:70px;}

/* --- Menu Hamburger Button ------------------------------------------------ */

#menu-button {float:left;width:48px;height:48px;padding:12px;margin:11px 0;border-radius:5px;background:var(--teal);transition:background 0.3s;}

#menu-button:hover,
#menu-button.is-active {background:rgb(74,74,73);}

/* 24x24 box fills the button's content area; the three bars are absolutely
   positioned against it. margin-top is half the bar height, to centre it. */
.hamburger-box {width:24px;height:24px;display:block;position:relative;}
.hamburger-inner {display:block;top:50%;margin-top:-1px;}
.hamburger-inner,
.hamburger-inner::before,
.hamburger-inner::after {width:24px;height:2px;background-color:#FFF;border-radius:4px;position:absolute;transition-property:transform;transition-duration:0.15s;transition-timing-function:ease;}

.hamburger-inner::before,
.hamburger-inner::after {content:"";display:block;}
.hamburger-inner::before {top:-7px;}
.hamburger-inner::after {bottom:-7px;}

/* Squeeze: top bar fades, bottom bar rotates up, middle bar rotates to form
   the cross. Only transform and opacity animate, so this stays on the
   compositor. Delays stagger the two halves into a single motion. */
.hamburger--squeeze .hamburger-inner {transition-duration:0.075s;transition-timing-function:cubic-bezier(0.55, 0.055, 0.675, 0.19);}
.hamburger--squeeze .hamburger-inner::before {transition:top 0.075s 0.12s ease, opacity 0.075s ease;}
.hamburger--squeeze .hamburger-inner::after {transition:bottom 0.075s 0.12s ease, transform 0.075s cubic-bezier(0.55, 0.055, 0.675, 0.19);}

.hamburger--squeeze.is-active .hamburger-inner {transform:rotate(45deg);transition-delay:0.12s;transition-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);}
.hamburger--squeeze.is-active .hamburger-inner::before {top:0;opacity:0;transition:top 0.075s ease, opacity 0.075s 0.12s ease;}
.hamburger--squeeze.is-active .hamburger-inner::after {bottom:0;transform:rotate(-90deg);transition:bottom 0.075s ease, transform 0.075s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);}


@media (min-width: 900px){
    #header .logo {float:left;}
    #header nav,
    #header nav.is-open {display:inline-block;position:static;float:right;height:32px;padding:19px 0;background:none;overflow:visible;}
    #menu-button {display:none;}
    #header nav li.mobile-only {display:none;}
}

/*----------------------------------------------------------------------------*/
/* Header Search (new site)
/*----------------------------------------------------------------------------*/

#searchform {display:grid;grid-template-rows:0fr;background:#EFEFEF;box-shadow:0px 2px 8px 0px rgba(0,0,0,0.24);transition:grid-template-rows 250ms ease;z-index:1;}
#searchform.is-open {grid-template-rows:1fr;}

/* Delay on the way out, none on the way in. Opening flips to visible in the
   same frame as the class, so script can focus the input immediately; closing
   holds visible for the 250ms the row takes to collapse, so the controls do
   not vanish mid-animation. Transitioning visibility in both directions left
   it computed as hidden for the first frame, and a hidden element cannot take
   focus. */
#searchform > .cont {overflow:hidden;min-height:0;visibility:hidden;transition:visibility 0s linear 250ms;}
#searchform.is-open > .cont {visibility:visible;transition-delay:0s;}

#searchform .wrap {display:flex;flex-direction:column;align-items:center;gap:20px;padding:25px 0;text-align:center;}

#searchform .searchform-title {font-size:1.6rem;line-height:2rem;font-weight:bold;margin:0;}
#searchform .searchform-intro {margin:0;}
#searchform .searchform-or {margin:0;}
#searchform .alert {margin:0;}

#locationsearchform {position:relative;width:100%;max-width:600px;}
#locationsearchinput {width:100%;height:56px;padding:0 68px 0 15px;font-size:1.2rem;line-height:1.6rem;color:rgb(74,74,73);background:#FFF;border:rgb(88, 86, 87) 2px solid;border-radius:5px;}
#locationsearchinput::placeholder {color:#767676;opacity:1;}

#locationsearchsubmit {position:absolute;top:4px;right:4px;width:56px;height:48px;display:flex;align-items:center;justify-content:center;color:#FFF;background:var(--teal);border-radius:3px;cursor:pointer;transition:background 0.3s;}
#locationsearchsubmit:focus-visible {outline-color:#FFF;outline-offset:-4px;}
#locationsearchsubmit:hover {background:var(--teal-dark);}

/* Secondary action, so outlined rather than filled. */
#searchform #location {display:inline-flex;align-items:center;gap:8px;height:56px;padding:0 20px;font-size:1.2rem;color:rgb(74,74,73);background:none;border:rgb(88, 86, 87) 2px solid;border-radius:5px;cursor:pointer;transition:background 0.3s, color 0.3s;}
#searchform #location:hover {background:rgb(88, 86, 87);color:#FFF;}


/* --- Search results ------------------------------------------------------- */

#searchform .search-busy {display:flex;align-items:center;justify-content:center;gap:10px;}

.search-spinner {width:22px;height:22px;border:3px solid rgba(0,0,0,0.15);border-top-color:var(--teal);border-radius:50%;animation:tsp-spin 0.8s linear infinite;}
@keyframes tsp-spin { to { transform:rotate(360deg); } }

#searchform .search-results {width:100%;text-align:left;border-top:rgba(0,0,0,0.15) 1px solid;padding-top:20px;}

/* Shorter on a phone so the first results sit above the fold. */
#searchform #map {width:100%;height:280px;margin:0 0 20px 0;background:#DDD;border:rgba(0,0,0,0.15) 1px solid;border-radius:5px;}

/* Google sizes its attribution and controls in fixed-height boxes and relies
   on the browser's default line-height. The theme's global 1.6rem line-height
   on p, span and a overflows those boxes and clips the copyright text. */
#map, #map *,
.general-map, .general-map * {line-height:normal;}

#searchform .search-summary {margin:0 0 20px 0;font-weight:bold;}
@media (max-height: 599px) {
    #searchform .search-summary {scroll-margin-top:15px;}
}

/* Card rules live under "Park cards", shared with the county archive. This
   list only overrides its own spacing — tighter than the archive because the
   panel is a scrolling overlay rather than a page. */
#searchform .search-list {gap:20px;margin:0;}

/* The only action at the foot of the results, so it takes the filled
   treatment rather than the outlined grey it had. Same darker teal as
   #finderlocation: both are fills sitting on the #EFEFEF panel, and the
   extra step keeps them distinct from it. Contrast is no longer the
   reason — white on var(--teal) is 4.68:1 and would pass here.

   display:flex does two jobs here. It makes the button a block-level box so
   the auto margins actually centre it — margin:auto does nothing to a
   button's default inline-block, which is why this has been sitting left all
   along — and it centres the label, which the reset's
   button{text-align:inherit} was pulling left from .search-results.

   min-height rather than height so a long label wraps instead of spilling:
   "Show all 128 skateparks" is close to the limit at 320px. */
#searchform .search-more {display:flex;align-items:center;justify-content:center;width:100%;max-width:320px;min-height:56px;margin:30px auto 0 auto;padding:10px 20px;font-size:1.2rem;line-height:1.6rem;color:#FFF;background:var(--teal-dark);border:0;border-radius:5px;cursor:pointer;transition:background 0.3s;}
#searchform .search-more:hover {background:var(--teal-darker);}
#searchform .search-more:focus-visible {outline-color:#FFF;}

/* Second way out, for when the reader has scrolled past the header. */
#searchform .search-close {display:inline-flex;align-items:center;gap:8px;height:48px;padding:0 20px;font-size:1.2rem;color:rgb(74,74,73);background:none;border:0;cursor:pointer;}
#searchform .search-close:hover {text-decoration:underline;}


/*----------------------------------------------------------------------------*/
/* Header Search (from old site)
/*----------------------------------------------------------------------------*/

.search {width:100%;background-color:#EFEFEF;border-bottom:2px solid #585657;padding:40px 0;}
.search h3 {text-align:center;font-size:27px;line-height:34px;}
.search span {float:left;width:100%;text-align:center;font-size:18px;line-height:22px;}


section.search {
  float:left;
  z-index:99;
}


#loading{
  margin-top:0;
  margin-bottom:20px;
}


/*----------------------------------------------------------------------------*/
/* Admin Bar
/*----------------------------------------------------------------------------*/

#edit {padding:10px;border:#EEE 1px solid;border-radius:5px;margin:0 0 20px 0;}
#edit span {display:block;}
#edit a {color:var(--teal);font-weight:bold;}


/*----------------------------------------------------------------------------*/
/* Breadcrumbs
/*----------------------------------------------------------------------------*/

/* Owns its own vertical space, top and bottom equal. Whatever follows adds
   no top margin of its own, so the gap either side of the trail stays the
   same wherever the component is used. */
#breadcrumbs {
	margin:30px 0;
	padding:0;
}
#breadcrumbs ol {
	display:flex;
	flex-wrap:wrap;
	align-items:baseline;
	margin:0;
	padding:0;
	list-style:none;
}

#breadcrumbs ol > li {
	font-size:1rem;
	line-height:1.5rem;
	text-transform:capitalize;
}

#breadcrumbs ol > li a {
		font-size: 1rem;
        line-height: 1.5rem;
	}

#breadcrumbs ol > li a {color:var(--teal);}
#breadcrumbs ol > li a:hover {text-decoration:underline;}

#breadcrumbs ol > li::after {
    content: "/";
    color: #CCC;
    margin: 0 8px;
    position: relative;
    top: 1px;
	}
#breadcrumbs ol > li:last-child::after {
    content: " ";
    margin: 0;
	}
#breadcrumbs ol > li.current {
        cursor: default;
	}

/*----------------------------------------------------------------------------*/
/* Parkfinder Template (templates/parkfinder.php)
/*----------------------------------------------------------------------------*/

/* Header Section */

/* The page's primary function rather than a navigation affordance, so it is
   full-bleed dark with the h1 inside. Structure mirrors #searchform: the
   panel and this block are the same control set in two places. */

.finder-head {
	background:rgb(88, 86, 87);
	margin:0 0 40px 0;
}

.finder-head .wrap {
	float:none;
    display:flex;
	flex-direction:column;
	align-items:center;
	gap:20px;
	padding:50px 0;
	text-align:center;
}

.finder-head .finder-title {
	color:#FFF;
	margin:0;
}

.finder-head .finder-intro,
.finder-head .finder-or {
	color:#FFF;
	margin:0;
}

#finderform {position:relative;width:100%;max-width:600px;}

#finderinput {width:100%;height:56px;padding:0 68px 0 15px;font-size:1.2rem;line-height:1.6rem;color:rgb(74,74,73);background:#FFF;border:0;border-radius:5px;}
#finderinput::placeholder {color:#767676;opacity:1;}

#findersubmit {position:absolute;top:4px;right:4px;width:56px;height:48px;display:flex;align-items:center;justify-content:center;color:#FFF;background:var(--teal);border-radius:3px;cursor:pointer;transition:background 0.3s;}
#findersubmit:focus-visible {outline-color:#FFF;outline-offset:-4px;}
#findersubmit:hover {background:var(--teal-dark);}

/* Filled rather than outlined, to bring some colour onto the grey. The darker
   teal separates the fill from the #EFEFEF panel behind it — var(--teal) would
   clear 4.5:1 for the label on its own, so this is hierarchy rather than
   contrast. */
#finderlocation {display:inline-flex;align-items:center;gap:8px;height:56px;padding:0 20px;font-size:1.2rem;color:#FFF;background:var(--teal-dark);border:0;border-radius:5px;cursor:pointer;transition:background 0.3s;}
#finderlocation:hover {background:var(--teal-darker);}
#finderlocation:focus-visible {outline-color:#FFF;}

/* Category List */

/* Wraps the set of county groups so the block can be spaced from whatever
   follows, and so the run of border-tops has something to close against. */
#finder .menu-list-group {
	float:left;
	width:100%;
	margin:0 0 60px 0;
}

#finder .menu-list-group-title {
	margin:10px 0 30px 0;
}

/* On mobile the closed headings stack into a navigation list. No padding here,
   so the only vertical space is the button's own — which keeps the gap above
   and below each label equal and the dividing lines evenly spaced. The
   min-width block below restores the padding for the expanded layout. */
#finder div.menu-list {
	float:left;
	width:100%;
	border-top:#DCDCDC 1px solid;
}

/* Below the breakpoint each county group collapses behind its heading. The
   button sits inside the h3 rather than replacing it, so the group stays
   reachable by heading navigation while the control is a real button.

   .list-wrap is a BFC root and may not overlap a float's margin box, so the
   heading must not be a float. It no longer is globally, but the constraint
   is worth recording. */

#finder .menu-list-title {
	font-size:1.375rem;
	line-height:1.75rem;
	font-weight:bold;
	margin:0;
}

#finder .menu-list-title button {
	display:flex;
	align-items:center;
	justify-content:space-between;
	gap:10px;
	width:100%;
	font:inherit;
	color:inherit;
	text-align:left;
	padding:15px 0;
	background:none;
	cursor:pointer;
	-webkit-tap-highlight-color:transparent;
}

/* Masked rather than a background image, so the icon takes its colour from
   the text and one asset serves both the dark footer and the white finder. */
#finder .menu-list-title button::after {
	content:"";
	flex:0 0 20px;
	height:20px;
	background-color:currentColor;
	-webkit-mask:url('assets/icons/tsp-down-arrow.svg') no-repeat center / 20px 20px;
	        mask:url('assets/icons/tsp-down-arrow.svg') no-repeat center / 20px 20px;
}

#finder .menu-list-title button.icon-close::after {
	-webkit-mask-image:url('assets/icons/tsp-close.svg');
	        mask-image:url('assets/icons/tsp-close.svg');
}

/* Same row mechanism as the footer nav. The state class sits on .list-wrap,
   which is what aria-controls already points at, so the JS needs to know
   nothing about the surrounding markup.

   Scoped to [id] because finder-list.php only gives the panel an id when the
   section has a title — and with no title there is no heading and no button,
   so an untitled panel has no way to be opened and must stay open. */
#finder .list-wrap[id] {display:grid;grid-template-rows:0fr;transition:grid-template-rows 200ms linear, margin 200ms linear;}
#finder .list-wrap[id].is-open {grid-template-rows:1fr;}
/* overflow:hidden is what actually collapses the panel — the grid row goes to
   0fr and this clips what no longer fits. It is deliberately not lifted in the
   min-width block below, because the closed state still needs it on a narrow
   window that is later widened. It also clips the focus ring on the outer
   columns, which the horizontal padding further down pays for. */
#finder .list-wrap[id] > ul {min-height:0;overflow:hidden;visibility:hidden;transition:visibility 200ms;}
#finder .list-wrap[id].is-open > ul {visibility:visible;}

@media (min-width: 550px) {
	#finder div.menu-list {padding:25px 0 60px 0;}
	#finder .menu-list-title {margin:0 0 25px 0;}
	#finder .menu-list-title button {padding:0;cursor:auto;}
	#finder .menu-list-title button::after {display:none;}
	#finder .list-wrap[id],
	#finder .list-wrap[id].is-open {grid-template-rows:1fr;transition:none;}
	#finder .list-wrap[id] > ul {visibility:visible;transition:none;}
}

/* One list, columned by the browser. column-width is a minimum rather than a
   fixed size, so the count follows the available space and collapses to a
   single full-width column on a phone with no media query. Items fill each
   column top to bottom before moving across, which is what an alphabetical
   index wants.

   The Lists reset strips markers from navigation and UI lists only, and these
   sit outside that scope, so list-style is cleared here. role="list" in the
   template keeps Safari announcing them as lists once the markers are gone.

   The 4px of horizontal padding is room for the focus ring, not indentation.
   The panel above clips with overflow:hidden, the links are display:block and
   so run the full column width, and the ring is drawn 4px outside the border
   box — 2px offset plus 2px width, per the :focus-visible rule. Without the
   padding that ring falls outside the clipping box on the first and last
   columns and is cut off. The matching negative margin puts the content box
   back where it was, so the column count and the text alignment do not move.
   Change one and change the other. */
#finder .list-wrap ul {
	columns:220px;
	column-gap:20px;
	margin:0 -4px;
	padding:0 4px;
	list-style:none;
}

#finder .list-wrap li {
	break-inside:avoid;
	padding:7px 0;
}

#finder .list-wrap li a {
	display:block;
	transition:color 0.3s;
}

#finder .list-wrap li a:hover,
#finder .list-wrap li a:focus-visible {
	color:var(--teal-dark);
	text-decoration:underline;
}

@media (max-width: 549px) {
	/* One column below the accordion breakpoint, so opening a panel never
	   reflows two columns of counties at once. This overrides the column-width
	   at line 703 rather than relying on the viewport happening to be narrow
	   enough — two columns otherwise start at 460px. */
	#finder .list-wrap ul {columns:auto;}
	#finder .menu-list-group {border-bottom:#DCDCDC 1px solid;}
    #finder .list-wrap {margin:0 0 15px 0;}
    #finder .list-wrap[id] {margin:0;}
    #finder .list-wrap[id].is-open {margin:0 0 15px 0;}
}


/*----------------------------------------------------------------------------*/
/* Skatepark Profile Page (single.php)
/*----------------------------------------------------------------------------*/

/* Selectors here are not type-qualified. The section wrappers on this page
   become <section> elements, and a div.-prefixed selector stops matching the
   moment the element changes — silently, with no error and no visible clue
   beyond the styling vanishing. The class alone survives the swap.

   a.external-button keeps its prefix: that class only ever sits on a link and
   no element change is planned for it. */

.tsp-description {float:left;width:100%;}



.open-map {float:left;width:100%;margin:20px 0 0 0;}
a.external-button {float:left;display:inline-block;padding:15px 20px;border-radius:3px;background:var(--teal);}
a.external-button span {float:left;display:inline-block;color:#FFF;font-weight:bold;font-size: 1.2rem;line-height: 1.5rem;}
a.external-button svg {float:left;display:inline-block;margin:3px 0 3px 5px;}

.sp-gallery,
.sp-attributes {float:left;width:100%;}

/* .tsp-description and .sp-attributes get their bottom space for free, from
   the margin-bottom already on the wysiwyg <p> / attributes <ul> inside them.
   .contacts has no such child, so it needs the same 1.25rem itself to keep
   the rhythm going into whatever section follows. */
.contacts {float:left;width:100%;margin:0 0 1.25rem 0;}

/* Major sections (own h2, boxed content) all open with the same 50px top
   padding rather than relying on the previous element's bottom margin — see
   .tsp-location / .tsp-gallery / .tsp-disclaimer below. .sp-amenities and
   .builder-section join that rhythm here. */
.sp-amenities {float:left;width:100%;padding:50px 0 0 0;}

.builder-section {
    float:left;width:100%;padding:50px 0 0 0;
  }
    .builder-section > .builder {
      float:left;width:100%;margin:0 0 20px 0;background:#F7f7F7;padding:25px;border-radius:5px;
    }
      .builder-section > .builder .logo {
        float:left;width:90px;height:90px;margin:0 20px 0 0;
      }
      .builder-section > .builder .builder-name {
        display:block;margin:0 0 5px 0;
      }
      /* --teal is 4.68:1 on white but only 4.36:1 on this card's #F7F7F7
         background, below AA at this size. --teal-dark is 5.70:1. */
      .builder-section > .builder .builder-link {
        display:block;color:var(--teal-dark);
      }
      .builder-section > .builder .builder-link:hover {
        text-decoration:underline;
      }


.tsp-location {float:left;width:100%;padding:50px 0 0 0;}
.tsp-location .tabs-tabs {float:left;width:100%;position:relative;margin:20px 0 -1px 0;z-index:1;}
.tsp-location .tabs-tabs button {float:left;font:inherit;color:inherit;padding:15px 20px;border:#EEE 1px solid;border-right:none;border-radius:0;background:#F7F7F7;text-align:center;cursor:pointer;-webkit-appearance:none;appearance:none;}
.tsp-location .tabs-tabs button.last {border-right:#EEE 1px solid;}
.tsp-location .tabs-tabs button[aria-selected="true"] {border-top:var(--teal) 1px solid;border-bottom:#FFF 1px solid;background:none;}
.tsp-location .tabs-tabs button:hover {background:#EEE;}
.tsp-location .tabs-tabs button[aria-selected="true"]:hover {background:none;cursor:auto;}
.tsp-location .tabs-tabs button span {float:left;display:block;width:100%;min-width:90px;text-align:center;font-size:1.2rem;line-height:1.4rem;}
.tsp-location .tabs-tabs button i {display:inline-block;width:30px;height:30px;overflow:hidden;}
.tsp-location .tabs-tabs button i svg {display:inline-block;width:30px;height:30px;margin:0;}

.tsp-location .tabs-content {display:none;float:left;width:100%;padding:40px 20px 30px 20px;margin:0 0 30px 0;border:#EEE 1px solid;}
.tsp-location .tabs-content.active {display:block;}
.tsp-location .tabs-content p {float:left;width:100%;margin:30px 0 0 0;}

/* The address panel opens with its <p> as the first child; the 30px top margin
   above is only meant to separate stacked paragraphs, not to pad the panel. */
.tsp-location .tabs-content p:first-child {margin-top:0;}


@media screen and (max-width: 600px){
    .tsp-location .tabs-tabs button {padding:15px 25px;}
    .tsp-location .tabs-tabs button span {position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;}
}


.tsp-gallery {float:left;width:100%;padding:50px 0 0 0;}
.gallery {float:left;width:100%;}
.gallery ul {list-style:none;margin:0 -10px 50px -10px;display: flex;flex-direction: row;flex-wrap: wrap;}
.gallery ul li {width:20%;padding:10px 10px 10px 10px;display:flex;}
.gallery ul li a {background:#333;border-radius:5px;overflow:hidden;}
.gallery ul li a img {transition: opacity 0.2s ease-in;}
.gallery ul li a:hover img {opacity:0.5;}


@media screen and (max-width: 1000px){
    .gallery ul li {width:25%;}
}
@media screen and (max-width: 800px){
    .gallery ul li {width:33.3%;}
}
@media screen and (max-width: 600px){
    .gallery ul li {width:50%;}
}

.tsp-disclaimer {float:left;width:100%;padding:50px 0 0 0;}


/*----------------------------------------------------------------------------*/
/* Skatepark Archive (category.php)
/*----------------------------------------------------------------------------*/

/* The header contents are plain blocks. The float:left;width:100% they used to
   carry did nothing block flow does not, and it would have forced a float:none
   override on the region list below. */

.park-archive .options {border-top:#CCC 1px solid;padding:20px 0;}

/* Standalone on a page layout. The archive gets its lower gap from the
   .options bar's 20px bottom padding as well as the container's own margin,
   and a page has no options bar — so the default carries the full 35px and
   the archive overrides it back down. */

.button-container {margin:0 0 35px 0;}

.park-archive .button-container {margin:0 0 15px 0;}

/* .park-button is the base class for archive and page controls alike. These
   were scoped to .park-archive, which is a class on the cont in category.php
   only — so the same button on a page layout got nothing. The graveyard link
   is an <a> rather than a button but already carries .park-button, so one
   selector covers both. */

.park-button {display:inline-block;padding:10px 20px;background:rgb(244, 244, 244);border-radius:3px;font-size:1rem;line-height:1.5rem;margin:5px 10px 5px 0;border:#CCC 1px solid;cursor:pointer;color:#333;}

.map-button {background:rgb(244, 244, 244) url('assets/icons/tsp-location.svg') no-repeat left 10px center;background-size:20px 20px;padding:10px 20px 10px 40px;}

.park-button.button-active {background-color:var(--teal);color:#FFF;}
/* Region navigation. Links to other archives rather than controls for this
   one, so they are outlined in the link colour instead of filled like the
   buttons. The reset already drops list markers inside nav. */

.park-archive .archive-regions {margin:0 0 40px 0;padding:0 0 20px 0;border-bottom:#CCC 1px solid;}

.park-archive .archive-regions p {margin:0 0 10px 0;font-weight:bold;}

.park-archive .archive-regions ul {display:flex;flex-wrap:wrap;gap:10px;}

.park-archive .archive-regions a {display:inline-block;padding:10px 14px;font-size:1rem;line-height:1.5rem;color:var(--teal);border:var(--teal) 1px solid;border-radius:3px;}

.park-archive .archive-regions a:hover,
.park-archive .archive-regions a:focus-visible {background:var(--teal);color:#FFF;}

/* The wrapper is what animates. The map keeps its full height throughout and
   is clipped rather than resized, so the Map constructor has real dimensions
   the moment the button is pressed and tiles fetch during the reveal instead
   of after it. Margin lives here so the closed state takes up no space.

   Plain height rather than a grid row: a 0fr track is minmax(auto, 0fr), and
   that auto floor sizes to the item's min-content contribution — 450px for an
   item with a definite height. min-height:0 does not lift it, because that
   only applies where the item's own height is auto. */
.general-map-reveal {
  --map-height:450px;
  height:0;
  margin:0;
  overflow:hidden;
  transition:height 200ms linear, margin 200ms linear;
}

.general-map-reveal.is-open {
  height:var(--map-height);
  margin:0 0 30px 0;
}

/* Full height at all times, overflowing the wrapper while it is shut. Its own
   overflow only has to keep tiles inside the rounded corners; visibility keeps
   Google's controls out of the tab order while the wrapper is closed. */
.general-map {
  width:100%;
  height:var(--map-height);
  background:#DDD;
  border:rgba(0,0,0,0.15) 1px solid;
  border-radius:5px;
  overflow:hidden;
  visibility:hidden;
  transition:visibility 200ms;
}

.general-map-reveal.is-open .general-map {
  visibility:visible;
}

/* The count is the heading for the list below as well as a stat, so it is an
   h2 sized down to body copy rather than a span inside a wrapper div. */
.park-archive .options h2 {
  font-size:1.2rem;
  line-height:1.6rem;
  font-weight:400;
  color:#333;
  margin:0 0 20px 0;
}

.park-archive .archive-parent {
  margin:0 0 20px 0;
}

.park-archive .archive-parent a {
  color:var(--teal);
}

.park-archive .archive-parent a:hover {
  text-decoration:underline;
}

/* Park cards */

/* One card treatment, shared by the county archive and the header search
   results, so the two lists cannot drift apart. The image box and its ratio,
   the placeholder, the heading and the link stretched across the card are all
   common. The lists differ only in their columns and gap, and in the last line
   inside .info: the archive prints the location trail and attributes, search
   prints the distance.

   Mobile-first. Explicit columns rather than auto-fill: the content width caps
   at 1306px, and an intrinsic minimum wide enough to hold three columns there
   collapses to one below 720px, while one narrow enough to keep two columns at
   601px allows four at the top end. The two constraints cannot both be met by
   intrinsic sizing, so the breakpoints stay.

   gap replaces the old -10px list margin and 10px/20px item padding: 20px
   between columns, 30px between rows, same as before. */

.park-cards {
  list-style:none;
  display:grid;
  grid-template-columns:1fr;
  gap:30px 20px;
  margin:0 0 50px 0;
  padding:0;
}

@media screen and (min-width: 601px){
  .park-cards {
    grid-template-columns:repeat(2, 1fr);
  }
}

@media screen and (min-width: 1001px){
  .park-cards {
    grid-template-columns:repeat(3, 1fr);
  }
}

/* The li is the card. The heading link is stretched across it by the ::after
   below, so nothing else inside may be interactive without its own stacking
   context — a second link would be unclickable. */

.park-cards li {
  position:relative;
  display:flex;
  flex-direction:column;
  background:#FFF;
  border:rgb(220,220,220) 1px solid;
  border-radius:8px;
  overflow:hidden;
  transition:box-shadow 0.5s;
}

  /* focus-within carries the hover treatment to keyboard users, whose focus
     ring otherwise lands on a link the size of the heading text alone. */
  .park-cards li:hover,
  .park-cards li:focus-within {
    box-shadow: 0px 0px 21px -5px rgba(0,0,0,0.75);
  }

  /* The box carries the ratio rather than the image, so a park with no picture
     reserves the same space and the row stays level. */
  .park-cards li div.image {
    aspect-ratio:16 / 9;
    background-color:#EFEFEF;
  }

    .park-cards li div.image.no-image {
      background-image:url("assets/no-img-icon.png");
      background-repeat:no-repeat;
      background-position:center;
      background-size:150px 150px;
    }

    .park-cards li div.image img {
      display:block;
      width:100%;
      height:100%;
      object-fit:cover;
      background-color:#EFEFEF;
    }

  .park-cards li div.info {
    padding:20px;
  }

  .park-cards li h3 {
    color:#000;
    font-size:18px;
    line-height:22px;
    font-weight:400;
    margin:0 0 20px 0;
  }

    /* font:inherit keeps the global p/span/a type rule off the link, the same
       pattern the footer and finder headings use for their buttons. */
    .park-cards li h3 a {
      color:inherit;
      font:inherit;
    }

    .park-cards li h3 a::after {
      content:"";
      position:absolute;
      inset:0;
    }

  /* The secondary lines share one treatment: the archive's location trail and
     attributes, and the search pane's distance. */
  .park-cards li .sp-cats,
  .park-cards li .attributes span,
  .park-cards li .miles {
    font-size:14px;
    line-height:18px;
    color:rgb(88, 86, 87);
  }

  .park-cards li .sp-cats {
    margin:0 0 20px 0;
    padding:0 0 0 20px;
    background:url('assets/icons/tsp-location.svg') no-repeat left 1px;
    background-size:14px 14px;
  }

  .park-cards li .park-status {
    display:block;
    color:#C41E21;
  }

  .park-cards li .park-status:not(:last-child) {
    margin:0 0 20px 0;
  }

  .park-cards li .attributes {
    margin:0;
  }

  .park-cards li .attributes span {
    margin:0 10px 0 0;
    display:inline-block;
  }

  .park-cards li .miles {
    display:block;
    margin:0;
  }

@media screen and (max-width: 700px){

  div.right-buttons {
    float:none;
    display:inline;
  }

  button.park-button.right-button {
    margin:10px 10px 0 0;
  }

}

/*----------------------------------------------------------------------------*/
/* News Archive (archive-news.php)
/*----------------------------------------------------------------------------*/

/* Its own block rather than an extension of .park-cards, even though the
   chrome is identical. A park card's heading is an h3 sitting under a county
   heading; a news card is a top-level section of its archive and takes an h2,
   so one selector cannot hold both. Keeping them apart also lets the card
   carry a date and a summary without those rules reaching the park lists.

   Everything above .news-cards li div.info is the half the two share, if they
   ever need to be merged behind a common class. */

.news-cards {
  list-style:none;
  display:grid;
  grid-template-columns:1fr;
  gap:30px 20px;
  margin:0 0 40px 0;
  padding:0;
}

@media screen and (min-width: 601px){
  .news-cards {grid-template-columns:repeat(2, 1fr);}
}

@media screen and (min-width: 1001px){
  .news-cards {grid-template-columns:repeat(3, 1fr);}
}

.news-cards li {
  position:relative;
  display:flex;
  flex-direction:column;
  background:#FFF;
  border:rgb(220,220,220) 1px solid;
  border-radius:8px;
  overflow:hidden;
  transition:box-shadow 0.5s;
}

  /* focus-within carries the hover treatment to keyboard users, whose focus
     ring otherwise lands on a link the size of the heading text alone. */
  .news-cards li:hover,
  .news-cards li:focus-within {box-shadow: 0px 0px 21px -5px rgba(0,0,0,0.75);}

  /* The box carries the ratio rather than the image, so an article with no
     picture reserves the same space and the row stays level. */
  .news-cards li div.image {
    aspect-ratio:16 / 9;
    background-color:#EFEFEF;
  }

    .news-cards li div.image.no-image {
      background-image:url("assets/no-img-icon.png");
      background-repeat:no-repeat;
      background-position:center;
      background-size:150px 150px;
    }

    .news-cards li div.image img {
      display:block;
      width:100%;
      height:100%;
      object-fit:cover;
      background-color:#EFEFEF;
    }

  .news-cards li div.info {padding:20px;}

  .news-cards li h2 {
    color:#000;
    font-size:18px;
    line-height:22px;
    font-weight:400;
    margin:0 0 10px 0;
  }

    /* font:inherit keeps the global p/span/a type rule off the link, the same
       pattern the park cards and footer headings use. */
    .news-cards li h2 a {color:inherit;font:inherit;}

    /* Stretched across the card, so nothing else inside may be interactive
       without its own stacking context. */
    .news-cards li h2 a::after {content:"";position:absolute;inset:0;}

  .news-cards li .date,
  .news-cards li .excerpt {
    font-size:14px;
    line-height:18px;
    color:rgb(88, 86, 87);
  }

  .news-cards li .date {margin:0 0 10px 0;}

  .news-cards li .excerpt {margin:0;}

/* Archive pagination
   ----------------------------------------------------------------------------
   Output by pagination_nav() in library/pagination.php. The marker reset is
   scoped to lists inside nav, and this list is not in one, so it needs its own
   list-style. Disabled ends are plain spans; live ones are links, and the
   .inactive class sits on the SVG path rather than the list item. */

.archive-pagination {
  list-style:none;
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:center;
  gap:6px;
  margin:0 0 50px 0;
  padding:0;
}

  .archive-pagination li {display:flex;}

  /* 44px minimum so the arrows are a real touch target on a phone. */
  .archive-pagination a,
  .archive-pagination li > span {
    display:flex;
    align-items:center;
    justify-content:center;
    min-width:44px;
    min-height:44px;
    padding:10px 14px;
    border:#CCC 1px solid;
    border-radius:3px;
    background:rgb(244, 244, 244);
    font-size:1rem;
    line-height:1.5rem;
    color:#333;
  }

  .archive-pagination a span {display:flex;}

  .archive-pagination a:hover,
  .archive-pagination a:focus-visible {
    background:var(--teal);
    border-color:var(--teal);
    color:#FFF;
  }

  /* The site-wide `span{color:#333}` reset (line 229) is a rule on the span
     itself, not an inherited value, so it beats the white set on the hovered
     <a> — the chevron icon (fill:currentColor) stays dark without this. */
  .archive-pagination a:hover span,
  .archive-pagination a:focus-visible span {
    color:#FFF;
  }

  /* The middle item is a label rather than a control, so it loses the box. */
  .archive-pagination .middle > span {
    border-color:transparent;
    background:none;
    min-width:0;
    padding:10px 6px;
    text-align:center;
  }

  /* Below ~360px the row (4 buttons + label) no longer fits on one line —
     360px is Android's most common CSS width, so this isn't a rare-device
     edge case. Breaking "Page" from "X of Y" and tightening the gap buys
     just enough room; both revert above the threshold where there's space
     to spare. */
  @media (min-width: 361px) {
    .archive-pagination { gap:10px; }
    .archive-pagination .middle br { display:none; }
  }

  /* The two arrow SVGs have different viewBoxes, so height is fixed and width
     is left to the aspect ratio rather than distorting the single chevron. */
  .archive-pagination svg {height:8px;width:auto;}

  .archive-pagination svg path {fill:currentColor;}
  .archive-pagination svg path.inactive {fill:#BBB;}

/*----------------------------------------------------------------------------*/
/* News Article (single-news.php)
/*----------------------------------------------------------------------------*/

/* The prose measure is handled by the shared .wysiwyg cap up in Typography.
   The article column itself is left full width so the hero image and the
   gallery use all of it. */

.single-news header {margin:0 0 25px 0;}

.single-news h1 {margin:0 0 10px 0;}

.single-news .article-meta {
  font-size:1rem;
  line-height:1.5rem;
  color:rgb(88, 86, 87);
  margin:0;
}

  .single-news .article-meta span,
  .single-news .article-meta time {font:inherit;color:inherit;}

  .single-news .article-meta .updated {display:block;}

.single-news .article-hero {margin:0 0 30px 0;}

  .single-news .article-hero img {
    width:100%;
    border-radius:8px;
    background:#EFEFEF;
    margin:0 0 10px 0;
  }

  .single-news .article-hero figcaption {
    font-size:14px;
    line-height:18px;
    color:rgb(88, 86, 87);
  }

/* Editor output. The global h2 is 36px, near enough to h1 to compete with the
   article title, so the body headings are sized down here rather than
   globally — the archive headers still want the larger size. */

.single-news .wysiwyg {margin:0 0 30px 0;}

  .single-news .wysiwyg h2 {font-size:28px;line-height:34px;font-weight:bold;margin:0 0 15px 0;}
  .single-news .wysiwyg h3 {font-size:20px;line-height:26px;font-weight:bold;margin:0 0 10px 0;}

  .single-news .wysiwyg a {color:var(--teal);text-decoration:underline;}

  .single-news .wysiwyg img {border-radius:8px;margin:0 0 1.25rem 0;}

.single-news .pull-quote {
  margin:0 0 30px 0;
  padding:0 0 0 20px;
  border-left:var(--teal) 3px solid;
}

  .single-news .pull-quote p {
    font-size:1.4rem;
    line-height:2rem;
    margin:0 0 10px 0;
  }

  .single-news .pull-quote figcaption {
    font-size:1rem;
    line-height:1.5rem;
    color:rgb(88, 86, 87);
  }

/* .gallery-block is tsp_gallery()'s wrapper class for this placement (see
   parts/news/sections.php) — margin-bottom to match the other flexible-
   content blocks above, rather than .tsp-gallery's float/padding rhythm,
   which is specific to the park profile's stacked boxed sections.
   flow-root, not a plain block: the inner .gallery is float:left, and
   without a block-formatting context of its own this wrapper collapses to
   zero height around it — same reason .cont uses flow-root. */
.single-news .gallery-block {display:flow-root;margin:0 0 30px 0;}

/* The shared gallery rules put five thumbnails across. That suits the dense
   park profile; an article gallery reads better with fewer, larger images. */

.single-news .gallery ul li {width:50%;}

@media screen and (min-width: 601px){
  .single-news .gallery ul li {width:33.333%;}
}

@media screen and (min-width: 801px){
  .single-news .gallery ul li {width:25%;}
}

/*----------------------------------------------------------------------------*/
/* Sidebar
/*----------------------------------------------------------------------------*/

/* Shared by every sidebar the theme grows: sidebar-news.php now, the park
   profile and park template later. Only the contents of a panel differ, so
   the box, the heading and the thumbnail list are defined once here and no
   sidebar file carries styling of its own.

   The column itself is placed by .layout in Structure. */

.sidebar {margin:0 0 30px 0;}

/* AdSense responsive unit. The container's width is what the unit measures to
   pick a format, so max-width caps it at 300 and lets it shrink on narrow
   screens rather than clipping. min-height rather than height: 300x250 is the
   likely fill so the space is reserved for it and the panels below do not
   jump, but a 300x600 has to be free to grow instead of being cut off.

   No overflow:hidden — cropping a served ad is a policy problem, not just a
   visual one. Nothing here goes on the <ins> itself, which AdSense rewrites
   inline as it resolves the size. */

.sidebar .sidebar-slot {
  max-width:300px;
  min-height:250px;
  margin:0 auto 30px auto;
    background:#CCC;
}

.sidebar .panel {margin:0 0 30px 0;}

  .sidebar .panel h2 {
    font-size:18px;
    line-height:22px;
    font-weight:bold;
    margin:0 0 15px 0;
  }

/* Thumbnail list. A fixed first track rather than a percentage, so the images
   line up whatever the panel width. */

.sidebar .side-list {
  list-style:none;
  margin:0;
  padding:0;
}

  .sidebar .side-list li {
    display:grid;
    grid-template-columns:64px minmax(0, 1fr);
    gap:12px;
    margin:0 0 15px 0;
  }

  .sidebar .side-list li:last-child {margin:0;}

    .sidebar .side-list .image {
      width:64px;
      height:64px;
      border-radius:5px;
      overflow:hidden;
      background-color:#EFEFEF;
    }

      .sidebar .side-list .image.no-image {
        background-image:url("assets/no-img-icon.png");
        background-repeat:no-repeat;
        background-position:center;
        background-size:40px 40px;
      }

      .sidebar .side-list .image img {
        width:100%;
        height:100%;
        object-fit:cover;
      }

    .sidebar .side-list .info a {
      display:block;
      font-size:1rem;
      line-height:1.35rem;
      color:#333;
      margin:0 0 5px 0;
    }

    .sidebar .side-list .info a:hover,
    .sidebar .side-list .info a:focus-visible {color:var(--teal);}

    .sidebar .side-list .date {
      font-size:13px;
      line-height:17px;
      color:rgb(88, 86, 87);
      margin:0;
    }

.sidebar .panel-more {margin:15px 0 0 0;}

  .sidebar .panel-more a {
    font-size:1rem;
    line-height:1.5rem;
    color:var(--teal);
  }

  .sidebar .panel-more a:hover {text-decoration:underline;}

/* Stacked sidebar. Below 1001px .layout collapses to one column and the panel
   runs the full content width, where a bare list of links reads as a
   continuation of the article. The grey box gives it an edge. Above 1001px the
   300px column already separates it, so the background is redundant weight.

   max-width rather than the usual min-width: the rule exists only while
   stacked, so expressing it that way needs no reset at 1001px. */

@media screen and (max-width: 1000px){

  .sidebar .panel {
    background:#EFEFEF;
    border-radius:8px;
    padding:20px;
  }

  /* --teal is 4.07:1 on #EFEFEF, below AA at this size. --teal-dark is 5.31:1. */
  .sidebar .panel-more a {color:var(--teal-dark);}

  /* The thumbnail placeholder is #EFEFEF too, so an article with no image
     would lose its box against the panel. One step down keeps the shape. */
  .sidebar .side-list .image {background-color:#DDD;}

}

/*----------------------------------------------------------------------------*/
/* Homepage
/*----------------------------------------------------------------------------*/

#home-hero {position:relative;float:none;overflow-x:clip;}

/* Sits behind .overlay by source order, so no z-index is needed. */
#home-hero .hero-image {position:absolute;inset:0;width:100%;height:100%;object-fit:cover;}

/* Not absolutely positioned: the content inside sets the height and min-height
   is only a floor, so long copy or a large text-size setting cannot overflow
   the section the way it could when .overlay was pinned to inset:0. */
#home-hero .overlay {position:relative;display:flow-root;min-height:550px;background-color:rgba(0,0,0,0.5);}

#home-hero .hero-content {padding:50px 0 40px 0;text-align:center;}

#home-hero h1 {color:#FFF;margin:0 0 20px 0;}

#home-hero .intro {color:#FFF;font-size:1.125rem;line-height:1.5rem;font-weight:300;margin:0 0 35px 0;}

#home-hero .hero-actions .button {display:inline-block;margin:0 5px 10px 5px;padding:15px 20px;background:var(--teal);color:#FFF;font-weight:bold;font-size:1.2rem;line-height:1.5rem;border-radius:3px;transition:background 0.3s;}
#home-hero .hero-actions .button:hover {background:var(--teal-dark);}

/* The global focus ring is teal, which all but disappears on a teal button over
   a dark photograph. */
#home-hero .hero-actions .button:focus-visible {outline:2px solid #FFF;outline-offset:2px;}

/* Decorative. Not rendered, and the badge artwork not requested, until there is
   room for them. */
#home-hero .slant,
#home-hero .hero-badge {display:none;}

@media screen and (min-width: 501px) {
	#home-hero .hero-content {padding-top:100px;}
}

@media screen and (min-width: 1000px) {
	#home-hero .overlay {min-height:700px;}
	#home-hero .hero-content {padding-top:180px;text-align:left;}
	#home-hero .intro {max-width:600px;}
	#home-hero .hero-actions .button {margin:0 10px 10px 0;}

	#home-hero .slant {display:block;position:absolute;top:0;right:0;bottom:0;width:30%;margin-right:-150px;background:var(--teal);}
	#home-hero .slant::after {content:"";position:absolute;inset:0;background:var(--teal);transform-origin:top left;transform:skew(-17deg, 0deg);}

	#home-hero .hero-badge {display:block;position:absolute;top:130px;right:30%;width:300px;height:300px;margin-right:-230px;border-radius:100%;background-color:#FFF;background-image:url("assets/images/the-skateparks-project-logo_270x270.png");background-repeat:no-repeat;background-position:center;background-size:270px 270px;}
}

@media screen and (min-width: 1200px) {
	#home-hero .slant {margin-right:0;}
	#home-hero .hero-badge {margin-right:-80px;}
}

/* Builder cards
   ----------------------------------------------------------------------------
   The directory at /builders/. Same chrome as the park cards — one border, one
   radius, the heading link stretched across the tile — but laid out sideways.
   A builder logo is a small square mark, not a 16:9 photograph, so a stacked
   card would be mostly empty space, and the list runs to thirty entries.

   Not folded into .park-cards: the internal structure differs enough that
   sharing would mean overriding most of it straight back. */

.builder-list {
  list-style:none;
  display:grid;
  grid-template-columns:1fr;
  gap:20px;
  margin:0 0 50px 0;
  padding:0;
}

@media screen and (min-width: 601px){
  .builder-list {
    grid-template-columns:repeat(2, 1fr);
  }
}

@media screen and (min-width: 1001px){
  .builder-list {
    grid-template-columns:repeat(3, 1fr);
  }
}

.builder-list li {
  position:relative;
  display:flex;
  align-items:center;
  gap:20px;
  background:#FFF;
  border:rgb(220,220,220) 1px solid;
  border-radius:8px;
  padding:20px;
  transition:box-shadow 0.5s;
}

  .builder-list li:hover,
  .builder-list li:focus-within {
    box-shadow: 0px 0px 21px -5px rgba(0,0,0,0.75);
  }

  /* A fixed square so every row lines up whatever shape the logo is. The
     flex-basis with no shrink stops a long builder name squeezing it. */
  .builder-list li .builder-logo {
    flex:0 0 90px;
    height:90px;
    background:#EFEFEF;
    border-radius:5px;
    overflow:hidden;
  }

    /* contain rather than cover: a logo cropped to fill the box is a logo with
       its edges cut off. White behind it because most of these files are
       artwork on white already, and the letterboxing should not show a
       different shade down the sides. */
    .builder-list li .builder-logo img {
      display:block;
      width:100%;
      height:100%;
      object-fit:contain;
      background:#FFF;
    }

    .builder-list li .builder-logo.no-logo {
      background:#EFEFEF url("assets/no-img-icon.png") no-repeat center;
      background-size:60px 60px;
    }

  /* min-width:0 lets a long name wrap instead of forcing the flex item wider
     than its column — the default min-width:auto on a flex child would push
     the tile out of the grid track. */
  .builder-list li .info {
    min-width:0;
  }

  .builder-list li h3 {
    color:#000;
    font-size:18px;
    line-height:22px;
    font-weight:400;
    margin:0 0 5px 0;
  }

    .builder-list li h3 a {
      color:inherit;
      font:inherit;
    }

    .builder-list li h3 a::after {
      content:"";
      position:absolute;
      inset:0;
    }

  .builder-list li .builder-count {
    display:block;
    font-size:14px;
    line-height:18px;
    color:rgb(88, 86, 87);
  }


/* Builders page furniture */

.add-builder {
  background:#EFEFEF;
  border-radius:8px;
  padding:30px;
  margin:0 0 50px 0;
}

  .add-builder h2 {
    margin:0 0 10px 0;
  }

  .add-builder p {
    margin:0 0 20px 0;
  }

.builder-disclaimer {
  margin:0 0 50px 0;
}

  .builder-disclaimer p {
    font-size:14px;
    line-height:20px;
    color:rgb(88, 86, 87);
  }


/* A general filled link button. The only .button rule until now was scoped to
   the footer CTA bar, so the same class rendered as plain text everywhere
   else — the builders page, the cookie disclaimer and the CTA layout all use
   it. The darker teal for the same contrast reason as #finderlocation. */

a.button {
  display:inline-block;
  padding:15px 20px;
  background:var(--teal-dark);
  color:#FFF;
  font-weight:bold;
  font-size:1.2rem;
  line-height:1.5rem;
  border-radius:5px;
  transition:background 0.3s;
}

  a.button:hover {background:var(--teal-darker);}

  a.button:focus-visible {outline-color:#FFF;outline-offset:-4px;}

/*----------------------------------------------------------------------------*/
/* Footer
/*----------------------------------------------------------------------------*/

#footer {float:left;width:100%;padding:0 0 40px 0;background:#4a4a49;}
#footer p, #footer span, #footer li, #footer a, #footer .heading {color:#FFF;}
#footer :focus-visible {outline-color:#FFF;}

#footer .footer-cta-bar {float:left;width:100%;background:#333;text-align:center;padding:50px 0;}
#footer .footer-cta-bar p.text {display:inline-block;font-size:1.5rem;line-height:2rem;margin:5px 10px;padding:15px 0;}
#footer .footer-cta-bar a.button {display:inline-block;margin:5px 10px;padding:15px 20px;background:var(--teal);color:#FFF;font-weight:bold;border-radius:5px;font-size:1.2rem;line-height:1.5rem;transition:background 0.3s;}
#footer .footer-cta-bar a.button:hover {background:var(--teal-dark);}

#footer .heading {display:block;font-family:inherit;font-size:1.2rem;line-height:1.5rem;font-weight:bold;}
#footer .bio .heading {margin:12px 0 12px 0;}

#footer .cols {float:left;width:100%;margin:80px 0 40px 0;}
#footer .col {float:left;width:100%;}

#footer .nav-heading {display:block;font:inherit;margin:12px 0 0 0;}
#footer .nav-heading button {display:block;width:100%;font-size:1.2rem;line-height:1.5rem;font-weight:bold;color:#FFF;text-align:left;padding:10px;background:#333 url('assets/icons/tsp-down-arrow.svg') no-repeat right 10px center;background-size:20px 20px;cursor:pointer;-webkit-tap-highlight-color: transparent;}

#footer .nav-heading button.icon-close {background-image:url('assets/icons/tsp-close.svg');}
/* The list is sized by a grid row on the nav rather than by its own height,
   which is what lets it transition — you cannot animate to height:auto, and
   that was the only thing slideDown was doing. min-height:0 overrides the
   automatic minimum size that would otherwise floor the row at the content
   height; overflow clips the overspill; visibility takes the links out of the
   tab order while closed, which is the one useful thing slideUp's display:none
   was doing. The top margin rides along so the closed state sits flush.

   The display:none that used to be here is gone: it left the footer nav
   permanently shut without JavaScript, with no way to open it. */
#footer .navigation nav {background:#333;display:grid;grid-template-rows:0fr;margin:0;transition:grid-template-rows 200ms linear, margin 200ms linear;}
#footer .navigation nav.is-open {grid-template-rows:1fr;margin:1px 0 0 0;}

#footer .navigation nav > ul {min-height:0;overflow:hidden;visibility:hidden;transition:visibility 200ms;}
#footer .navigation nav.is-open > ul {visibility:visible;}
#footer .navigation nav li {text-align:left;padding:5px 10px;margin:0;}
#footer .navigation nav li:first-child {padding-top:10px;}
#footer .navigation nav li:last-child {padding-bottom:10px;}
#footer .navigation nav li a {color:#FFF;font-size:1.2rem;line-height:1.6rem;}
#footer .navigation nav li a:hover {text-decoration:underline;}

#footer .bio {float:left;width:100%;text-align:center;}
#footer .bio p {display:inline-block;max-width:500px;text-align:center;}
#footer .social-icons {float:left;width:100%;height:24px;text-align:center;margin:20px 0;}
#footer .social-icons li {padding:0 10px;display:inline-block;height:24px;}
#footer .social-icons li a {float:left;display:block;height:24px;}
#footer .social-icons li svg {height:24px;}

#footer .bottom {float:left;width:100%;padding:40px 0 0 0;border-top:#FFF 1px solid;}
#footer .bottom p {float:left;width:100%;text-align:center;}
#footer .bottom nav {float:right;width:100%;margin:0 0 10px 0;}
#footer .bottom ul {text-align:center;}
#footer .bottom ul li {display:inline-block;margin:0 10px 0 0;line-height:1.5rem;}
#footer .bottom ul li.last-menu-item {margin:0;}
#footer .bottom ul li a {display:inline-block;}
#footer .bottom ul li a:hover {text-decoration:underline;}

@media screen and (min-width: 750px){
    #searchform .wrap {padding:50px 0;}
    #searchform #map {height:420px;}
    #footer .col {width:33.333%;}
    #footer .nav-heading button {background:none;text-align:center;cursor:auto;padding:0;}
    #footer .nav-heading button:active {background:none;}
    #footer .navigation nav,
    #footer .navigation nav.is-open {grid-template-rows:1fr;background:none;margin:1px 0 0 0;transition:none;}
    /* No accordion here — the rows are pinned open and the transition is off —
       so the clip that hides the collapsing panel serves no purpose and only
       cuts the focus ring off the first and last links, which now sit flush
       against the box with the list padding removed below. */
    #footer .navigation nav > ul {visibility:visible;transition:none;overflow:visible;}
    #footer .navigation nav li,
    #footer .navigation nav li:first-child,
    #footer .navigation nav li:last-child {text-align:center;padding:0;}
}

@media screen and (min-width: 1100px){
    .content {flex:1;}
    #footer .bottom p {width:auto;text-align:left;}
    #footer .bottom nav {width:auto;margin:0;}
    #footer .bottom ul {width:auto;text-align:left;}
}

@media screen and (min-width: 600px){
    #searchform .search-list {grid-template-columns:repeat(2, 1fr);}
}

@media screen and (min-width: 900px){
    #searchform .search-list {grid-template-columns:repeat(3, 1fr);}
}

@media screen and (min-width: 1200px){
    #searchform .search-list {grid-template-columns:repeat(4, 1fr);}
}

@media screen and (min-width: 1200px){
    #footer .col {padding:0 40px 20px 0;}
    #footer .col:last-child {padding-right:0;}
    #footer .navigation {float:left;margin:0;width:50%;}
    #footer .nav-heading button {text-align:left;}
    #footer .navigation nav li,
    #footer .navigation nav li:first-child,
    #footer .navigation nav li:last-child {text-align:left;}
    #footer .bio {width:50%;text-align:left;}
    #footer .bio p {text-align:left;}
    #footer .social-icons {text-align:left;margin:20px 0 0 0;}
    #footer .social-icons li {float:left;padding:0 15px 0 0;}
}

@media screen and (min-width: 1486px){
    main {background:#F8F8F9;}
    main > .cont {max-width:1486px;}
    main > .cont > .wrap {padding:0 60px;}
}

/* Without JavaScript there is no working control to open these, so they render
   open rather than shut behind a button that cannot do anything. Collapsed is
   the default above; this is the only thing that undoes it.

   Browsers older than Safari 17 / Chrome 120 do not support the query, so a
   no-JS visitor on one of those still gets the collapsed state — which is
   exactly where the footer already was, so nothing regresses. */
@media (scripting: none) {
	#footer .navigation nav {grid-template-rows:1fr;margin:1px 0 0 0;}
	#footer .navigation nav > ul {visibility:visible;}

	#finder .list-wrap[id] {grid-template-rows:1fr;}
	#finder .list-wrap[id] > ul {visibility:visible;}

	/* Tabs cannot be operated without script, so stack every panel rather
	   than sealing two of them behind controls that do nothing. */
	.tsp-location .tabs-tabs {display:none;}
	.tsp-location .tabs-content {display:block;}
}

@media (scripting: none) and (max-width: 549px) {
	#finder .list-wrap[id] {margin:0 0 15px 0;}
}

/*----------------------------------------------------------------------------*/
/* Lightbox
/*
/* One <dialog> is built by script and reused by every gallery on the page.
/* Layout is a grid rather than flex because the image row needs an explicit
/* minmax(0, 1fr): without the zero floor the row sizes to the image's own
/* min-content height and max-height:100% never takes effect, which is the
/* usual reason a contained image overflows its box.
/*
/* Without showModal() the script returns early and the thumbnails stay
/* ordinary links to the full-size file, so nothing here needs a no-JS state.
/*----------------------------------------------------------------------------*/

dialog.lightbox {
	position:fixed;
	inset:0;
	width:100%;
	max-width:100%;
	height:100%;
	max-height:100%;
	margin:0;
	padding:0;
	border:0;
	background:transparent;
	color:#FFF;
	overflow:hidden;
    overscroll-behavior:contain;
}

/* The UA sheet gives dialog a white background, a solid border and a
   max-width of calc(100% - 6px - 2em). All three are overridden above. */

dialog.lightbox::backdrop {
	background:rgba(0,0,0,0.92);
}

/* Answers the reader's own action, so it is welcome. The reduced-motion block
   at style.css line 193 clamps it for anyone who has asked for that. */
dialog.lightbox[open] {
	animation:lightbox-in 150ms ease-out;
}

@keyframes lightbox-in {
	from {opacity:0;}
	to   {opacity:1;}
}

/* Padding is what keeps the image off the edges, and it also reserves the
   space the controls sit in — they are positioned against the dialog, not
   against the image, so they never move as the image changes shape. */
.lightbox-stage {
	display:grid;
	height:100%;
	padding:76px 76px 32px 76px;
}

.lightbox-figure {
	display:grid;
	grid-template-rows:minmax(0, 1fr) auto;
	justify-items:center;
	align-content:center;
	gap:16px;
	width:100%;
	height:100%;
	min-height:0;
	margin:0;
}

/* width and height are set as attributes by the script so the intrinsic ratio
   is known before the file arrives and the box does not jump. auto here lets
   the max-* pair do the sizing regardless of those attributes. */
.lightbox-image {
	width:auto;
	height:auto;
	max-width:100%;
	max-height:100%;
	min-height:0;
	object-fit:contain;
	border-radius:5px;
	background:#333;
}

.lightbox-caption {
	max-width:70ch;
	color:#EEE;
	font-size:1rem;
	line-height:1.5rem;
	text-align:center;
}

.lightbox-caption[hidden] {display:none;}

.lightbox button {
	position:absolute;
	display:flex;
	align-items:center;
	justify-content:center;
	width:48px;
	height:48px;
	padding:0;
	border:0;
	border-radius:50%;
	background:rgba(0,0,0,0.55);
	color:#FFF;
	cursor:pointer;
}

.lightbox button:hover {background:rgba(255,255,255,0.22);}
.lightbox button[hidden] {display:none;}
.lightbox button svg {display:block;width:24px;height:24px;}

/* Teal on near-black is legible but weak. The theme already switches the ring
   to white over dark fills — see #locationsearchsubmit at style.css line 484. */
.lightbox button:focus-visible {outline-color:#FFF;}

.lightbox-close {top:14px;right:14px;}
.lightbox-prev  {top:50%;left:14px;transform:translateY(-50%);}
.lightbox-next  {top:50%;right:14px;transform:translateY(-50%);}

.lightbox-count {
	position:absolute;
	top:25px;
	left:22px;
	margin:0;
	color:#EEE;
	font-size:1rem;
	line-height:1.5rem;
}

.lightbox-count[hidden] {display:none;}

/* The controls keep their 48px target below the breakpoint; only the gutters
   tighten, so a portrait phone gives the image most of its width. */
@media screen and (max-width: 700px){
	.lightbox-stage {padding:70px 14px 26px 14px;}
	.lightbox-prev  {left:8px;}
	.lightbox-next  {right:8px;}
}

/*----------------------------------------------------------------------------*/
/* Contact Form (library/contact.php)
/*----------------------------------------------------------------------------*/

.contact-section {margin:0 0 100px 0;}

/* Sits where the form will be, so a browser without script gets an
   explanation rather than an empty gap. theme.js hides it. */
.contact-nojs {padding:20px;margin:0 0 30px 0;background:#F7F7F7;border-left:var(--teal) 4px solid;}

.contact-form {max-width:640px;}

.contact-form .field {margin:0 0 25px 0;}

.contact-form label {display:block;margin:0 0 8px 0;font-weight:bold;font-size:1.1rem;line-height:1.5rem;}

.field-optional {font-weight:normal;color:#666;}

/* Matched to #locationsearchinput so the form reads as part of the same
   system as the finder. 1.2rem is 19.2px, comfortably over the 16px floor
   below which iOS zooms the viewport on focus. */
.contact-form input,
.contact-form textarea {
	width:100%;
	padding:0 15px;
	font-size:1.2rem;
	line-height:1.6rem;
	color:rgb(74,74,73);
	background:#FFF;
	border:rgb(88,86,87) 2px solid;
	border-radius:5px;
}

.contact-form input {height:56px;}
.contact-form textarea {padding:15px;min-height:180px;}

.contact-form input[aria-invalid="true"],
.contact-form textarea[aria-invalid="true"] {border-color:#B3261E;}

.field-error {margin:8px 0 0 0;color:#B3261E;font-size:1rem;line-height:1.4rem;}

/* The honeypot. Deliberately not .visually-hidden: that class is reachable by
   assistive technology and the field would be read out as real. Off-screen
   and out of the tab order instead. */
.contact-hp {position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}

.contact-submit {
	display:flex;
	align-items:center;
	justify-content:center;
	width:100%;
	max-width:320px;
	min-height:56px;
	padding:10px 20px;
	font-size:1.2rem;
	line-height:1.6rem;
	color:#FFF;
	background:var(--teal-dark);
	border:0;
	border-radius:5px;
	cursor:pointer;
	transition:background 0.3s;
}

/* The global `p, span, a` colour (style.css:229) sets the label span to #333,
   which wins over the white inherited from .contact-submit. Restate it here. */
.contact-submit-label {color:#FFF;}

.contact-submit:hover {background:var(--teal-darker);}

/* Disabled state has to stay legible: it is on screen for the whole time the
   request is in flight, which on a slow connection is not brief. */
.contact-submit:disabled {background:#767676;cursor:default;}

.contact-status {margin:15px 0 0 0;color:#555;}
.contact-status:empty {margin:0;}

.contact-alert {margin:15px 0 0 0;padding:15px 20px;color:#B3261E;background:#FDECEA;border-radius:5px;}

.contact-success {padding:25px 30px;background:#F7F7F7;border-left:var(--teal) 4px solid;}
.contact-success h2 {margin:0 0 10px 0;font-size:1.4rem;line-height:1.8rem;}
.contact-success p {margin:0;}

/*----------------------------------------------------------------------------*/
/* Submit Form (library/submit.php)
/*----------------------------------------------------------------------------*/

/* Deliberately a parallel set of rules rather than reusing .contact-form's —
   the two forms have no shared class to hang a rule on, and duplicating a
   couple of dozen lines is cheaper than reworking the contact form's markup
   for this pass. Worth consolidating into shared classes if this form grows
   closer to parity with the contact form later. */

.submit-section {margin:0 0 100px 0;}

.submit-nojs {padding:20px;margin:0 0 30px 0;background:#F7F7F7;border-left:var(--teal) 4px solid;}

.submit-form {max-width:640px;}

.submit-form .field {margin:0 0 25px 0;}

.submit-form label {display:block;margin:0 0 8px 0;font-weight:bold;font-size:1.1rem;line-height:1.5rem;}

.submit-form input:not([type="checkbox"]),
.submit-form textarea {
	width:100%;
	padding:0 15px;
	font-size:1.2rem;
	line-height:1.6rem;
	color:rgb(74,74,73);
	background:#FFF;
	border:rgb(88,86,87) 2px solid;
	border-radius:5px;
}

.submit-form input:not([type="checkbox"]) {height:56px;}
.submit-form textarea {padding:15px;min-height:120px;}

.submit-form input[aria-invalid="true"],
.submit-form textarea[aria-invalid="true"] {border-color:#B3261E;}

/* The checkbox row: label wraps both the box and its text so the whole row
   is one tap target, comfortably over the 24px WCAG AA minimum without
   needing extra padding tricks. */
.submit-form .field-checkbox label {display:flex;align-items:flex-start;gap:12px;font-weight:normal;font-size:1.1rem;line-height:1.6rem;}
.submit-form .field-checkbox input[type="checkbox"] {width:24px;height:24px;flex:none;margin:2px 0 0 0;}
.submit-form .field-note {margin:8px 0 0 36px;color:#555;font-size:0.95rem;line-height:1.4rem;}

.submit-hp {position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}

.submit-submit {
	display:flex;
	align-items:center;
	justify-content:center;
	width:100%;
	max-width:320px;
	min-height:56px;
	padding:10px 20px;
	font-size:1.2rem;
	line-height:1.6rem;
	color:#FFF;
	background:var(--teal-dark);
	border:0;
	border-radius:5px;
	cursor:pointer;
	transition:background 0.3s;
}

.submit-submit-label {color:#FFF;}

.submit-submit:hover {background:var(--teal-darker);}
.submit-submit:disabled {background:#767676;cursor:default;}

.submit-status {margin:15px 0 0 0;color:#555;}
.submit-status:empty {margin:0;}

.submit-alert {margin:15px 0 0 0;padding:15px 20px;color:#B3261E;background:#FDECEA;border-radius:5px;}

.submit-success {padding:25px 30px;background:#F7F7F7;border-left:var(--teal) 4px solid;}
.submit-success h2 {margin:0 0 10px 0;font-size:1.4rem;line-height:1.8rem;}
.submit-success p {margin:0;}

/*----------------------------------------------------------------------------*/
/* FAQs (parts/layouts/faqs.php)
/*----------------------------------------------------------------------------*/

.faqs {margin:0 0 100px 0;}

.faq {margin:0 0 20px 0;}

.faq-question {margin:0;font-size:18px;}

.faq-question button {display:block;width:100%;font:inherit;color:inherit;text-align:left;padding:20px 40px;background:#F7F7F7;border:0;cursor:pointer;-webkit-tap-highlight-color:transparent;}

/* Same collapsing-grid-row mechanism as the footer nav (style.css:1854) and
   finder lists (style.css:812). .answer is the animated grid row; .answer-body
   is the single grid item that actually clips. Unlike the finder's single <ul>
   child, a WYSIWYG answer can render several block elements, so it needs its
   own wrapper to carry the overflow:hidden the grid-collapse trick relies on. */
.faq .answer {display:grid;grid-template-rows:0fr;background:#F7F7F7;transition:grid-template-rows 200ms linear;}
.faq .answer.is-open {grid-template-rows:1fr;}
.faq .answer-body {min-height:0;overflow:hidden;padding:0 40px 20px 40px;visibility:hidden;transition:visibility 200ms;}
.faq .answer.is-open .answer-body {visibility:visible;}

/*----------------------------------------------------------------------------*/
/* Maintenance mode (library/maintenance.php)
/*----------------------------------------------------------------------------*/

/* Its own standalone page (no header.php/footer.php), so it doesn't inherit
   the site-wide #header/#searchform/#main/#footer grid the generic body
   rule above sets up. */
body.maintenance-mode {display:flex;min-height:100vh;min-height:100dvh;}

#maintenance-mode {display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;padding:40px 30px;text-align:center;}

#maintenance-mode .logo {margin:0 0 30px 0;}

#maintenance-mode h1 {font-size:1.8rem;line-height:2.2rem;margin:0 0 15px 0;}

#maintenance-mode p {max-width:480px;margin:0 auto;font-size:1.1rem;line-height:1.6rem;color:rgb(88, 86, 87);}

/* Admin-only reminder bar, shown at the top of #main on every front-end page
   while maintenance mode is on — logged-out visitors never see this, only
   the maintenance page above. #FFF3CD/#664D03 is the same light-amber/
   dark-brown pairing as Bootstrap's "warning" alert, comfortably over
   4.5:1. */
.maintenance-bar {width:100%;padding:10px 20px;font-size:0.95rem;line-height:1.4rem;text-align:center;color:#664D03;background:#FFF3CD;}
