/* ==========================================================================
   ChannelCore — production additions
   Loaded after channelcore.css. Everything here exists because the production
   build needs something the prototype did not have: a real enquiry form with
   validation states, a keyboard-operable mega-menu caret, and replacements for
   the inline colours that were dropped when the markup was tidied.

   No design decisions are made here. Colours and spacing come from the tokens
   already defined in channelcore.css.
   ========================================================================== */

/* ------------------------------------------------ screen-reader-only text */
/* Used to extend repeated link text ("Read the story") with the thing it
   refers to, so a screen reader's list of links is not four identical rows. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ------------------------------------------------------ mega-menu caret */
/* The caret is a <button> rather than a <span> inside the nav link, so that it
   is reachable by keyboard and can announce its expanded state. These rules
   strip the button chrome so it looks exactly as it did before. */
.nav-caret {
  background: none;
  border: 0;
  padding: 0 4px 0 2px;
  margin: 0;
  font: inherit;
  font-size: 9px;
  line-height: 1;
  color: inherit;
  opacity: .55;
  cursor: pointer;
}

.nav-caret:hover {
  opacity: 1;
}

/* The caret sits directly against its link, so the pair still reads as one
   nav item rather than two controls with a gap between them. */
.nav-item.has-mega > .nav-link {
  padding-right: 4px;
}

/* --------------------------------------------------------------- forms */
.form-row legend {
  display: block;
  padding: 0;
  font-size: 14px;
  font-weight: 500;
  color: var(--navy);
}

/* fieldset carries the browser's own border and padding; the form's rows are
   separated by spacing, not boxes. */
.form-row:is(fieldset) {
  border: 0;
  padding: 0;
  margin-inline: 0;
  min-width: 0;
}

/* Enquiry form interests (snag list 2026-10-31): each pillar's box with its
   product dropdown beside it, stacking on a narrow form. The dropdown is not
   full width like other fields, so the box and its label keep their room. */
.interest-list {
  display: grid;
  gap: 10px;
}

.interest-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  align-items: center;
  gap: 8px 14px;
}

.interest-row .checkbox-row {
  margin: 0;
  font-weight: 400;
}

.interest-row select {
  padding-block: 8px;
  font-size: 14px;
}

@media (max-width: 640px) {
  .interest-row { grid-template-columns: 1fr; }
}

.form-row textarea {
  resize: vertical;
  min-height: 6em;
}

.form-row .req {
  color: var(--teal);
  font-weight: 700;
}

.form-row.has-error input,
.form-row.has-error select,
.form-row.has-error textarea {
  border-color: #B3261E;
}

.field-error {
  margin: 6px 0 0;
  font-size: 13.5px;
  /* Colour is not the only signal: the message itself names the problem, and
     the input carries aria-invalid. */
  color: #B3261E;
}

.form-status {
  border-radius: var(--r-sm);
  padding: 16px 18px;
  margin-bottom: var(--s-3);
}

.form-status p {
  margin: 0;
  max-width: none;
}

.form-status-error {
  border: 1px solid #B3261E;
  background: #FDF3F2;
  color: #7A1B15;
}

.form-status-error a {
  color: #7A1B15;
  text-decoration: underline;
}

.form-status-ok {
  padding: var(--s-4);
}

.form-status-ok h3 {
  margin-top: 0;
}

.form-note {
  font-size: 13.5px;
  color: var(--muted);
  margin: 0 0 var(--s-2);
}

.form-note a {
  color: var(--teal);
}

/* Honeypot. Hidden from people without display:none, which some bots detect
   and skip. Kept out of the tab order by tabindex="-1" in the markup and out
   of the accessibility tree by aria-hidden. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ------------------------------------------------------------ quotes */
/* The testimonial quotes are wrapped in <blockquote> here, which the prototype
   did not do — a quotation marked up as a quotation. The browser's default
   blockquote margin would otherwise indent them away from the design. */
.quote-slide blockquote,
.quote-slide-v2 blockquote {
  margin: 0;
  padding: 0;
  border: 0;
}

/* The partner's company logo, where one has been uploaded, in place of the
   initial circle. Logos come in every shape, so the box bounds both sides and
   the image keeps its own proportions inside it: a square mark sits at the
   initial's height, a wide wordmark gets more room. */
.quote-slide-v2 .who-logo {
  flex: 0 0 auto;
  display: block;
  width: auto;
  height: auto;
  max-width: 120px;
  max-height: 44px;
  object-fit: contain;
}

/* ------------------------------------------------- carousel slide state */
/* Slides that are off-screen are marked inert by site.js. In browsers without
   inert support the attribute is inconsequential, so this is belt and braces
   for pointer interaction only. */
.carousel-slide[inert] {
  pointer-events: none;
}

/* Every slide in a carousel is as tall as the tallest one, but the navy panel
   inside it was only as tall as its own copy. On Why Partner that left a
   white band under the shorter slides, between the panel and the arrows.
   Scoped to media slides with :has(): quote slides centre themselves with
   auto margins, which a flex parent would shrink to fit. */
.carousel-slide:has(> .media-slide, > .media-slide-v2) {
  display: flex;
}

.carousel-slide > .media-slide,
.carousel-slide > .media-slide-v2 {
  flex: 1;
}

/* ------------------------------------------------- header nav spacing */
/* The prototype let nav labels wrap: "Why Partner with us" and "Core
   Business Solutions" broke onto two lines while "Resources" sat on one, so
   the row read as ragged clumps rather than evenly spaced items. The labels
   never fit on one line at the 1180px content width -- logo, four labels and
   three CTAs need roughly 1140px before a single pixel of padding -- so
   stopping the wrap on its own would only have traded wrapping for overflow.
   The header therefore gets its own, wider container.

   Everything here is scoped to the desktop nav. Below 980px styles.css turns
   the same markup into a stacked mobile panel where full-width links and a
   zero gap are correct, and production.css loads last, so an unscoped rule
   would silently win there. */
