/* ==========================================================================
   Marble Consulting Group — section layer, part 2

   Split from sections.css after an editing mistake truncated that file and
   silently removed three whole sections' styles. Small files that are written
   whole, rather than appended to repeatedly, are much harder to damage.
   ========================================================================== */

/* ==========================================================================
   06 WHY BRANDS WORK WITH US   (.cmp, index.html)

   The heading promises a comparison, so the section is one. Four rows: the
   thing being compared, the usual arrangement, then ours.

   BOTH HALVES ARE ALWAYS VISIBLE. A toggle would have been more fun to build
   and worse to use - a buyer should not have to interact to see both sides of
   a claim, and half a comparison is just an assertion. The interaction earns
   its place instead by RESOLVING the row: on approach the gold rule draws
   across it, the numeral brightens, the "usually" column recedes and ours
   comes forward. The comparison is legible at rest and sharpened on contact.

   This replaced four photographic plates. They carried nothing the captions
   did not already carry and pushed the argument below the fold.
   ========================================================================== */
.cmp {
  position: relative;
  padding-block: clamp(2.5rem, 2rem + 2.4vw, 4.5rem);
  overflow: hidden;
}
.cmp__ghost {
  position: absolute;
  top: 6%;
  right: -1%;
  font-size: clamp(3.5rem, 10vw, 9rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(156, 120, 72, 0.09);
  pointer-events: none;
  user-select: none;
  z-index: 0;
}
.cmp__head {
  position: relative;
  z-index: 1;
  max-width: 46rem;
  margin-bottom: clamp(1.75rem, 1.4rem + 1.8vw, 2.75rem);
}
.cmp__h {
  font-size: clamp(1.5rem, 1.2rem + 1.5vw, 2.4rem);
  letter-spacing: -0.028em;
  text-wrap: balance;
}
.cmp__h em { color: var(--gold-light); font-style: italic; }

.cmp__table {
  position: relative;
  z-index: 1;
  list-style: none;
  border-top: 1px solid var(--border-gold);
}

.cmp__row {
  position: relative;
  display: grid;
  grid-template-columns: 2.5rem minmax(7rem, 0.55fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(0.85rem, 1.4vw, 2rem);
  align-items: start;
  padding: clamp(1.15rem, 0.95rem + 0.9vw, 1.75rem) 0;
  border-bottom: 1px solid var(--border-neutral);
  transition: background var(--dur) var(--ease-out);
}
.cmp__row:hover,
.cmp__row:focus-within { background: rgba(156, 120, 72, 0.04); }
/* the rule that draws across the row on approach */
.cmp__row::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 1px;
  width: 100%;
  background: linear-gradient(90deg, var(--gold-light), var(--gold-shadow));
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.7s var(--ease-out);
}
.cmp__row:hover::after,
.cmp__row:focus-within::after { transform: scaleX(1); }

.cmp__n {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--gold);
  opacity: 0.6;
  padding-top: 0.3em;
  transition: opacity var(--dur) var(--ease-out);
}
.cmp__row:hover .cmp__n,
.cmp__row:focus-within .cmp__n { opacity: 1; }

.cmp__topic {
  font-size: clamp(0.98rem, 0.93rem + 0.3vw, 1.15rem);
  font-weight: 600;
  color: var(--white);
  letter-spacing: -0.016em;
  line-height: 1.35;
  text-wrap: balance;
}

.cmp__cell { position: relative; transition: opacity var(--dur) var(--ease-out); }
.cmp__cell p {
  font-size: 0.93rem;
  line-height: 1.6;
  text-wrap: pretty;
}
.cmp__tag {
  display: block;
  margin-bottom: 0.4rem;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* the usual arrangement: set back, and set further back on contact */
.cmp__cell--them { opacity: 0.62; }
.cmp__cell--them .cmp__tag { color: var(--vein); }
.cmp__cell--them p { color: var(--vein); }
.cmp__row:hover .cmp__cell--them,
.cmp__row:focus-within .cmp__cell--them { opacity: 0.42; }

/* ours: carried by a gold edge, and brought forward on contact */
.cmp__cell--us {
  padding-left: clamp(0.85rem, 1.4vw, 1.35rem);
  border-left: 1px solid var(--border-gold);
}
.cmp__cell--us .cmp__tag { color: var(--gold-light); }
.cmp__cell--us p { color: var(--ink); }
.cmp__row:hover .cmp__cell--us,
.cmp__row:focus-within .cmp__cell--us { transform: translateX(2px); }

.cmp__cta { position: relative; z-index: 1; margin-top: clamp(1.5rem, 1.2rem + 1vw, 2.25rem); }

/* Under 900px four columns cannot hold two sentences. The row becomes a
   stack: topic, then the two cells one above the other, with the gold edge
   moved to the top of ours so the pairing still reads. */
@media (max-width: 900px) {
  .cmp__row {
    grid-template-columns: 2.25rem 1fr;
    gap: 0.5rem 0.85rem;
    padding-block: 1.25rem;
  }
  .cmp__n { grid-row: 1; }
  .cmp__topic { grid-column: 2; }
  .cmp__cell { grid-column: 2; margin-top: 0.6rem; }
  .cmp__cell--us {
    padding-left: 0;
    padding-top: 0.75rem;
    border-left: 0;
    border-top: 1px solid var(--border-gold);
  }
  .cmp__ghost { display: none; }
}

/* ==========================================================================
   08 IN THEIR WORDS   (.voices, index.html)

   Three cards across, sitting after the team so a visitor meets the people
   before they read what anyone says about them.

   THE SAMPLE FLAG IS DELIBERATELY UGLY-ADJACENT. It is a small gold-bordered
   tag on every placeholder card, because a placeholder that looks finished is
   how a fake testimonial reaches production. Deleting the .quote__flag span
   and swapping .quote--sample for .quote turns a slot into a live quote, and
   the card is styled identically either way apart from the tag and a slight
   dimming.

   Cards lift, brighten and draw a gold rule across the attribution row on
   approach. The middle card sits a touch proud on desktop, because a row of
   three identical boxes reads as a table and a row with a centre of gravity
   reads as a composition.
   ========================================================================== */
.voices { padding-block: clamp(2.5rem, 2rem + 2.4vw, 4.5rem); }
.voices__head { max-width: 46rem; margin-bottom: clamp(1.75rem, 1.4rem + 1.8vw, 3rem); }
.voices__h {
  font-size: clamp(1.5rem, 1.2rem + 1.5vw, 2.4rem);
  letter-spacing: -0.028em;
  text-wrap: balance;
}
.voices__h em { color: var(--gold-light); font-style: italic; }
.voices__lead {
  margin-top: 0.9rem;
  color: var(--vein);
  font-size: var(--text-base);
  line-height: 1.7;
  text-wrap: pretty;
}

.voices__grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
  gap: clamp(1rem, 0.85rem + 0.8vw, 1.5rem);
  align-items: stretch;
}
/* a lone card should read as a statement, not a grid with holes */
.voices__grid:has(> :only-child) { grid-template-columns: minmax(0, 46rem); }

