/*
Theme Name: Vellum — Sandy Baker
Theme URI: https://sandybakerjewelry.com
Author: Bag of Apples
Author URI: https://bagofapples.com
Description: Per-site Vellum child theme for Sandy Baker. A designer's monograph: warm paper, full-ink rules, and photography that dominates. Sets tokens plus the collection, archive and chronology components.
Template: vellum
Version: 1.0.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: vellum-sb
*/

/* ============================================================
   SANDY BAKER — design tokens
   House style decision (site-styling, 2026-07-28):
   light editorial monograph, accent drawn from the red coral
   in her own work, type scaled up one notch for legibility.
   ============================================================ */

:root {
  /* ── TYPE ──
     DM Sans on both registers: the house fine-art default. The
     handwritten signature logotype is the only voice with
     personality on the page, so the typeface stays quiet. */
  --font-sans:    "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --font-display: var(--font-sans);

  /* ── PALETTE ──
     Warm paper so her black-and-white plates sit like prints in a
     monograph. Accent is an oxblood drawn from the red coral she
     inlays, reserved for links, hover and focus only. */
  --color-bg:         #F5F3EE;
  --color-text:       #0A0A0A;
  --color-text-muted: #6B6B68;
  --color-line:       #0A0A0A;          /* light-mode rules are full ink */
  --color-accent:     #8C2F23;
  --color-accent-dim: rgba(140, 47, 35, .10);

  /* ── EXTENSIONS (not parent tokens) ── */
  --sb-hairline:  0 0 0 1px rgba(10, 10, 10, .10);  /* white-image hairline */
  --sb-rule:      1px solid var(--color-line);

  /* ── TYPE SCALE ──
     Display pulled back from Vellum's default: the photography is
     the headline. Body and small pushed up for an older audience. */
  --type-display: clamp(44px, 5.5vw, 92px);
  --type-h1:      clamp(34px, 4.6vw, 68px);
  --type-h2:      clamp(26px, 3.4vw, 46px);
  --type-h3:      clamp(19px, 2.2vw, 30px);
  --type-body:    clamp(16px, 1.25vw, 19px);
  --type-small:   clamp(13px, 1vw, 15px);
}

/* ── LINKS ────────────────────────────────────────────────── */
.vellum-page__body a:not(.sb-card):not(.vellum-zoom) {
  color: var(--color-accent);
  text-underline-offset: .18em;
  text-decoration-thickness: 1px;
}
.vellum-page__body a:not(.sb-card):not(.vellum-zoom):hover { text-decoration-thickness: 2px; }

/* ── COLLECTION GRID ──────────────────────────────────────── */
.sb-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(260px, 100%), 1fr));
  gap: var(--gap);
  margin: var(--gap-lg) 0;
  padding: 0;
  list-style: none;
}
.sb-grid__item { margin: 0; }

.sb-figure { margin: 0; }
.sb-figure__frame {
  display: block;
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  background: #fff;
  box-shadow: var(--sb-hairline);
  cursor: zoom-in;
}
/* Thumbnails are uniform squares with no inset padding. Tall pictures fill
   the square; wide ones are shown whole on white or black, whichever their
   own edges are (assets/js/tiles.js decides). The lightbox shows the full
   uncropped file. */
.sb-figure__frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-md) var(--ease-out);
}
@media (hover: hover) {
  .sb-figure__frame:hover img { transform: scale(1.03); }
}
.sb-figure__cap {
  margin-top: .6em;
  font-size: var(--type-small);
  line-height: 1.45;
}
.sb-figure__name  { display: block; font-weight: 500; }
.sb-figure__desc  { display: block; color: var(--color-text-muted); margin-top: .15em; }

/* Long descriptions under a thumbnail stop at four lines so tiles in a row
   read alike. assets/js/tiles.js lifts the cut entirely when the text runs
   five lines or fewer (a More button to reveal one line is noise), and adds
   an animated More/Less toggle to the rest. The lightbox always carries the
   full caption. */
.sb-figure__desc,
.sb-chrono__text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  overflow: hidden;
}
.sb-figure__desc.is-full,
.sb-chrono__text.is-full,
.sb-figure__desc.is-open,
.sb-chrono__text.is-open {
  display: block;
  -webkit-line-clamp: unset;
  line-clamp: none;
}
.sb-figure__desc.is-full,
.sb-chrono__text.is-full { overflow: visible; }
.sb-more {
  display: inline-block;
  margin: .35em 0 0;
  padding: .2em 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--type-small);
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: .18em;
  text-decoration-thickness: 1px;
  cursor: pointer;
}
.sb-more:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

/* ── COLLECTION INDEX CARDS ───────────────────────────────── */
.sb-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
  gap: var(--gap-lg) var(--gap);
  margin: var(--gap-lg) 0;
  padding: 0;
  list-style: none;
}
.sb-card { display: block; text-decoration: none; color: inherit; }
.sb-card__frame {
  display: block;
  aspect-ratio: 4 / 3;      /* collection cards stay landscape */
  overflow: hidden;
  background: #fff;
  box-shadow: var(--sb-hairline);
}
.sb-card__frame img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--dur-md) var(--ease-out);
}
@media (hover: hover) { .sb-card:hover .sb-card__frame img { transform: scale(1.04); } }
.sb-card__title {
  margin: .7em 0 0;
  font-size: var(--type-h3);
  line-height: 1.15;
  letter-spacing: -.02em;
}
.sb-card__meta {
  font-size: var(--type-small);
  color: var(--color-text-muted);
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* ── SECTION HEADS ────────────────────────────────────────── */
.sb-section { margin: var(--gap-lg) 0; }
.sb-section__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gap-sm);
  padding-bottom: .5em;
  border-bottom: var(--sb-rule);
}
.sb-section__title { margin: 0; font-size: var(--type-h2); letter-spacing: -.025em; }
.sb-section__count {
  font-size: var(--type-small); color: var(--color-text-muted);
  letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
}
/* About Sandy on the homepage: text beside her portrait, with the same air
   under the rule as the card grid above it. Page-title intros elsewhere stay
   tight as subtitles. */
.sb-about { margin-top: var(--gap-lg); display: grid; gap: var(--gap-lg); align-items: start; }
.sb-about .sb-lede { margin-bottom: var(--gap); }
.sb-about__photo { margin: 0; justify-self: start; width: min(100%, 420px); }
.sb-about__photo img { display: block; width: 100%; height: auto; box-shadow: var(--sb-hairline); }
@media (min-width: 861px) {
  .sb-about { grid-template-columns: minmax(0, 1fr) minmax(260px, 380px); gap: clamp(32px, 5vw, 96px); }
  .sb-about__photo { justify-self: end; width: 100%; }
}
.sb-lede {
  max-width: 62ch;
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--color-text-muted);
  margin: 0 0 var(--gap-lg);
}