@media (min-width: 981px) {
  .site-header .container {
    max-width: 1320px;
  }

  /* .nav-link is display:flex, so it is block-level and the sibling caret
     button was being pushed onto a second line inside the item. That made
     every mega-menu item two lines tall, and the list's align-items:center
     then dropped the single-line "Partner Portal" to the middle of them --
     which is the misalignment, not anything to do with the gap. Making the
     item itself a flex row puts the caret back beside its label. */
  .main-nav .nav-item {
    display: flex;
    align-items: center;
  }

  .main-nav .nav-item .nav-link {
    white-space: nowrap;
    /* Spacing comes from the list gap alone. With padding on the links too,
       an item carrying a caret sits closer to its neighbour than one without
       -- which is the unevenness this is meant to remove. */
    padding-left: 0;
    padding-right: 0;
  }

  /* channelcore.css insets the hover underline 12px to match the padding it
     assumed. With the padding gone that would leave the rule floating short
     of the word at both ends. */
  .main-nav .nav-item .nav-link::after {
    left: 0;
    right: 0;
  }

  /* The caret's own right padding would otherwise be added to the gap after
     every mega-menu item, leaving those four pairs 4px wider than the rest.
     Its 2px left padding still holds it off its label. */
  .main-nav .nav-caret {
    padding-right: 0;
  }

  /* The mega panel hangs 10px below its nav item. Without something filling
     that gap the pointer leaves the item on the way down, and the menu closes
     before it can be reached. This invisible strip makes the item and its
     panel one continuous hover target; site.js adds a short grace period on
     top, for overshooting the edge on the way to a far column. */
  .nav-item.has-mega.open::after {
    content: "";
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 12px;
  }

  .main-nav > ul {
    gap: 26px;
  }

  /* Below the wider container the bar has to give something back. Tighten
     first; only when that is exhausted drop "Book a meeting", the one header
     CTA with no destination yet. */
  @media (max-width: 1320px) {
    .main-nav > ul { gap: 18px; }
  }

  @media (max-width: 1180px) {
    .main-nav > ul { gap: 12px; }
    .main-nav .nav-item .nav-link { font-size: 14px; }
    .header-ctas .btn-outline:first-child { display: none; }
  }
}

/* ----------------------------------------------------------- footer logo */
/* The footer used to sit the logo on a white plaque, because the only logo
   asset has an opaque white background baked into the PNG and would otherwise
   have shown as a white block on the navy footer. channelcore.css already
   tried to remove the plaque, but its `.logo-chip-white` rule lost on
   specificity to `.footer-brand .logo-chip-white` in styles.css, so the plaque
   stayed. The markup now uses a reversed, transparent logo instead and needs
   no plaque at all. */
.footer-brand .footer-logo {
  height: 40px;
  width: auto;
  margin-bottom: 16px;
}

/* --------------------------------------------------- pillar capability panel */
/* Replaces the flat PNG that used to sit in the right-hand column of each
   pillar on Our Core Solutions.

   Borrowed from Veeam: eyebrow above heading, a generous surface with real
   breathing room, capabilities as scannable rows rather than a dense bullet
   list, and one accent doing the signposting. NOT borrowed: its soft drop
   shadows. This design system is explicit that content uses 1px rules and no
   shadows, and mixing the two would read as two sites stitched together. The
   depth here comes from a tinted surface and a rule instead. */
.pillar-head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: var(--s-1);
}

.pillar-head h2 {
  margin: 0;
}

.brochure-row {
  margin-top: 12px;
}

/* The Partner Programme brochure button on Why Partner: one button, centred
   under the benefits grid like the section heading above it. */
.programme-cta {
  justify-content: center;
  margin-top: var(--s-4);
}

/* The one-line close of the home page's About section ("One ecosystem. One
   relationship. Unlimited potential."): set apart from the paragraphs above
   it without becoming a heading. */
.about-v2 .tagline {
  font-weight: 600;
  color: var(--navy);
}

.pillar-panel {
  background: var(--surface-alt);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: var(--s-3);
}

.pillar-panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-2);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--rule);
}

.pillar-panel-head .eyebrow {
  margin: 0;
}

/* The pillar's position in the set: quiet, tabular, and never competing with
   the capability names for attention. */
.pillar-count {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  white-space: nowrap;
}

.pillar-count i {
  font-style: normal;
  opacity: .45;
  padding: 0 2px;
}

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

.capability-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 4px;
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-body);
  font-size: 15.5px;
  color: var(--ink);
}

/* No trailing rule: the panel's own border already closes the list, and a
   second line there reads as an empty row. */
.capability-list li:last-child {
  border-bottom: none;
  padding-bottom: 4px;
}

/* A small accent bar rather than a bullet or a tick. A tick claims these are
   things you already have; a bar just marks the row. */
.cap-mark {
  flex: 0 0 auto;
  width: 3px;
  height: 18px;
  border-radius: 2px;
  background: var(--teal);
  opacity: .55;
  transition: opacity .18s var(--ease), height .18s var(--ease);
}

.capability-list li:hover .cap-mark {
  opacity: 1;
  height: 22px;
}

@media (prefers-reduced-motion: reduce) {
  .cap-mark {
    transition: none;
  }
  .capability-list li:hover .cap-mark {
    height: 18px;
  }
}

@media (max-width: 640px) {
  .pillar-panel {
    padding: var(--s-2);
  }
  .capability-list li {
    font-size: 15px;
    padding: 12px 2px;
  }
}

/* On a tinted pillar section the panel would vanish into the background, so
   it swaps to the plain surface -- the same move the service cards make. */
section.alt .pillar-panel {
  background: var(--surface);
}

