/* ==========================================================================
   Express Group theme: WordPress additions to the concept CSS.
   main.css and pages.css are the concept's files, unchanged (copy them over
   again when the concept changes). Everything WordPress needs on top is here.
   ========================================================================== */

/* Tender form: honeypot field (bots fill it, people never see it) */
.form-hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Tender form: a message from the server (expired form, file too large, sending failed) */
.tender-form__alert {
  margin-top: 20px;
  padding: 16px 20px;
  border: 1px solid rgba(180, 35, 24, 0.35);
  border-radius: var(--r-md);
  background: #FDF1F0;
  color: var(--c-error);
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1.5;
}

/* Tender form: while it is being sent */
.tender-form.is-sending button[type="submit"] {
  opacity: 0.6;
  cursor: progress;
}

/* Project status "Won" (the concept has on site, complete and TBC) */
.status--won { background: var(--c-ink); color: var(--c-accent); }

/* Logged-in editors: keep the sticky header and section nav below the WordPress toolbar */
body.admin-bar .site-header { top: 32px; }
body.admin-bar.page-inner { --sticky-top: calc(76px + 32px); }
@media (min-width: 768px) {
  body.admin-bar.page-inner { --sticky-top: calc(86px + 32px); }
}
@media (max-width: 782px) {
  body.admin-bar .site-header { top: 46px; }
  body.admin-bar.page-inner { --sticky-top: calc(76px + 46px); }
}
@media (max-width: 600px) {
  body.admin-bar .site-header { top: 0; }
}
/* T-015 R2-01: focus also clears the toolbar (main.css --scroll-pad-top: 82px, 92px from 768px). */
@media (min-width: 601px) {
  html:has(> body.admin-bar) { --scroll-pad-top: calc(82px + 46px); }
}
@media (min-width: 768px) {
  html:has(> body.admin-bar) { --scroll-pad-top: calc(92px + 46px); }
}
@media (min-width: 783px) {
  html:has(> body.admin-bar) { --scroll-pad-top: calc(92px + 32px); }
}

/* Content from the editor on plain pages */
.screen-reader-text {
  position: absolute !important;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.prose .alignleft { float: left; margin: 0 1.5em 1em 0; }
.prose .alignright { float: right; margin: 0 0 1em 1.5em; }
.prose .aligncenter { margin-inline: auto; }
.prose .wp-caption-text,
.prose figcaption { font-size: var(--fs-xs); color: var(--c-muted); }

/* The photographer's credit line (.photo-credit, T-015 R2-07) moved to the concept's main.css in round 3. */

/* Project cards: "Delivered by Express Facades" (lead, T-013 review). A small label on the photo, in
   the style of the "Visualisation" label (pages.css .media-label), at the top so the two never meet.
   It lets clicks through to the card link. */
.project-card__media { position: relative; }
.delivered-by {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  max-width: calc(100% - 20px);
  padding: 4px 12px 4px 4px;
  border-radius: var(--r-pill);
  background: rgba(20, 20, 20, 0.8);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.25;
  color: #fff;
  pointer-events: none;
}
.delivered-by__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--c-accent);
  color: var(--c-ink);
}
.delivered-by__icon .icon { width: 13px; height: 13px; }

/* Cookie banner and cookie settings (T-014; not in the concept: inc/consent.php, assets/js/consent.js).
   A light card at the foot of the screen, above the mobile bar; Accept and Reject look the same. */
.consent-banner {
  position: fixed;
  left: var(--gutter);
  bottom: var(--gutter);
  z-index: 45;
  display: grid;
  gap: 14px;
  width: min(34rem, calc(100% - 2 * var(--gutter)));
  padding: 22px 22px 16px;
  border: 1px solid var(--c-line);
  border-radius: var(--r-lg);
  background: var(--c-surface);
  box-shadow: var(--shadow-lift);
  color: var(--c-ink);
}
.consent-banner[hidden] { display: none; }
/* After a cookie choice, focus may go to <main> as the starting point for the next Tab (consent.js, T-015
   R5-02): no ring around the whole page content. */
#main[tabindex="-1"]:focus { outline: none; }
.consent-banner__title { font-size: 1.125rem; font-weight: 600; line-height: 1.3; letter-spacing: -0.01em; }
.consent-banner__text { margin-top: 6px; font-size: var(--fs-small); line-height: 1.55; color: var(--c-text-2); }
.consent-banner__text a,
.consent-dialog__intro a { color: var(--c-ink); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: rgba(20, 20, 20, 0.35); }
.consent-banner__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.consent-banner__choice { justify-content: center; padding: 5px 20px; }
.consent-banner__settings {
  min-height: 44px;
  padding: 0 10px;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--c-ink);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: rgba(20, 20, 20, 0.28);
  cursor: pointer;
}
.consent-banner__settings:hover { color: var(--c-accent-ink); text-decoration-color: var(--c-accent-ink); }