.quote {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(1.5rem, 1.2rem + 1.2vw, 2.1rem);
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(156, 120, 72, 0.05), rgba(6, 6, 8, 0) 62%);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out),
              background var(--dur) var(--ease-out);
}
/* the centre card carries the row */
@media (min-width: 900px) {
  .quote:nth-child(2) { transform: translateY(-0.85rem); }
  .quote:nth-child(2):hover,
  .quote:nth-child(2):focus-within { transform: translateY(-1.2rem); }
}
.quote:hover,
.quote:focus-within {
  border-color: var(--border-gold-strong);
  transform: translateY(-4px);
  background: linear-gradient(180deg, rgba(156, 120, 72, 0.09), rgba(6, 6, 8, 0) 62%);
}
/* a wash that only appears on approach */
.quote::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 18% 0%, rgba(156, 120, 72, 0.14), transparent 60%);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
}
.quote:hover::after,
.quote:focus-within::after { opacity: 1; }

/* the placeholder tag */
.quote--sample { opacity: 0.92; }
.quote__flag {
  position: relative;
  align-self: flex-start;
  margin-bottom: 0.9rem;
  padding: 0.28rem 0.6rem;
  border: 1px solid var(--border-gold-strong);
  border-radius: 999px;
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-light);
  background: rgba(156, 120, 72, 0.08);
}

.quote__mark {
  position: relative;
  font-size: clamp(2.1rem, 1.7rem + 1.6vw, 3rem);
  line-height: 0.7;
  color: var(--gold);
  opacity: 0.45;
  margin-bottom: 0.65rem;
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.quote:hover .quote__mark,
.quote:focus-within .quote__mark { opacity: 1; transform: translateY(-2px); }

.quote__body { position: relative; flex: 1; }
.quote__body p {
  color: var(--ink);
  font-size: clamp(0.95rem, 0.92rem + 0.25vw, 1.06rem);
  line-height: 1.62;
  text-wrap: pretty;
}

.quote__foot {
  position: relative;
  margin-top: clamp(1.15rem, 1rem + 0.7vw, 1.6rem);
  padding-top: clamp(0.85rem, 0.7rem + 0.5vw, 1.15rem);
}
/* the attribution rule fills in with the hover */
.quote__foot::before,
.quote__foot::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 1px;
}
.quote__foot::before { right: 0; background: var(--border-neutral); }
.quote__foot::after {
  width: 100%;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: 0 50%;
  transition: transform 0.7s var(--ease-out);
}
.quote:hover .quote__foot::after,
.quote:focus-within .quote__foot::after { transform: scaleX(1); }

.quote__who { display: flex; flex-direction: column; gap: 0.15rem; }
.quote__name {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--white);
  letter-spacing: -0.012em;
}
.quote__role {
  font-size: var(--text-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}

.voices__foot { margin-top: clamp(1.5rem, 1.2rem + 1vw, 2.25rem); }
.quote__call {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.95rem;
  font-weight: 600;
  white-space: nowrap;
}
.quote__call svg { transition: transform var(--dur) var(--ease-out); }
.quote__call:hover svg { transform: translateX(3px); }

@media (max-width: 560px) {
  .quote__foot { padding-top: 0.9rem; }
}

/* ==========================================================================
   09 CAREERS   (.joinus, index.html)

   Voice left, fact right. The struck-through lines are the best writing on
   the site, and the rule is drawn as a gold hairline rather than a text
   decoration so it reads as deliberate rather than as a browser default.

   The right column is what the block never had: what the role is, where it
   is, and how you are paid. An applicant should not have to click through to
   learn whether the job is in their city.
   ========================================================================== */
.joinus { padding-block: clamp(2.5rem, 2rem + 2.4vw, 4.5rem); }
.joinus__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(1.75rem, 1.4rem + 2.4vw, 4rem);
  align-items: start;
}
.joinus__h {
  font-size: clamp(1.6rem, 1.25rem + 1.6vw, 2.6rem);
  letter-spacing: -0.03em;
  margin-bottom: clamp(1.25rem, 1rem + 1vw, 1.9rem);
  text-wrap: balance;
}
.joinus__h em { color: var(--gold-light); font-style: italic; }
.joinus__negs { list-style: none; display: grid; gap: 0.5rem; }
.joinus__negs s {
  text-decoration: none;
  position: relative;
  color: var(--vein);
  font-size: clamp(1rem, 0.95rem + 0.35vw, 1.18rem);
  line-height: 1.5;
}
.joinus__negs s::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 52%;
  height: 1px;
  background: var(--gold);
  opacity: 0.7;
}
.joinus__yes {
  margin-top: clamp(1rem, 0.85rem + 0.6vw, 1.5rem);
  color: var(--white);
  font-size: clamp(1.05rem, 0.98rem + 0.4vw, 1.3rem);
  line-height: 1.5;
  font-weight: 600;
  letter-spacing: -0.014em;
  text-wrap: pretty;
}
.joinus__spec { border-top: 1px solid var(--border-gold); }
.joinus__spec > div {
  display: grid;
  grid-template-columns: minmax(6rem, 0.4fr) 1fr;
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--border-neutral);
}
.joinus__spec dt {
  font-size: var(--text-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
}
.joinus__spec dd { color: var(--ink); font-size: 0.95rem; line-height: 1.45; }
.joinus__note {
  margin-top: 1rem;
  color: var(--vein);
  font-size: 0.92rem;
  line-height: 1.6;
  text-wrap: pretty;
}
.joinus__act { margin-top: clamp(1.25rem, 1rem + 0.8vw, 1.75rem); }
@media (max-width: 860px) {
  .joinus__grid { grid-template-columns: 1fr; }
}

/* ============================================================
   .cmark - client logo, flush left inside a prose block
   .strip__mark and .roster__mark are both centred inside their own rows.
   This is the flush-left variant for the client and industry blocks on the
   inner pages, where the brand name is already set as an <h3> directly
   underneath. Because that name is present as real text, the <img> carries
   alt="" and the wrapper is aria-hidden: announcing "AT&T" twice in a row is
   worse for a screen reader than not announcing the logo at all.
   Reversed to white by the same brightness/invert trick as .strip__mark -
   the source files are dark ink on transparency.
   ============================================================ */
.cmark {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  height: clamp(1.45rem, 1.2rem + 0.95vw, 2rem);
  margin-bottom: clamp(0.8rem, 0.65rem + 0.5vw, 1.15rem);
  opacity: 0.72;
  filter: brightness(0) invert(1);
  transition: opacity var(--dur) var(--ease-out);
}
.cmark__img {
  max-height: 100%;
  width: auto;
  max-width: clamp(6.25rem, 10.5vw, 8.75rem);
  object-fit: contain;
}
.value:hover .cmark { opacity: 1; }

/* Two named people rather than three. Without this the pair sits in a
   3-column grid and leaves a visibly empty third cell. */
.crew__row--two {
  grid-template-columns: repeat(2, 1fr);
  max-width: 44rem;
}

/* ============================================================
   .offr - the six services, as a ledger (about.html)
   Deliberately NOT the homepage's .svcx tab rig. That component is the
   showcase and owns the interaction budget for the whole site; running it
   twice makes the second one read as the copy. Here the same six services
   are a scannable two-column ledger you read top to bottom in one pass,
   with services.html carrying the detail.

   The animation is the hairline: each rule draws left to right as its row
   arrives, so the list assembles itself rather than fading in as a slab.
   It rides the existing .reveal/.is-visible IO baseline - no new JS.
   ============================================================ */
.offr__grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: clamp(2rem, 4vw, 4.5rem);
}
.offr__item {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: clamp(0.85rem, 1.5vw, 1.25rem);
  padding: clamp(1.1rem, 0.9rem + 0.6vw, 1.6rem) 0;
  border-top: 1px solid var(--border-neutral);
}
/* the drawn rule sits ON the border above, so it replaces it in gold */
.offr__item::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: -1px;
  height: 1px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.75s var(--ease-out);
}
.offr__item.is-visible::after { transform: scaleX(1); }
.offr__n {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--gold);
  padding-top: 0.3rem;
  font-variant-numeric: tabular-nums;
  transition: color var(--dur) var(--ease-out);
}
.offr__name {
  font-size: clamp(1.02rem, 0.96rem + 0.32vw, 1.22rem);
  font-weight: 600;
  letter-spacing: -0.018em;
  color: var(--white);
}
.offr__desc {
  margin-top: 0.4rem;
  color: var(--vein);
  font-size: var(--text-sm);
  line-height: 1.62;
  text-wrap: pretty;
}
.offr__item:hover .offr__n { color: var(--gold-light); }
.offr__act { margin-top: clamp(1.5rem, 1.2rem + 1vw, 2.25rem); }
@media (max-width: 760px) {
  .offr__grid { grid-template-columns: 1fr; }
}