/* In the panel each row is a link down to its service card. Ink rather than
   link colour: the rows are a contents list, and a block of teal would shout
   louder than the heading above it. */
.capability-list a.cap-text {
  flex: 1;
  color: var(--ink);
  text-decoration: none;
}

.capability-list a.cap-text:hover,
.capability-list a.cap-text:focus-visible {
  color: var(--teal-dark);
  text-decoration: underline;
}

/* --------------------------------------------------------- service cards */
/* One card per service under each pillar on Our Core Solutions: description,
   capabilities, outcomes. Same rules as the panel above -- a 1px rule and a
   surface change for depth, no shadow. */
.service-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3);
  margin-top: var(--s-5);
}

/* Where the pop-out runs, the cards are its source rather than part of the
   page: the "What's included" list opens each one. They stay in the markup
   for search engines and as the no-JavaScript fallback. See header.php. */
.has-dialog .service-grid {
  display: none;
}

.service-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  padding: var(--s-3);
  /* Clears the sticky header when arriving from the mega-menu. */
  scroll-margin-top: 110px;
  position: relative;
  transition: transform .2s var(--ease), box-shadow .2s var(--ease), border-color .2s var(--ease);
}

/* Only seen where the cards are on the page -- without JavaScript or <dialog>;
   otherwise they are hidden and open in the pop-out instead.
   The card lifts towards the reader: on hover, while it has focus (a click
   opens it in the pop-out dialog below, and focus comes back to it on close,
   so the card last opened stays marked), and when arrived at from a link. Marketing asked for the cards to "pop out" (2026-10-09), and this is
   the one place the no-shadow rule above gives way -- a lift with no shadow
   under it reads as the card sliding, not rising. Hover is limited to devices
   that can hover, so a tap on a phone does not leave a card stuck up. */
.service-card:focus,
.service-card:target {
  z-index: 1;
  outline: none;
  border-color: var(--teal);
  transform: translateY(-6px) scale(1.02);
  box-shadow: 0 18px 40px -18px rgba(14, 26, 51, .35), inset 0 0 0 1px var(--teal);
}

@media (hover: hover) and (pointer: fine) {
  .service-card {
    cursor: pointer;
  }

  .service-card:hover {
    z-index: 1;
    border-color: var(--teal);
    transform: translateY(-6px) scale(1.02);
    box-shadow: 0 18px 40px -18px rgba(14, 26, 51, .35);
  }
}

/* ------------------------------------------------ service pop-out dialog */
/* Opened by site.js from a pillar's "What's included" list or a card: the
   card's contents, larger, over a dimmed page. The <dialog> itself is an
   unpadded full-size box so that a click on the backdrop is distinguishable
   from a click inside (see site.js). */
.service-dialog {
  width: min(720px, calc(100% - 32px));
  max-height: calc(100vh - 48px);
  padding: 0;
  border: 0;
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--body);
  box-shadow: 0 30px 80px -20px rgba(14, 26, 51, .45);
  overflow: hidden;
}

.service-dialog[open] {
  display: flex;
  animation: service-pop .22s var(--ease);
}

.service-dialog::backdrop {
  background: rgba(14, 26, 51, .55);
}

/* The page behind does not scroll under the dialog. */
html.service-dialog-open {
  overflow: hidden;
}