@media (max-width: 767.98px) {
  .consent-banner {
    left: 12px;
    right: 12px;
    bottom: calc(12px + env(safe-area-inset-bottom));
    width: auto;
    max-height: calc(100vh - 24px);
    overflow-y: auto;
    padding: 18px 18px 12px;
  }
  .consent-banner__actions { display: grid; grid-template-columns: 1fr 1fr; }
  .consent-banner__settings { grid-column: 1 / -1; justify-self: start; padding: 0; }
}
@media (max-width: 379.98px) {
  .consent-banner__actions { grid-template-columns: 1fr; }
  .consent-banner__choice { white-space: normal; }
}
/* Short screens (T-036, the Acoustics A3-01 finding checked on the Group; WCAG 2.4.11): a landscape phone or a
   laptop zoomed to 200% (about 683 x 340) left the stacked banner (220 to 240px) and the sticky header so little
   room that focused controls ended up under the banner. Here the banner is compact: no visible title (it still
   names the region), one small paragraph, the three buttons in one row, and at most about a third of the screen. */
@media (max-height: 500px) {
  .consent-banner {
    left: 12px;
    right: auto;
    bottom: calc(8px + env(safe-area-inset-bottom));
    width: min(46rem, calc(100% - 24px));
    max-height: 36vh;
    overflow-y: auto;
    gap: 8px;
    padding: 10px 14px;
  }
  .consent-banner__title { display: none; }
  .consent-banner__text { margin-top: 0; font-size: 0.8125rem; line-height: 1.4; }
  .consent-banner__actions { display: flex; flex-wrap: nowrap; gap: 6px; }
  .consent-banner__choice { min-height: 40px; padding: 4px 14px; white-space: nowrap; }
  .consent-banner__settings { min-height: 40px; padding: 0 6px; white-space: nowrap; }
}
/* While the banner is open (html.consent-open, consent.js) the phone's bottom bar steps aside: the banner covers
   it, and its two links would be focus stops hidden under the banner (T-036; as express-core 1.3.3). The space
   kept clear at the foot of the screen is then the banner's alone, not the banner's plus the bar's. The legal
   pages' contents list scrolls with the page while the banner is open, so its last links can clear it. */
html.consent-open .mobile-bar { visibility: hidden; transform: translateY(110%); }
html.consent-open { scroll-padding-bottom: calc(max(var(--bottom-ui, 0px), var(--banner-h, 0px)) + 12px); }
html.consent-open .legal__toc { position: static; }

.consent-dialog {
  width: min(36rem, calc(100% - 24px));
  max-width: none;
  max-height: calc(100% - 24px);
  padding: 0;
  border: 0;
  border-radius: var(--r-lg);
  background: var(--c-surface);
  color: var(--c-ink);
  box-shadow: var(--shadow-lift);
}
.consent-dialog::backdrop { background: rgba(14, 14, 13, 0.55); }
.consent-dialog__form { position: relative; display: grid; gap: 16px; padding: 28px 24px 22px; }
.consent-dialog__title { padding-right: 48px; font-size: clamp(1.5rem, 1.3rem + 0.8vw, 1.875rem); font-weight: 600; letter-spacing: -0.03em; line-height: 1.15; }
.consent-dialog__intro { font-size: var(--fs-small); line-height: 1.55; color: var(--c-text-2); }
.consent-option {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  padding: 16px 0 0;
  border-top: 1px solid var(--c-line);
}
.consent-option__title { font-size: 1rem; font-weight: 600; line-height: 1.35; }
.consent-option__title label { cursor: pointer; }
.consent-option__text { margin-top: 4px; font-size: var(--fs-xs); line-height: 1.5; color: var(--c-muted); }
.consent-option__state {
  flex: none;
  padding: 4px 12px;
  border-radius: var(--r-pill);
  background: var(--c-surface-2);
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--c-text-2);
  white-space: nowrap;
}
.consent-switch {
  flex: none;
  position: relative;
  width: 52px;
  height: 30px;
  margin: 0;
  border-radius: var(--r-pill);
  background: var(--c-line-2);
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  transition: background-color 0.25s var(--ease);
}
.consent-switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(28, 28, 26, 0.3);
  transition: transform 0.25s var(--ease);
}
.consent-switch:checked { background: var(--c-accent-ink); }
.consent-switch:checked::after { transform: translateX(22px); }
.consent-switch:focus-visible { outline: 3px solid var(--c-accent-ink); outline-offset: 3px; }
.consent-dialog__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; padding-top: 8px; }
.consent-dialog__actions .btn { justify-content: center; padding: 6px 24px; }
.consent-dialog__close {
  position: absolute;
  top: 16px;
  right: 16px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--c-line);
  border-radius: 50%;
  background: var(--c-surface);
  color: var(--c-ink);
  cursor: pointer;
}
.consent-dialog__close:hover { border-color: var(--c-ink); }
.consent-dialog__close .icon { width: 17px; height: 17px; }
@media (prefers-reduced-motion: reduce) {
  .consent-switch,
  .consent-switch::after { transition: none; }
}

