/* Icon Grid block.

   Ported from style.css's .icon-placeholder and .benefit-title, which
   for-families and how-it-works still render from their templates. The two are
   independent from here: this block never references the old classes, and they
   come out of style.css with the last template that uses them. */

/* ── Icon frame ─────────────────────────────────────────────────────────────
   Two frames at one footprint. The theme has two icon vocabularies at two
   scales — glyphs of 23 to 41 units, and illustrations of 460 to 535 — and the
   ring exists to give the glyphs presence they do not have on their own. The
   illustrations do not need it and look wrong inside it.

   Both are 90px so that changing the frame does not move anything else in the
   row. The bare frame caps width at 150px rather than squaring off, because the
   glyph set runs from 0.66:1 to 1.5:1 and a square box crops the wide ones
   harder than the tall ones. */
.offplan-icon-badge {
  width: 90px;
  height: 90px;
  margin: 0 auto 1.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.offplan-icon-badge-ring {
  border: 2px solid var(--op-orange);
  border-radius: 50%;
}

.offplan-icon-badge-ring img {
  width: 36px;
  height: 36px;
  object-fit: contain;
}

/* The image is sized by its height, and the badge shrink-wraps to it.

   It cannot be the other way round: these SVGs carry a viewBox and no width or
   height, so they have an intrinsic ratio but no intrinsic size. Sizing the
   image as a percentage of a badge that is itself sizing to the image is
   circular, and the browser resolves it to zero — the badge renders 0x90 and
   the icon disappears. The ring variant never hits it because it states 36px
   in both axes.

   So: a definite height on the image, width derived from the viewBox ratio,
   and max-width only as a backstop for artwork wider than 1.66:1. */
.offplan-icon-badge-bare {
  width: auto;
  max-width: 150px;
}

.offplan-icon-badge-bare img {
  width: auto;
  height: 90px;
  max-width: 150px;
  object-fit: contain;
}

/* Reserves a common height so a title wrapping to two lines does not push its
   own body copy out of step with the rest of the row.

   Written h3.offplan-icon-title, not .offplan-icon-title. The title is a real
   heading now, and Bootstrap sets margin-bottom: .5rem on h1-h6 and .h1-.h6 in
   a rule whose .h4 selector ties this one on specificity — and block CSS prints
   *above* bootstrap-css, so a tie loses. As a <p> it won on 0,1,0 against
   Bootstrap's 0,0,1 p rule and the class alone was enough; as an <h3> it is not.
   The trap the Eighty/Twenty figure found, in a second place.

   4rem, not the 3.5rem that was measured against .h5. At .h4 a line box is
   1.5rem x 1.2, so two lines need 3.6rem and the old reservation would have
   been overrun by exactly the case it exists to prevent. */
h3.offplan-icon-title {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 4rem;
  margin-bottom: 0.75rem;
}

/* ── Left-aligned items ─────────────────────────────────────────────────────
   The header stays centred either way; this is the row only. Three things are
   centred by something other than text-align and have to be told:

   The chip is a block-level d-flex, so margin-left: auto is what centres it.
   The numeral's orange rule is a ::after with auto margins of its own. And the
   title is a flex container, centred on its main axis.

   The icon badge needs nothing: it is inline-flex, so text-align already moves
   it and its own margin: 0 auto never applied horizontally. */
.offplan-icon-grid-left .offplan-icon-chip,
.offplan-icon-grid-left .offplan-icon-grid-number::after {
  margin-left: 0;
}

.offplan-icon-grid-left h3.offplan-icon-title {
  justify-content: flex-start;
}

/* ── Numeral mark ───────────────────────────────────────────────────────────
   The alternative to an icon: the item's position at display size, over the
   short orange rule the templates drew with .step-number::after. Sized by
   .display-3 and weighted by .fw-bold in the markup rather than here, because
   both are Bootstrap utilities on this same element and a block stylesheet
   prints above bootstrap-css — declaring either here would lose the tie. */
.offplan-icon-grid-number {
  line-height: 1;
  margin-bottom: 3rem;
}

.offplan-icon-grid-number::after {
  content: '';
  display: block;
  width: 72px;
  height: 3px;
  background: var(--op-orange);
  margin: 1rem auto 0;
}

/* ── Tier chip mark ─────────────────────────────────────────────────────────
   A filled navy square holding the item's position — self-funded,
   fully-insured and level-funded each open their Structure Change on one.

   The box only. Everything visible about it — bg-op-navy, text-white, fw-bold,
   fs-4, rounded-2 — stays as utilities in the markup, for the numeral's
   reason: fs-4 and rounded-2 are Bootstrap's, a block stylesheet prints above
   bootstrap-css, and a rule here would lose the tie.

   72px is the template's, not the 90px the two icon frames share. That
   footprint is what keeps ring and bare interchangeable around the same
   artwork; changing the mark itself already reflows. The 3rem gap is the
   template's .mb-5 wrapper, and the same one .offplan-icon-grid-number takes.

   `margin: 0 auto` is what centres it: the chip is a fixed-width block in a
   column the block centres by text-align, which does not reach it. */
.offplan-icon-chip {
  width: 72px;
  height: 72px;
  margin: 0 auto 3rem;
}

/* ── Header body ────────────────────────────────────────────────────────────
   A run of copy between the subhead and the grid. advisors' The Engine is the
   first of the fourteen instances to want one: three paragraphs introducing
   Reclassify before the three steps that describe it, where every other grid in
   the theme goes straight from its lead into the row.

   1.5rem between paragraphs, which is the template's mb-4 and the same rhythm
   .two-col-header-body and .hero-subhead already use — the theme's three
   rich-text bodies space alike. The trailing margin is zeroed on any last
   element rather than on p alone, so a body ending on a list closes flush.

   Deliberately not Prose's :has(> strong:only-child) label rule. A fully bold
   paragraph here is an emphatic line in the middle of a run — "The goal is not
   to eliminate risk." — not a label belonging to what follows it, and pulling
   its bottom margin to 0.25rem would attach it to the wrong paragraph. */
.offplan-icon-grid-body > p {
  margin-bottom: 1.5rem;
}

.offplan-icon-grid-body > :last-child {
  margin-bottom: 0;
}

/* Emphasis takes its colour from the surface, as every other prose body in the
   theme does. On a dark section it inherits, which is the plain bold white the
   template writes; the rule is scoped rather than left to the cascade, because
   style.css loads after block CSS and would win a tie either way. */
.offplan-icon-grid-body strong,
.offplan-icon-grid-body b {
  color: var(--op-navy);
}

.bg-op-navy .offplan-icon-grid-body strong,
.bg-op-navy .offplan-icon-grid-body b,
.bg-op-navy-gradient .offplan-icon-grid-body strong,
.bg-op-navy-gradient .offplan-icon-grid-body b {
  color: inherit;
}

/* ── Connectors ─────────────────────────────────────────────────────────────
   A chevron pointing from one item to the next, for a row that is a sequence
   rather than a set. advisors' Reclassify steps are the one instance; the other
   thirteen grids are parallel benefits, where a connector would assert an order
   that is not there, which is why this is off by default.

   lg and up only. The template drew these from md, where its own col-md-4 put
   all three items on one row — but this block's three-column class is
   col-md-6 col-lg-4, so at md the row is two across and a chevron drawn from
   the second item would point into the gap where the third one used to be.
   Below lg the sequence is carried by the item kickers, which is where it also
   lives on the page.

   The end of a visual row gets none, whatever the item count: the count class
   is what makes nth-child correct here rather than a guess, since the row wraps
   at exactly the column count from lg up. :last-child covers a final row that
   is short. */
@media (min-width: 992px) {
  .offplan-icon-grid-linked > [class*="col-"] {
    position: relative;
  }

  .offplan-icon-grid-linked > [class*="col-"]::after {
    content: '';
    position: absolute;
    top: 58%;
    right: -0.5rem;
    width: 1.8rem;
    height: 1.8rem;
    border-top: 3px solid var(--op-orange);
    border-right: 3px solid var(--op-orange);
    transform: translateY(-50%) rotate(45deg);
  }

  .offplan-icon-grid-linked-2 > [class*="col-"]:nth-child(2n)::after,
  .offplan-icon-grid-linked-3 > [class*="col-"]:nth-child(3n)::after,
  .offplan-icon-grid-linked-4 > [class*="col-"]:nth-child(4n)::after,
  .offplan-icon-grid-linked > [class*="col-"]:last-child::after {
    content: none;
  }
}

/* ── Column separators ──────────────────────────────────────────────────────
   A rule between one column and the next. Restored rather than invented: this
   block's notes recorded physicians' Roadmap separator as dropped because "no
   other three-across row in the theme divides its columns", and employers' Your
   Starting Point is the second instance of exactly that device. The count was
   the only argument for the deletion, so the deletion goes.

   **physicians' implementation, not employers'.** The two templates spelled it
   1px `var(--op-navy)` and 2px of the same colour at 85%; the token is the
   house value for a navy rule, the way .offplan-card-bordered is 1px of it, and
   85% of a colour is a number nothing chooses. And a ::before rather than a
   border, which is what lets the stacked rule centre itself in the row gutter
   instead of hanging off the top of the lower item — employers' border-top
   needed a 3rem padding to fake that and still sat off-centre.

   Suppressed at the start of each visual row rather than drawn with an adjacent
   sibling combinator, which is what the templates used and what breaks the
   moment a grid runs to a second row. Mirrors the connector rule above, from
   the other end: that one suppresses at the row's last column, this at its
   first. :nth-child here is a position *inside the block's own grid*, which is
   what the conventions' warning about sibling selectors exempts — it encodes
   "first in its row", not "third section on the page". */
.offplan-icon-grid-divided > [class*="col-"] {
  position: relative;
}

.offplan-icon-grid-divided > [class*="col-"]::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: 1px;
  background: var(--op-navy);
}