@keyframes service-pop {
  from { opacity: 0; transform: translateY(12px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

.service-dialog-inner {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-height: calc(100vh - 48px);
  border-top: 4px solid var(--teal);
}

.service-dialog-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  padding: 14px var(--s-3);
  border-bottom: 1px solid var(--rule);
}

.service-dialog-where {
  font-size: 13px;
  font-weight: 600;
  color: var(--teal);
}

.service-dialog-close {
  width: 36px;
  height: 36px;
  border: 1px solid var(--rule);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.service-dialog-close:hover,
.service-dialog-close:focus-visible {
  border-color: var(--teal);
  color: var(--teal);
}

/* The only part that scrolls, so the bar and the buttons stay in view on a
   short screen with a long list. */
.service-dialog-body {
  padding: var(--s-3);
  overflow-y: auto;
}

.service-dialog-body h3 {
  margin: 0 0 var(--s-1);
  font-size: 28px;
}

.service-dialog-body .service-desc {
  font-size: 17px;
  max-width: none;
}

.service-dialog-body .service-caps {
  margin-bottom: var(--s-3);
}

.service-dialog-body .service-caps li {
  font-size: 15.5px;
}

.service-dialog-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px var(--s-3);
  border-top: 1px solid var(--rule);
  background: var(--surface-alt);
}

.service-dialog-nav button[disabled] {
  opacity: .35;
  cursor: default;
}

@media (max-width: 640px) {
  .service-dialog-body,
  .service-dialog-bar,
  .service-dialog-nav {
    padding-left: var(--s-2);
    padding-right: var(--s-2);
  }
  .service-dialog-body h3 {
    font-size: 23px;
  }
  /* Three buttons do not fit a phone's width side by side: the contact link
     takes the top row, Previous and Next share the one below. */
  .service-dialog-nav {
    flex-wrap: wrap;
  }
  .service-dialog-talk {
    order: -1;
    flex: 1 0 100%;
    text-align: center;
    justify-content: center;
  }
  .service-dialog-prev,
  .service-dialog-next {
    flex: 1;
    justify-content: center;
  }
}

@media (prefers-reduced-motion: reduce) {
  .service-dialog[open] {
    animation: none;
  }
}

/* Single column: the card already spans the screen, so growing it would push
   past the edge and scroll the page sideways. It only rises. */
@media (max-width: 860px) {
  .service-card:focus,
  .service-card:target {
    transform: translateY(-4px);
  }
}

/* No movement for anyone who has asked for less of it; the border and shadow
   still mark the card. */
@media (prefers-reduced-motion: reduce) {
  .service-card {
    transition: none;
  }

  .service-card:hover,
  .service-card:focus,
  .service-card:target {
    transform: none;
  }
}

.service-card h3 {
  margin: 0 0 var(--s-1);
}

.service-desc {
  font-size: 15.5px;
}

/* Two columns where the card is wide enough: the longest list (Cyber
   Security, eleven items) would otherwise make its card twice the height of
   its neighbour. */
.service-caps {
  list-style: none;
  margin: 0 0 var(--s-3);
  padding: 0;
  columns: 2 200px;
  column-gap: var(--s-3);
}

.service-caps li {
  position: relative;
  break-inside: avoid;
  padding: 5px 0 5px 16px;
  font-size: 14.5px;
  line-height: 1.45;
  color: var(--body);
}

.service-caps li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(5px + .7em);
  width: 7px;
  height: 2px;
  border-radius: 1px;
  background: var(--teal);
}

/* Pinned to the foot of the card, so outcomes line up across a row whatever
   the length of the lists above them. */
.service-outcome {
  margin-top: auto;
  padding-top: var(--s-2);
  border-top: 1px solid var(--rule);
}

.service-outcome .eyebrow {
  margin-bottom: 4px;
}

.service-outcome p {
  margin: 0;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
}

/* "Talk to us about this" under the outcomes. A card with no outcomes pins
   the button to the foot itself, so buttons still share a line across a row. */
.service-cta {
  align-self: flex-start;
  margin-top: var(--s-2);
}

.service-desc + .service-cta,
.service-caps + .service-cta {
  margin-top: auto;
}

@media (max-width: 860px) {
  .service-grid {
    grid-template-columns: 1fr;
    margin-top: var(--s-4);
  }
}

@media (max-width: 640px) {
  .service-card {
    padding: var(--s-2);
  }
}

/* ------------------------------------------------ events and blog cards */
/* Date and location line, shown only when the record actually has one. */
.event-card .event-when,
.blog-card .event-when {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 6px;
}

.event-card .event-link {
  font-size: 13px;
  font-weight: 600;
  color: var(--teal);
  margin-left: auto;
}

.event-card .pill-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* A real image replaces the text thumbnail once one is set. Cropped to one
   shape, so a row of cards with differently-sized uploads still lines up. */
.blog-card img.thumb,
.event-card img.thumb {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
  background: var(--grey-100);
}

/* ------------------------------------------------- case-study media */
/* An uploaded image fills the navy band behind the label and title. The
   gradient darkens the bottom, where the text is, so white stays readable
   whatever the photo; the band keeps its height, so cards with and without
   an image line up. */
.case-card-v2 .case-thumb-v2.has-image {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.case-card-v2 .case-thumb-v2 .case-thumb-img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.case-card-v2 .case-thumb-v2.has-image::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top, rgba(14, 26, 51, .88) 0%, rgba(14, 26, 51, .35) 70%, rgba(14, 26, 51, .15) 100%);
}

/* The client's logo above the summary, bounded the way testimonial logos
   are: a square mark and a wide wordmark both fit without distortion. */
.case-body-v2 .case-logo,
.article-prose .article-logo {
  display: block;
  width: auto;
  height: auto;
  max-width: 140px;
  max-height: 44px;
  object-fit: contain;
  margin: 0 0 12px;
}

.article-prose .article-logo {
  max-width: 200px;
  max-height: 64px;
  margin-bottom: 1.2em;
}

/* ------------------------------------------------ infographic icons */
/* The icon set carries geometry only; each context sets size and colour.
   These are the contexts added for marketing's second round of changes. */
.step-icon svg,
.icon-grid svg,
.journey-icon svg,
.equation-icons .ic svg,
.tier-grid svg {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ---------------------------------------------- cross-fading carousel */
/* A carousel whose slides share one grid cell and fade, rather than sliding
   along a track. The engine still sets translateX on the track, so that is
   overridden. The engine marks the current slide aria-hidden="false"; before
   it runs, or without JavaScript, the first slide is the visible one. */
.carousel-fade .carousel-slides {
  display: grid;
  transform: none !important;
  transition: none;
}

.carousel-fade .carousel-slide {
  grid-area: 1 / 1;
  min-width: 0;
  opacity: 0;
  transition: opacity .6s var(--ease);
}

.carousel-fade .carousel-slide:first-child {
  opacity: 1;
}

.carousel-fade .carousel-slide[aria-hidden="true"] {
  opacity: 0;
}

.carousel-fade .carousel-slide[aria-hidden="false"] {
  opacity: 1;
}

/* Pause / play for auto-advancing carousels: two bars while playing, a
   triangle once paused. The aria-label says which. */
.carousel-pause {
  width: 32px;
  height: 32px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, .3);
  border-radius: var(--r-sm);
  color: #fff;
  cursor: pointer;
}

.carousel-pause:hover {
  border-color: #fff;
}

.carousel-pause::before {
  content: "";
  box-sizing: border-box;
  width: 9px;
  height: 11px;
  border-left: 3px solid currentColor;
  border-right: 3px solid currentColor;
}

.carousel-pause.is-paused::before {
  width: 0;
  height: 0;
  margin-left: 2px;
  border-style: solid;
  border-width: 6px 0 6px 10px;
  border-color: transparent transparent transparent currentColor;
}

/* -------------------------------------------------------- hero video */
/* The animation is 5:4 on a pale background; it keeps that shape and sits
   in the hero's right-hand column, vertically centred against the copy. */
.hero-visual-v2 > .hero-video {
  flex: 0 0 auto;
  margin: auto 0;
}

.hero-video {
  position: relative;
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, .16);
  /* The video's own background, so the box does not change colour when the
     poster or first frame arrives. */
  background: #EEEEEE;
}

.hero-video video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 5 / 4;
  object-fit: cover;
}