/* Search (T-014; not in the concept): search.php, inc/search.php */
.search-form { display: flex; gap: 8px; max-width: 40rem; margin-top: 28px; }
.search-form__input { flex: 1 1 auto; min-width: 0; border-radius: var(--r-pill); padding-left: 22px; }
.search-form__button { flex: none; }
.search-results__count { margin-bottom: 8px; font-size: var(--fs-small); color: var(--c-muted); }
.search-results__list { display: grid; max-width: 52rem; border-top: 1px solid var(--c-line); }
.search-result { display: grid; gap: 6px; padding: 22px 0; border-bottom: 1px solid var(--c-line); }
.search-result__kind { font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-accent-ink); }
.search-result__title { font-size: var(--fs-h3); font-weight: 600; line-height: 1.25; letter-spacing: -0.02em; }
.search-result__title a { text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 4px; text-decoration-color: rgba(20, 20, 20, 0.2); }
.search-result__title a:hover { color: var(--c-accent-ink); text-decoration-color: var(--c-accent-ink); }
.search-result__text { max-width: 44rem; color: var(--c-text-2); }
.search-results__empty { display: grid; gap: 12px; max-width: 44rem; color: var(--c-text-2); }
.search-results__links { display: flex; flex-wrap: wrap; gap: 0 22px; }
@media (max-width: 479.98px) {
  .search-form__button .btn__label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .search-form__button { padding: 6px; }
}

/* Legal pages (T-015 R1-03): the privacy notice and cookie policy drafts (wordpress/tools/legal-to-html.py).
   Cookie names as code; the concept greys the last table row (its "list follows" placeholder), real rows
   keep the body colour; a TBC chip sits on the text line. */
.legal__body code {
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--c-surface-2);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.875em;
  color: var(--c-ink);
  overflow-wrap: anywhere;
}
.legal-table tbody tr:last-child td { color: inherit; }
.legal__body .tbc { vertical-align: 0.08em; }
/* T-015 R2-02: the help pages' addresses are links and break where they must, so nothing runs off a
   320px screen. */
.legal__body a { overflow-wrap: anywhere; }

/* Projects catalogue filters (T-015 R1-17): one column below 380px, so "All services" and "Newest first"
   are not cut off at 320px. */
@media (max-width: 379.98px) {
  .filter-bar__controls { grid-template-columns: minmax(0, 1fr); }
}

/* (T-036 D-01: the hidden view's two-director rule went with the old photo boxes. Since T-055 About's
   people are the concept's team portraits, `.team-group` and `.member` in pages.css, the same in both views.)
   A five-figure stats band (About "At a glance") keeps three figures when the unconfirmed ones are hidden:
   one row of three from 768px instead of a half-empty row. */
@media (min-width: 768px) {
  .stats-band--5:not(:has(> .figure:nth-child(4))) { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stats-band--5:not(:has(> .figure:nth-child(4))) > .figure { grid-column: auto; }
  .stats-band--5:has(> .figure:nth-child(4)):not(:has(> .figure:nth-child(5))) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .stats-band--5:has(> .figure:nth-child(4)):not(:has(> .figure:nth-child(5))) > .figure { grid-column: auto; }
}
/* With the TBC markers hidden a block can lose its neighbour: a feature grid left with one tile and a
   two-column split left with one side (Careers "What we ask") take the full row. */
.feature-grid > .feature:only-child { grid-column: 1 / -1; }
.split > :only-child { grid-column: 1 / -1; }
/* A certificate card whose number and expiry are hidden (FIRAS, T-015 R4-03) keeps only its heading: it sits
   in the middle of the card instead of above an empty lower half. A visible certificate link (margin-top: auto)
   still goes to the foot of the card. Not the "Certification body" card (T-062: its mark and text sit in a row). */
.cert:not(.cert--note):not(.cert--body):not(:has(> .cert__facts)) { justify-content: center; }

/* T-015 R6-01 (WCAG 2.4.11): while the cookie banner is open, the page ends above it, so the last footer links
   can scroll into view instead of staying under the banner (scroll-padding cannot lift content once the page
   cannot scroll further). consent.js sets --banner-h only while the banner is open; on phones the mobile
   bar's space (--bottom-ui) stays the minimum, as in main.css. */
body { padding-bottom: max(var(--bottom-ui, 0px), var(--banner-h, 0px)); }

/* The map panel's Google map (1.4.6, T-038; inc/map.php, js/map.js; as express-core 1.3.6). The panel shows the
   pin card with "Show map" and one line about Google; on the click the map fills the panel in place (same size,
   nothing moves) and the card underneath leaves the page and the tab order. Without JavaScript the button and the
   line are hidden. */
.map-embed__show { background: #fff; }
.map-embed__note {
  max-width: 44ch;
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--c-text-2, var(--c-muted));
  text-wrap: balance;
}
.no-js .map-embed__show,
.no-js .map-embed__note { display: none; }
.map-embed.is-loaded > :not(.map-embed__frame) { visibility: hidden; }
.map-embed__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: #E7E5DE;
}
.map-embed__frame:focus-visible {
  outline: 3px solid var(--c-accent-ink, currentColor);
  outline-offset: -3px;
}