/* ============================================================
   .hrul - the house rules (team.html culture)
   The two day-in-the-life timelines already on the site (about.html #culture
   and team.html #floor) both answer "what does a day look like". This
   answers the different question a candidate actually has: what is the
   standard, and who enforces it. Kept as flat statements with a consequence
   attached, because a culture section that lists adjectives is the exact
   thing the values section was rebuilt to stop being.

   The numeral is outlined rather than filled and only fills on hover, so a
   column of six numbers reads as structure at rest and as a control when
   pointed at.
   ============================================================ */
.hrul__list { list-style: none; }
.hrul__item {
  position: relative;
  display: grid;
  grid-template-columns: clamp(3rem, 6vw, 5.25rem) 1fr;
  gap: clamp(0.9rem, 2vw, 2rem);
  align-items: start;
  padding: clamp(1.4rem, 1.15rem + 0.9vw, 2.2rem) 0;
  border-bottom: 1px solid var(--border-neutral);
}
.hrul__item::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: -1px;
  height: 1px;
  background: linear-gradient(90deg, var(--gold), transparent 85%);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.6s var(--ease-out);
}
.hrul__item:hover::after,
.hrul__item:focus-within::after { transform: scaleX(1); }
.hrul__n {
  font-size: clamp(1.9rem, 1.45rem + 2.1vw, 3.1rem);
  font-weight: 700;
  line-height: 0.88;
  letter-spacing: -0.03em;
  color: transparent;
  -webkit-text-stroke: 1px var(--border-gold-strong);
  font-variant-numeric: tabular-nums;
  transition: color var(--dur) var(--ease-out);
}
.hrul__item:hover .hrul__n { color: var(--gold); }
.hrul__rule {
  font-size: clamp(1.12rem, 1rem + 0.55vw, 1.45rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.28;
  color: var(--white);
  text-wrap: balance;
}
.hrul__prac {
  margin-top: 0.55rem;
  color: var(--vein);
  font-size: var(--text-sm);
  line-height: 1.65;
  max-width: 46rem;
  text-wrap: pretty;
}
.hrul__prac b { color: var(--ink); font-weight: 600; }
@media (max-width: 560px) {
  .hrul__item { grid-template-columns: 1fr; gap: 0.5rem; }
}

/* ============================================================
   .cf - the contact form, conventional
   Replaces the numbered "sheet": engraved serials 01-05, floating labels and
   bare underlines. It looked like a document and not like something you fill
   in - people could not tell where to type, which is the one thing a contact
   form has to make obvious.

   So: visible label above every field, a real bordered box with a background
   a shade lighter than the page, and a focus ring. Nothing here is clever.
   A form is the one component on a site where being boring IS the design -
   the user has a job to do and every ornament is in the way.
   ============================================================ */
.cf {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(1rem, 0.85rem + 0.6vw, 1.5rem);
  max-width: 46rem;
}
.cf__row--full { grid-column: 1 / -1; }
.cf__label {
  display: block;
  margin-bottom: 0.5rem;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--ink);
}
.cf__req { color: var(--gold); margin-left: 0.15rem; }
.cf__opt {
  margin-left: 0.4rem;
  font-weight: 400;
  font-size: var(--text-xs);
  color: var(--vein);
}
.cf__in {
  display: block;
  width: 100%;
  padding: 0.85rem 1rem;
  font-family: inherit;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--white);
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--border-neutral);
  border-radius: var(--radius-md);
  transition: border-color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
}
.cf__in::placeholder { color: var(--vein); opacity: 0.72; }
.cf__in:hover { border-color: var(--border-gold-strong); }
.cf__in:focus {
  outline: none;
  border-color: var(--gold);
  background: rgba(255, 255, 255, 0.055);
  box-shadow: 0 0 0 3px rgba(156, 120, 72, 0.16);
}
textarea.cf__in {
  min-height: 9.5rem;
  resize: vertical;
  line-height: 1.62;
}
.cf__hint {
  margin-top: 0.4rem;
  font-size: var(--text-xs);
  color: var(--vein);
  line-height: 1.5;
}
.cf__foot {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  margin-top: 0.35rem;
}
.cf__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
}
.cf__alt {
  color: var(--vein);
  font-size: var(--text-sm);
  line-height: 1.55;
}
.cf__alt a { color: var(--gold-light); text-decoration: underline; text-underline-offset: 3px; }
/* The status line is a polite live region, so it stays rendered even when
   empty - display:none on a live region costs the announcement. An empty <p>
   is already zero-height, so the spacing below is applied ONLY when it has
   something to say, and an untouched form shows no phantom gap. */
.cf__status {
  font-size: var(--text-sm);
  line-height: 1.5;
  color: var(--gold-light);
}
.cf__status:not(:empty) { margin-bottom: 0.9rem; }
.cf__status.is-error { color: #e0785f; }
@media (max-width: 620px) {
  .cf { grid-template-columns: 1fr; }
}

/* ============================================================
   .gmap - the office map, as a plain Google embed
   Was a MapLibre GL vector map repainted to the brand palette with every
   label switched off. It was the better-looking object and the worse map:
   with no street names, no search and no "open in Maps", a visitor could not
   do the one thing a contact-page map exists for.
   A real embed gives back labels, zoom, Street View and directions for free.
   ============================================================ */
.gmap__grid {
  display: grid;
  grid-template-columns: 1.55fr 1fr;
  gap: clamp(1.25rem, 1rem + 1.5vw, 2.5rem);
  align-items: stretch;
}
.gmap__frame {
  position: relative;
  min-height: clamp(17rem, 14rem + 14vw, 25rem);
  overflow: hidden;
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-md);
  background: var(--surface);
}
.gmap__frame iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}
.gmap__side {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.35rem;
}
.gmap__label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 0.35rem;
}
.gmap__addr {
  font-size: clamp(1.05rem, 0.98rem + 0.4vw, 1.3rem);
  font-weight: 600;
  color: var(--white);
  line-height: 1.45;
  letter-spacing: -0.015em;
}
.gmap__meta { margin-top: 0.85rem; color: var(--vein); font-size: var(--text-sm); line-height: 1.6; }
.gmap__meta a { color: var(--ink); }
.gmap__meta a:hover { color: var(--gold-light); }
.gmap__act { margin-top: clamp(1.1rem, 0.9rem + 0.7vw, 1.6rem); }
@media (max-width: 820px) {
  .gmap__grid { grid-template-columns: 1fr; }
}