/* Beside the contact form (2026-10-12). The section takes the video's own
   grey -- #EEEEEE (Our (5), 2026-10-31), measured from the encoded frames, the same value as
   .hero-video's background -- and the video drops its border, so the two
   meet with no visible edge. Re-measure if a new cut changes the background:
     ffmpeg -ss 10 -i channelcore-intro.mp4 -frames:v 1 -vf "crop=20:20:5:5,scale=1:1"
            -f rawvideo -pix_fmt rgb24 - | od -An -tx1 */
.contact-section {
  background: #EEEEEE;
}

/* Snag list (2026-10-31): the email and phone links read as plain text, so
   they carry a standing underline and pick up the accent on hover/focus. */
.contact-section .footer-contact-row a {
  text-decoration: underline;
  text-decoration-color: var(--teal);
  text-underline-offset: 3px;
}

.contact-section .footer-contact-row a:hover,
.contact-section .footer-contact-row a:focus-visible {
  color: var(--teal);
  text-decoration-thickness: 2px;
}

.contact-video {
  margin: 24px 0 0;   /* <figure> brings a 40px side margin of its own */
  border: 0;
  border-radius: 0;
}

/* Over a light video, so it carries its own dark backing. */
.hero-video-toggle {
  position: absolute;
  right: 14px;
  bottom: 14px;
  background: rgba(16, 26, 54, .78);
  border-color: rgba(255, 255, 255, .45);
}

.hero-video-toggle[hidden] {
  display: none;
}

/* Marketing asked (2026-10-09) for the pause button to appear only while the
   pointer is over the video. Limited to devices that can hover: on a touch
   screen there is no hover, and hiding it there would leave no way to stop
   the loop (WCAG 2.2.2). Opacity rather than visibility, so it stays in the
   tab order and shows when it takes keyboard focus. It also stays visible
   while paused, so a stopped video -- or one whose autoplay the browser
   refused -- always shows how to start it. */
@media (hover: hover) and (pointer: fine) {
  .hero-video-toggle {
    opacity: 0;
    transition: opacity .2s var(--ease);
  }

  .hero-video:hover .hero-video-toggle,
  .hero-video-toggle:focus-visible,
  .hero-video-toggle.is-paused {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .hero-video-toggle {
    transition: none;
  }
}

/* ------------------------------------------------------- hero slider */
.hero-slider {
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, .03);
}

.hero-slider .carousel-track {
  flex: 1;
  display: flex;
  border-radius: 0;
}

.hero-slider .carousel-slides {
  flex: 1;
}

.hero-slider .carousel-slide {
  display: flex;
}

.hero-slide {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--s-4) var(--s-4) var(--s-3);
}

.hero-slide p {
  margin: 0;
  max-width: 26ch;
  font-family: var(--font-display);
  font-size: clamp(22px, 2.2vw, 29px);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: #fff;
}

.hero-slide .eyebrow {
  color: var(--teal-bright);
}

.hero-slide-logo img {
  width: min(300px, 80%);
  height: auto;
  margin-bottom: var(--s-3);
}

.hero-slide-logo p {
  color: var(--teal-bright);
  font-size: clamp(19px, 1.8vw, 23px);
}

/* Dots and pause share the foot of the box, lined up with the copy above. */
.hero-slider .carousel-nav {
  margin: 0;
  padding: 0 var(--s-4) var(--s-3);
  justify-content: space-between;
}

.hero-slider .carousel-dot {
  background: rgba(255, 255, 255, .3);
}

.hero-slider .carousel-dot.active {
  background: var(--teal-bright);
}

@media (max-width: 640px) {
  .hero-slide {
    padding: var(--s-3) var(--s-3) var(--s-2);
  }
  .hero-slider .carousel-nav {
    padding: 0 var(--s-3) var(--s-2);
  }
}

/* ------------------------------------------ process infographic (home) */
/* The section runs wider than the usual 1180px content width, and the copy
   column gives up most of it, so that five steps and the outcome chips each
   fit on one row and the slide stays short (marketing asked for thinner
   cards). The wider limit only matters on screens over 1180px; below that
   the viewport is the limit, as it is for every other section. */
.container.container-wide {
  max-width: 1400px;
}

.media-slide-v2.has-process {
  grid-template-columns: minmax(0, 5fr) minmax(0, 12fr);
  gap: var(--s-3);
}

@media (max-width: 860px) {
  .media-slide-v2.has-process {
    grid-template-columns: 1fr;
  }
}

.media-visual-v2.infographic {
  display: block;
  min-height: 0;
  padding: var(--s-3);
  container-type: inline-size;
}

.process-title {
  margin: 0 0 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--teal-bright);
}

.process-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 16px;
}

.process-steps li {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 12px;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .04);
}

/* The arrow from one step to the next, centred in the gap between them. */
.process-steps li:not(:last-child)::after {
  content: "\2192";
  position: absolute;
  top: 50%;
  right: -13px;
  transform: translateY(-50%);
  font-size: 13px;
  line-height: 1;
  color: var(--teal-bright);
}

.step-num {
  position: absolute;
  top: 8px;
  right: 10px;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  color: rgba(255, 255, 255, .4);
}

.step-icon {
  color: var(--teal-bright);
}

.step-icon svg {
  display: block;
  width: 26px;
  height: 26px;
}

.step-text strong {
  display: block;
  margin-bottom: 4px;
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #fff;
}

.step-text span {
  display: block;
  font-size: 12.5px;
  line-height: 1.4;
  color: #B4BDD4;
}

.process-outcomes {
  margin-top: var(--s-3);
  padding-top: 14px;
  border-top: 1px solid rgba(255, 255, 255, .14);
}

.process-outcomes ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 8px;
}

/* One row of equal boxes sharing out the panel's width, as in marketing's
   mockup; a long label takes two lines inside its box rather than pushing a
   box onto a second row. Boxes only wrap when the panel itself is narrow
   (the container query below), and then grow so each row ends flush. */
