/* ===========================================================================
   Appex content blocks

   The nine blocks an author can drop into a body: call to action, callout, pull
   quote, key statistics, gallery, FAQs, video, client review, lead form.

   WHY THIS IS ITS OWN FILE AND NOT §55 OF site-fixes.css. It is loaded twice —
   by the site, and by the admin panel, where the editor draws each block's real
   view as its preview. site-fixes.css could not be the second of those: it is
   two thousand lines of rules aimed at the site's own markup and would take the
   panel apart. This file styles nothing but `.block-*`, so it is safe in both.

   TWO RULES THAT GOVERN EVERY SELECTOR BELOW, both learned by getting them
   wrong:

   1. NO `[data-article]` PREFIX. That attribute is on the article wrapper, and
      the editor's preview has no wrapper — scoping to it would style the site
      and leave the panel bare, which is the problem this file exists to end.

   2. TWO CLASSES WHERE A TAG IS INVOLVED. site-fixes.css §46 styles `p`, `a`,
      `h2`, `h3`, `ul`, `li`, `img` and `blockquote` under `[data-article]`, and
      that is specificity (0,1,1) — one class beats it nowhere. `.block-cta
      .block-cta__text` is (0,2,0) and wins, with no `!important` anywhere.

   NO `data-*` ATTRIBUTE MAY BE USED AS A HOOK. The body sanitiser drops unknown
   data attributes, so `[data-count="3"]` matches in the editor and never on the
   site — a difference that only shows up in production. Layout counts its own
   children instead.

   Palette is the site's: brand #0031BC, ink #152a45, body #3d4f61, hairline
   #e4ebf3, accent #b45f1e.
   =========================================================================== */

.block-cta,
.block-callout,
.block-quote,
.block-stats,
.block-gallery,
.block-faqs,
.block-video,
.block-review,
.block-lead-form {
  /* One rhythm for all nine, so a body that mixes them reads evenly. Matches
     the 38px an <h2> takes above itself in §46. */
  margin: 38px 0;
  /* The blocks are laid out with flex and grid, and an author cannot be asked
     to think about overflow — a long unbroken word in a stat label used to push
     the whole article sideways on a phone. */
  min-width: 0;
}

/* ---------------------------------------------------------------------------
   The editor's own note

   Only ever rendered when a block is asked for its preview: an empty gallery, a
   URL that is not a video, a review that has been unapproved, the FAQs that
   come from the record rather than the block. It says on the page what would
   otherwise be an unexplained blank in the middle of an article.
   --------------------------------------------------------------------------- */
.block-note {
  margin: 0;
  padding: 14px 16px;
  border: 1px dashed #c3d0e0;
  border-radius: 10px;
  background: #f7f9fc;
  color: #5b6b7d;
  font-size: 14px;
  line-height: 1.55;
}

/* ---------------------------------------------------------------------------
   Call to action

   A panel, not a button in a paragraph. The copy and the button sit on one row
   while there is room for both and stack below 560px, where a button sharing a
   row with two lines of text ends up 90px wide.
   --------------------------------------------------------------------------- */
.block-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
  padding: 28px 30px;
  border-radius: 14px;
}

.block-cta__copy {
  flex: 1 1 260px;
  min-width: 0;
}

.block-cta .block-cta__heading {
  margin: 0;
  font-size: 22px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.25;
  color: inherit;
}

.block-cta .block-cta__text {
  margin: 8px 0 0;
  font-size: 16px;
  line-height: 1.6;
  color: inherit;
  /* The panel styles read at full strength on their own ground; this keeps the
     supporting line a step behind the heading without naming a second colour
     for each of the four styles. */
  opacity: 0.86;
}

.block-cta .block-cta__button {
  flex: 0 0 auto;
  display: inline-block;
  padding: 13px 26px;
  border: 2px solid transparent;
  border-radius: 9px;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease;
}

.block-cta .block-cta__button:hover {
  transform: scale(1.04);
}

/* Primary — the one an author gets by default. */
.block-cta--primary {
  background: #0031BC;
  color: #ffffff;
}