/* ============================================================
   about.html hero - the two plates
   Overrides the carved-block geometry in editorial-2.css:2813-3234. It lives
   HERE, not there, for two reasons: sections-2.css is the last stylesheet on
   every page, so these win on source order; and the originals are spread
   across five media-query blocks (3178-3234) that would each need patching
   separately. Selectors are prefixed .hero--block so they out-specify every
   one of those single-class rules regardless of which block they sit in.

   The old geometry and why it failed is documented at the markup in
   about.html. In short: a height that stopped growing at 30rem, a width that
   never stopped growing, images clamped to 100% while still offset -6%, and
   a --bleed measured from 100vw (scrollbar included) that pushed the right
   plate off the page.
   ============================================================ */
.hero--block .blk__stage {
  position: relative;
  width: 100%;
  max-width: none;
  margin: 0;
}
.hero--block .blk__block {
  position: static;
  height: auto;
  aspect-ratio: auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(0.6rem, 0.45rem + 0.5vw, 1rem);
  row-gap: clamp(0.5rem, 0.4rem + 0.3vw, 0.8rem);
}
/* one ratio for both plates: two photographs at the same size read as a
   pair, which is what the labels claim. Unequal slots read as a collage. */
.hero--block .bface {
  position: relative;
  inset: auto;
  width: auto;
  height: auto;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius-md);
  box-shadow: inset 0 0 0 1px rgba(156, 120, 72, 0.3), 0 14px 38px -24px rgba(0, 0, 0, 0.9);
}
.hero--block .bface--a { grid-area: 1 / 1; }
.hero--block .bface--b { grid-area: 1 / 2; }
/* static + 100%/100%: the old -6%/112% headroom existed for a GSAP drift
   that no longer runs, and main.css:120 capped the width at 100% anyway */
.hero--block .bface img {
  position: static;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero--block .bface--a img { object-position: 42% 52%; }
.hero--block .bface--b img { object-position: 50% 46%; }
/* the labels leave the stone and sit under their own plate, so the rule that
   used to hang beside them now underlines the column */
.hero--block .blk__idx {
  position: static;
  padding-left: 0;
  white-space: normal;
}
.hero--block .blk__idx--a { grid-area: 2 / 1; }
.hero--block .blk__idx--b { grid-area: 2 / 2; }
.hero--block .blk__idx::before {
  position: static;
  display: block;
  width: 1.55rem;
  margin-bottom: 0.5rem;
}
.hero--block .blk__tell {
  padding-right: 0;
  max-width: none;
}
@media (max-width: 640px) {
  .hero--block .blk__block { grid-template-columns: 1fr; }
  .hero--block .bface--a { grid-area: 1 / 1; }
  .hero--block .blk__idx--a { grid-area: 2 / 1; }
  .hero--block .bface--b { grid-area: 3 / 1; }
  .hero--block .blk__idx--b { grid-area: 4 / 1; }
}

/* ============================================================
   Repeat visits: no curtain
   The preloader now runs only on the first page of a session (see the inline
   head script on every page). On every page after that <html> carries
   .no-preload, and the curtain must be gone before first paint - not faded
   out afterwards, which would still flash a full-screen panel over content
   that is already there.

   display:none rather than opacity/visibility because the element is fixed
   and inset:0: anything short of removing it from layout leaves a full-page
   node over the site until something takes it away.
   ============================================================ */
html.no-preload .preloader { display: none; }
/* .is-loading is never set on these loads, so nothing is scroll-locked or
   held at opacity 0 - this is belt and braces for a stale class surviving a
   bfcache restore. */
html.no-preload,
html.no-preload body { overflow: visible; }
html.no-preload main,
html.no-preload .nav { opacity: 1; }

/* ============================================================
   The record - from a struck ledger to a four-up card
   Was four full-width ruled rows stacked vertically (editorial.css:2544-2866):
   728px of page for four numbers, and a quarter of the homepage's scroll for
   the least copy on it. Same four figures, same notes, one band.

   MARKUP AND JS ARE UNTOUCHED. initLedger() in motion.js builds its digit
   reels from .ledger__row / .ledger__fig / data-figure, so the rows stay rows
   in the DOM and only the axis changes here. The figure moves above the name
   with `order`, not by re-nesting - re-nesting would have cost the reels.

   Prefixed .ledger so these out-specify the originals and the two
   max-width blocks at editorial.css:2848 and 2865 that patch the old layout.
   ============================================================ */
.ledger .ledger__list {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(156, 120, 72, 0.055), transparent 62%), var(--surface);
  overflow: hidden;
}
/* the shared right-aligned digit column only means something in a vertical
   ledger; in a four-up each figure is centred over its own label */
.ledger .ledger__col,
.ledger .ledger__rule,
.ledger .ledger__index { display: none; }
.ledger .ledger__row::before { display: none; }

.ledger .ledger__row {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.55rem;
  grid-template-columns: none;
  padding: clamp(1.35rem, 1.1rem + 1vw, 2rem) clamp(0.7rem, 1.4vw, 1.4rem);
  opacity: 1;
}
.ledger .ledger__row + .ledger__row { border-left: 1px solid var(--border-neutral); }

.ledger .ledger__icon {
  order: 1;
  display: grid;
  place-items: center;
  width: clamp(2.1rem, 1.85rem + 1vw, 2.75rem);
  aspect-ratio: 1;
  border-radius: 50%;
  color: var(--gold-light);
  background: rgba(156, 120, 72, 0.14);
  border: 1px solid var(--border-gold-strong);
  transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.ledger .ledger__icon svg { width: 55%; height: 55%; }
.ledger .ledger__row:hover .ledger__icon {
  background: rgba(156, 120, 72, 0.24);
  color: var(--gold-light);
}

.ledger .ledger__value {
  order: 2;
  min-width: 0;
  margin: 0;
  padding-left: 0;
  text-align: center;
  font-size: clamp(1.85rem, 1.4rem + 2.1vw, 3rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1;
}
.ledger .ledger__fig { justify-content: center; }

.ledger .ledger__term {
  order: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  grid-template-columns: none;
}
.ledger .ledger__copy { align-items: center; transform: none; }
.ledger .ledger__row:hover .ledger__copy { transform: none; }
/* the name becomes the label under the figure, so it takes the small caps
   treatment the reference layout uses rather than staying a body-size line */
.ledger .ledger__name {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
}
.ledger .ledger__note {
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--vein);
  max-width: 20rem;
  text-wrap: pretty;
}
/* the section itself no longer needs the height of a full ledger */
.ledger { padding-block: clamp(1.6rem, 1.2rem + 1.8vw, 2.9rem); }
.ledger .ledger__head { margin-bottom: clamp(0.9rem, 0.7rem + 0.7vw, 1.4rem); }

@media (max-width: 860px) {
  .ledger .ledger__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* with two per row the left border must reset on each new row, or column 1
     of row 2 carries a divider with nothing to its left */
  .ledger .ledger__row + .ledger__row { border-left: 0; }
  .ledger .ledger__row:nth-child(even) { border-left: 1px solid var(--border-neutral); }
  .ledger .ledger__row:nth-child(n + 3) { border-top: 1px solid var(--border-neutral); }
}
@media (max-width: 460px) {
  .ledger .ledger__list { grid-template-columns: 1fr; }
  .ledger .ledger__row:nth-child(even) { border-left: 0; }
  .ledger .ledger__row + .ledger__row { border-top: 1px solid var(--border-neutral); }
}

/* ============================================================
   Client strip - two lines, and the Fortune 500 mark
   Was one horizontal row: label, three logos and the category line all
   competing for the same band, which left the categories reading as a
   footnote hung off the right of the logos. Now the logos own line one and
   the claim owns line two, centred under them.

   The badge is the point of the change. "Fortune 500" is the strongest
   credential on the page and it was previously stated only once, in a stat
   cell on about.html - so it is given its own mark here, in gold, directly
   under the logos it refers to.
   ============================================================ */
.strip__inner {
  flex-direction: column;
  gap: clamp(0.7rem, 0.55rem + 0.6vw, 1.15rem);
}
.strip__top {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: clamp(1rem, 0.8rem + 1.6vw, 2.75rem);
}
.strip__note {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.6rem 0.85rem;
  /* the parent sets nowrap for the single-line version; on its own line the
     category list must be free to wrap on a phone */
  white-space: normal;
  text-align: center;
}
.strip__badge {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.3rem 0.7rem;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold-light);
  background: rgba(156, 120, 72, 0.12);
  border: 1px solid var(--border-gold-strong);
  border-radius: 999px;
  white-space: nowrap;
}
.strip__badge::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--gold-light);
  flex: none;
}
.strip__cats { color: var(--vein); }