.process-outcomes li {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  line-height: 1.25;
  padding: 6px 8px;
  border: 1px solid rgba(53, 179, 162, .4);
  border-radius: var(--r-xs);
  font-size: 12.5px;
  font-weight: 500;
  color: #CDE8E3;
}

@container (max-width: 640px) {
  .process-outcomes ul {
    flex-wrap: wrap;
  }
  .process-outcomes li {
    flex: 1 1 auto;
  }
}

/* Too narrow for five across: the steps become a list, icon beside text,
   with the arrow turned to point down. */
@container (max-width: 520px) {
  .process-steps {
    grid-template-columns: 1fr;
    gap: 14px;
  }
  .process-steps li {
    flex-direction: row;
    align-items: center;
    gap: 14px;
    padding: 10px 36px 10px 14px;
  }
  .process-steps li:not(:last-child)::after {
    top: auto;
    right: auto;
    bottom: -12px;
    left: 26px;
    transform: rotate(90deg);
    font-size: 11px;
  }
  .step-num {
    top: 50%;
    transform: translateY(-50%);
  }
}

/* ------------------------------------- Why Partner slide infographics */
/* Slide 01: Partner + Technology + Enablement, an icon over each term, with
   the sum on its own row under a rule (marketing's mockup, 2026-10-01). */
.equation-icons {
  width: 100%;
  justify-content: center;
  align-items: flex-end;
  gap: 18px 26px;
}

.equation-icons .term {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  border-top: none;
  padding: 0;
  text-align: center;
}

.equation-icons .term .ic {
  display: block;
  color: var(--teal-bright);
}

.equation-icons .term .ic svg {
  display: block;
  width: 44px;
  height: 44px;
}

.equation-icons .term strong {
  font-size: 13px;
  letter-spacing: .06em;
  text-transform: uppercase;
}

.equation-icons > .op {
  align-self: center;
  padding: 0;
  font-size: 26px;
  font-weight: 400;
}

.equation-sum {
  flex-basis: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  padding-top: 18px;
  border-top: 1px solid rgba(255, 255, 255, .24);
}

.equation-sum .op {
  align-self: center;
  padding: 0;
  font-size: 26px;
  font-weight: 400;
}

.equation-icons .term.result {
  flex-direction: row;
  gap: 12px;
}

.equation-icons .term.result .ic svg {
  width: 32px;
  height: 32px;
}

/* Slide 03: the programme, two columns with an icon beside each item. */
.media-visual .tier-grid {
  list-style: none;
  margin: 0;
  width: 100%;
  column-gap: 24px;
}

.tier-grid li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-top: 1px solid rgba(255, 255, 255, .14);
  font-size: 13.5px;
  line-height: 1.3;
  color: #D3DAEA;
}

.tier-grid li span {
  padding: 0;
  border: none;
  font-size: inherit;
  color: inherit;
}

.tier-grid svg {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  color: var(--teal-bright);
}

/* Slide 02: the six reasons, as an icon grid. */
.icon-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 22px 16px;
}

.icon-grid li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  text-align: center;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  color: #fff;
}

.icon-grid svg {
  width: 38px;
  height: 38px;
  color: var(--teal-bright);
}

/* Slide 04: the partner journey, top to bottom on one connecting line. */
.journey {
  width: 100%;
  text-align: left;
}

.journey-title {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 700;
  color: var(--teal-bright);
}

.journey-list {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

.journey-list::before {
  content: "";
  position: absolute;
  top: 14px;
  bottom: 14px;
  left: 14px;
  width: 1px;
  background: var(--teal-bright);
}

.journey-list li {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 5px 0;
}

.journey-icon {
  flex: 0 0 auto;
  width: 29px;
  height: 29px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Turquoise like the "Your Partner Journey" title (marketing, 2026-10-01). */
  border: 1px solid var(--teal-bright);
  border-radius: 50%;
  background: var(--navy);
  color: var(--teal-bright);
}

.journey-icon svg {
  width: 16px;
  height: 16px;
}

.journey-text {
  padding-top: 4px;
  font-size: 13px;
  line-height: 1.45;
  color: #B4BDD4;
}

.journey-text strong {
  margin-right: 4px;
  color: #fff;
}

@media (max-width: 640px) {
  .icon-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --------------------------------------------------------- legal pages */
/* The Privacy Notice and anything else written in the console's legal-page
   editor. Long-form reading, so a narrower measure than the marketing pages
   and real spacing between sections. */
.legal-prose {
  max-width: 760px;
  color: var(--grey-700);
  line-height: 1.7;
}

.legal-prose h2 {
  color: var(--navy);
  margin: 2.2em 0 .5em;
  /* Clears the sticky header when arriving at /privacy-notice.php#section. */
  scroll-margin-top: 110px;
}

.legal-prose h3 {
  color: var(--navy);
  margin: 1.6em 0 .4em;
  scroll-margin-top: 110px;
}

.legal-prose > :first-child { margin-top: 0; }
.legal-prose ul, .legal-prose ol { padding-left: 1.4em; margin: 0 0 1em; }
/* styles.css strips list markers from every <ul>; prose lists need them back. */
.legal-prose ul { list-style: disc; }
.legal-prose ol { list-style: decimal; }
.legal-prose li { margin-bottom: .35em; }
.legal-prose a { color: var(--teal-dark); text-decoration: underline; }

/* Case study and blog post pages (includes/article-page.php). They reuse
   .legal-prose for the body, since the text comes from the same formatter. */
.article-prose .article-lead {
  font-size: 1.15em;
  color: var(--navy);
  font-weight: 500;
}

.article-prose .article-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  margin: 0 0 1.6em;
}

.article-prose .article-back {
  margin-top: 2.5em;
}

/* Cookie notice (includes/cookie_notice.php). Fixed to the foot of the
   viewport and never modal: it explains, it does not ask, so nothing on the
   page is blocked behind it. Above the sticky header's stacking level. */
.cookie-notice {
  position: fixed;
  left: 16px;
  right: 16px;
  bottom: 16px;
  z-index: 200;
  max-width: 760px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: 16px 24px;
  padding: 16px 20px;
  background: var(--navy);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--r-md);
  box-shadow: 0 10px 30px rgba(8, 16, 31, .35);
  font-size: 14px;
  line-height: 1.5;
}