.offplan-icon-grid-divided > [class*="col-"]:first-child::before {
  content: none;
}

/* Two across between md and lg whatever the column count, because that is what
   $col_classes does — 3 and 4 both go through col-md-6 on the way down. */
@media (min-width: 768px) and (max-width: 991.98px) {
  .offplan-icon-grid-divided > [class*="col-"]:nth-child(2n+1)::before {
    content: none;
  }
}

@media (min-width: 992px) {
  .offplan-icon-grid-divided-2 > [class*="col-"]:nth-child(2n+1)::before,
  .offplan-icon-grid-divided-3 > [class*="col-"]:nth-child(3n+1)::before,
  .offplan-icon-grid-divided-4 > [class*="col-"]:nth-child(4n+1)::before {
    content: none;
  }
}

/* One column below md: the rule turns horizontal and centres itself in the row
   gutter, inset from both edges so it reads as a divider rather than a section
   break. Both numbers are physicians'. */
@media (max-width: 767.98px) {
  .offplan-icon-grid-divided > [class*="col-"]::before {
    top: calc(var(--bs-gutter-y) * -0.5);
    left: 30px;
    right: 0;
    bottom: auto;
    width: calc(100% - 60px);
    height: 1px;
  }
}

/* ── Item body ──────────────────────────────────────────────────────────────
   Only present when the body is more than one paragraph — a single one is
   rendered as the paragraph itself, carrying mb-0 directly. See render.php. */
.offplan-icon-grid-item-body > :last-child {
  margin-bottom: 0;
}