/* the note used to be hidden on small screens as a nicety; it now carries the
   Fortune 500 credential, so it stays and the badge stacks above the list */
@media (max-width: 720px) {
  .strip__note { display: flex; flex-direction: column; gap: 0.5rem; }
}

/* ============================================================
   .vs - the agency comparison, as a real table
   MOBILE FIRST, because this site is opened on a phone far more than on a
   desktop. The default below IS the phone layout: each row is a block with
   the thing being compared as its heading, then the usual arrangement, then
   ours against a gold rule. A three-column table does not survive 375px, so
   it is not attempted there - the <thead> is hidden from sight (kept in the
   accessibility tree) and each cell carries its own inline label instead.

   From 760px up it becomes the table it is marked up as: column headings
   stated ONCE, four rows beneath them, inline labels off. Stating "Usually /
   With Marble" once instead of eight times is the whole point - the repeated
   badges are what made the previous version look unfinished.

   Semantics are real: <th scope="col"> and <th scope="row">, so a screen
   reader announces "The channel, With Marble, a consultant at the door"
   rather than reading a wall of unlabelled cells.
   ============================================================ */
.vs__scroll { width: 100%; }
.vs {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}
/* hidden from sight on phones, still announced */
.vs thead {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.vs__row {
  display: block;
  padding: clamp(1rem, 0.85rem + 0.6vw, 1.4rem) 0;
  border-top: 1px solid var(--border-neutral);
}
.vs tbody .vs__row:last-child { border-bottom: 1px solid var(--border-neutral); }
.vs__topic {
  display: block;
  font-size: clamp(1.02rem, 0.96rem + 0.34vw, 1.2rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--white);
  margin-bottom: 0.7rem;
}
.vs__cell {
  display: block;
  position: relative;
  padding-left: 0.9rem;
  font-size: var(--text-sm);
  line-height: 1.6;
  text-wrap: pretty;
}
.vs__cell + .vs__cell { margin-top: 0.75rem; }
.vs__cell::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.25rem;
  bottom: 0.25rem;
  width: 2px;
  border-radius: 2px;
  background: var(--border-neutral);
}
.vs__cell--them { color: var(--vein); }
.vs__cell--us { color: var(--ink); }
.vs__cell--us::before { background: var(--gold); }
.vs__lbl {
  display: block;
  margin-bottom: 0.2rem;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.vs__cell--them .vs__lbl { color: var(--vein); }
.vs__cell--us .vs__lbl { color: var(--gold); }

@media (min-width: 760px) {
  .vs thead {
    position: static;
    width: auto;
    height: auto;
    clip: auto;
    white-space: normal;
  }
  .vs thead th {
    padding: 0 0 0.7rem;
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    border-bottom: 1px solid var(--border-gold);
  }
  .vs__col--them { color: var(--vein); padding-left: 1.5rem; }
  .vs__col--us { color: var(--gold); padding-left: 1.5rem; }
  .vs__row { display: table-row; padding: 0; border-top: 0; }
  .vs tbody .vs__row:last-child { border-bottom: 0; }
  .vs__topic,
  .vs__cell {
    display: table-cell;
    vertical-align: top;
    padding: clamp(1rem, 0.85rem + 0.6vw, 1.45rem) 0;
    border-top: 1px solid var(--border-neutral);
  }
  .vs__topic { width: 22%; padding-right: 1.5rem; margin-bottom: 0; }
  .vs__cell { width: 39%; padding-left: 1.5rem; }
  .vs__cell + .vs__cell { margin-top: 0; }
  /* the gold rule becomes the column divider */
  .vs__cell::before { top: 0; bottom: 0; }
  .vs__cell--them::before { background: var(--border-neutral); }
  .vs__lbl { display: none; }
  /* hovering a row resolves the contrast; nothing is hidden without it */
  .vs__row:hover .vs__cell--them { opacity: 0.55; }
  .vs__row:hover .vs__cell--us { color: var(--white); }
  .vs__row:hover .vs__cell--us::before { background: var(--gold-light); }
  .vs__cell,
  .vs__cell::before { transition: opacity var(--dur) var(--ease-out), color var(--dur) var(--ease-out), background var(--dur) var(--ease-out); }
}

/* ==========================================================================
   MOBILE CORRECTIONS
   This site is opened on a phone far more than on a desktop, so these are
   corrections to the primary surface, not defensive tweaks for a minor one.

   They live here, at the end of the last stylesheet, because they override
   rules spread across main.css, editorial-1b/2/3.css, sections.css and
   roles.css. Collecting them in one block keeps the reasoning in one place;
   the alternative was fourteen edits in five files at specific line numbers.

   The 12-column .grid collapse is NOT here - that one is a correction to the
   rule itself and lives at main.css:338 where the grid is defined.
   ========================================================================== */

/* --- Breaking: the primary CTA was wider than the phone ------------------
   'Start a partnership conversation' inherits white-space:nowrap from .btn,
   giving it a 339px intrinsic width. Centred in the 320px content column of
   a 360px phone it landed 10px from both screen edges, punching through the
   gutter every other element respects - and .cta-band has overflow:hidden,
   so under ~340px the label was silently sliced. The hero button already had
   this treatment; the closing CTA never got it. */
@media (max-width: 760px) {
  .cta-band .hero__actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    max-width: 22rem;
    margin-inline: auto;
  }
  .cta-band .hero__actions .btn {
    white-space: normal;
    padding-inline: 1.25rem;
    font-size: 0.875rem;
  }
}