.cookie-notice p { margin: 0; flex: 1 1 auto; color: #fff; }
.cookie-notice a { color: var(--teal-bright); text-decoration: underline; }
.cookie-notice form { flex: 0 0 auto; margin: 0; }

@media (max-width: 640px) {
  .cookie-notice { flex-direction: column; align-items: stretch; }
  .cookie-notice .btn { width: 100%; justify-content: center; }
}

@media print {
  .cookie-notice { display: none; }
}

/* ------------------------------------------------------------ website chat */
/* The chat window (includes/footer.php, assets/js/chat.js). A launcher fixed
   to the bottom right, opening a panel above it. Sits just under the cookie
   notice's stacking level so the notice can always be read and closed. */
.chat [hidden] { display: none !important; }

.chat-fab {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 190;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 18px;
  border: 0;
  border-radius: 999px;
  background: var(--purple);
  color: #fff;
  font: 600 14.5px/1 var(--font-body);
  box-shadow: 0 10px 24px rgba(8, 16, 31, .28);
  cursor: pointer;
}
.chat-fab:hover { background: var(--purple-deep); }
/* A reply from the team arrived while the window was minimised. */
.chat-fab-alert::after {
  content: ""; position: absolute; top: -2px; right: -2px;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--teal-bright); border: 2px solid #fff;
}
.chat-fab:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.chat-fab svg {
  width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}

.chat-panel {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 190;
  width: 400px;
  max-width: calc(100vw - 32px);
  /* Grows with the conversation, up to the viewport; past that only the
     message list scrolls, so the header and the reply box stay in view. */
  height: auto;
  max-height: min(680px, calc(100vh - 40px));
  margin: 0;
  /* The site gives every <section> 96px of vertical padding for page
     layout. This one is a dialog, not a page section. */
  padding: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--r-md);
  box-shadow: 0 18px 48px rgba(8, 16, 31, .28);
  overflow: hidden;
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink);
}
/* The site's p rule sets a colour, a margin and a reading measure, all wrong
   inside a chat bubble. */
.chat-panel p { max-width: none; }

