/* Self-hosted fonts (latin and latin-ext subsets of the Google Fonts files).
   Source Serif 4 is a variable font: one file covers weights 400 to 600. */
/* Poppins 600 normal latin-ext */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/poppins-600-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Poppins 600 normal latin */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/poppins-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Poppins 700 normal latin-ext */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/poppins-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Poppins 700 normal latin */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/poppins-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Source Serif 4 400 italic latin-ext */
@font-face {
  font-family: 'Source Serif 4';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/source-serif-4-400-italic-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Source Serif 4 400 italic latin */
@font-face {
  font-family: 'Source Serif 4';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/source-serif-4-400-italic-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Source Serif 4 400-600 normal (variable file) latin-ext */
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(fonts/source-serif-4-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Source Serif 4 400-600 normal (variable file) latin */
@font-face {
  font-family: 'Source Serif 4';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url(fonts/source-serif-4-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================
   1. LEGACY TOKEN ALIASES
   Single source of truth is theme.json. The component CSS below
   keeps the original v6 var names; these bind them 1:1 to the
   WordPress presets so the v6 rules port unchanged.
   ============================================================ */
:root{
  --ink:var(--wp--preset--color--ink);
  --ink-soft:var(--wp--preset--color--ink-soft);
  --red:var(--wp--preset--color--red);
  --red-dark:var(--wp--preset--color--red-dark);
  --paper:var(--wp--preset--color--paper);
  --paper-tint:var(--wp--preset--color--paper-tint);
  --line:var(--wp--preset--color--line);
  --display:var(--wp--preset--font-family--display);
  --body:var(--wp--preset--font-family--body);
  --max:1100px;
  /* In-page anchors (nav, Contact, CTAs) land the section title this far
     below the sticky header. --header-h is the header's measured height
     (72px row + 1px border) at every breakpoint. */
  --header-h:73px;
  --anchor-gap:32px;
}

/* ============================================================
   2. BASE (ported from v6)
   ============================================================ */
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  font-family:var(--body);
  color:var(--ink);
  background:var(--paper);
  font-size:1.0625rem;
  line-height:1.7;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;height:auto;display:block}
a{color:var(--red)}
:focus-visible{outline:3px solid var(--red);outline-offset:3px;border-radius:2px}

/* ============================================================
   3. .wrap, REBUILT FOR BLOCKS
   v6 keyed the content measure and the 24px gutter on .wrap, which
   block markup does not emit. Every top-level band is now an
   alignfull Group carrying .band. The band itself owns the 24px
   gutter (written into each section's own padding shorthand below,
   so no specificity tie can zero it), and the band's DIRECT CHILDREN
   are capped at the same 1052px content box .wrap produced
   (1100px max-width minus its own 48px of padding, border-box).
   Inner components that set their own narrower max-width (.hero-sub
   680, .video-frame 920, .section-head 640, .speaking-body 880,
   .art-note 640) declare it AFTER this rule and win the tie, landing
   on exactly the v6 measure.
   The header's inner Group carries the class .wrap (the header is native
   blocks since 2026-09-22), so the original .wrap rule survives there, scoped.
   ============================================================ */
.band > *{
  max-width:calc(var(--max) - 48px);
  margin-left:auto;margin-right:auto;
}
.site-header .wrap{max-width:var(--max);margin:0 auto;padding:0 24px}

/* ---------- Header ---------- */
.site-header{
  position:sticky;top:0;z-index:50;
  background:rgba(255,255,255,.94);
  backdrop-filter:blur(8px);
  border-bottom:1px solid transparent;
  transition:border-color .25s;
}
.site-header.scrolled{border-bottom-color:var(--line)}
.nav{display:flex;align-items:center;justify-content:space-between;height:72px}
/* Links and the Contact button share one group on the right of the header */
.nav-right{display:flex;align-items:center;gap:26px}
a.wordmark{
  font-family:var(--display);font-weight:700;font-size:1.05rem;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink);text-decoration:none;white-space:nowrap;
}
a.wordmark .dot{color:var(--red)}
/* Invisible 12px tap margin round the wordmark (header and footer): 44px+ tall
   on touch screens with no change to the layout. */
a.wordmark{position:relative}
a.wordmark::after{content:"";position:absolute;inset:-12px -6px}
.nav-links{display:flex;align-items:center;gap:26px;list-style:none}
.nav-links a{
  font-family:var(--display);font-weight:600;font-size:.8rem;
  letter-spacing:.08em;text-transform:uppercase;
  color:var(--ink);text-decoration:none;
}
.nav-links a:hover{color:var(--red)}
.btn{
  display:inline-block;
  font-family:var(--display);font-weight:600;font-size:.8rem;
  letter-spacing:.08em;text-transform:uppercase;
  padding:13px 26px;border-radius:4px;
  text-decoration:none;cursor:pointer;border:0;
  transition:background .2s,color .2s,box-shadow .2s;
}
/* .btn.btn-* rather than .btn-*: theme.json's element-link color lands at the
   same specificity as a lone class, and its source order is not guaranteed. */
.btn.btn-red{background:var(--red);color:#fff}
.btn.btn-red:hover{background:var(--red-dark);color:#fff}
.btn.btn-ghost{background:transparent;color:var(--ink);box-shadow:inset 0 0 0 2px var(--ink)}
.btn.btn-ghost:hover{color:var(--red);box-shadow:inset 0 0 0 2px var(--red)}
.nav .btn{padding:11px 20px}   /* 44px tall: the header button is a tap target on iPads */
/* 9/11px padding makes the 22x26 bars a 44x44 button; the -3px keeps the bars
   where the 8px-padded button had them. */
.menu-toggle{display:none;background:none;border:0;cursor:pointer;padding:9px 11px;margin-right:-3px}
.menu-toggle span{
  display:block;width:22px;height:2px;background:var(--ink);margin:5px 0;
}
.nav-book{display:none}

/* ---------- Hero ---------- */
.hero{padding:32px 24px 56px;text-align:center}
.eyebrow{
  font-family:var(--display);font-weight:600;font-size:.78rem;
  letter-spacing:.22em;text-transform:uppercase;color:var(--red);
  display:inline-flex;align-items:center;gap:10px;
}
.eyebrow::before,.eyebrow::after{
  content:"";width:26px;height:2px;background:var(--red);opacity:.45;
}
.hero h1{
  font-family:var(--display);font-weight:700;
  font-size:clamp(2.4rem,6vw,4.2rem);
  line-height:1.08;letter-spacing:-.01em;
  margin:0 auto;max-width:14ch;
}
.stroke-word{position:relative;display:inline-block;white-space:nowrap}
.stroke-word svg{
  position:absolute;left:-3%;bottom:-.18em;width:106%;height:.36em;
  pointer-events:none;
}
/* 38px under the h1 box leaves ~26px of air below the red underline, which
   hangs .18em under the headline (was 22px, ~10px of air: too tight). */
.hero-sub{max-width:680px;margin:38px auto 0;color:var(--ink-soft);font-size:1.125rem}

/* Click-to-play video facade */
.video-frame{
  margin:32px auto 0;max-width:920px;
  border-radius:10px;overflow:hidden;
  box-shadow:0 24px 60px -24px rgba(28,24,19,.35);
  background:#000;
}
.video-frame .ratio{position:relative;padding-top:56.25%}
.video-frame iframe,.video-facade{position:absolute;inset:0;width:100%;height:100%;border:0}
.video-facade{
  display:block;cursor:pointer;padding:0;background:#000;
}
.video-facade img{width:100%;height:100%;object-fit:cover;opacity:.85}
.video-facade .play{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:74px;height:52px;background:var(--red);border-radius:12px;
  display:flex;align-items:center;justify-content:center;
  transition:background .2s;
}
.video-facade:hover .play{background:var(--red-dark)}
.video-facade .play::after{
  content:"";border-style:solid;border-width:11px 0 11px 19px;
  border-color:transparent transparent transparent #fff;margin-left:4px;
}

/* ---------- Credits strip ---------- */
/* v6 keyed the flex row on `.credits .wrap`; blocks do not emit .wrap, so the
   row is a Group with its own .credits-row class (one paragraph per name). */
.credits{background:var(--red);padding:26px 24px}
.credits-row{
  display:flex;align-items:center;justify-content:center;gap:18px 36px;flex-wrap:wrap;
}
.credits-label{
  font-family:var(--display);font-weight:600;font-size:.72rem;
  letter-spacing:.18em;text-transform:uppercase;color:#fff;opacity:.85;
}
.credits-name{
  font-family:var(--display);font-weight:600;font-size:.95rem;
  letter-spacing:.05em;color:#fff;white-space:nowrap;
}

/* ---------- Sections ---------- */
section{padding:88px 24px}
/* Anchor landing without JS (and the first landing when arriving from another
   page): section top padding is 88px (64px on phones, 56px on #reviews), so
   this puts the title --anchor-gap below the header. site.js replaces it per
   section with the exact measured value, which also covers #art's eyebrow. */
section[id]{scroll-margin-top:calc(var(--header-h) + var(--anchor-gap) - 88px)}
#reviews{scroll-margin-top:calc(var(--header-h) + var(--anchor-gap) - 56px)}
.section-tint{background:var(--paper-tint)}
.section-head{max-width:640px;margin-bottom:48px}
.section-head.center{margin-left:auto;margin-right:auto;text-align:center}
/* Was an inline style="margin-bottom:36px" on the speaking section head. */
.section-head.speaking-head{margin-bottom:36px}
h2{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.7rem,3.4vw,2.4rem);line-height:1.15;
  margin-top:12px;
}
.section-head p{margin-top:16px;color:var(--ink-soft)}
/* Heads that lead with the h2 (no eyebrow) lose the eyebrow gap */
.section-head h2:first-child,.contact-info h2:first-child,.story-copy h2:first-child{margin-top:0}

/* Story. 3fr/4fr with a 48px gap puts the copy on a ~50-character measure and
   leaves the photo column wide enough to run the full height of the text. */
.story-grid{display:grid;grid-template-columns:3fr 4fr;gap:48px;align-items:center}
.story-copy h2+p{margin-top:20px}
.story-copy p+p{margin-top:18px}
/* Kept at v6's single-class specificity on purpose: `.story-copy p+p` (0,1,1)
   outranks these in v6, so the signature and origin link actually render at
   18px of top margin. Raising them to 0,2,0 silently changed the layout. */
.signature{margin-top:26px;font-style:italic;font-size:1.35rem}
.origin-link{margin-top:26px}
.origin-link a{
  font-family:var(--display);font-weight:600;font-size:.85rem;
  letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink);text-decoration:none;border-bottom:2px solid var(--red);
  padding-bottom:2px;
}
.origin-link a:hover{color:var(--red)}
.origin-link a{position:relative}
.origin-link a::after{content:"";position:absolute;inset:-11px -6px}   /* 45px tap target */
/* Photo collage. The 1fr/2fr split plus these two tile ratios make the stacked
   pair exactly as tall as the lakeside portrait's native 3:4, so the hero
   photo is never cropped and the block runs the height of the copy. The two
   small tiles give up about 6% of their width per side, which keeps both
   subjects clear. */
.story-media{display:grid;grid-template-columns:1fr 2fr;gap:16px;align-content:center}
.story-photo{border-radius:10px;overflow:hidden;box-shadow:0 18px 44px -20px rgba(28,24,19,.3)}
.story-photo img{width:100%;height:100%;object-fit:cover}
.story-photo-main{grid-column:2;grid-row:1/3}          /* portrait 3:4, uncropped */
.story-photo-wide{grid-column:1;grid-row:1;aspect-ratio:1.163}
.story-photo-tall{grid-column:1;grid-row:2;aspect-ratio:.581}

/* Speaking */
.speaking-body{max-width:880px;margin:0 auto}
.speaking-body p{text-wrap:pretty}
.speaking-body p+p{margin-top:18px}
.speaking-body .question{font-weight:600}
.speaking-close{text-align:center}
.speaking-cta{margin-top:0}

/* Reviews. One testimonial at a time, centred (2026-09-23; the 3-column
   italic cards with a red quote glyph are in backups/2026-09-23-pre-testimonial-slider).
   Markup: Group .reviews-grid > identical Groups .review-card, each a core
   Quote (short quote + cite) and a core Details (full review). The quotation
   marks are typed into the text itself; nothing is drawn by CSS.
   JS off: the cards stack in one centred column at the reading measure and
   each Details expands in place.
   JS on: site.js turns .reviews-grid into a slider (.is-slider, below) and the
   Details summary opens the full review in a <dialog>. */
#reviews{padding:56px 24px}
#reviews .section-head{margin-bottom:28px}
.reviews-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:24px;max-width:720px}
.review-card{
  background:var(--paper);border:1px solid var(--line);border-radius:10px;
  padding:40px 48px 34px;
  display:flex;flex-direction:column;justify-content:center;
  text-align:center;
}
.review-card .review-quote,.review-dialog blockquote{margin:0;padding:0;border:0;background:none}
.review-card p,.review-dialog p{font-style:normal;color:var(--ink);text-wrap:pretty}
.review-card .review-quote p{font-size:var(--wp--preset--font-size--lead);line-height:1.65}
.review-card cite,.review-dialog cite{
  display:block;margin-top:16px;font-style:normal;
  font-family:var(--display);font-weight:600;font-size:.85rem;
  letter-spacing:.04em;color:var(--ink);
}
.review-card > .review-quote > cite{margin-top:20px}
/* "Read the full review": the site's underlined link language (.origin-link). */
.review-card > .review-full{margin-top:0;padding-top:18px}
.review-full > summary{
  display:inline-block;list-style:none;cursor:pointer;
  font-family:var(--display);font-weight:600;font-size:.78rem;line-height:1.6;
  letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink);border-bottom:2px solid var(--red);padding-bottom:2px;
  transition:color .2s;
}
.review-full > summary::-webkit-details-marker{display:none}
.review-full > summary::marker{content:""}
.review-full > summary:hover{color:var(--red)}
/* 44px-tall tap target around the 24px link, with no visual change. */
.review-full > summary{position:relative}
.review-full > summary::after{content:"";position:absolute;inset:-10px -6px}
/* JS off: the full review opens in place, under the link, set left for
   reading like the popup. */
.review-full > p{margin-top:14px;text-align:left}

/* The slider (built by site.js). All cards share one grid cell of
   .reviews-frame, so the frame is as tall as the longest testimonial and
   nothing below it moves between slides. The current card sits in place; the
   others wait off to one side, hidden and inert. A change slides the outgoing
   card out one side while the incoming one slides in from the other. The
   frame clips at the card's own edge, so the motion stays inside the card's
   outline. Arrows reuse the photo strip's .gal-btn look, in a row with the dots. */
.reviews-grid.is-slider{display:block}
.reviews-frame{display:grid;overflow:hidden;border-radius:10px;touch-action:pan-y}
.reviews-frame > .review-card{
  grid-area:1/1;min-width:0;
  visibility:hidden;transform:translateX(calc(100% + 24px));
}
.reviews-frame > .review-card.is-before{transform:translateX(calc(-100% - 24px))}
.reviews-frame > .review-card.is-current{visibility:visible;transform:none}
@media (prefers-reduced-motion: no-preference){
  .reviews-frame > .review-card{
    transition:transform .6s cubic-bezier(.33,0,.2,1),visibility 0s linear .6s;
  }
  .reviews-frame > .review-card.is-current{
    transition:transform .6s cubic-bezier(.33,0,.2,1),visibility 0s;
  }
  .reviews-frame > .review-card.no-slide{transition:none}
}
/* Two classes: WordPress's flow-layout margin reset for the Group's children
   is (0,1,0) and would otherwise tie with this on source order. */
.reviews-grid > .reviews-controls{
  display:flex;align-items:center;justify-content:center;gap:12px;margin-top:22px;
}
.reviews-controls .gal-btn{position:static;transform:none;flex:none}
.reviews-dots{display:flex;align-items:center}
/* 28x44 tap target around an 8px dot. Hollow = waiting, filled red = showing,
   so the state does not rest on colour alone. */
.reviews-dot{
  width:28px;height:44px;padding:0;border:0;background:none;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
}
.reviews-dot::before{
  content:"";width:8px;height:8px;border-radius:50%;
  box-shadow:inset 0 0 0 1.5px var(--ink-soft);
  transition:background .2s,box-shadow .2s;
}
.reviews-dot:hover::before{box-shadow:inset 0 0 0 1.5px var(--red)}
.reviews-dot[aria-current="true"]::before{background:var(--red);box-shadow:none}
/* Touch screens: full 44px dot targets. */
@media (pointer:coarse){
  .reviews-dot{width:44px}
}
/* The keyboard ring goes round the dot, not the tall tap box. */
.reviews-dot:focus-visible{outline:none}
.reviews-dot:focus-visible::before{outline:3px solid var(--red);outline-offset:4px}

/* The full-review popup (created by site.js). */
.review-dialog{
  padding:0;border:0;background:transparent;color:var(--ink);
  width:min(640px, calc(100vw - 32px));max-width:none;
  max-height:calc(100vh - 32px);max-height:calc(100dvh - 32px);
  margin:auto;overflow:visible;
}
.review-dialog::backdrop{background:rgba(28,24,19,.6)}
.review-dialog-card{
  position:relative;background:var(--paper);border:1px solid var(--line);
  border-radius:10px;overflow:hidden;
  box-shadow:0 24px 60px -24px rgba(28,24,19,.45);
}
.review-dialog-body{
  max-height:calc(100vh - 34px);max-height:calc(100dvh - 34px);
  overflow-y:auto;overscroll-behavior:contain;
  padding:56px 30px 30px;
}
.review-dialog p + p{margin-top:14px}
.review-dialog-close{
  position:absolute;top:10px;right:10px;z-index:1;
  width:44px;height:44px;border-radius:50%;
  border:1px solid var(--line);background:var(--paper);color:var(--ink);
  font-size:1.5rem;line-height:0;cursor:pointer;padding:0;
  display:flex;align-items:center;justify-content:center;
  transition:background .2s,color .2s,border-color .2s;
}
.review-dialog-close:hover{background:var(--red);border-color:var(--red);color:#fff}
@media (prefers-reduced-motion: no-preference){
  .review-dialog[open]{animation:review-in .22s ease-out}
  .review-dialog[open]::backdrop{animation:review-fade .22s ease-out}
}
@keyframes review-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
@keyframes review-fade{from{opacity:0}to{opacity:1}}

/* Event photos, inside the speaking section */
.gallery-shell{position:relative;margin:44px 0}
.event-gallery{
  display:flex;gap:16px;overflow-x:auto;
  position:relative;                 /* offsetParent for the loop maths */
  scroll-snap-type:x mandatory;
  padding-bottom:4px;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:none;
}
.event-gallery::-webkit-scrollbar{display:none}
.event-gallery figure{flex:0 0 auto;scroll-snap-align:start}
.event-gallery figure:first-child{margin-left:auto}
.event-gallery figure:last-child{margin-right:auto}
/* Seamless loop: the script appends a duplicate set before and after the real
   figures, so the strip can run past either end and be re-anchored to the
   middle copy without a visible jump. The clones only exist while the real
   set actually overflows; otherwise they stay out of the layout and the
   centring auto-margins above apply as before. */
.event-gallery figure.gal-clone{display:none}
.event-gallery.looping figure.gal-clone{display:block}
.event-gallery.looping figure:first-child{margin-left:0}
.event-gallery.looping figure:last-child{margin-right:0}
.event-gallery img{
  height:280px;width:auto;border-radius:10px;
  box-shadow:0 14px 34px -18px rgba(28,24,19,.3);
}
.gal-btn{
  position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:44px;height:44px;border-radius:50%;border:1px solid var(--line);
  background:rgba(255,255,255,.95);color:var(--red);
  font-size:1.6rem;cursor:pointer;padding:0;
  box-shadow:0 8px 20px -8px rgba(28,24,19,.35);
  transition:background .2s,color .2s;
  /* Flex centring lines up the text box, but the chevron's ink sits 2px below
     that centre (font ascent 23 / descent 5 against ink 13 / -1 at 25.6px).
     -.078em lifts the ink onto the circle's true centre. */
  display:flex;align-items:center;justify-content:center;
  line-height:0;
}
.gal-btn span{display:block;transform:translateY(-.078em)}
.gal-btn:hover{background:var(--red);color:#fff}
.gal-prev{left:-8px}
.gal-next{right:-8px}
.gallery-shell.no-overflow .gal-btn{display:none}

/* Art */
.art-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
a.art{
  display:block;text-decoration:none;color:var(--ink);
  border-radius:10px;overflow:hidden;background:var(--paper);
  border:1px solid var(--line);
}
/* Each product shot is 900x1200: black backdrop, white moulding, a bevel
   shadow, then the white mat field holding the painting and its printed
   title. The tile punches in to that mat field only. Mat bands measured off
   the sources (clean white between bevel and print):
     Blue Joy / The King, Red  x 193..711  y 198..1007
     Tree of Life              x 187..703  y 191..1013
   Crop boxes at a shared 0.62 ratio:
     Blue Joy / The King, Red  204,202 496x800  (6px inside the mat band)
     Tree of Life              193,181 498x802
   The tree painting sits higher on its paper than the other two (35px of
   paper above it vs ~54px), so its crop is keyed to the printed keyline
   around the painting instead of the mat band. Each print's keyline is its
   own size (Blue Joy 220..678 x 243..915, King 227..677 x 247..908, tree
   216..668 x 226..889); the tree is matched to KING, its adjacent tile:
   same top and bottom fractions (0.05625 / 0.8825), centred horizontally.
   Matching the average of both neighbours put the tree 3px taller than
   King, which read as oversized (client, 2026-09-24). Blue Joy's keyline
   is ~2px taller than King's at tile scale and stays as it always was.
   The source photo is retouched for this: rows 160..192 across the paper's
   width are painted white (2026-09-24), because the real paper ended at
   y=186 and the crop top (181) lands above it.
   From a crop (cx,cy,cw,ch): width=W/cw, left=-cx/cw, top=-cy/ch, as %. */
.art .art-img{position:relative;overflow:hidden;aspect-ratio:31/50;background:var(--paper-tint)}
.art .art-img img{position:absolute;height:auto;max-width:none;transition:transform .35s ease}
.art:hover .art-img img{transform:scale(1.04)}
.art-img.punch-print img{width:181.452%;left:-41.129%;top:-25.250%}
.art-img.punch-tree img{width:180.905%;left:-38.844%;top:-22.539%}
/* No caption strip: the punched-in crop already shows the printed title. */
.art figure{display:block}
.art-note{margin:36px auto 0;max-width:640px;text-align:center}
.art-note p{text-wrap:pretty}
.art-cta{margin-top:26px}

/* Contact */
.contact-grid{display:grid;grid-template-columns:5fr 7fr;gap:56px}
.contact-info p{margin-top:16px;color:var(--ink-soft)}
.contact-direct{margin-top:28px;font-family:var(--display);font-weight:600;font-size:.95rem}
.contact-direct a{color:var(--ink);text-decoration:none;border-bottom:2px solid var(--red)}
form{display:grid;gap:18px}
.field-row{display:grid;grid-template-columns:1fr 1fr;gap:18px}
/* Conditional field groups are display:grid, so [hidden] needs the override */
[hidden]{display:none !important}
label{
  font-family:var(--display);font-weight:600;font-size:.75rem;
  letter-spacing:.1em;text-transform:uppercase;display:block;margin-bottom:7px;
}
input,select,textarea{
  width:100%;min-width:0;font-family:var(--body);font-size:1rem;color:var(--ink);
  padding:13px 14px;border:1px solid var(--line);border-radius:6px;
  background:var(--paper);
}
input:focus,select:focus,textarea:focus{
  outline:none;border-color:var(--red);box-shadow:0 0 0 3px rgba(200,16,46,.12);
}
textarea{min-height:130px;resize:vertical}
.form-note{font-size:.9rem;color:var(--ink-soft)}
/* Was an inline style="margin-top:14px" on the submit button. */
.form-submit{margin-top:14px}
.form-status{font-size:.92rem;color:var(--ink-soft);min-height:1.4em}

/* Footer */
.site-footer{background:var(--red);padding:56px 24px 40px}
.site-footer a.wordmark{color:#fff}
.site-footer a.wordmark .dot{color:#fff}
.footer-grid{display:grid;grid-template-columns:2fr 1fr 1fr;gap:40px}
.footer-grid h4{
  font-family:var(--display);font-weight:700;font-size:.78rem;
  letter-spacing:.16em;text-transform:uppercase;margin-bottom:14px;color:#fff;
}
.footer-grid ul{list-style:none}
.footer-grid li+li{margin-top:9px}
.footer-grid a{color:rgba(255,255,255,.85);text-decoration:none;font-size:.95rem}
.footer-grid a:hover{color:#fff}
.footer-about p{color:rgba(255,255,255,.85);font-size:.95rem;max-width:36ch;margin-top:6px}
.footer-bottom{
  margin-top:44px;padding-top:22px;border-top:1px solid rgba(255,255,255,.3);
  display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;
  font-size:.85rem;color:rgba(255,255,255,.85);
}

/* Reveal animation.
   JS-ADDITIVE: site.js adds .js-reveal to every .reveal before observing, so
   with JS off nothing is ever hidden. The reduced-motion media query means
   reduced-motion visitors never see the hidden state either, matching v6. */
@media (prefers-reduced-motion: no-preference){
  .reveal.js-reveal{opacity:0;transform:translateY(22px);transition:opacity .6s ease,transform .6s ease}
  .reveal.js-reveal.in{opacity:1;transform:none}
}
@media (prefers-reduced-motion: reduce){
  html{scroll-behavior:auto}
  .art img{transition:none}
  html figure.wp-block-image.art img{transition:none} /* outranks the bridge rule below */
}

/* ---------- Responsive ---------- */
/* On desktop the whole video frame lands inside the first screen. 381px is the
   measured stack above it at the widest h1 (73 header + 32 hero padding +
   145 h1 + 38 gap + 61 subline + 32 margin; re-measured 2026-09-23 after the
   sub-line gap grew); the constant below adds ~17px so the bottom edge clears
   the fold rather than touching it. svh where supported: the height with any
   browser toolbar showing. The 560px floor keeps a very short window from
   shrinking the video to a thumbnail; below ~715px of height the frame stops
   shrinking and runs past the fold. Above 881px only: narrower than that the
   video runs the full content width, uncapped. */
@media (min-width:881px){
  /* Desktop nav links: 45px-tall, 44px+-wide hit boxes (iPad landscape gets
     this layout). The 8px side padding comes out of the 26px gap, so the
     words sit exactly where they did. */
  .nav-links{gap:10px;margin-right:-8px}
  /* 16/12 rather than 14/14: as block boxes the words centre 2px higher than
     the inline links did; the uneven padding puts them back on the same pixel row. */
  .nav-links a{display:block;padding:16px 8px 12px}
  .video-frame{max-width:min(920px, max(560px, calc((100vh - 398px) * 16 / 9)))}
  @supports (height:100svh){
    .video-frame{max-width:min(920px, max(560px, calc((100svh - 398px) * 16 / 9)))}
  }
}
@media (max-width:880px){
  .story-grid,.contact-grid{grid-template-columns:minmax(0,1fr);gap:40px}
  .story-media{order:2;max-width:520px;margin:0 auto}
  /* One column: keep the story at a reading measure (~70 characters on an
     iPad in portrait instead of ~95), centred over the photos. */
  .story-copy{max-width:640px;width:100%;margin-inline:auto}
  .art-grid{grid-template-columns:1fr 1fr}
  /* Odd tile out keeps the column width instead of stretching to full bleed.
     Needs an explicit width, not max-width: the punched-in image is absolutely
     positioned, so the tile has no intrinsic width to shrink-wrap to. */
  .art-grid .art:last-child{grid-column:1/-1;width:calc(50% - 11px);justify-self:center}
  .footer-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .footer-about{grid-column:1/-1}
  .nav-links{
    position:absolute;top:72px;left:0;right:0;
    background:var(--paper);border-bottom:1px solid var(--line);
    flex-direction:column;gap:0;padding:8px 0;display:none;
  }
  .nav-links.open{display:flex}
  .nav-links li{width:100%;text-align:center}
  .nav-links a{display:block;padding:14px 0}
  .menu-toggle{display:block}
  .nav-book{display:block;padding:8px 24px 12px}
  .nav-links li.nav-book a{
    background:var(--red);color:#fff;border-radius:4px;padding:13px 0;
  }
  .nav-links li.nav-book a:hover{background:var(--red-dark);color:#fff}
}
/* 641-880px: the header Contact button is still showing, so the menu does
   not repeat it. */
@media (min-width:641px) and (max-width:880px){
  .nav-links li.nav-book{display:none}
}
@media (max-width:640px){
  section{padding:64px 24px}
  section[id]{scroll-margin-top:calc(var(--header-h) + var(--anchor-gap) - 64px)}   /* #reviews keeps its 56px rule: an id outranks this */
  /* Phone hero (variant C, 2026-09-23): 40px under the header instead of 24,
     and a bigger headline. 11.9vw reaches the 2.9rem cap at 390px wide (the
     approved mock); the 2.55rem floor keeps both lines whole at 320px. */
  .hero{padding:40px 24px 40px}
  .hero h1{font-size:clamp(2.55rem,11.9vw,2.9rem)}
  .hero-sub{margin-top:30px}
  .nav .btn{display:none}
  .art-grid,.field-row{grid-template-columns:minmax(0,1fr)}
  .art-grid .art:last-child{grid-column:auto;width:auto;justify-self:stretch}
  .event-gallery img{height:240px}
  /* The band wraps to three or four lines on phones: more air above, below
     and between them than the single-line desktop band needs. */
  .credits{padding:38px 24px}
  .credits-row{gap:16px 22px}
  .review-card{padding:30px 24px 26px}
}
@media (max-width:400px){
  .review-dialog-body{padding:56px 22px 24px}
}

/* ============================================================
   4. WP BRIDGE
   Adapts block-generated DOM to the v6 component system. Nothing
   here is new design; it re-hangs v6 rules onto the elements
   blocks actually emit.
   ============================================================ */

/* WP's constrained layout adds a 24px block-gap stripe between every
   top-level section. theme.json sets blockGap to 0, this makes it explicit. */
.wp-block-post-content > *{margin-block-start:0;margin-block-end:0}
.wp-block-post-content{margin-block-start:0;margin-block-end:0}

/* Template-part wrappers are pass-through; they must not introduce a box.
   display:contents, not margin:0. WordPress wraps every template part in a
   div, and that div is only as tall as its contents. `.site-header` is
   position:sticky, so a 73px-tall wrapper gives it 0px of travel and it
   scrolls away with the page instead of sticking. In v6 the header's parent
   is <body>. Removing the wrapper box restores that: the header's containing
   block becomes .wp-site-blocks, which spans the document.
   .wp-site-blocks carries no is-layout-* class, so promoting the header and
   footer to its direct children brings no constrained-layout max-width with
   it, and every measured box is unchanged. */
.wp-block-template-part{display:contents}

/* Section heads that lead with an eyebrow.
   WordPress global styles emit three zero-margin rules for flow containers:
     :root :where(.is-layout-flow) > :first-child {margin-block-start:0}  (0,2,0)
     :root :where(.is-layout-flow) > :last-child  {margin-block-end:0}    (0,2,0)
     :root :where(.is-layout-flow) > *            {margin-block:0}        (0,1,0)
   Those outrank v6's `.section-head p` (0,1,1) and `h2` (0,0,1), so the 16px
   eyebrow gap and the 12px heading gap were being flattened to zero. Only the
   #art head has an eyebrow, so only it was affected: 93px in v6, 74px here,
   which propagated as a 20px short document. Restated above (0,2,0).
   The :first-child line carries v6's exemption forward: every other section
   head leads with its h2 and must stay at margin-top 0. */
.wp-block-group.section-head > p{margin-top:16px}
.wp-block-group.section-head > h2{margin-top:12px}
.wp-block-group.section-head > h2:first-child{margin-top:0}

/* Core image block: its own margin and img rules would beat the .story-photo
   collage rules on a specificity tie, so restate them at figure level. */
figure.wp-block-image{margin:0}
figure.wp-block-image.story-photo img{width:100%;height:100%;object-fit:cover;max-width:none}

/* ---------- Client-editable conversions (2026-09-22) ----------
   Each block below replaces a v6 Custom HTML fragment with native blocks and
   re-hangs the v6 look on the markup those blocks emit. Measured against the
   pre-conversion page at 1280/1024/768/390/375/320: 0px box deltas. */

/* Header. Native blocks: Group (header) > Group (.wrap .nav) > wordmark
   (Custom HTML, the logo lockup) + Group .nav-right > Group (nav) > List
   (.nav-links) + Paragraph (.nav-cta, the Contact button). site.js adds the
   menu toggle. The paragraph is a flex box so it is exactly as tall as its
   button, as the bare v6 anchor was; below 641px the button hides, so the
   paragraph must go too or the row keeps an empty 26px gap. */
.site-header .nav-cta{display:flex}
.site-header .nav-links > li{list-style:none}
@media (max-width:640px){
  .site-header .nav-cta{display:none}
}

/* Hero video. The poster is a core Image block linked to the YouTube watch
   URL: Jim swaps the poster with Replace and the video with the image link.
   JS off, the link opens YouTube. JS on, site.js swaps in the embed. The
   figure keeps the v6 .ratio box (16:9) and the play button is drawn on the
   link, so nothing here is markup Jim can break. */
figure.wp-block-image.video-poster{position:relative;aspect-ratio:16/9;margin:0}
figure.wp-block-image.video-poster > a{
  position:absolute;inset:0;display:block;background:#000;cursor:pointer;
}
figure.wp-block-image.video-poster img{
  width:100%;height:100%;object-fit:cover;opacity:.85;max-width:none;
}
figure.wp-block-image.video-poster > a::before{
  content:"";position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:74px;height:52px;background:var(--red);border-radius:12px;
  transition:background .2s;z-index:1;   /* above the .85-opacity poster, which stacks */
}
figure.wp-block-image.video-poster > a::after{
  content:"";position:absolute;top:50%;left:50%;transform:translate(-7.5px,-11px);
  border-style:solid;border-width:11px 0 11px 19px;
  border-color:transparent transparent transparent #fff;z-index:1;
}
figure.wp-block-image.video-poster > a:hover::before{background:var(--red-dark)}

/* Credits. One paragraph per name, so Jim adds a name by adding a paragraph.
   Any paragraph in the row takes the name style, even one without the class. */
.credits-row > p{
  font-family:var(--display);font-weight:600;font-size:.95rem;
  letter-spacing:.05em;color:#fff;white-space:nowrap;
}
.credits-row > p.credits-label{
  font-size:.72rem;letter-spacing:.18em;text-transform:uppercase;opacity:.85;
  white-space:normal;
}

/* Art tiles. Each tile is a core Image block: the figure is the bordered
   tile, its link is the punched-in crop box (v6 .art-img), and the image is
   positioned by the same measured percentages. */
.art-grid > figure.wp-block-image.art{
  display:block;border-radius:10px;overflow:hidden;background:var(--paper);
  border:1px solid var(--line);
}
figure.wp-block-image.art > a{
  display:block;position:relative;overflow:hidden;aspect-ratio:31/50;
  background:var(--paper-tint);color:var(--ink);text-decoration:none;
}
figure.wp-block-image.art img{
  position:absolute;height:auto;max-width:none;transition:transform .35s ease;
}
figure.wp-block-image.art:hover img{transform:scale(1.04)}
figure.wp-block-image.art.punch-print img{width:181.452%;left:-41.129%;top:-25.250%}
figure.wp-block-image.art.punch-tree img{width:180.905%;left:-38.844%;top:-22.539%}
/* The tile clips its link, so the focus ring moves out to the tile. */
figure.wp-block-image.art > a:focus-visible{outline:none}
figure.wp-block-image.art:has(> a:focus-visible){outline:3px solid var(--red);outline-offset:3px}

/* Event strip. Every photo is a core Image block inside the strip Group, so
   Jim adds, removes and reorders photos in the editor. site.js reads the
   strip's children generically and builds the arrows itself. */
.event-gallery > figure.wp-block-image{flex:0 0 auto;scroll-snap-align:start}
.event-gallery > figure.wp-block-image img{
  height:280px;width:auto;max-width:none;border-radius:10px;
  box-shadow:0 14px 34px -18px rgba(28,24,19,.3);
}
@media (max-width:640px){
  .event-gallery > figure.wp-block-image img{height:240px}
}

/* Direct email line: a paragraph now, kept at ink (not ink-soft). */
.contact-info p.contact-direct{margin-top:28px;color:var(--ink)}

/* ---------- Contact form: Fluent Forms bridge ----------
   The form is Fluent Forms (block "fluentfom/guten-block"), set to "Inherit
   Theme Style", with Fluent's default look dequeued in functions.php. Its
   structural stylesheet still loads, so every v6 form rule is restated here
   under .contact-form at a specificity that wins. Target: the v6 form's boxes
   within 2px (labels 20.4 tall + 7 gap, inputs 50, selects 52, rows 18 apart).
   Fluent's markup: fieldset > .ff-el-group (label div + content div), with
   two-column rows as .ff-t-container.field-row > .ff-t-cell. */
.contact-form{min-width:0}
.contact-form .fluentform,
.contact-form .fluentform form,
.contact-form .fluentform fieldset{display:block;margin:0;padding:0;border:0;min-width:0}
.contact-form .fluentform .ff-el-group,
.contact-form .fluentform .ff-t-container{margin:0 0 18px;padding:0}
.contact-form .fluentform .ff-t-cell .ff-el-group{margin:0}
/* Two-column rows. Fluent's conditional logic writes an inline display:block
   on a row it shows (class ff_cond_v) and display:none on one it hides
   (class ff_excluded), so the shown state needs !important to stay a grid. */
.contact-form .fluentform .ff-t-container.field-row{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:18px;
}
.contact-form .fluentform .ff-t-container.field-row.ff_cond_v{display:grid !important}
.contact-form .fluentform .ff-t-cell{min-width:0;width:auto;padding:0;flex:none}
.contact-form .fluentform .ff-el-input--label{
  display:block;margin:0;padding:0;line-height:inherit;
}
.contact-form .fluentform .ff-el-input--label label{
  display:block;margin:0 0 7px;padding:0;
  font-family:var(--display);font-weight:600;font-size:.75rem;line-height:inherit;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink);
}
.contact-form .fluentform .ff-el-input--label label::after,
.contact-form .fluentform .ff-el-input--label label::before{content:none}
.contact-form .fluentform .ff-el-input--content{margin:0;padding:0}
.contact-form .fluentform .ff-el-form-control{
  width:100%;min-width:0;height:auto;margin:0;
  font-family:var(--body);font-size:1rem;line-height:normal;color:var(--ink);
  padding:13px 14px;border:1px solid var(--line);border-radius:6px;
  background:var(--paper);box-shadow:none;
}
.contact-form .fluentform textarea.ff-el-form-control{
  display:inline-block;vertical-align:baseline;min-height:130px;height:130px;resize:vertical;
}
.contact-form .fluentform .ff-el-form-control:focus{
  outline:none;border-color:var(--red);box-shadow:0 0 0 3px rgba(200,16,46,.12);
}
.contact-form .fluentform .ff-el-is-error .ff-el-form-control{border-color:var(--red)}
/* Field errors sit on the label line, right-aligned, out of the flow. In the
   flow they pushed the button down, and when the visitor left the message box
   to click Send, the error cleared on blur, the button jumped back up between
   mousedown and mouseup, and the click was lost. Out of the flow nothing moves. */
.contact-form .fluentform .ff-el-group{position:relative}
.contact-form .fluentform .ff-el-group .error.text-danger{
  position:absolute;top:0;right:0;margin:0;max-width:62%;
  font-family:var(--body);font-size:.8rem;line-height:20.4px;color:var(--red);
  text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.contact-form .ff-errors-in-stack{margin-top:6px;font-size:.85rem;line-height:1.5;color:var(--red)}
.contact-form .fluentform .ff-custom_html{margin-bottom:0}
.contact-form .fluentform .ff_submit_btn_wrapper{
  margin:0;padding:0 0 1.288rem;   /* the v6 status line's 1.4em at .92rem */
  text-align:left;
}
/* The submit button keeps the site .btn.btn-red look. Fluent's .ff-btn sets
   padding, size and line-height at the same specificity, so restate it. */
.contact-form .fluentform button.ff-btn-submit.btn{
  display:inline-block;margin-top:14px;
  font-family:var(--display);font-weight:600;font-size:.8rem;line-height:normal;
  letter-spacing:.08em;text-transform:uppercase;
  padding:13px 26px;border:0;border-radius:4px;
  background:var(--red);color:#fff;box-shadow:none;opacity:1;
  transition:background .2s,color .2s,box-shadow .2s;
}
.contact-form .fluentform button.ff-btn-submit.btn:hover,
.contact-form .fluentform button.ff-btn-submit.btn:focus{background:var(--red-dark);color:#fff;opacity:1}
.contact-form .fluentform button.ff-btn-submit.btn:focus-visible{outline:3px solid var(--red);outline-offset:3px}
/* After sending: Fluent hides the form and shows its confirmation message. */
.contact-form .ff-message-success{
  margin:0;padding:22px 24px;border:1px solid var(--line);border-left:3px solid var(--red);
  border-radius:6px;background:var(--paper-tint);box-shadow:none;
  font-family:var(--body);font-size:1.0625rem;line-height:1.7;color:var(--ink);
}
.contact-form .ff-message-success p{margin:0}
/* No-JS fallback notice (functions.php) when a post fails validation. */
.contact-form .form-error{margin:0 0 18px;font-size:.92rem;color:var(--red)}
@media (max-width:640px){
  .contact-form .fluentform .ff-t-container.field-row,
  .contact-form .fluentform .ff-t-container.field-row.ff_cond_v{grid-template-columns:minmax(0,1fr)}
}

/* Core list block inside the footer columns (v6 used bare <ul>). */
.footer-grid ul.wp-block-list{list-style:none;padding-left:0}
/* Touch screens: each footer link becomes a ~44px-tall target. The padding
   replaces the 9px list gap, and the list's negative margin keeps the first
   and last link where they were. */
@media (pointer:coarse){
  .footer-grid ul.wp-block-list{margin-block:-9px}
  .footer-grid li+li{margin-top:0}
  .footer-grid li a{display:inline-block;padding:9px 0}
}

/* Core button blocks (404 template). The .btn classes in this theme are
   written for anchors; on a core button they land on the WRAPPER div and
   would paint a square behind the rounded anchor. Neutralize the wrapper. */
div.wp-block-button{background:transparent}
.wp-block-button__link{
  font-family:var(--display);font-weight:600;font-size:.8rem;
  letter-spacing:.08em;text-transform:uppercase;
  padding:13px 26px;border-radius:4px;text-decoration:none;
  transition:background .2s,color .2s,box-shadow .2s;
}
.btn-red > .wp-block-button__link{background:var(--red);color:#fff}
.btn-red > .wp-block-button__link:hover{background:var(--red-dark);color:#fff}
.btn-ghost > .wp-block-button__link,
.is-style-outline > .wp-block-button__link{
  background:transparent;color:var(--ink);box-shadow:inset 0 0 0 2px var(--ink);border:0;
}
.btn-ghost > .wp-block-button__link:hover,
.is-style-outline > .wp-block-button__link:hover{
  color:var(--red);box-shadow:inset 0 0 0 2px var(--red);background:transparent;
}

/* 404 body band: gives the template the same vertical rhythm as a section. */
.error-band{padding:120px 24px 140px;text-align:center}
.error-band .eyebrow{margin-bottom:14px}
.error-band .wp-block-buttons{display:flex;gap:14px;justify-content:center;margin-top:30px;flex-wrap:wrap}

/* Blog index fallback (templates/index.html). Single-page site: this exists so
   the theme is valid and post URLs never 404 into nothing. */
.blog-band{padding:88px 24px}
.blog-band .wp-block-post-title{margin-top:32px}
.blog-band .wp-block-post-title a{color:var(--ink);text-decoration:none}
.blog-band .wp-block-post-title a:hover{color:var(--red)}

/* ==========================================================================
   Static contact form (replaces the Fluent Forms plugin). The markup keeps
   Fluent's class names so every .contact-form rule above still applies.
   assets/form.js shows and hides the conditional fields.
   ========================================================================== */
.contact-form .ff_screen_reader_title{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;border:0;
}
.contact-form .ff-hp{position:absolute;left:-9999px;width:1px;height:1px;opacity:0}
.contact-form .fluentform .has-conditions{display:none}
.contact-form .fluentform .ff-el-group.has-conditions.ff_cond_v{display:block}
.contact-form .fluentform .ff-t-container.field-row.has-conditions.ff_cond_v{display:grid}
.contact-form .ff-errors-in-stack{margin-top:14px}