/* --- Breaking: a strike-through that missed its own text -----------------
   .joinus__negs draws the gold strike as an absolutely-positioned pseudo on
   an INLINE <s>. The moment the sentence wraps, the <s> splits into two line
   boxes and the pseudo resolves against one fragment: measured at 360px it
   rendered as a stray 35px gold dash floating BETWEEN the two lines, with
   neither line actually struck. The section's whole device - two claims
   visibly crossed out, leaving the one that counts - was lost.
   A real text-decoration follows every wrapped line. */
@media (max-width: 860px) {
  .joinus__negs s {
    display: block;
    text-decoration: line-through;
    text-decoration-color: var(--gold);
    text-decoration-thickness: 1px;
  }
  .joinus__negs s::after { display: none; }
}

/* --- iOS zoom-on-focus ---------------------------------------------------
   Safari force-zooms the whole page when a focused control is under 16px,
   and does not zoom back out on blur. The footer email field was 14px. */
@media (max-width: 1020px) {
  .imp__field input { font-size: 1rem; padding-block: 0.6rem; }
}

/* --- Tap targets ---------------------------------------------------------
   44px is the floor. Measured before: footer phone and email 24px tall and
   6.4px apart (a low tap on the number opened the mail client instead), the
   nine footer links 20px in rows 36px apart, the newsletter submit a 32px
   icon with no label, 'Back to top' 20px on a page ~19 screens long. */
@media (max-width: 1020px) {
  .imp__reach { gap: 0; }
  .imp__reach a,
  .imp__run a,
  .imp__top-link,
  .lat__mail,
  .rle__back {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .imp__run { gap: 0.25rem 1.5rem; }
  .lat__num { min-height: 44px; padding-block: 0.4rem; }
  .imp__top-link { padding-block: 0.7rem; }
  /* keeps the 32px circle the design draws, widens only what the thumb hits */
  .imp__field button { position: relative; }
  .imp__field button::before { content: ""; position: absolute; inset: -6px; }
}

/* --- Type that had shrunk below legibility -------------------------------
   Two captions were clamped to 0.56rem = 8.96px on phones: the about hero
   plate labels, and the caption set on top of the team-walk photograph. */
@media (max-width: 620px) {
  .hero--block .blk__idx { font-size: 0.75rem; letter-spacing: 0.18em; }
  .frm__cap { font-size: 0.7rem; letter-spacing: 0.14em; }
}

/* --- Two-up portraits on a narrow phone ----------------------------------
   sections.css:562 collapses .crew__row to one column under 460px, but
   .crew__row--two re-declares two columns from THIS file, which loads later.
   Media queries do not add specificity, so the later rule won and the pair
   stayed side by side at 360px. */
@media (max-width: 460px) {
  .crew__row--two { grid-template-columns: minmax(0, 1fr); max-width: 22rem; }
}

/* ============================================================
   Anchored sections clear the fixed header
   Buttons now point at sections rather than page tops (contact.html#write,
   careers.html#apply, services.html#services ...). The nav is fixed, so
   without this the browser scrolls the target to y=0 and the header sits on
   top of the heading you were sent to see.

   Same-page clicks already get an -80px offset from the Lenis handler in
   motion.js; this covers the case that handler cannot reach - arriving from
   another page, a bookmark, or a browser back/forward restore.
   ============================================================ */
[id] { scroll-margin-top: clamp(4.5rem, 4rem + 2vw, 6rem); }

/* ============================================================
   The pendant over "How we count"  (services.html, .rules)
   Copied from the darkroom bench further down the same page - .lat__lamp for
   the cord and shade, .lat__safelight::after for the cone - so the two
   sections are lit by the same object rather than by two different lamps.

   Scoped and self-contained: .rules gets position:relative and
   overflow:hidden, or the cone spills into the sections above and below it.
   Both nodes are aria-hidden and pointer-events:none.
   ============================================================ */
.rules {
  position: relative;
  overflow: hidden;
  --lamp-x: clamp(1.5rem, 9vw, 9rem);
  --lamp-w: 3.6rem;
  --lamp-h: clamp(4.5rem, 8vw, 7.5rem);
  --cone-w: clamp(13rem, 26vw, 26rem);
}
.rules > .container { position: relative; z-index: 2; }

/* the warm wash the shade throws across the top of the section */
.rules__glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(34% 30% at 82% 2%, rgba(206, 166, 104, 0.16), rgba(156, 120, 72, 0.05) 46%, transparent 72%),
    radial-gradient(88% 52% at 64% 30%, rgba(146, 108, 58, 0.08), transparent 72%);
}
/* the cone. clip-path makes the trapezoid, blur softens the edges. */
.rules__glow::after {
  content: "";
  position: absolute;
  top: calc(var(--lamp-h) - 0.5rem);
  right: calc(var(--lamp-x) + var(--lamp-w) / 2 - var(--cone-w) / 2);
  width: var(--cone-w);
  height: clamp(15rem, 30vw, 30rem);
  clip-path: polygon(44% 0%, 56% 0%, 100% 100%, 0% 100%);
  background: linear-gradient(180deg, rgba(214, 172, 108, 0.22), rgba(192, 156, 96, 0.055) 44%, transparent 78%);
  filter: blur(16px);
}

.rules__lamp {
  position: absolute;
  top: 0;
  right: var(--lamp-x);
  z-index: 1;
  width: var(--lamp-w);
  height: var(--lamp-h);
  pointer-events: none;
}
/* the cord */
.rules__lamp::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 1px;
  height: calc(100% - 1.15rem);
  background: linear-gradient(180deg, transparent, rgba(156, 120, 72, 0.55));
}
/* the shade, and the light it throws straight down out of its rim */
.rules__lamp::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 0;
  width: var(--lamp-w);
  height: 1.4rem;
  transform: translateX(-50%);
  border-radius: 100% 100% 4px 4px / 100% 100% 4px 4px;
  background: linear-gradient(178deg, #1d1912 0%, #0d0b09 100%);
  border: 1px solid rgba(156, 120, 72, 0.5);
  border-bottom: 0;
  box-shadow:
    0 2px 3px -1px rgba(238, 206, 150, 0.75),
    0 8px 22px -4px rgba(214, 172, 108, 0.5),
    0 28px 60px -8px rgba(192, 156, 96, 0.3),
    0 70px 130px -20px rgba(156, 120, 72, 0.26);
}
/* on a phone the lamp sits in from the edge and the cone narrows with it */
@media (max-width: 620px) {
  .rules { --lamp-x: 0.75rem; --lamp-w: 2.6rem; }
  .rules__lamp::after { width: 2.6rem; height: 1.05rem; }
}

/* ============================================================
   .ph - image placeholder
   Moved here from careers.css: it started as a careers component but is
   a generic utility, and team.html needs it too. Loaded on every page.
   ============================================================ */
.ph {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: var(--ph-ar, 4 / 5);
  overflow: hidden;
  border: 1px dashed var(--border-gold-strong);
  border-radius: var(--radius-md);
  background:
    repeating-linear-gradient(135deg, rgba(156, 120, 72, 0.05) 0 10px, transparent 10px 20px),
    var(--surface);
  color: var(--vein);
}
.ph__label {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  padding: 0.5rem 1rem;
  line-height: 1.5;
  text-wrap: balance;
}
/* a real photograph drops in here and needs no other change */
.ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ph:has(img) { border-style: solid; }
.ph:has(img) .ph__label { display: none; }