.chat-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  background: var(--navy);
  color: #fff;
}
.chat-head h2 { margin: 0; font: 700 17px/1.2 var(--font-display); letter-spacing: 0; color: #fff; }
.chat-head p { margin: 2px 0 0; font-size: 12.5px; color: #c4cae2; }
.chat-x {
  width: 32px; height: 32px; flex: 0 0 auto;
  border: 1px solid rgba(255, 255, 255, .24); border-radius: var(--r-sm);
  background: transparent; color: #fff; font-size: 18px; line-height: 1; cursor: pointer;
}
.chat-x:hover { border-color: var(--teal-bright); color: var(--teal-bright); }

.chat-log {
  flex: 1 1 auto;
  min-height: 180px;
  margin: 0;
  padding: 16px;
  list-style: none;
  overflow-y: auto;
  background: var(--surface-alt);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.chat-msg {
  max-width: 85%;
  padding: 10px 12px;
  border-radius: var(--r-md);
  line-height: 1.45;
}
.chat-msg p { margin: 0; color: inherit; white-space: pre-line; overflow-wrap: anywhere; }
.chat-msg a { display: inline-block; margin-top: 6px; font-weight: 600; color: var(--teal); }
.chat-msg-bot, .chat-msg-staff { align-self: flex-start; background: var(--surface); border: 1px solid var(--rule); }
.chat-msg-visitor { align-self: flex-end; background: var(--purple); color: #fff; }
.chat-msg-system {
  align-self: center; max-width: 100%; padding: 2px 8px;
  background: none; color: var(--muted); font-size: 12.5px; text-align: center;
}
.chat-who { display: block; margin-bottom: 2px; font-size: 12px; font-weight: 600; color: var(--teal); }

.chat-typing { display: inline-flex; gap: 4px; padding: 12px 14px; }
.chat-typing span {
  width: 6px; height: 6px; border-radius: 50%; background: var(--muted);
  animation: chat-dot 1s infinite ease-in-out;
}
.chat-typing span:nth-child(2) { animation-delay: .15s; }
.chat-typing span:nth-child(3) { animation-delay: .3s; }
@keyframes chat-dot { 0%, 80%, 100% { opacity: .3; } 40% { opacity: 1; } }

.chat-suggest, .chat-actions, .chat-compose, .chat-error { flex: 0 0 auto; }
.chat-suggest {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 10px 16px 0;
}
.chat-suggest:empty { display: none; }
.chat-chip {
  padding: 6px 10px;
  border: 1px solid var(--teal);
  border-radius: 999px;
  background: var(--surface);
  color: var(--teal);
  font: 500 13px/1.2 var(--font-body);
  cursor: pointer;
}
.chat-chip:hover { background: var(--teal-wash); }

.chat-actions {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 16px 0;
}
.chat-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--teal);
  font: 600 13px/1.4 var(--font-body);
  text-decoration: underline;
  cursor: pointer;
}
.chat-link-emphasis {
  padding: 5px 10px;
  border-radius: var(--r-sm);
  background: var(--teal);
  color: #fff;
  text-decoration: none;
}

.chat-error {
  margin: 8px 16px 0;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  background: #FDECEC;
  color: #8A1C1C;
  font-size: 13px;
}

.chat-compose {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  padding: 10px 16px 14px;
}
.chat-compose textarea {
  flex: 1 1 auto;
  min-height: 40px;
  max-height: 120px;
  padding: 9px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  font: inherit;
  resize: none;
}
.chat-compose button {
  width: 40px; height: 40px; flex: 0 0 auto;
  border: 0; border-radius: var(--r-sm);
  background: var(--purple); color: #fff; font-size: 16px; cursor: pointer;
}
.chat-compose button:hover { background: var(--purple-deep); }
.chat-compose textarea:focus-visible,
.chat-followup input:focus-visible,
.chat-followup textarea:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }

.chat-followup {
  flex: 0 1 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 16px 14px;
  border-top: 1px solid var(--rule);
  overflow-y: auto;
}
.chat-followup-intro { margin: 0 0 6px; font-size: 13.5px; }
.chat-followup label { font-size: 13px; font-weight: 600; }
.chat-followup input,
.chat-followup textarea {
  padding: 8px 10px;
  border: 1px solid var(--rule);
  border-radius: var(--r-sm);
  font: inherit;
}
.chat-optional { font-weight: 400; color: var(--muted); }
.chat-field-error { min-height: 0; font-size: 12.5px; color: #8A1C1C; }
.chat-small { margin: 6px 0 0; font-size: 12px; color: var(--muted); }
.chat-small a { color: var(--teal); }
.chat-followup-actions { display: flex; align-items: center; gap: 14px; margin-top: 8px; }

/* Off-screen rather than display:none, so form bots still find and fill it. */
.chat-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

@media (max-width: 640px) {
  .chat-fab { right: 16px; bottom: 16px; }
  .chat-fab span { display: none; }   /* icon only: the label covers too much page */
  .chat-fab { padding: 14px; }
  .chat-panel { right: 0; bottom: 0; width: 100vw; max-width: 100vw; height: 100dvh; max-height: 100dvh; border-radius: 0; }
}

@media print {
  .chat { display: none; }
}

/* ------------------------------------------------------------- Our Team */
/* The number of people is set in the console (migration 017), so the cards
   wrap and centre rather than filling a fixed four-column grid -- three
   people sit in the middle, not in the left three quarters. */
.avatar-grid { display: flex; flex-wrap: wrap; justify-content: center; }
.avatar-grid .avatar-card { flex: 0 1 calc((100% - 60px) / 4); min-width: 200px; padding: 24px 16px 20px; }
.avatar-card .avatar-photo { display: block; object-fit: cover; background: var(--grey-100); }

@media (max-width: 640px) {
  .avatar-grid .avatar-card { flex-basis: 100%; }
}

/* ------------------------------------------------------- coming soon */
/* A feature that is not built yet (coming_soon() in components.php): the
   link's own shape, greyed, with "Coming soon" on a line underneath. It is
   a span, so there is no hover or focus state to undo -- only the colours. */
.is-soon { cursor: not-allowed; }
.is-soon small {
  display: block;
  margin-top: 2px;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
}

.btn.is-soon,
.btn.is-soon:hover {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.15;
  padding-block: 7px;
  background: var(--surface-alt);
  border-color: var(--rule);
  color: var(--muted);
}

.btn-sm.is-soon { padding-block: 4px; }

/* On a dark band (the Partner Portal hero), grey that reads on navy. */
.dark .btn.is-soon,
.dark .btn.is-soon:hover {
  background: rgba(255, 255, 255, .06);
  border-color: rgba(255, 255, 255, .2);
  color: rgba(255, 255, 255, .5);
}

.site-footer .is-soon {
  display: inline-block;
  font-size: 14px;
  color: rgba(152, 162, 190, .55);
}

/* ---------------------------------------------------------- UI icons */
/* SVG icons from icons.php in place of the Unicode symbols these controls
   used to carry (2026-10-12). Stroked like the pillar icons; each control
   sets the size its old symbol was drawn at. */
.ic svg, .nav-caret svg, .mobile-toggle svg, .carousel-arrow svg,
.back-to-top svg, .chat-x svg, .chat-compose button svg,
.service-dialog-close svg, .socials a svg, .arr svg {
  display: inline-block;
  width: 1em;
  height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -.125em;
}

.nav-caret svg { width: 12px; height: 12px; stroke-width: 2.5; }
.ic svg { width: 16px; height: 16px; }
.mobile-toggle svg { width: 22px; height: 22px; }
.carousel-arrow svg { width: 18px; height: 18px; }
.back-to-top svg { width: 18px; height: 18px; }
.chat-x svg { width: 16px; height: 16px; }
.chat-compose button svg { width: 18px; height: 18px; }
.service-dialog-close svg { width: 18px; height: 18px; }
.socials a svg { width: 14px; height: 14px; }

/* book-a-meeting.php: the booking tool's frame. A fixed height, because
   height:100% has no parent height to resolve against in normal flow. */
.booking-frame {
  display: block;
  width: 100%;
  height: 900px;
  max-height: 85vh;
  min-height: 640px;
  border: 0;
  border-radius: 12px;
  background: #fff;
}
.booking-fallback { margin-top: 16px; font-size: 14px; text-align: center; }

/* FAQ categories collapse to their headings (render_faqs()): the summary
   takes over the heading's rule and carries the same +/- as the questions. */
.faq-group > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 4px;
  border-bottom: 1px solid var(--rule);
}
.faq-group > summary::-webkit-details-marker { display: none; }
.faq-group > summary::after { content: "+"; font-size: 22px; color: var(--purple); flex-shrink: 0; }
.faq-group[open] > summary { border-bottom: 2px solid var(--navy); }
.faq-group[open] > summary::after { content: "–"; }
.faq-group > summary h3 { margin: 0; padding: 0; border-bottom: 0; }
.faq-group[open] { margin-bottom: 24px; }