.block-cta--primary .block-cta__button {
  background: #ffffff;
  border-color: #ffffff;
  color: #0031BC;
}

.block-cta--primary .block-cta__button:hover {
  background: #60C8FC;
  border-color: #60C8FC;
  color: #0031BC;
}

/* Subtle — for an article that already has a coloured section near it. */
.block-cta--subtle {
  background: #eef3ff;
  border: 1px solid #d6e2fb;
  color: #152a45;
}

.block-cta--subtle .block-cta__button,
.block-cta--outline .block-cta__button {
  background: #0031BC;
  border-color: #0031BC;
  color: #ffffff;
}

.block-cta--subtle .block-cta__button:hover,
.block-cta--outline .block-cta__button:hover {
  background: #084b8f;
  border-color: #084b8f;
}

.block-cta--outline {
  background: transparent;
  border: 2px solid #0031BC;
  color: #152a45;
}

.block-cta--dark {
  background: #152a45;
  color: #ffffff;
}

.block-cta--dark .block-cta__button {
  background: #b45f1e;
  border-color: #b45f1e;
  color: #ffffff;
}

.block-cta--dark .block-cta__button:hover {
  background: #c96f2a;
  border-color: #c96f2a;
}

@media (max-width: 560px) {
  .block-cta {
    padding: 24px 20px;
  }

  /* Full width rather than left-aligned: a 150px button under a full-width
     heading reads as an afterthought. */
  .block-cta .block-cta__button {
    flex: 1 1 100%;
    text-align: center;
  }
}

/* ---------------------------------------------------------------------------
   Callout / note

   Five types, and they differ only in two custom properties, so adding a sixth
   is one rule and no new markup. The badge is drawn here rather than written
   into the template for the same reason.
   --------------------------------------------------------------------------- */
.block-callout {
  --callout-ink: #0031BC;
  --callout-tint: #eef3ff;

  position: relative;
  padding: 18px 22px 18px 58px;
  border: 1px solid transparent;
  border-left: 4px solid var(--callout-ink);
  border-radius: 10px;
  background: var(--callout-tint);
}

.block-callout::before {
  content: var(--callout-mark, "i");
  position: absolute;
  top: 18px;
  left: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--callout-ink);
  color: #ffffff;
  font-size: 14px;
  font-weight: 700;
  line-height: 1;
}

.block-callout .block-callout__title {
  margin: 0 0 6px;
  font-size: 16px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--callout-ink);
}

.block-callout__body {
  color: #3d4f61;
}

/* The body is a small rich-text field, so it arrives as paragraphs and lists
   that §46 has already styled at article size. Inside a callout they want to be
   a step smaller and tighter, and the last one must not leave a gap. */
.block-callout .block-callout__body p,
.block-callout .block-callout__body li {
  font-size: 16px;
  line-height: 1.65;
  color: #3d4f61;
}

.block-callout .block-callout__body p {
  margin: 0 0 10px;
}

.block-callout .block-callout__body > :last-child {
  margin-bottom: 0;
}

.block-callout .block-callout__body ul,
.block-callout .block-callout__body ol {
  margin: 0 0 10px;
  gap: 6px;
}