/* ============================================================
   .fnc - how the team is built (team.html)
   Replaced .fld: four photographic panes tiling one field, their seams
   travelling on a scroll-linked --g. That was ~1,000px of page and four
   images to define four seats. This is the same four definitions as text,
   in one scannable row.
   ============================================================ */
.fnc { padding-block: clamp(2.25rem, 1.8rem + 2.4vw, 4rem); }
.fnc__head { max-width: 46rem; margin-bottom: clamp(1.5rem, 1.2rem + 1.4vw, 2.25rem); }
.fnc__h {
  font-size: clamp(1.5rem, 1.2rem + 1.5vw, 2.4rem);
  font-weight: 600;
  letter-spacing: -0.028em;
  color: var(--white);
  text-wrap: balance;
}
.fnc__h em { font-style: italic; color: var(--gold-light); }
.fnc__lead { margin-top: 0.85rem; color: var(--vein); line-height: 1.65; text-wrap: pretty; }

.fnc__grid {
  list-style: none;
  display: grid;
  gap: 0;
}
.fnc__item {
  padding: clamp(0.95rem, 0.85rem + 0.5vw, 1.3rem) 0;
  border-top: 1px solid var(--border-neutral);
}
.fnc__grid .fnc__item:last-child { border-bottom: 1px solid var(--border-neutral); }
.fnc__n {
  display: block;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
  margin-bottom: 0.4rem;
}
.fnc__kicker {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vein);
  margin-bottom: 0.25rem;
}
.fnc__name {
  font-size: clamp(0.98rem, 0.93rem + 0.3vw, 1.12rem);
  font-weight: 600;
  letter-spacing: -0.018em;
  line-height: 1.3;
  color: var(--white);
  text-wrap: balance;
}
.fnc__copy { margin-top: 0.35rem; font-size: var(--text-sm); line-height: 1.55; color: var(--vein); text-wrap: pretty; }

/* four across from 820px: the whole point of the rebuild is that all four
   seats are readable in one glance without scrolling */
@media (min-width: 820px) {
  .fnc__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: clamp(1.25rem, 1rem + 1.4vw, 2.5rem);
    border-top: 1px solid var(--border-gold);
    padding-top: clamp(1.1rem, 0.95rem + 0.6vw, 1.6rem);
  }
  .fnc__item { padding: 0; border-top: 0; }
  .fnc__grid .fnc__item:last-child { border-bottom: 0; }
}
@media (min-width: 560px) and (max-width: 819px) {
  .fnc__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 1.75rem; }
  .fnc__item:nth-child(2) { border-top: 1px solid var(--border-neutral); }
}

/* ============================================================
   .vhero - about hero, centred text over a video background
   The video file does not exist yet. The <video> element is here with no
   <source>, which renders nothing and leaves the marble ground and scrim
   behind it - so the hero is complete and readable today, and adding the
   film is a single <source> line inside the existing element.

   .vhero__ph is the "video goes here" note. :has(source) removes it the
   moment a real source is added, so it cannot be left on the page by
   accident.
   ============================================================ */
.vhero {
  position: relative;
  display: grid;
  place-items: center;
  min-height: clamp(30rem, 78vh, 46rem);
  padding-block: clamp(6.5rem, 5rem + 8vw, 9rem) clamp(3rem, 2.5rem + 3vw, 5rem);
  overflow: hidden;
  text-align: center;
}
.vhero__media { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
/* AN IFRAME CANNOT BE object-fit: cover, so the cover has to be built.
   Size it to the viewport's 16:9 in both directions and let min-* take
   whichever is larger, then centre and crop the overflow. 177.78vh is
   16/9 of the height; 56.25vw is 9/16 of the width. */
/* the still that is always there. The film, when it runs, covers it. */
.vhero__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 55% 50%;
}
/* A <video> CAN be object-fit: cover, unlike the iframe this replaced, so
   the whole 177.78vh / 56.25vw cover trick below is no longer needed for it.
   It fades in on `playing` so the cut from still to film is not a flash. */
.vhero__vid {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  opacity: 0;
  transition: opacity 1s var(--ease-out);
  pointer-events: none;
}
.vhero__vid.is-playing { opacity: 1; }
/* the scrim is what keeps the copy readable over ANY footage handed over -
   without it the hero depends on the film being dark enough, which is not a
   thing to leave to chance */
.vhero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(6, 6, 8, 0.66) 0%, rgba(6, 6, 8, 0.46) 45%, rgba(6, 6, 8, 0.8) 100%),
    radial-gradient(70% 60% at 50% 45%, rgba(156, 120, 72, 0.1), transparent 72%);
}
.vhero__ph {
  position: absolute;
  left: 50%;
  bottom: clamp(1rem, 3vw, 2rem);
  transform: translateX(-50%);
  padding: 0.4rem 0.9rem;
  border: 1px dashed var(--border-gold-strong);
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vein);
  white-space: nowrap;
}
.vhero__media:has(source) .vhero__ph { display: none; }

.vhero__inner { position: relative; z-index: 1; }
.vhero .eyebrow { justify-content: center; }
.vhero .eyebrow::before { display: none; }
.vhero__h {
  font-size: clamp(1.85rem, 1.4rem + 2.4vw, 3.1rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--white);
  max-width: 20ch;
  margin-inline: auto;
  text-wrap: balance;
}
.vhero__h em { font-style: italic; color: var(--gold-light); }
.vhero__sub {
  margin: clamp(1rem, 0.85rem + 0.6vw, 1.4rem) auto 0;
  max-width: 40rem;
  color: var(--ink);
  font-size: var(--text-base);
  line-height: 1.65;
  text-wrap: pretty;
}
.vhero__note {
  margin: clamp(0.9rem, 0.8rem + 0.5vw, 1.25rem) auto 0;
  max-width: 34rem;
  color: var(--vein);
  font-size: var(--text-sm);
  line-height: 1.6;
}
.vhero__act { margin-top: clamp(1.5rem, 1.25rem + 1vw, 2.25rem); }

/* motion off: a looping background film is exactly what this setting is for.
   The JS also declines to fetch the file at all under this setting - this
   rule is the belt to that braces, in case the script never runs. */
@media (prefers-reduced-motion: reduce) {
  .vhero__vid { display: none; }
}

/* ==========================================================================
   MOBILE UI PASS  -  the findings in MOBILE-UI-REPORT.md
   Measured live at 390x844, not read off the stylesheet. Nothing here changes
   a layout; it is all type size and padding, which is what the report found.
   ========================================================================== */

/* --- Tap targets ---------------------------------------------------------
   44px is the floor for a thumb, and a miss on a phone usually means hitting
   the wrong thing. Measured before this rule: the email address rendered
   240x17 - the highest-intent tap on a sales site, at 17px tall - and every
   .link-line CTA came in at 30px.

   min-height on an inline-flex, NOT padding: padding on an inline <a> inside a
   paragraph overlaps the lines above and below it, which is how a "fix" for
   this turns into two overlapping hit areas. */