/* ── CHRONOLOGY (History) ─────────────────────────────────── */
.sb-chrono {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: var(--gap-lg) var(--gap);
  list-style: none;
  margin: var(--gap) 0 0;
  padding: 0;
}
.sb-chrono__item { margin: 0; }
.sb-chrono__frame {
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
  background: #fff;
  box-shadow: var(--sb-hairline); cursor: zoom-in;
}
.sb-chrono__frame img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  object-position: 50% 0;   /* clippings: keep the headline */
}
.sb-card__frame.is-tall-light img,
.sb-figure__frame.is-wide img,
.sb-card__frame.is-wide img,
.sb-chrono__frame.is-wide img { object-fit: contain; object-position: 50% 50%; }
.sb-figure__frame.is-dark-top,
.sb-card__frame.is-dark-top,
.sb-chrono__frame.is-dark-top { background: linear-gradient(#0a0a0a 50%, #fff 50%); }
.sb-figure__frame.is-dark-bottom,
.sb-card__frame.is-dark-bottom,
.sb-chrono__frame.is-dark-bottom { background: linear-gradient(#fff 50%, #0a0a0a 50%); }
.sb-figure__frame.is-dark-top.is-dark-bottom,
.sb-card__frame.is-dark-top.is-dark-bottom,
.sb-chrono__frame.is-dark-top.is-dark-bottom { background: #0a0a0a; }
.sb-chrono__year {
  margin: .65em 0 .15em;
  font-size: var(--type-h4);
  line-height: 1;
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.sb-chrono__text {
  margin: 0;
  font-size: var(--type-small);
  line-height: 1.5;
  color: var(--color-text-muted);
}

/* ── ARCHIVE NOTE ─────────────────────────────────────────── */
.sb-note {
  border-left: 2px solid var(--color-accent);
  padding: .2em 0 .2em 1em;
  margin: var(--gap) 0;
  font-size: var(--type-small);
  color: var(--color-text-muted);
  max-width: 62ch;
}

/* ── MOTION ───────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .sb-figure__frame img,
  .sb-card__frame img { transition: none !important; }
  .sb-figure__frame:hover img,
  .sb-card:hover .sb-card__frame img { transform: none !important; }
}

/* ── HOME HERO ────────────────────────────────────────────── */
.sb-hero {
  position: relative;
  min-height: min(88vh, 880px);
  display: grid;
  align-items: end;
  overflow: hidden;
  background: #0A0A0A;
}
.sb-hero__bg,
.sb-slide__bg {
  position: absolute; inset: 0;
  z-index: 0;
  width: 100%; height: 100%;
  object-fit: cover; object-position: center 35%;
}

/* Scrim spans the WHOLE hero.
   It used to hang off .sb-hero__inner::before, but .sb-hero__inner is a grid
   item aligned to the bottom, so `inset: 0` resolved against that block's own
   box rather than the hero. The darkening therefore began partway down the
   photograph and left a hard horizontal edge where it started. Anchoring it to
   .sb-hero instead means the fade runs the full height, top to bottom. */
.sb-hero::after {
  content: "";
  position: absolute; inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    /* A short band just for the nav: the five slides vary a lot in brightness
       and the menu has to stay readable on every one of them. */
    linear-gradient(to bottom, rgba(0,0,0,.46) 0px, rgba(0,0,0,.18) 96px, rgba(0,0,0,0) 180px),
    linear-gradient(to bottom, rgba(0,0,0,.30) 0%,  rgba(0,0,0,.14) 26%,
                               rgba(0,0,0,.42) 62%, rgba(0,0,0,.84) 100%),
    linear-gradient(to right,  rgba(0,0,0,.62) 0%,  rgba(0,0,0,.26) 40%,
                               rgba(0,0,0,0)   72%);
}

.sb-hero__inner {
  position: relative;
  z-index: 2;
  padding: var(--gap-lg) var(--gutter) calc(var(--gap-lg) * 1.2);
  color: #fff;
}
.sb-hero__eyebrow {
  margin: 0 0 .6em;
  font-size: var(--type-eyebrow);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(255,255,255,.82);
}
.sb-hero__title {
  margin: 0;
  /* The heading now holds the signature mark; the text inside it is
     screen-reader-only, so the type tokens no longer drive its size. */
  line-height: 1;
}

/* ── SIGNATURE MARK ───────────────────────────────────────
   Sized by width so it lands at roughly the optical weight the old
   display-type wordmark had. Colour comes from `currentColor`, so the
   same asset is ink on paper and white over the hero photograph. */
.sb-signature {
  display: block;
  width: clamp(230px, 34vw, 500px);
  max-width: 100%;
  color: inherit;
}
.sb-signature svg {
  display: block;
  width: 100%;
  height: auto;
}
.sb-hero .sb-signature {
  color: #fff;
  /* Lifts the strokes off a busy photograph without a hard box. */
  filter: drop-shadow(0 2px 14px rgba(0, 0, 0, .55));
}
.sb-hero__lede {
  max-width: 56ch;
  margin: .8em 0 0;
  font-size: var(--type-body);
  line-height: 1.55;
  color: rgba(255,255,255,.90);
}
.sb-hero__actions { margin: 1.4em 0 0; display: flex; flex-wrap: wrap; gap: var(--gap-sm); }

/* ── BUTTONS ──────────────────────────────────────────────── */
.sb-btn {
  display: inline-block;
  padding: .72em 1.5em;
  font-size: var(--type-small);
  letter-spacing: .10em;
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid currentColor;
  color: inherit;
  transition: background-color var(--dur-xs) var(--ease), color var(--dur-xs) var(--ease);
}
.sb-hero .sb-btn { color: #fff; }
.sb-hero .sb-btn:hover { background: #fff; color: #0A0A0A; }
.sb-btn--quiet { opacity: .85; }
.vellum-page__body .sb-btn { color: var(--color-text); }
.vellum-page__body .sb-btn:hover { background: var(--color-text); color: var(--color-bg); }

/* ── PRESS LIST ───────────────────────────────────────────── */
.sb-press { list-style: none; margin: var(--gap) 0 0; padding: 0; }
.sb-press__item { border-bottom: 1px solid rgba(10,10,10,.14); }
.sb-press__item a {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gap-sm);
  padding: .95em 0;
  text-decoration: none; color: inherit;
  transition: padding-left var(--dur-sm) var(--ease-out);
}
@media (hover: hover) { .sb-press__item a:hover { padding-left: .8em; } }
.sb-press__title { font-size: var(--type-body); line-height: 1.35; }
.sb-press__date {
  font-size: var(--type-small); color: var(--color-text-muted);
  white-space: nowrap; letter-spacing: .06em; text-transform: uppercase;
}

/* ── ABOUT PAGE PROSE ─────────────────────────────────────── */
.sb-prose { max-width: var(--sb-narrow-col); font-size: var(--type-body); line-height: 1.68; }
.sb-prose p { margin: 0 0 1.15em; }
.sb-portrait {
  float: left;
  margin: .3em 1.6em 1em 0;
  max-width: 200px;
  box-shadow: var(--sb-hairline);
}
@media (max-width: 620px) {
  .sb-portrait { float: none; margin: 0 0 1.2em; max-width: 60%; }
}
.sb-video { margin: var(--gap-lg) 0; max-width: 960px; }
.sb-video video { width: 100%; height: auto; display: block; background: #000; }

/* ── CONTACT ──────────────────────────────────────────────── */
.sb-contact { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px,100%), 1fr)); gap: var(--gap-lg); }

@media (prefers-reduced-motion: reduce) {
  .sb-press__item a { transition: none !important; }
  .sb-press__item a:hover { padding-left: 0 !important; }
}

/* ── ANSWER-FIRST LEDE + FAQ (GEO editorial layer) ────────── */
.sb-answer {
  border-left: 3px solid var(--color-accent);
  padding: .1em 0 .1em 1.1em;
  margin: 0 0 1.6em;
}
.sb-answer p { margin: 0; font-size: var(--type-body); line-height: 1.6; }

.sb-faq { margin: var(--gap-lg) 0 0; max-width: var(--sb-narrow-col); }
.sb-faq h2 {
  font-size: var(--type-h3);
  letter-spacing: -.02em;
  padding-bottom: .4em;
  border-bottom: var(--sb-rule);
}
.sb-faq__list { margin: 0; }
.sb-faq__q {
  margin: 1.4em 0 .35em;
  font-weight: 500;
  font-size: var(--type-body);
  line-height: 1.35;
}
.sb-faq__a {
  margin: 0;
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--color-text-muted);
}

/* ── VISUALLY HIDDEN ──────────────────────────────────────
   Defined here rather than relying on WordPress's block-library stylesheet,
   which is not guaranteed to be enqueued on every template. The hero <h1>
   depends on this to keep real text for search engines and screen readers
   while showing the signature mark. */
.screen-reader-text {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.screen-reader-text:focus {
  position: static !important;
  width: auto; height: auto;
  margin: 0; overflow: visible;
  clip-path: none; white-space: normal;
}

/* ── NEWS / PRESS MASONRY ─────────────────────────────────
   Row spans are assigned by assets/js/masonry.js. Before that runs (or if it
   never does) this is a plain auto-flow grid, which is a perfectly usable
   fallback — just not tightly packed. */
.sb-news {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(290px, 100%), 1fr));
  grid-auto-rows: 8px;
  column-gap: var(--gap);
  row-gap: var(--gap-lg);
  margin: var(--gap-lg) 0 0;
}
.sb-news:not(.is-laid-out),
.sb-news.is-single { grid-auto-rows: auto; }
.sb-news.is-single { row-gap: var(--gap-lg); }

.sb-news__item { margin: 0; }
.sb-news__link {
  display: block;
  text-decoration: none;
  color: inherit;
}
.sb-news__frame {
  display: block;
  overflow: hidden;
  background: #fff;
  box-shadow: var(--sb-hairline);
  aspect-ratio: 4 / 3;      /* replaced inline by the image's real ratio */
}
.sb-news__frame img {
  display: block;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform var(--dur-md) var(--ease-out),
              opacity   var(--dur-sm) var(--ease);
}
@media (hover: hover) {
  .sb-news__link:hover .sb-news__frame img { transform: scale(1.03); }
  .sb-news__link:hover .sb-news__title { text-decoration: underline; text-underline-offset: .16em; }
}

.sb-news__body { display: block; padding-top: .7em; }
.sb-news__date {
  display: block;
  font-size: var(--type-small);
  letter-spacing: .10em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.sb-news__title {
  display: block;
  margin-top: .22em;
  font-size: var(--type-h4);
  line-height: 1.22;
  letter-spacing: -.015em;
  text-wrap: pretty;
}
.sb-news__excerpt {
  display: block;
  margin-top: .4em;
  font-size: var(--type-small);
  line-height: 1.55;
  color: var(--color-text-muted);
}

/* ── PAGINATION ───────────────────────────────────────────── */
.sb-pagination { margin: var(--gap-lg) 0 0; border-top: var(--sb-rule); padding-top: var(--gap); }
.sb-pagination ul {
  display: flex; flex-wrap: wrap; gap: var(--gap-sm);
  /* Vellum centres .page-numbers; the rest of this page is left-aligned. */
  justify-content: flex-start;
  list-style: none; margin: 0; padding: 0;
}
.sb-pagination a, .sb-pagination span {
  display: inline-block;
  padding: .45em .9em;
  font-size: var(--type-small);
  text-decoration: none;
  border: 1px solid var(--color-line);
  color: var(--color-text);
}
.sb-pagination .current { background: var(--color-text); color: var(--color-bg); }

@media (prefers-reduced-motion: reduce) {
  .sb-news__frame img { transition: none !important; }
  .sb-news__link:hover .sb-news__frame img { transform: none !important; }
}

/* ── NARROW EDITORIAL PAGES (About, Contact) ──────────────
   A centred reading column. The section head keeps the same scale and rule
   as the collection pages so the whole site shares one heading rhythm. */
:root {
  --sb-narrow-col: 68ch;
  /* One value drives both vertical gaps on the Contact page: heading to fields
     on the left, Instagram to portrait on the right. Keeping them equal is the
     whole point of the layout, so they read from the same place. */
  --sb-field-gap: 22px;
}

/* Head and body share ONE column width, so the rule under the title lines up
   with the text instead of running the full container. */
.sb-narrow__body,
.sb-narrow .sb-section__head {
  max-width: var(--sb-narrow-col);
  margin-inline: auto;
}
.sb-narrow__body > .sb-prose,
.sb-narrow__body > .sb-faq,
.sb-narrow__body > .sb-answer { margin-inline: auto; }
.sb-narrow .sb-section__title { text-align: left; }
.sb-narrow__body .sb-video { margin-inline: auto; }
.sb-narrow__body .sb-contact { max-width: none; }

/* ── ARTICLE FEATURED IMAGE ───────────────────────────────
   Vellum ships the featured figure unstyled, so it rendered at the file's
   intrinsic width and floated small inside the reading column. Fill the
   article width instead. */
.vellum-article__featured {
  margin: 0 0 var(--gap-lg);
}
/* The white ground and hairline belong to the picture, not the caption:
   on the figure they boxed the credit line in a white bar. */
.vellum-article__featured img {
  display: block;
  width: 100%;
  height: auto;
  background: #fff;
  box-shadow: var(--sb-hairline);
}
.vellum-article__featured figcaption {
  padding: .35em 0 0;
  font-size: var(--type-small);
  line-height: 1.4;
  color: var(--color-text-muted);
}

/* ── MINIMAL SOCIAL / LINK ICONS ──────────────────────────
   Masked SVG rather than <img>, so every icon inherits currentColor and
   picks up hover and dark backgrounds without a second asset. */
.sb-ico {
  display: inline-block;
  width: 1.15em; height: 1.15em;
  flex: 0 0 auto;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center;  mask-position: center;
  -webkit-mask-size: contain;     mask-size: contain;
  vertical-align: -0.2em;
}
.sb-ico[data-ico="instagram"] { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.7%22%20stroke-linecap%3D%22round%22%3E%3Crect%20x%3D%223%22%20y%3D%223%22%20width%3D%2218%22%20height%3D%2218%22%20rx%3D%225.2%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%224.1%22%2F%3E%3Ccircle%20cx%3D%2217.3%22%20cy%3D%226.7%22%20r%3D%221.15%22%20fill%3D%22%23000%22%20stroke%3D%22none%22%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.7%22%20stroke-linecap%3D%22round%22%3E%3Crect%20x%3D%223%22%20y%3D%223%22%20width%3D%2218%22%20height%3D%2218%22%20rx%3D%225.2%22%2F%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%224.1%22%2F%3E%3Ccircle%20cx%3D%2217.3%22%20cy%3D%226.7%22%20r%3D%221.15%22%20fill%3D%22%23000%22%20stroke%3D%22none%22%2F%3E%3C%2Fsvg%3E"); }
.sb-ico[data-ico="twitter"] { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22%23000%22%3E%3Cpath%20d%3D%22M23.2%204.9a8.5%208.5%200%200%201-2.5.7A4.3%204.3%200%200%200%2022.6%203a8.6%208.6%200%200%201-2.7%201.1A4.3%204.3%200%200%200%2012.5%208a12.2%2012.2%200%200%201-8.9-4.5%204.3%204.3%200%200%200%201.3%205.7%204.2%204.2%200%200%201-1.9-.5v.1a4.3%204.3%200%200%200%203.4%204.2%204.3%204.3%200%200%201-1.9.1%204.3%204.3%200%200%200%204%203A8.6%208.6%200%200%201%201%2017.9a12.1%2012.1%200%200%200%206.6%201.9c7.9%200%2012.2-6.5%2012.2-12.2V7a8.7%208.7%200%200%200%202.1-2.2z%22%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22%23000%22%3E%3Cpath%20d%3D%22M23.2%204.9a8.5%208.5%200%200%201-2.5.7A4.3%204.3%200%200%200%2022.6%203a8.6%208.6%200%200%201-2.7%201.1A4.3%204.3%200%200%200%2012.5%208a12.2%2012.2%200%200%201-8.9-4.5%204.3%204.3%200%200%200%201.3%205.7%204.2%204.2%200%200%201-1.9-.5v.1a4.3%204.3%200%200%200%203.4%204.2%204.3%204.3%200%200%201-1.9.1%204.3%204.3%200%200%200%204%203A8.6%208.6%200%200%201%201%2017.9a12.1%2012.1%200%200%200%206.6%201.9c7.9%200%2012.2-6.5%2012.2-12.2V7a8.7%208.7%200%200%200%202.1-2.2z%22%2F%3E%3C%2Fsvg%3E"); }
.sb-ico[data-ico="ring"] { -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.7%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%229%22%2F%3E%3Ccircle%20cx%3D%2213%22%20cy%3D%2211%22%20r%3D%223.4%22%2F%3E%3C%2Fsvg%3E"); mask-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20stroke%3D%22%23000%22%20stroke-width%3D%221.7%22%3E%3Ccircle%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%229%22%2F%3E%3Ccircle%20cx%3D%2213%22%20cy%3D%2211%22%20r%3D%223.4%22%2F%3E%3C%2Fsvg%3E"); }

/* ── CONTACT ──────────────────────────────────────────────
   Tightened: the headings used to sit a full body line-height above their
   fields, which read as two disconnected blocks rather than one form. */
.sb-contact h2 {
  margin: 0 0 .45em;
  font-size: var(--type-h3);
  letter-spacing: -.02em;
}
.sb-contact .wpcf7 { margin-top: 0; }
.sb-contact p { margin-top: 0; }
.sb-contact label { display: block; margin-bottom: .9em; }
.sb-contact__note { margin-top: 1.4em; font-size: var(--type-small); color: var(--color-text-muted); }

.sb-social { display: flex; flex-direction: column; gap: .55em; margin: 0; }
.sb-social__link {
  display: inline-flex; align-items: center; gap: .55em;
  text-decoration: none; color: var(--color-text);
  width: fit-content;
}
.sb-social__link:hover { color: var(--color-accent); }
.sb-social__name { font-size: var(--type-body); }

/* ── CONNECT ──────────────────────────────────────────────
   One screen, reached from a QR code or a card. */
.sb-connect__inner {
  max-width: 34rem;
  margin-inline: auto;
  text-align: center;
  padding-block: var(--gap-lg);
}
.sb-connect__mark { width: min(260px, 62%); margin: 0 auto var(--gap); }
.sb-connect__title {
  margin: 0;
  font-size: var(--type-h2);
  letter-spacing: -.03em;
}
.sb-connect__who { margin: .3em 0 var(--gap-lg); line-height: 1.4; }
.sb-connect__name { display: block; font-size: var(--type-body); }
.sb-connect__role {
  display: block;
  font-size: var(--type-small);
  letter-spacing: .10em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}
.sb-connect__intro { margin-bottom: var(--gap); }

.sb-connect__links { display: flex; flex-direction: column; gap: 0; margin: 0 0 var(--gap-lg); }
.sb-connect__link {
  display: flex; align-items: center; gap: .7em;
  padding: 1em .2em;
  text-decoration: none;
  color: var(--color-text);
  border-top: 1px solid var(--color-line);
  text-align: left;
  transition: padding-left var(--dur-sm) var(--ease-out);
}
.sb-connect__links .sb-connect__link:last-child { border-bottom: 1px solid var(--color-line); }
.sb-connect__arrow { margin-left: auto; opacity: .5; }
@media (hover: hover) {
  .sb-connect__link:hover { padding-left: .8em; }
  .sb-connect__link:hover .sb-connect__arrow { opacity: 1; }
}

.sb-signup { text-align: left; }
.sb-signup__title { margin: 0 0 .3em; font-size: var(--type-h3); letter-spacing: -.02em; }
.sb-signup__copy { margin: 0 0 1em; font-size: var(--type-small); line-height: 1.55; color: var(--color-text-muted); }
 /* CF7 runs wpautop over the form, so the field and the button end up inside a
   single <p> rather than as direct children. Make the row work either way. */
.sb-signup__row,
.sb-signup__row > p {
  display: flex;
  gap: .5em;
  flex-wrap: wrap;
  align-items: flex-start;
  margin: 0;
}
.sb-signup__row > p { flex: 1 1 100%; }
.sb-signup__row .wpcf7-form-control-wrap {
  flex: 1 1 12rem; min-width: 0;
  display: flex;                 /* so the input fills the stretched wrapper */
}
.sb-signup__row input[type="email"] { flex: 1 1 auto; }
.sb-signup__row input[type="submit"] { flex: 0 0 auto; }
.sb-signup__row br { display: none; }
.sb-connect input[type="email"] {
  width: 100%;
  padding: .8em .9em;
  line-height: 1.25;
  font: inherit;
  font-size: var(--type-small);
  color: var(--color-text);
  background: #fff;
  border: 1px solid var(--color-line);
  border-radius: 0;
}
.sb-connect input[type="email"]:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
.sb-connect input[type="submit"] {
  padding: .8em 1.5em;
  line-height: 1.25;
  font: inherit;
  font-size: var(--type-small);
  letter-spacing: .10em;
  text-transform: uppercase;
  color: var(--color-bg);
  background: var(--color-text);
  border: 1px solid var(--color-text);
  cursor: pointer;
  transition: background-color var(--dur-xs) var(--ease);
}
.sb-connect input[type="submit"]:hover { background: var(--color-accent); border-color: var(--color-accent); }
.sb-connect .wpcf7 form .wpcf7-response-output {
  margin: 1em 0 0; padding: .7em .9em;
  font-size: var(--type-small);
  border: 1px solid var(--color-line);
}

@media (prefers-reduced-motion: reduce) {
  .sb-connect__link { transition: none !important; }
  .sb-connect__link:hover { padding-left: .2em !important; }
}

/* ── SIGNUP FIELD + BUTTON PARITY ─────────────────────────
   Vellum's CF7 layer pins the submit to `min-height: 56px` with 18px padding,
   which my earlier padding-only rule could not override, so the button sat 6px
   lower and 7px taller than the field. Give both the same box explicitly. */
.sb-connect .sb-signup__row input[type="email"],
.sb-connect .sb-signup__row input[type="submit"],
.sb-connect .sb-signup__row .wpcf7-form input.wpcf7-submit {
  min-height: 52px;
  height: 52px;
  padding-block: 0;
  line-height: 1.2;
  box-sizing: border-box;
  margin: 0;              /* CF7's layer adds a 6px top margin to the submit */
}
.sb-connect .sb-signup__row input[type="email"]  { padding-inline: .9em; }
.sb-connect .sb-signup__row input[type="submit"],
.sb-connect .sb-signup__row .wpcf7-form input.wpcf7-submit { padding-inline: 1.6em; }

/* ── HERO SLIDER ──────────────────────────────────────────
   Crossfade between five stills. No JS means slide one simply stays put, which
   is a perfectly good hero, so nothing here is load-bearing. */
/* No z-index on the stage: it would trap the cards in its own layer, under
   the hero scrim (.sb-hero::after, z 1), and every secondary image would
   read as dimmed. Without it, the cards (z 2) sit above the scrim and below
   the copy, which comes later in the markup at the same level. */
.sb-slider__stage { position: absolute; inset: 0; }
/* The face-logo slide has no photograph; a pure black field lets the logo's
   own black ground disappear into it. */
.sb-slide:not(:has(.sb-slide__bg)) { background: #000; }
/* The JPEG's "black" is a few levels above true black and left a faint box;
   lighten drops it out so only the white artwork shows. */
.sb-slide:not(:has(.sb-slide__bg)) .sb-slide__card { mix-blend-mode: lighten; }
.sb-slide {
  position: absolute; inset: 0;
  margin: 0;
  opacity: 0;
  transition: opacity var(--dur-lg) var(--ease);
}
.sb-slide.is-active { opacity: 1; }
.sb-slider:not(.is-ready) .sb-slide:first-child { opacity: 1; }

.sb-slider__captions { position: relative; min-height: 8.5em; }
.sb-slide__cap {
  /* Indented from the signature above it, which stays flush with the gutter.
     Set on the cap itself, not as padding on .sb-slider__captions: these are
     absolutely positioned, so they resolve against the containing block's
     padding box and a padding change would not move them. */
  position: absolute; inset-inline: 40px 0; top: 0;
  opacity: 0; visibility: hidden;
  transform: translateY(8px);
  transition: opacity var(--dur-md) var(--ease), transform var(--dur-md) var(--ease-out), visibility 0s linear var(--dur-md);
}
.sb-slide__cap.is-active {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity var(--dur-md) var(--ease), transform var(--dur-md) var(--ease-out), visibility 0s;
}
.sb-slide__title {
  margin: 0;
  font-size: var(--type-h2);
  line-height: 1.04;
  letter-spacing: -.03em;
  color: #fff;
  max-width: 18ch;
}
.sb-slide__sub {
  margin: .45em 0 0;
  max-width: 42ch;
  font-size: var(--type-body);
  line-height: 1.5;
  color: rgba(255,255,255,.9);
}
.sb-slide__cta { margin: 1.1em 0 0; }

/* ── SLIDER CONTROLS ─────────────────────────────────────── */
.sb-slider__nav {
  position: absolute; top: 50%; z-index: 3;
  width: 88px; height: 88px;
  transform: translateY(-50%);
  background: none; border: 0; padding: 0;
  cursor: pointer; opacity: .65;
  transition: opacity var(--dur-xs) var(--ease);
}
.sb-slider__nav:hover, .sb-slider__nav:focus-visible { opacity: 1; }
.sb-slider__nav::before {
  content: ""; display: block;
  width: 32px; height: 32px;      /* twice the old 15px, same 2px stroke */
  margin: 0 auto;
  border-top: 2px solid #fff; border-right: 2px solid #fff;
}
.sb-slider__nav--prev { left: 6px; }
.sb-slider__nav--next { right: 6px; }
.sb-slider__nav--prev::before { transform: rotate(-135deg); }
.sb-slider__nav--next::before { transform: rotate(45deg); }
@media (min-width: 861px) {
  .sb-slider__nav--prev { left: 18px; }
  .sb-slider__nav--next { right: 18px; }

  /* Desktop: the signature lockup sits in the vertical middle of the hero
     and a step in from the gutter, clear of the left arrow. Phones keep it
     at the bottom, where it covers less of the jewelry. */
  .sb-hero:has(.sb-slider__stage) { align-items: center; }
  .sb-hero:has(.sb-slider__stage) .sb-hero__inner {
    padding-block: var(--gap-lg);
    /* On very wide screens the lockup and the card used to ride the two
       window edges with an ever-growing gap between them. Both now sit
       inside a centred 1240px band; below ~1440px nothing changes. */
    padding-inline-start: max(calc(var(--gutter) + 6vw), calc((100vw - 1240px) / 2 + 60px));
  }
  .sb-hero .sb-slide__card { right: max(clamp(24px, 7vw, 132px), calc((100% - 1240px) / 2)); }
}
/* iPad and small laptops: at full size the card ran into the slide title.
   A slightly smaller card leaves clear air between the two. */
@media (min-width: 861px) and (max-width: 1199px) {
  .sb-hero .sb-slide:has(.sb-slide__bg) .sb-slide__card { max-width: 35vw; height: min(62%, 520px); }
}

.sb-slider__dots {
  position: absolute; z-index: 3;
  left: 50%; transform: translateX(-50%);
  bottom: calc(var(--gap-lg) * .55);
  display: flex; gap: 9px;
}
.sb-slider__dot {
  width: 9px; height: 9px; padding: 0;
  border: 1px solid rgba(255,255,255,.85);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background-color var(--dur-xs) var(--ease);
}
.sb-slider__dot.is-active { background: #fff; }
.sb-slider__dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

@media (max-width: 600px) {
  .sb-slider__captions { min-height: 11em; }
  .sb-slide__title { max-width: 14ch; }
}

@media (prefers-reduced-motion: reduce) {
  .sb-slide, .sb-slide__cap { transition: none !important; }
  .sb-slide__cap { transform: none !important; }
}

/* Studio portrait alongside the Connect links on the Contact page. */
.sb-contact__portrait {
  display: block;
  width: 100%;
  height: auto;
  margin-top: var(--gap);
  background: #fff;
  box-shadow: var(--sb-hairline);
}

/* ── CONTACT FORM LABEL SPACING ───────────────────────────
   CF7 emits each label as its own <p> ahead of the field's <p>, so the gap
   between a label and its input was two stacked paragraph margins and read as
   two unrelated blocks. Tighten the label-to-field pair, keep the gap between
   one field and the next. */
.sb-contact__form .wpcf7-form p { margin: 0 0 22px; }
.sb-contact__form .wpcf7-form p:has(+ p .wpcf7-form-control-wrap) {
  margin-bottom: 20px;
  line-height: 1.35;
}

/* ── SLIDE CARD ───────────────────────────────────────────
   The original slider layered a second, portrait image to the right of the
   copy on four of the five slides. Same idea here, sized off the hero height
   so it scales instead of being pinned to RevSlider's fixed pixel grid. */
.sb-slide__card {
  position: absolute;
  z-index: 2;
  right: clamp(24px, 7vw, 132px);
  top: 50%;
  transform: translateY(-50%);
  height: min(72%, 620px);
  width: auto;
  max-width: 42vw;
  object-fit: contain;
  filter: drop-shadow(0 18px 42px rgba(0, 0, 0, .45));
}
/* Slide three has no background photograph and its card is landscape, so it
   gets a shorter height. It stays on the right with the others: centred, it
   sat directly behind the signature and the headline. */
.sb-slide:not(:has(.sb-slide__bg)) .sb-slide__card {
  height: min(56%, 440px);
  filter: none;
}

@media (max-width: 860px) {
  /* Phones and small tablets: the copy sits at the bottom of the hero, so
     every card moves to the open space above it, centered, instead of
     disappearing. The band runs from under the nav to above the text block
     (--sb-copy-h is measured by slider.js; the fallback covers no-JS). */
  .sb-slide__card {
    right: auto;
    left: 50%;
    top: calc(var(--nav-h, 72px) + 8px);
    transform: translateX(-50%);
    height: calc(100% - var(--nav-h, 72px) - var(--sb-copy-h, 300px) - 24px);
    max-height: 420px;
    max-width: 82vw;
  }
  /* The face-logo slide has no photograph behind it: the logo IS the slide,
     so it runs nearly full width. */
  .sb-slide:not(:has(.sb-slide__bg)) .sb-slide__card {
    width: 94vw;
    max-width: 94vw;
    height: auto;
    /* Centered in the band: the logo is 1364x1024, so 94vw wide is ~70.6vw tall. */
    top: calc(var(--nav-h, 72px) + 8px + max(0px, (100% - var(--nav-h, 72px) - var(--sb-copy-h, 300px) - 24px - 70.6vw) / 2));
    max-height: calc(100% - var(--nav-h, 72px) - var(--sb-copy-h, 300px) - 16px);
  }
  .sb-slider__nav { width: 60px; height: 60px; }
  .sb-slider__nav::before { width: 22px; height: 22px; }

  /* The desktop scrim darkens the whole frame, which greyed the white face
     logo and dulled the cards. Here only the nav strip and the copy block
     at the bottom need it. */
  .sb-hero::after {
    background:
      linear-gradient(to bottom, rgba(0,0,0,.42) 0px, rgba(0,0,0,0) 120px),
      linear-gradient(to bottom, rgba(0,0,0,0) calc(100% - var(--sb-copy-h, 300px) - 40px),
                                 rgba(0,0,0,.72) calc(100% - var(--sb-copy-h, 300px) + 60px),
                                 rgba(0,0,0,.86) 100%);
  }
}

/* ── PHONES: SIGNATURE MOVES TO THE HEADER ────────────────
   Phones only (iPad and up keep the large signature in the hero). The hero
   signature is the page's H1, so it is hidden visually but stays in the
   document for search and screen readers; the header shows the smaller
   logo instead, white over the photograph, dark once the header turns
   light or the menu opens. The copy block shrinks, slider.js re-measures
   it, and the secondary image grows into the space. */
@media (max-width: 600px) {
  .sb-hero .sb-hero__title {
    position: absolute !important;
    width: 1px; height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%);
    white-space: nowrap;
  }
  .sb-slide__cap { inset-inline: 0; }
  .vellum-homepage .vellum-nav__mark { visibility: visible; }
  /* Bigger mark on the phone homepage; the header logo itself is drawn by
     the site-wide rule under HEADER LOGO. */
  .vellum-homepage .vellum-nav__logo-img { height: 46px; max-height: none; width: auto; }
  .vellum-homepage .vellum-nav__mark { transform: translateY(4px); }
  .sb-slide__card { max-height: 520px; }
}

/* Hero Slider plugin on this site: Vellum's --nav-h token reads ~99px on
   phones but the header itself ends at ~80px; cards sit under the real edge. */
@media (max-width: 860px) { .boafx-hero.vellum-bleed { --bhs-nav-h: 80px; } }   /* outranks the plugin's own default */

/* ── HEADER LOGO ──────────────────────────────────────────
   The signature in the header is drawn from the vector header artwork
   (assets/img/logo-header.svg, the heavier cut made for small sizes) in the
   header's own text colour: ink on the light header, white over the
   homepage photographs. The uploaded logo image stays in the markup for its
   alt text and to size the slot, but is not shown. */
.vellum-nav__mark { position: relative; }
.vellum-nav__logo-img { opacity: 0; }
.vellum-nav__mark::after {
  content: "";
  position: absolute;
  inset: 0;
  background: currentColor;
  -webkit-mask: url("assets/img/logo-header.svg") left center / contain no-repeat;
          mask: url("assets/img/logo-header.svg") left center / contain no-repeat;
  pointer-events: none;
}

/* ── HOMEPAGE NAV OVER THE SLIDER ─────────────────────────
   Vellum inverts the homepage nav with `mix-blend-mode: difference`, which
   only works while the backdrop stays dark. This homepage now cycles five
   photographs and the nav disappeared entirely over the bright ones. Plain
   white plus the hero scrim is legible on all five. */
.vellum-homepage .vellum-nav { mix-blend-mode: normal; color: #fff; }
.vellum-homepage .vellum-nav a,
.vellum-homepage .vellum-nav__links a { color: #fff; }
.vellum-homepage .vellum-nav:not(.is-scrolled) {
  text-shadow: 0 1px 10px rgba(0, 0, 0, .55);
}
.vellum-homepage .vellum-nav.is-scrolled,
.vellum-homepage .vellum-nav.is-scrolled a { color: var(--page-text); text-shadow: none; }

/* ── SLIDE WITH NO PHOTOGRAPH (slide 3) ───────────────────
   Its card is a rectangular JPEG on a dark field. Fading the whole slide as one
   unit meant the outgoing photograph was still visible underneath while the
   card faded up, so you saw the card's edges sitting on someone's face. Bring
   the black field in fast to cover the outgoing slide, THEN fade the card. */
.sb-slide:not(:has(.sb-slide__bg)) {
  background: #0A0A0A;
  transition: opacity var(--dur-sm) var(--ease);
}
.sb-slide:not(:has(.sb-slide__bg)) .sb-slide__card {
  opacity: 0;
  transition: opacity var(--dur-md) var(--ease) var(--dur-sm);
}
.sb-slide.is-active:not(:has(.sb-slide__bg)) .sb-slide__card { opacity: 1; }
/* Leaving the slide: drop the card immediately so it never outlives its field. */
.sb-slide:not(.is-active):not(:has(.sb-slide__bg)) .sb-slide__card { transition-delay: 0s; }

@media (prefers-reduced-motion: reduce) {
  .sb-slide:not(:has(.sb-slide__bg)) .sb-slide__card { transition: none !important; }
}

/* ── FORMIQA IN HOUSE STYLE ───────────────────────────────
   The suite module ships its own navy (#1a2340) and gold (#E8A320), which
   fight this site's ink and oxblood. Retint it here rather than forking the
   plugin, so suite updates still land. Structure and behaviour untouched. */
.sb-contact .boa-tf-wrap { font-family: var(--font-sans); }
.sb-contact .boa-tf-progress { margin-bottom: var(--gap-lg); }
.sb-contact .boa-tf-dot        { background: rgba(10,10,10,.14); border-radius: 0; }
.sb-contact .boa-tf-dot.done   { background: var(--color-accent); }
.sb-contact .boa-tf-dot.active { background: var(--color-text); }

.sb-contact .boa-tf-num {
  color: var(--color-accent);
  font-size: var(--type-small);
  letter-spacing: .12em;
}
.sb-contact .boa-tf-q {
  color: var(--color-text);
  font-family: var(--font-display);
  font-size: var(--type-h3);
  font-weight: 600;
  letter-spacing: -.02em;
  margin-bottom: 1em;
}
.sb-contact .boa-label { color: var(--color-text); }
.sb-contact .boa-required { color: var(--color-accent); }
.sb-contact .boa-tf-hint { color: var(--color-text-muted); font-size: var(--type-small); }
.sb-contact .boa-tf-err  { color: var(--color-accent); font-size: var(--type-small); }

.sb-contact .boa-tf-next,
.sb-contact .boa-tf-submit {
  background: var(--color-text);
  color: var(--color-bg);
  border-radius: 0;
  font-size: var(--type-small);
  letter-spacing: .10em;
  text-transform: uppercase;
}
.sb-contact .boa-tf-next:hover,
.sb-contact .boa-tf-submit:hover {
  background: var(--color-accent);
  transform: none;
}
.sb-contact .boa-tf-back { color: var(--color-text-muted); }
.sb-contact .boa-tf-back:hover { color: var(--color-text); }

.sb-contact .boa-tf-wrap input[type="text"],
.sb-contact .boa-tf-wrap input[type="email"],
.sb-contact .boa-tf-wrap input[type="tel"],
.sb-contact .boa-tf-wrap textarea {
  font-family: var(--font-sans);
  font-size: var(--type-body);
  color: var(--color-text);
  background: #fff;
  border: 1px solid var(--color-line);
  border-radius: 0;
}
.sb-contact .boa-tf-wrap input:focus-visible,
.sb-contact .boa-tf-wrap textarea:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: -2px;
}
.sb-contact .boa-tf-success-title { color: var(--color-text); font-family: var(--font-display); }
.sb-contact .boa-tf-success-sub   { color: var(--color-text-muted); }

/* The Formiqa progress bar sat flush against the page-title rule. */
.sb-contact .boa-tf-progress { margin-top: var(--gap); }
.sb-contact .boa-tf-wrap select {
  font-family: var(--font-sans);
  font-size: var(--type-body);
  color: var(--color-text);
  background: #fff;
  border: 1px solid var(--color-line);
  border-radius: 0;
  padding: .8em .9em;
  width: 100%;
}

/* ── CONTACT LAYOUT (matches the approved mockup) ─────────
   Order is: progress bar, intro copy, then the first question.
   Formiqa injects the bar as the first child of <form>, and the intro is a
   sibling of the whole form, so no amount of flex `order` can interleave them.
   Lift the bar out of the form's flow and pin it to the top of the column
   instead: it is a fixed-height row of segments, so this is stable. */
/* Both columns start on the same line: the first question on the left sits
   level with the Connect heading on the right. */
.sb-contact { padding-top: 40px; }
.sb-contact__form { position: relative; padding-top: 0; }
.sb-contact__form .wpcf7 { margin-top: 0; }
.sb-contact .boa-tf-wrap { min-height: 0; }
/* The question heading carries the leading, same as the Connect heading, so
   the two line up glyph-to-glyph rather than box-to-box. */
/* +4px: the line box ends below the glyphs, so an equal margin would read as a
   smaller gap than the portrait's. This makes the two gaps match optically. */
.sb-contact .boa-tf-q { line-height: 1; margin-bottom: calc(var(--sb-field-gap) + 4px); }
/* The module pads each step; the intro's own margin already provides the gap. */
.sb-contact .boa-tf-step { padding-top: 0; }

/* Connect column: the social link sits directly under the heading. */
/* line-height 1 so the heading's box hugs the glyphs: the default leading put
   the cap-height 4px ABOVE the rule and left dead space under it, which is why
   the heading looked high and the Instagram link looked far away. */
.sb-contact__connect h2 { margin: 0 0 .30em; line-height: 1; }
.sb-contact__connect .sb-social { margin: 0; }
.sb-contact__portrait { margin-top: var(--sb-field-gap); }

/* Formiqa relocates the CF7 submit into its own step nav, but the paragraph
   CF7 wrapped it in stays behind as an empty 52px block at the top of the
   form, pushing the first question below the Connect heading opposite. */
body.boa-tf-active .sb-contact .wpcf7-form > p:has(input.wpcf7-submit),
body.boa-tf-active .sb-contact .wpcf7-form > p:empty { display: none; }

/* The keyboard hint under each field states what the OK button already shows. */
.sb-contact .boa-tf-hint { display: none; }

/* ── CONTACT: single left column, portrait right ──────────
   Form, a rule, then the Connect links all stack on the left. The portrait
   sits opposite, its top edge level with the first question's cap-height. */
.sb-contact__main { min-width: 0; }
.sb-contact__rule {
  border: 0;
  border-top: 1px solid var(--color-line);
  margin: var(--gap-lg) 0;
}
.sb-contact__media {
  min-width: 0;
  /* The heading's box top sits ~5px above its cap-height (font ascent vs cap,
     even at line-height 1). Pull the image up by that much so its top edge
     lines up with the letterforms rather than with the invisible box. */
  margin-top: -5px;
}
.sb-contact__media .sb-contact__portrait { margin-top: 0; }

@media (max-width: 700px) {
  /* Stacked: the portrait reads better after the form than before it. */
  .sb-contact__media { order: 2; }
  .sb-contact__media .sb-contact__portrait { margin-top: var(--gap-lg); }
}

/* ── MOTION ───────────────────────────────────────────────────────────
   Page transitions, scroll reveals and the lightbox. All of it stands down
   under prefers-reduced-motion.

   Page fade: Vellum's curtain was tuned to .14s, which reads as a flicker.
   Leaving a page now dims over .35s; arriving lifts the curtain over .8s
   while the content rises a few pixels into place. The transition that runs
   is the one on the state being entered, so .is-active sets the exit speed
   and the base rule the entrance. */
/* The deployed Vellum parent still sets --z-nav: 60, under the mobile menu
   overlay (100), which hid the burger and left no way to close the menu.
   The parent's current value is 110; match it here. */
:root { --dur-curtain: .8s; --z-nav: 110; }
/* Over the open menu the page is cream, so the homepage's white header
   (set for the dark hero) has to turn dark or the close X disappears. */
.vellum-nav.is-open,
.vellum-nav.is-open a,
.vellum-homepage .vellum-nav.is-open,
.vellum-homepage .vellum-nav.is-open a { color: var(--page-text) !important; text-shadow: none !important; }
.vellum-nav.is-open .vellum-nav__burger span,
.vellum-nav.is-open .vellum-nav__burger::before,
.vellum-nav.is-open .vellum-nav__burger::after { background-color: var(--page-text) !important; }
.vellum-curtain.is-active { transition-duration: .35s; }

@keyframes sb-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .vellum-main { animation: sb-rise 1s cubic-bezier(.16, 1, .3, 1) both; }
}

/* Scroll reveals: tiles fade up in a short stagger as they enter the view.
   html.sb-motion is set in the head (functions.php) and lifted again after
   four seconds if tiles.js never runs, so nothing can stay hidden. */
.sb-motion .sb-grid__item,
.sb-motion .sb-chrono__item,
.sb-motion .sb-cards > li,
.sb-motion .sb-news__item {
  opacity: 0;
  transition: opacity .8s var(--ease), transform 1.1s var(--ease-out);
  transition-delay: var(--sb-delay, 0s);
}
.sb-motion .sb-grid__item,
.sb-motion .sb-chrono__item,
.sb-motion .sb-cards > li { transform: translateY(22px); }
.sb-motion .sb-grid__item.is-in,
.sb-motion .sb-chrono__item.is-in,
.sb-motion .sb-cards > li.is-in,
.sb-motion .sb-news__item.is-in { opacity: 1; transform: none; }

/* Lightbox: the figure eases up from slightly small on open and settles
   back on close; images and captions crossfade on every step. */
.vellum-lightbox__figure {
  transform: scale(.965) translateY(10px);
  transition: transform .8s var(--ease-out);
}
.vellum-lightbox.is-open .vellum-lightbox__figure { transform: none; }
.vellum-lightbox__img {
  transition: opacity .55s var(--ease), transform .8s var(--ease-out);
}
.vellum-lightbox__img.is-hidden {
  opacity: 0;
  transform: translateX(var(--enter-x, 0px)) scale(.985);
  transition: none;
}
.vellum-lightbox__ghost {
  position: fixed;
  margin: 0;
  max-width: none; max-height: none;
  object-fit: contain;
  pointer-events: none;
  transition: opacity .45s var(--ease), transform .7s var(--ease-out);
}
.vellum-lightbox__caption { transition: opacity .5s var(--ease) .12s; }
.vellum-lightbox__caption.is-hidden { opacity: 0; transition: none; }

@media (prefers-reduced-motion: reduce) {
  .vellum-lightbox__figure,
  .vellum-lightbox__img,
  .vellum-lightbox__caption { transition: none !important; transform: none !important; }
}