.block-callout--info { --callout-ink: #0031BC; --callout-tint: #eef3ff; --callout-mark: "i"; }
.block-callout--tip { --callout-ink: #0f766e; --callout-tint: #effbf8; --callout-mark: "\2605"; }
.block-callout--success { --callout-ink: #16a34a; --callout-tint: #f0fdf4; --callout-mark: "\2713"; }
.block-callout--warning { --callout-ink: #b45f1e; --callout-tint: #fff7ed; --callout-mark: "!"; }
.block-callout--danger { --callout-ink: #dc2626; --callout-tint: #fef2f2; --callout-mark: "!"; }

/* ---------------------------------------------------------------------------
   Pull quote

   Deliberately unlike a blockquote: no left rule, centred, and large enough to
   interrupt the column. The editor offers both, and two things that look the
   same are one thing with a confusing menu.
   --------------------------------------------------------------------------- */
.block-quote {
  padding: 8px 0 0;
  text-align: center;
  border-top: 2px solid #e4ebf3;
  border-bottom: 2px solid #e4ebf3;
}

.block-quote .block-quote__text {
  margin: 26px auto 22px;
  max-width: 34ch;
  padding: 0;
  border: 0;
  font-size: clamp(21px, 2.8vw, 27px);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: -0.015em;
  color: #152a45;
  /* Hanging quotation marks, so the first word still starts on the measure. */
  quotes: "\201C" "\201D";
}

.block-quote .block-quote__text::before { content: open-quote; color: #0031BC; }
.block-quote .block-quote__text::after { content: close-quote; color: #0031BC; }

.block-quote__cite {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-bottom: 22px;
  font-style: normal;
}

.block-quote__author {
  font-size: 15px;
  font-weight: 700;
  color: #152a45;
}

.block-quote__role {
  font-size: 14px;
  color: #5b6b7d;
}

/* ---------------------------------------------------------------------------
   Key statistics

   One to four figures on a row. `flex: 1 1 140px` rather than a four-column
   grid: the block accepts any count from one to four, and a grid would leave
   two of them stranded in the left half of the column.
   --------------------------------------------------------------------------- */
.block-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding: 26px 8px;
  border-top: 1px solid #e4ebf3;
  border-bottom: 1px solid #e4ebf3;
}

.block-stats__item {
  flex: 1 1 140px;
  min-width: 0;
  padding: 0 18px;
  text-align: center;
}

/* A hairline between figures, not around them — so one statistic has no stray
   rule beside it and four have three. */
.block-stats__item + .block-stats__item {
  border-left: 1px solid #e4ebf3;
}

.block-stats .block-stats__value {
  margin: 0;
  font-size: clamp(30px, 4vw, 40px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.03em;
  color: #0031BC;
}

.block-stats .block-stats__label {
  margin: 8px 0 0;
  font-size: 14px;
  line-height: 1.45;
  color: #5b6b7d;
}

@media (max-width: 520px) {
  /* Two per row on a phone; the border follows, or every other figure keeps a
     rule on the left edge of the column. */
  .block-stats__item {
    flex: 1 1 calc(50% - 4px);
    padding: 12px;
  }

  .block-stats__item:nth-child(odd) {
    border-left: 0;
  }
}

/* ---------------------------------------------------------------------------
   Gallery / logo slideshow

   CONTAIN, NEVER CROP. The block's own help text names certification badges,
   so a cover-fit that trims the edge off somebody's credential is wrong even
   where it would look tidier. Every image sits whole inside a fixed box.
   --------------------------------------------------------------------------- */
.block-gallery {
  padding: 0;
}

.block-gallery .block-gallery__heading {
  margin: 0 0 14px;
  /* §46 gives an article paragraph a 1.75 line-height, which is loose for a
     13px uppercase label. */
  line-height: 1.4;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #5b6b7d;
}

.block-gallery .block-gallery__track {
  margin: 0;
  padding: 0;
  list-style: none;
  gap: 14px;
  /* §46 makes every list in an article a COLUMN flexbox. Setting `display:flex`
     on the carousel below overrode the display and inherited the direction, so
     the strip stacked its logos vertically down the page — on the site only,
     because the editor's preview has no `[data-article]` above it to inherit
     from. Reset here rather than in the carousel, so the next layout that wants
     a flex track does not have to learn this again. */
  flex-direction: row;
}

.block-gallery .block-gallery__item {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
}

.block-gallery .block-gallery__image {
  width: 100%;
  max-height: 120px;
  margin: 0;
  padding: 12px;
  border: 1px solid #e4ebf3;
  border-radius: 10px;
  background: #ffffff;
  object-fit: contain;
}

.block-gallery .block-gallery__link {
  display: block;
  font-weight: inherit;
  text-decoration: none;
  transition: transform .18s ease;
}

.block-gallery .block-gallery__link:hover {
  transform: translateY(-2px);
}

.block-gallery .block-gallery__caption {
  font-size: 13px;
  line-height: 1.4;
  text-align: center;
  color: #5b6b7d;
}

.block-gallery--grid .block-gallery__track {
  display: grid;
  /* `auto-fill`, so three badges stay badge-sized instead of stretching to a
     third of the column each. */
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

.block-gallery--carousel .block-gallery__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* Room for the scrollbar, so it does not sit on the captions. */
  padding-bottom: 10px;
  scrollbar-width: thin;
}

.block-gallery--carousel .block-gallery__item {
  flex: 0 0 auto;
  width: 170px;
  scroll-snap-align: start;
}

/* ---------------------------------------------------------------------------
   Video

   `aspect-ratio` on the frame rather than the old padding-top trick: the iframe
   can then be a plain child at 100%/100% and the caption needs no absolute
   positioning to escape it.

   The dark ground matters. With consent required the iframe ships empty — the
   URL is in `data-src` until the visitor opts in — so without a ground of its
   own the block is a white rectangle in a white column, which reads as a
   failure rather than as a video waiting for consent.
   --------------------------------------------------------------------------- */
.block-video {
  padding: 0;
}

.block-video__frame {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 12px;
  background: #0c1a2c;
}

.block-video__frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

.block-video .block-video__caption {
  margin: 12px 0 0;
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
  color: #5b6b7d;
}

/* ---------------------------------------------------------------------------
   Client review
   --------------------------------------------------------------------------- */
.block-review {
  padding: 26px 28px;
  border: 1px solid #e4ebf3;
  border-radius: 14px;
  background: #ffffff;
  box-shadow: 0 18px 40px -34px rgba(11, 31, 51, 0.5);
}

.block-review__stars {
  font-size: 18px;
  letter-spacing: 2px;
  color: #e8a33d;
}

/* schema.org needs the number in the markup; a reader does not need it twice.
   Hidden the accessible way — `display:none` would take it out of the
   accessibility tree, and some crawlers discount it. */
.block-review__rating-value {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.block-review .block-review__headline {
  margin: 12px 0 0;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.35;
  color: #152a45;
}

.block-review .block-review__quote {
  margin: 10px 0 20px;
  padding: 0;
  border: 0;
  font-size: 17px;
  line-height: 1.7;
  color: #3d4f61;
}

.block-review__author {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-top: 18px;
  border-top: 1px solid #eef2f7;
}

.block-review .block-review__avatar {
  flex: 0 0 auto;
  width: 44px;
  margin: 0;
  padding: 0;
  border: 1px solid #e4ebf3;
  border-radius: 50%;
  object-fit: cover;
  aspect-ratio: 1;
}

.block-review__who {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.block-review__name {
  font-size: 15px;
  font-weight: 700;
  color: #152a45;
}

.block-review__role {
  font-size: 13px;
  line-height: 1.4;
  color: #5b6b7d;
}

/* ---------------------------------------------------------------------------
   FAQs

   The block only decides WHERE the page's questions go — they render at the end
   of the page without it — so this has to match the page's own FAQ section
   rather than introduce a second look for the same content.
   --------------------------------------------------------------------------- */
.block-faqs {
  padding: 0;
}

.block-faqs .block-faqs__heading {
  margin: 0 0 18px;
  font-size: clamp(22px, 2.8vw, 27px);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: #152a45;
}

.block-faqs .faq {
  padding: 16px 0;
  border-top: 1px solid #e4ebf3;
}

.block-faqs .faq:last-child {
  border-bottom: 1px solid #e4ebf3;
}

.block-faqs .faq h3 {
  margin: 0 0 8px;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.4;
  color: #152a45;
}

.block-faqs .faq summary {
  position: relative;
  padding-right: 28px;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.4;
  color: #152a45;
  cursor: pointer;
  list-style: none;
}

/* Safari still draws its own triangle without this. */
.block-faqs .faq summary::-webkit-details-marker {
  display: none;
}

.block-faqs .faq summary::after {
  content: "+";
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
  font-size: 20px;
  font-weight: 700;
  color: #0031BC;
}

.block-faqs .faq[open] summary::after {
  content: "\2212";
}

.block-faqs .faq summary + div {
  margin-top: 10px;
}

.block-faqs .faq p {
  margin: 0 0 10px;
  font-size: 16px;
  line-height: 1.7;
  color: #3d4f61;
}

.block-faqs .faq > div > :last-child {
  margin-bottom: 0;
}

/* ---------------------------------------------------------------------------
   Lead capture form

   `.dynamic-form` is styled here rather than in site-fixes.css because this
   block is its only caller — the contact page has its own markup — so the form
   and the block it lives in are one piece of design.
   --------------------------------------------------------------------------- */
.block-lead-form {
  padding: 28px 30px;
  border: 1px solid #d6e2fb;
  border-radius: 14px;
  background: #f7f9ff;
}

.block-lead-form .block-lead-form__heading {
  margin: 0 0 18px;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.3;
  color: #152a45;
}

.dynamic-form {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.dynamic-form__row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.dynamic-form__row--checkbox {
  flex-direction: row;
  align-items: center;
  gap: 10px;
}

.dynamic-form .dynamic-form__label {
  font-size: 14px;
  font-weight: 600;
  color: #152a45;
}

.dynamic-form__required {
  color: #dc2626;
}

.dynamic-form input,
.dynamic-form select,
.dynamic-form textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid #cbd8ea;
  border-radius: 9px;
  background: #ffffff;
  font: inherit;
  font-size: 15px;
  color: #152a45;
  transition: border-color .16s ease, box-shadow .16s ease;
}

.dynamic-form input[type="checkbox"],
.dynamic-form input[type="radio"] {
  width: auto;
  accent-color: #0031BC;
}

.dynamic-form input:focus,
.dynamic-form select:focus,
.dynamic-form textarea:focus {
  outline: none;
  border-color: #0031BC;
  box-shadow: 0 0 0 3px rgba(0, 49, 188, 0.14);
}

.dynamic-form textarea {
  resize: vertical;
}

.dynamic-form__options {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  font-size: 15px;
  color: #3d4f61;
}

.dynamic-form .dynamic-form__help {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: #5b6b7d;
}

.dynamic-form .dynamic-form__error {
  margin: 0;
  font-size: 13px;
  line-height: 1.45;
  color: #dc2626;
}

/* The honeypot. Off-screen rather than `display:none`, which some bots read as
   "do not fill this in". */
.dynamic-form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.dynamic-form .dynamic-form__submit {
  align-self: flex-start;
  padding: 13px 28px;
  border: 0;
  border-radius: 9px;
  background: #0031BC;
  color: #ffffff;
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  transition: background-color .18s ease, transform .18s ease;
}

.dynamic-form .dynamic-form__submit:hover {
  background: #084b8f;
  transform: scale(1.04);
}

@media (max-width: 560px) {
  .block-lead-form {
    padding: 24px 20px;
  }

  .dynamic-form .dynamic-form__submit {
    align-self: stretch;
    text-align: center;
  }
}

/* ---------------------------------------------------------------------------
   Inside the editor

   `.fi-fo-rich-editor-custom-block-preview` exists only in the admin panel, so
   everything under it is panel-only and cannot reach the site.

   The panel follows the system theme. These blocks are a piece of the public
   site, and the public site is light — a call to action that went dark-navy in
   a dark panel would be showing the author something that does not exist. The
   preview gets its own white ground and dark text so the block looks like what
   will actually be published, in either theme.
   --------------------------------------------------------------------------- */
.fi-fo-rich-editor-custom-block-preview {
  padding: 16px;
  border-radius: 10px;
  background: #ffffff;
  color: #3d4f61;
}

/* The shared 38px is the rhythm between blocks in an article. In the editor
   each preview is already in its own bordered card, so the margin only adds a
   gap inside it. */
.fi-fo-rich-editor-custom-block-preview > * {
  margin-top: 0;
  margin-bottom: 0;
}