@media (max-width: 1020px) {
  .link-line,
  .imp__reach a,
  .cf__alt a,
  .prof__meta a,
  .gmap__meta a,
  main a[href^="mailto:"],
  main a[href^="tel:"] {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  /* the email address is long enough to wrap on a phone; when it does, the
     44px floor must not stretch the whole wrapped block */
  main a[href^="mailto:"] { flex-wrap: wrap; }
}

/* --- Type below the legibility floor -------------------------------------
   Below ~11.5px, tracked uppercase type stops being readable at arm's length
   and starts being decoration. These were measured at 9-11.2px.

   .wordmark__sub is the important one: 9px, in the header, on every page. */
@media (max-width: 1020px) {
  .wordmark__sub { font-size: 0.75rem; letter-spacing: 0.14em; }
  /* the hero's "Face to face marketing | Cincinnati, Ohio" rule */
  .eyebrow--bare span,
  .skyhero__eyebrow span { font-size: 0.75rem; }
  .fbeat__tag { font-size: 0.72rem; }
  .acx__lbl,
  .rcard__freq { font-size: 0.72rem; }
  .pq__role,
  .rrole__tags li { font-size: 0.75rem; }
}

/* --- iOS zoom-on-focus, absolute rule ------------------------------------
   Safari force-zooms the page when a focused control is under 16px and does
   not zoom back out. The real forms are already 16px; this catches the CSS-tab
   radios on the homepage so the rule has no exceptions. */
@media (max-width: 1020px) {
  input, select, textarea { font-size: max(1rem, 1em); }
}

/* The careers stamp keeps its 9.5px arc text: it is aria-hidden, purely
   decorative, and reads as a stamp BECAUSE it is small. Deliberately not
   lifted. */

/* ============================================================
   .shot  -  a photograph inside a section
   The homepage carried ZERO photographs: twelve sections of type, rules and
   numbers. On a site whose whole argument is "we send people to doors", that
   is the one thing the page should show and did not.

   One component, used on alternating sections so the page breathes rather
   than turning into a gallery. Ratio-locked so nothing reflows as the image
   decodes, and captioned - a photograph with no caption on a claims-based
   page is decoration; with one it is evidence.
   ============================================================ */
.shot {
  position: relative;
  margin-top: clamp(1.75rem, 1.4rem + 1.6vw, 2.75rem);
  /* SPAN THE WHOLE ROW. Several of the sections these land in are two-column
     grids (.plain__grid is 485/643, .joinus__grid likewise). Without this the
     figure becomes a third grid item, takes column 1 on a new row, and sits
     at 485px with the other column empty beside it - which is exactly how it
     looked wrong. grid-column is inert on a non-grid parent, so the one rule
     is safe everywhere. */
  grid-column: 1 / -1;
}
.shot__frame {
  position: relative;
  display: block;
  overflow: hidden;
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-md);
  background: var(--surface);
  aspect-ratio: var(--shot-ar, 21 / 9);
}
.shot__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--shot-pos, 50% 42%);
  filter: saturate(0.94) contrast(1.03);
  transform: scale(1.01);
  transition: transform 1.2s var(--ease-out), filter var(--dur) var(--ease-out);
}
.shot:hover .shot__frame img { transform: scale(1.05); filter: saturate(1) contrast(1.04); }
/* the scrim is what lets a caption sit ON the photograph and stay readable
   whatever the image is doing underneath it */
.shot__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, transparent 40%, rgb(var(--scrim-rgb) / 0.72) 100%);
}
.shot__cap {
  position: absolute;
  left: clamp(0.9rem, 0.8rem + 0.6vw, 1.5rem);
  bottom: clamp(0.75rem, 0.65rem + 0.5vw, 1.2rem);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
}
.shot__cap::before {
  content: "";
  width: 1.4rem;
  height: 1px;
  background: var(--gold);
  flex: none;
}
/* a 21:9 letterbox is 170px tall on a phone - too thin to read as a picture */
@media (max-width: 720px) {
  .shot__frame { aspect-ratio: var(--shot-ar-m, 3 / 2); }
}

/* the two-channel columns each carry their own photograph: one business, one
   home. Side by side they ARE the argument the section is making. */
.duo2__shot {
  --shot-ar: 4 / 3;
  --shot-ar-m: 3 / 2;
  margin: 0 0 clamp(1rem, 0.85rem + 0.6vw, 1.5rem);
}

/* ============================================================
   .quote__logo  -  the client's mark on a testimonial card
   The card carries the brand it came from, so a reader can see WHO said it
   before reading WHAT they said. Reversed to white by the same
   brightness/invert used on .strip__mark - the source files are dark ink on
   transparency.
   ============================================================ */
.quote__logo {
  display: flex;
  align-items: center;
  height: clamp(1.35rem, 1.15rem + 0.8vw, 1.85rem);
  margin-bottom: clamp(1rem, 0.85rem + 0.6vw, 1.4rem);
  opacity: 0.72;
  filter: brightness(0) invert(1);
  transition: opacity var(--dur) var(--ease-out);
}
.quote:hover .quote__logo { opacity: 1; }
.quote__logo img {
  max-height: 100%;
  width: auto;
  max-width: clamp(5.5rem, 9vw, 7.5rem);
  object-fit: contain;
}

/* ============================================================
   .cli  -  the brands we represent
   Occupies the slot a testimonial section would, and is shaped so a quote
   drops straight in later: add a <blockquote class="cli__quote"> above the
   footer and the card becomes a testimonial with no restructuring.

   NO INVENTED QUOTES. What is on these cards is only what the site can
   already stand behind - the mark, the category, and what we actually do for
   that brand. Real and checkable beats a placeholder or a fabrication.
   ============================================================ */
.cli__grid {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
  gap: clamp(0.9rem, 0.75rem + 0.7vw, 1.4rem);
  align-items: stretch;
}
.cli {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(1.35rem, 1.1rem + 1vw, 2rem);
  border: 1px solid var(--border-gold);
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, var(--gold-wash), transparent 60%), var(--surface);
  transition: border-color var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.cli:hover { border-color: var(--border-gold-strong); transform: translateY(-3px); }
.cli__logo {
  display: flex;
  align-items: center;
  height: clamp(1.4rem, 1.2rem + 0.8vw, 1.9rem);
  margin-bottom: clamp(1rem, 0.85rem + 0.6vw, 1.4rem);
  opacity: 0.75;
  filter: brightness(0) invert(1);
  transition: opacity var(--dur) var(--ease-out);
}
.cli:hover .cli__logo { opacity: 1; }
.cli__logo img { max-height: 100%; width: auto; max-width: clamp(5.5rem, 9vw, 7.5rem); object-fit: contain; }
.cli__cat {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}
.cli__what {
  margin-top: 0.6rem;
  color: var(--ink);
  font-size: var(--text-sm);
  line-height: 1.62;
  text-wrap: pretty;
}
/* margin-top:auto pins the footer to the bottom so three cards with
   different copy lengths still line their rules up */
.cli__foot {
  margin-top: auto;
  padding-top: clamp(0.9rem, 0.8rem + 0.5vw, 1.25rem);
  border-top: 1px solid var(--border-neutral);
}
.cli__meta { font-size: 0.78rem; letter-spacing: 0.04em; color: var(--vein); }
.cli__meta b { color: var(--gold-light); font-weight: 600; }
/* the slot a real quote will occupy - styled now so adding one is one tag */
.cli__quote {
  margin: 0 0 clamp(0.9rem, 0.8rem + 0.5vw, 1.25rem);
  font-size: var(--text-base);
  line-height: 1.68;
  color: var(--ink);
}

/* small orphans from the sections above */
.svcx__more { flex: none; }
.crew__meta { min-width: 0; }
