/* ============================================================================
   FHA — Section 3 : ARTISTS
   Laws: claude/fha-page-template.md, claude/fha-section2-proportion-law.md and
   its round-14 / round-15 continuations. Loaded AFTER section2.css, which this
   sheet extends rather than replaces — the glass, the slider button, the
   accordion, the Connect rail and the title tiers all come from there.

   Two page types:
     .s3  artist portrait  — masthead, name + role, bio on glass, Connect rail,
                             one signature button
     .ng  NEXT GEN + GEN X — the standard FHA banner, then a full-width
                             editorial run beneath it
   ========================================================================= */

/* ---------------------------------------------------------------- shared -- */
:root {
  --fha-navy:  #022C44;
  --fha-teal:  #045567;
  --fha-deep:  #056981;
  --fha-pale:  #CBEAEA;
  --fha-bright:#E7F4F4;
  --fha-aqua:  #A2E7E8;
  --fha-glass:      rgba(235,248,249,.22);
  --fha-glass-edge: rgba(255,255,255,.35);
  --fha-glass-lift: inset 0 1px 0 rgba(255,255,255,.18), 0 4px 14px rgba(2,24,38,.25);
}

/* =========================== ARTIST PORTRAIT ============================== */
@media (min-width: 992px) {

  /* ---- Section 2 parity ------------------------------------------------
     style.css still carries the pre-redesign `.artists-page` block, and those
     selectors are keyed on the per-artist body class, so they out-specify the
     Section 2 system. That is what pulled these two pages out of line:

       .artists-page .brand-logo *          width: 22.031vw
       .artists-steven  .action *           max-width: 16.271vw  -> CTA wrapped
                                            to two lines (58.7px vs S2's 45.7)
       .artists-michael .details .action    margin-bottom: 0     -> its CTA sat
                                            15px below Steven's

     Restated here at FULL ancestor depth. Third time this trap has bitten —
     see the proportion law §13 and §20.

     The .action rules stay even though the portraits no longer render a generic
     CTA: they are the parity statement for any Section 3 page that DOES carry one
     (NEXT GEN does), and removing them would hand those pages back to the legacy
     block. */
  .s3.artists-page .banner .banner-detail-container .action *,
  .s3.artists-page.artists-steven .banner .banner-detail-container .action *,
  .s3.artists-page.artists-michael .banner .banner-detail-container .action * {
    width: 100%; max-width: max(23.37vw, 262px); line-height: 1.5; }
  /* line-height is `inherit` on the button (bootstrap), and the Section 2 pages
     resolve it to 27px from an ancestor the artist pages do not share — which
     left the CTA 7px shorter and 7px off the anchor. Pinned to the same 1.5. */
  .s3.artists-page.artists-steven .banner .banner-detail-container .details .action,
  .s3.artists-page.artists-michael .banner .banner-detail-container .details .action {
    margin-bottom: 1.042vw; }

  /* ---- masthead: sized on the Coldiac word, not on the art box ----------
     Service CATALOG and Artist PORTRAIT are different lockups — 2.500 vs 3.171
     aspect — so sizing both by WIDTH gave PORTRAIT a 21% smaller cap band
     (21.4px against CATALOG's 27.2px at 1440) and lifted the whole title stack
     21.6px, which in turn dragged the CTA off the shared anchor.

     Both arts carry their caps at 26.5% of art height, so matching the RENDERED
     HEIGHT matches the caps exactly. Section 2 renders width/2.5, i.e.
     clamp(224px,17.792vw,300px)/2.5 = clamp(89.6px, 7.1168vw, 120px). */
  .s3.theme-teal .banner .banner-detail-container .brand-logo *,
  .s3.theme-teal .banner .banner-detail-container .brand-logo img,
  .s3.artists-page .banner .banner-detail-container .brand-logo *,
  .s3.artists-page.artists-michael .banner .banner-detail-container .brand-logo * {
    width: auto; height: clamp(89.6px, 7.1168vw, 120px);
    max-width: 100%; object-fit: contain; margin-left: 0; margin-right: 0; }
  .s3.artists-page .banner .banner-detail-container .brand-logo,
  .s3.artists-page.artists-michael .banner .banner-detail-container .brand-logo {
    max-width: none; margin: 0 auto 1.7vw; justify-content: center; }

  /* ---- the block carries the Connect rail, so it takes the menu page's width
     services-menu widens to clamp(342px,27vw,480px) precisely because its rail
     sits INSIDE the block. These pages do the same, so they get the same width
     — which also gives the bio and the signature button the 311.8px the menu
     page's service rows get, instead of 268.6px. */
  .s3 .content-scroll-in { max-width: clamp(342px, 27vw, 480px); }

  /* ---- the section's three scripts, matched by OPTICAL CORE ---------------
     His note: the NEXT GEN script reads small next to the other two. It is not
     a bake problem — all three arts are tightly trimmed, so nothing can be
     cropped or padded to change it. The cause is the LETTERFORMS: measured as
     the ink rows between the 12% and 88% cumulative marks, over box height —

         sub-steven   frac .5266   core 20.12px at the shared 38.2px tier
         sub-kanyon   frac .4249   core 16.23px      (-19%)
         sub-nextgen  frac .4222   core 16.13px      (-20%)

     Kanyon's line carries taller swashes, so more of its box is ascender and
     less is readable middle; at a common height the readable word comes out
     a fifth smaller. Same trap the Section 1 page titles hit, same fix: give
     each page its own RENDER HEIGHT so the cores land together. Steven's is the
     reference and does not move — the pages he already approved are unchanged.

     target core 20.12px  ->  steven 38.21px (2.653vw, base rule)
                              kanyon 47.36px (3.289vw)  392.8px wide
                              nextgen 47.65px (3.309vw) 382.3px wide

     Kanyon's 392.8px runs 4px past the 388.8px block, so the sub gets the same
     max-width:none the page titles already have (ttl-steven renders 533px in a
     558.7px column). Both stay well inside the column. */
  .s3.theme-teal .banner .banner-detail-container .details .our-mission-img img,
  .ng.theme-teal .banner .banner-detail-container .details .our-mission-img img {
    max-width: none; }
  .s3.artists-michael.theme-teal .banner .banner-detail-container .details .our-mission-img *,
  .s3.artists-michael.theme-teal .banner .banner-detail-container .details .our-mission-img img {
    height: clamp(34.7px, 3.289vw, 49.6px); }
  .ng.theme-teal .banner .banner-detail-container .details .our-mission-img *,
  .ng.theme-teal .banner .banner-detail-container .details .our-mission-img img {
    height: clamp(34.9px, 3.309vw, 49.9px); }

  /* the bio panel — the Section 1 glass, one continuous sheet */
  /* His bios run 5-6 paragraphs; at a legible size they are taller than the column.
     The panel scrolls INSIDE its own glass so the page still fits at rest and the
     CTA stays on the shared Section 1 anchor. */
  /* The bio FILLS the scroll box rather than being clamped to a vh figure.
     Measured before this change: .content-scroll was 517.1px tall but its content
     only 475.3px — 41.8px of empty scroll area doing nothing, which is what left
     the CTA looking marooned. The menu page has no such slack (17.9px, and that
     is just the last card's margin), which is the density he pointed at. Padding
     also comes down to the menu page's rhythm. */
  .s3 .s3bio { position: relative; border-radius: 2px; padding: clamp(10px,1.35vh,14px) 16px;
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    scrollbar-width: thin; scrollbar-color: rgba(162,231,232,.5) transparent;
    background: var(--fha-glass);
    -webkit-backdrop-filter: blur(16px) saturate(1.25); backdrop-filter: blur(16px) saturate(1.25);
    border: 1px solid var(--fha-glass-edge); box-shadow: var(--fha-glass-lift);
    margin-bottom: clamp(10px, 1.6vh, 16px); }
  /* Body size and shadow are the column's, measured off Section 2's
     .details-disc p (12.672px / 0 1px 1px rgba(2,44,68,.5) at 1440). Only the
     alignment and leading differ, and deliberately: a five-to-six paragraph bio
     reads as a column of prose, not as a centred stand-first. */
  /* RIGHT-aligned, his call. It also agrees with the rest of the column — the
     menu sheet, the Connect rail and the whole mobile pane are right-anchored —
     so the bio now reads to the same edge as everything around it. */
  .s3.theme-teal .banner .banner-detail-container .details .s3bio p {
    color: var(--fha-bright); font-family: 'Raleway', sans-serif; font-weight: 500;
    font-size: clamp(12px, .88vw, 14px); line-height: 1.5; text-align: right;
    margin: 0 0 .72em; text-wrap: pretty; text-shadow: 0 1px 1px rgba(2,44,68,.5); }
  .s3.theme-teal .banner .banner-detail-container .details .s3bio p:last-child { margin-bottom: 0; }
  .s3.theme-teal .banner .banner-detail-container .details .s3bio em {
    font-style: italic; color: var(--fha-pale); }
  .s3 .s3bio .seg { white-space: nowrap; }
  .s3 .s3bio::-webkit-scrollbar { width: 5px; }
  .s3 .s3bio::-webkit-scrollbar-thumb { background: rgba(162,231,232,.45); border-radius: 3px; }
  .s3 .s3bio::-webkit-scrollbar-track { background: transparent; }
  /* A soft edge so a scrolled bio reads as continuing, not as cut off.
     A mask on the panel itself, not an overlay: an overlay had to be positioned
     against a height nothing was measuring (--bioH was never set), and it would
     have to sit above the glass, tinting it. The mask fades the TYPE and leaves
     the glass whole. section3.js adds/removes the two classes at each end, so
     the first and last lines are never dimmed. */
  .s3 .s3main { position: relative; }
  .s3 .s3bio.moreBelow {
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent);
            mask-image: linear-gradient(to bottom, #000 calc(100% - 26px), transparent); }
  .s3 .s3bio.moreAbove.moreBelow {
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14px,
                                        #000 calc(100% - 26px), transparent);
            mask-image: linear-gradient(to bottom, transparent, #000 14px,
                                        #000 calc(100% - 26px), transparent); }
  .s3 .s3bio.moreAbove:not(.moreBelow) {
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14px);
            mask-image: linear-gradient(to bottom, transparent, #000 14px); }

  /* the portrait column carries the Connect rail beside the bio, the way his
     .pxd does — rail left, content right, same 15px gutter as the menu page */
  /* the flex chain that lets the bio fill: the scroll box gives its height to the
     column, the column to .s3main, and .s3main to the bio, with the signature
     button staying pinned beneath it */
  /* The scroll box is already `flex:1 1 auto; min-height:0` inside .details
     (theme-teal), so it has a definite used height. Making it a flex column too
     hands that height down: inner -> column -> .s3main -> bio, with the signature
     button pinned beneath. Deliberately NOT `min-height:100%` on the inner — a
     percentage against a flex-basis:auto parent resolves against an indefinite
     height and forced 82-204px of overflow at every viewport when I tried it. */
  .s3 .content-scroll { display: flex; flex-direction: column; }
  .s3 .content-scroll-in { display: flex; flex-direction: column;
    flex: 1 1 auto; min-height: 0; }
  .s3 .s3col { display: flex; align-items: stretch; gap: 15px; flex: 1 1 auto; min-height: 0; }
  .s3 .s3col > .s2connect { margin-top: 2px; align-self: flex-start; }
  .s3 .s3col > .s3main { flex: 1; min-width: 0;
    display: flex; flex-direction: column; min-height: 0; }
  .s3 .s3main > .s2slot { flex: 0 0 auto; }
}

/* ---- artist portrait, mobile ---- */
#fhaMobile.s3m .colInner .s3name .t { display: block; text-align: center; color: var(--fha-bright);
  font-family: 'Coldiac Free', 'Playfair Display', serif; letter-spacing: .05em;
  font-size: 15px; line-height: 1.15; text-shadow: 0 1px 1px rgba(2,44,68,.6); }
#fhaMobile.s3m .colInner .s3role .t { display: block; text-align: center; color: var(--fha-pale);
  font-family: 'Distant Stroke', 'Playfair Display', serif; font-weight: 500;
  font-size: 19px; line-height: 1.2; margin: 2px 0 12px; }
#fhaMobile .s3bio { border-radius: 2px; padding: 12px 14px; margin-bottom: 12px;
  background: rgba(235,248,249,.20);
  -webkit-backdrop-filter: blur(14px) saturate(1.2); backdrop-filter: blur(14px) saturate(1.2);
  border: 1px solid rgba(255,255,255,.32); box-shadow: 0 4px 14px rgba(2,24,38,.25); }
#fhaMobile .s3bio p { color: var(--fha-bright); font-family: 'Raleway', sans-serif;
  font-weight: 500; font-size: 13px; line-height: 1.45; margin: 0 0 .7em; text-align: right; }
#fhaMobile .s3bio p:last-child { margin-bottom: 0; }
/* the mobile pane scrolls, so the bio is never clipped there — his copy law */
#fhaMobile .s3bio em { font-style: italic; color: var(--fha-pale); }

/* The scripts are matched by OPTICAL CORE on mobile too — same measurement, same
   reference (Steven at the shared 27px, core 14.22px). Without this the pane
   repeats the desktop mismatch at a smaller size. max-width lifted from 90% for
   the same reason it was lifted on desktop: the taller render is also wider. */
#fhaMobile.s3m.pg-kanyon .psub { height: 33.5px; max-width: 96%; }
#fhaMobile.ngm .psub { height: 33.7px; max-width: 96%; }

/* ---- NEXT GEN in the mobile pane: the same one screen, same copy ---------- */
#fhaMobile .s3bio.ngOne { text-align: center; padding: 16px 14px; }
#fhaMobile .s3bio.ngOne p { text-align: center; font-size: 13.5px; line-height: 1.5; }
#fhaMobile .s3bio.ngOne .ngLead { font-family: 'Playfair Display', serif; font-weight: 600;
  color: #fff; font-size: 16px; line-height: 1.3; margin: 0 0 1em;
  text-shadow: 0 1px 1px rgba(2,44,68,.55); }
#fhaMobile .s3bio.ngOne .ngClose { margin: 1.05em 0 0; padding-top: 1em;
  color: var(--fha-aqua); font-family: 'Playfair Display', serif; font-weight: 600;
  font-style: italic; font-size: 18px; line-height: 1.34;
  border-top: 1px solid rgba(162,231,232,.30); text-shadow: 0 1px 1px rgba(2,44,68,.55); }
#fhaMobile .ngAsk { text-align: center; color: var(--fha-pale); margin: 14px 0 10px;
  font-family: 'Playfair Display', serif; font-weight: 600; font-size: 12px;
  letter-spacing: .16em; text-shadow: 0 1px 1px rgba(2,44,68,.5); }
/* On this page the fixed bar's .cta is a <button> rather than the Boulevard <a>
   (his call — it opens the sheet instead of the booking widget). Strip the UA
   button chrome so it is pixel-identical to the anchor on every other page. */
#fhaMobile.ngm .ctaRow button.cta { -webkit-appearance: none; appearance: none;
  border: 0; font: inherit; text-align: center; cursor: pointer; }


/* ========================= NEXT GEN + GEN X =============================== */
/* The editorial run lives BELOW the standard banner, full width, so the split
   and the oversized type have room his 400px content column cannot give them.
   Everything else — colour, glass, silver, the ambigram, the footer — is the
   same system. */

.ng .ngWrap { --pad: clamp(20px, 5vw, 96px);
  position: relative; width: 100%; overflow: hidden;
  background: linear-gradient(180deg, #022C44 0%, #04455a 38%, #045567 62%, #022C44 100%);
  color: var(--fha-bright); font-family: 'Raleway', sans-serif; }
.ng .ngWrap::before {           /* the ambigram, dimensional and barely there */
  content: ''; position: absolute; right: -6vw; top: 8vh; width: 46vw; height: 46vw;
  background: url(../images/mobile/fha-logo-vertical.png?v=15) center/contain no-repeat;
  opacity: .05; pointer-events: none; }
.ng .ngSec { position: relative; z-index: 2; padding: clamp(48px, 9vh, 120px) var(--pad);
  max-width: 1480px; margin: 0 auto; }
.ng .ngSec + .ngSec { padding-top: 0; }
.ng .ngRule { height: 1px; border: 0; margin: 0 var(--pad);
  background: linear-gradient(90deg, transparent, rgba(162,231,232,.42), transparent); }

/* --- shared editorial type ------------------------------------------------ */
.ng h2 { font-family: 'Coldiac Free', 'Playfair Display', serif; font-weight: 400;
  letter-spacing: .04em; line-height: 1.02; color: var(--fha-bright);
  font-size: clamp(26px, 4.4vw, 62px); margin: 0 0 clamp(14px, 2.4vh, 30px);
  text-shadow: 0 2px 1px rgba(2,24,38,.5); }
.ng h3 { font-family: 'Raleway', sans-serif; font-weight: 800; letter-spacing: .16em;
  text-transform: uppercase; color: var(--fha-aqua); font-size: clamp(11px, .84vw, 13px);
  margin: 0 0 12px; }
.ng p { font-size: clamp(14px, 1.06vw, 18px); line-height: 1.62; color: var(--fha-bright);
  margin: 0 0 1em; max-width: 62ch; text-wrap: pretty; }
.ng p.lead { font-size: clamp(16px, 1.34vw, 23px); line-height: 1.5; color: #fff;
  font-weight: 500; max-width: 46ch; }
.ng .kicker { font-family: 'Coldiac Free', 'Playfair Display', serif;
  font-size: clamp(20px, 2.5vw, 38px); color: var(--fha-aqua); letter-spacing: .03em;
  margin-top: clamp(16px, 2.4vh, 28px); }

/* --- the split ------------------------------------------------------------ */
.ng .ngSplit { display: grid; grid-template-columns: 1fr 1px 1fr;
  gap: clamp(18px, 3vw, 56px); align-items: start; }
.ng .ngSplit .spine { align-self: stretch; width: 1px;
  background: linear-gradient(180deg, transparent, rgba(162,231,232,.55) 12%,
              rgba(162,231,232,.55) 88%, transparent); }
.ng .ngSide { will-change: transform; }
.ng .ngSide .who { font-family: 'Coldiac Free', 'Playfair Display', serif;
  font-size: clamp(22px, 3vw, 44px); letter-spacing: .05em; color: #fff; line-height: 1.05; }
.ng .ngSide .label { font-family: 'Raleway', sans-serif; font-weight: 800;
  letter-spacing: .2em; font-size: clamp(10px, .78vw, 12.5px); color: var(--fha-aqua);
  margin: 6px 0 clamp(14px, 2vh, 22px); }
.ng .ngSide ul { list-style: none; margin: 0 0 clamp(14px, 2vh, 22px); padding: 0; }
.ng .ngSide li { font-family: 'Playfair Display', serif; font-size: clamp(15px, 1.35vw, 24px);
  line-height: 1.42; color: var(--fha-pale); }
.ng .ngSide.r { text-align: right; }
.ng .ngSide.r ul { padding: 0; }
.ng .ngSide p { font-size: clamp(13px, .98vw, 16px); color: var(--fha-bright); max-width: 40ch; }
.ng .ngSide.r p { margin-left: auto; }

/* --- the contrast ladder, resolving into CARE ----------------------------- */
.ng .ngPairs { margin: clamp(26px, 5vh, 64px) 0 0; }
.ng .ngPair { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center;
  gap: clamp(10px, 2vw, 30px); padding: clamp(5px, .9vh, 11px) 0; }
.ng .ngPair span { font-family: 'Raleway', sans-serif; font-weight: 200;
  letter-spacing: .22em; font-size: clamp(12px, 1.5vw, 24px); color: rgba(231,244,244,.72); }
.ng .ngPair span:first-child { text-align: right; }
.ng .ngPair i { font-style: normal; color: rgba(162,231,232,.5); font-size: .8em; }
.ng .ngResolve { text-align: center; margin-top: clamp(20px, 4vh, 48px); }
.ng .ngResolve .word { font-family: 'Coldiac Free', 'Playfair Display', serif;
  font-size: clamp(48px, 12vw, 170px); line-height: .95; letter-spacing: .06em;
  color: #fff; text-shadow: 0 3px 2px rgba(2,24,38,.45); }
.ng .ngResolve .sub { margin-top: 10px; color: var(--fha-pale);
  font-family: 'Playfair Display', serif; font-size: clamp(14px, 1.3vw, 21px); }
.ng .ngMission { text-align: center; margin-top: clamp(18px, 3vh, 34px);
  font-family: 'Coldiac Free', 'Playfair Display', serif; color: var(--fha-aqua);
  font-size: clamp(16px, 2vw, 30px); letter-spacing: .03em; }
.ng .ngMission .plus { color: #fff; }

/* --- the pull quote ------------------------------------------------------- */
.ng .ngQuote { position: relative; border-radius: 3px; text-align: center;
  padding: clamp(28px, 6vh, 74px) clamp(18px, 4vw, 70px);
  background: var(--fha-glass);
  -webkit-backdrop-filter: blur(18px) saturate(1.25); backdrop-filter: blur(18px) saturate(1.25);
  border: 1px solid var(--fha-glass-edge); box-shadow: var(--fha-glass-lift); }
.ng .ngQuote q { display: block; quotes: none;
  font-family: 'Coldiac Free', 'Playfair Display', serif; font-style: normal;
  font-size: clamp(26px, 4.6vw, 68px); line-height: 1.1; color: #fff; letter-spacing: .02em;
  text-shadow: 0 2px 1px rgba(2,24,38,.5); }
.ng .ngQuote .by { margin-top: clamp(12px, 2vh, 22px); color: var(--fha-aqua);
  font-family: 'Raleway', sans-serif; font-weight: 700; letter-spacing: .2em;
  font-size: clamp(10px, .8vw, 12.5px); text-transform: uppercase; }
.ng .ngQuote .by::before { content: '\2014\00a0'; }

/* --- lists on glass ------------------------------------------------------- */
.ng .ngCols { column-count: 2; column-gap: clamp(20px, 4vw, 64px); }
@media (min-width: 1200px) { .ng .ngCols { column-count: 3; } }
.ng .ngTicks { list-style: none; margin: 0; padding: 0; }
.ng .ngTicks li { break-inside: avoid; position: relative; padding: 7px 0 7px 22px;
  font-size: clamp(13px, 1vw, 16.5px); line-height: 1.4; color: var(--fha-bright);
  border-bottom: 1px solid rgba(162,231,232,.14); }
.ng .ngTicks li::before { content: ''; position: absolute; left: 2px; top: 1.05em;
  width: 9px; height: 1px; background: var(--fha-aqua); opacity: .85; }
.ng .ngChips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.ng .ngChips li { border-radius: 2px; padding: 8px 14px; background: rgba(235,248,249,.16);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  border: 1px solid rgba(255,255,255,.28); color: var(--fha-bright);
  font-size: clamp(12px, .9vw, 15px); letter-spacing: .04em; }
.ng .ngCare .big { font-family: 'Coldiac Free', 'Playfair Display', serif;
  font-size: clamp(24px, 3.6vw, 54px); line-height: 1.08; color: #fff; margin: 0 0 6px; }
.ng .ngCare .std { color: var(--fha-aqua); font-family: 'Playfair Display', serif;
  font-style: italic; font-size: clamp(14px, 1.2vw, 20px); margin-bottom: clamp(18px,3vh,34px); }

/* --- the CTA and its panel ------------------------------------------------ */
.ng .ngCta { text-align: center; }
.ng .ngBtn { -webkit-appearance: none; appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 14px; border-radius: 2px;
  padding: clamp(13px, 1.6vh, 18px) clamp(24px, 3vw, 44px); margin-top: clamp(14px,2.4vh,26px);
  background: var(--fha-navy); border: 1px solid rgba(162,231,232,.42); color: var(--fha-aqua);
  font-family: 'Playfair Display', serif; font-size: clamp(14px, 1.2vw, 19px);
  letter-spacing: .18em; box-shadow: 0 4px 16px rgba(2,24,38,.35);
  transition: background .25s ease, color .25s ease, transform .18s ease; }
.ng .ngBtn:hover { background: #04364f; color: #fff; transform: translateY(-1px); }
.ng .ngBtn svg { width: 16px; height: 16px; flex: none; }
.ng .ngPanel { max-height: 0; overflow: hidden; text-align: left;
  transition: max-height .5s cubic-bezier(.3,.8,.25,1); }
.ng .ngCta.open .ngPanel { max-height: 760px; }
.ng .ngPanelIn { margin: clamp(16px,2.6vh,28px) auto 0; max-width: 720px; border-radius: 3px;
  padding: clamp(20px, 3vh, 34px) clamp(18px, 3vw, 38px);
  background: var(--fha-glass);
  -webkit-backdrop-filter: blur(18px) saturate(1.25); backdrop-filter: blur(18px) saturate(1.25);
  border: 1px solid var(--fha-glass-edge); box-shadow: var(--fha-glass-lift); }
.ng .ngPanelIn h4 { font-family: 'Coldiac Free', 'Playfair Display', serif;
  font-size: clamp(18px, 1.9vw, 28px); color: #fff; margin: 0 0 6px; letter-spacing: .04em; }
.ng .ngPanelIn .note { color: var(--fha-pale); font-size: clamp(12.5px,.95vw,15px);
  margin: 0 0 16px; max-width: none; }
.ng .ngPanelIn .send { display: inline-flex; align-items: center; gap: 10px; margin-top: 18px;
  border-radius: 2px; padding: 12px 24px; text-decoration: none;
  background: rgba(162,231,232,.14); border: 1px solid rgba(162,231,232,.5);
  color: var(--fha-aqua); font-family: 'Playfair Display', serif; letter-spacing: .14em;
  font-size: clamp(13px,1.05vw,16px); transition: background .25s ease, color .25s ease; }
.ng .ngPanelIn .send:hover { background: rgba(162,231,232,.26); color: #fff; }

/* --- responsive ----------------------------------------------------------- */
@media (max-width: 991px) {
  .ng .ngWrap { display: none; }        /* the mobile pane carries this page */
}
@media (prefers-reduced-motion: reduce) {
  .ng .ngSide { transform: none !important; }
}


/* ---- NEXT GEN hero, inside the standard banner column -------------------- */
/* The Section 3 masthead needs NO Coldiac anchor: PORTRAIT lands at 50.08% of
   title-artist-portrait.png because the lockup is composited from his two
   separate .pxd layers rather than recovered from one flattened export. */
.s3.theme-teal .banner .banner-detail-container .brand-logo img,
.ng.theme-teal .banner .banner-detail-container .brand-logo img { transform: none; }

/* ---- NEXT GEN as ONE SCREEN --------------------------------------------
   2026-08-19. It carries the `s3` body class now, so it inherits the Section 3
   system whole: masthead tier, the 28.8px title tier, the 38.2px script tier, the
   388.8px block, the glass panel, the flex chain. Its title and subtitle are BAKED
   ART like every other page in the section (built by _build/build_nextgen_assets.py
   — Playfair 800 caps with his navy edge, Distant Stroke script), which is why the
   old live-text .ngTitle / .ngScript rules are gone.

   The one structural difference from a portrait: this page HAS a generic CTA,
   because it has no signature service button to act as one. So it sits back on the
   shared anchor at y 731.4 with every Section 2 page. */
@media (min-width: 992px) {
  /* The copy is centred in the panel, and set LARGER than a bio's. A portrait runs
     five or six paragraphs and has to be economical; this page runs four short ones
     in the same 388.8px block. At bio size the copy filled barely half the glass and
     left exactly the dead space he objected to — so the type steps up to fill it,
     which is also the more readable choice for the one page a stranger reads cold. */
  /* The panel sizes to its copy and never grows — a bio can flex-fill because it
     always has more words than room, this page never does. On a tall viewport the
     leftover air is split above the panel and below the ask (the two auto margins),
     so the group sits optically centred under the subtitle instead of the glass
     inflating into a half-empty box: at 2560x1440 the filled version dropped to 46%
     ink and read as a mistake.

     `overflow-y: auto`, not visible: the enlarged couplet tips the copy past the
     panel on a short viewport (114% of the box at 1440x830, 119% at 1366x768) and
     visible let it spill straight out of the glass. It now scrolls inside its own
     panel exactly as a bio does — section3.js already drives the mask fade for
     anything matching .s3bio, so .ngOne inherits it for free. */
  .ng .s3bio.ngOne { display: flex; flex-direction: column; justify-content: center;
    flex: 0 1 auto; min-height: 0; margin-top: auto; text-align: center;
    overflow-y: auto; overscroll-behavior: contain;
    padding: clamp(11px,1.7vh,18px) clamp(16px,1.6vw,22px); }
  .ng.theme-teal .banner .banner-detail-container .details .s3bio.ngOne p {
    text-align: center; font-size: clamp(14px, 1.07vw, 17px); line-height: 1.46;
    margin-bottom: .8em; }

  /* "Two masters. Two disciplines. One seat." — the positioning line */
  .ng.theme-teal .banner .banner-detail-container .details .s3bio.ngOne .ngLead {
    font-family: 'Playfair Display', serif; font-weight: 600; color: #fff;
    font-size: clamp(16px, 1.32vw, 21px); line-height: 1.28;
    margin: 0 0 .85em; text-shadow: 0 1px 1px rgba(2,44,68,.55); }

  /* the couplet. Set apart above a hairline, because it is the page's last word
     and his draft breaks it over two lines. Aqua, not white — it is a statement,
     not a heading. Set LARGEST in the panel, above even the lead: he says the
     line all the time, so it carries the page. The colour was already right —
     var(--fha-aqua) is #A2E7E8, the identical ink the baked page titles use
     (build_s3_assets.TITLE_CAPS = 162,231,232). */
  .ng.theme-teal .banner .banner-detail-container .details .s3bio.ngOne .ngClose {
    margin: .9em 0 0; padding-top: .85em; color: var(--fha-aqua);
    font-family: 'Playfair Display', serif; font-weight: 600; font-style: italic;
    font-size: clamp(18px, 1.55vw, 25px); line-height: 1.34;
    border-top: 1px solid rgba(162,231,232,.30);
    text-shadow: 0 1px 1px rgba(2,44,68,.55); }

  /* "THINK YOU'RE THE ONE?" — the line that hands off to the button */
  .ng .ngAsk { flex: 0 0 auto; margin-bottom: auto; text-align: center; color: var(--fha-pale);
    font-family: 'Playfair Display', serif; font-weight: 600;
    font-size: clamp(11.5px, .88vw, 14px); letter-spacing: .16em;
    line-height: 1.4; margin: clamp(9px,1.4vh,14px) 0 0;
    text-shadow: 0 1px 1px rgba(2,44,68,.5); }
}

/* ---- the INTRODUCE YOURSELF sheet --------------------------------------- */
/* His choice: a frosted panel, then their own mail app. No form, no database, no
   "application" — the mailto arrives pre-addressed and pre-prompted so the reader
   writes to a person. Fixed and centred rather than expanding in the column,
   because the column has no room and this is a deliberate stop. */
/* Two things had to be true for this to show on mobile, and both bit in turn:
   1. z-index above the mobile pane (#fhaMobile is fixed at 5000), AND the sheet
      must be a BODY-level child — nested in <main> it is ordered inside <main>'s
      stacking context and loses regardless of its own z-index.
   2. mobile-home.css line 4 is `body > *:not(#fhaMobile) { visibility: hidden
      !important }`, which is the locked template's way of blanking the desktop
      page under the pane. The sheet is a body child, so it inherited that and
      rendered fully laid out, opacity 1, and invisible. It needs its own
      !important exemption, exactly like #fhaMobile has — and that exemption has
      to OUT-SPECIFY it: `body > *:not(#fhaMobile)` scores (1,0,1) because :not()
      carries its argument's id weight, so a bare `.ngSheet` (0,1,0) loses even
      with !important. Only the CHILDREN were winning at first, which is why the
      panel drew but its scrim and backdrop-blur did not. */
body > #ngSheet.ngSheet, body > #ngSheet.ngSheet * { visibility: visible !important; }
.ngSheet { position: fixed; inset: 0; z-index: 5200; display: flex;
  align-items: center; justify-content: center; padding: 24px;
  background: rgba(2,26,40,.62);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .28s ease; }
.ngSheet[hidden] { display: none; }
.ngSheet.open { opacity: 1; }
.ngSheetIn { position: relative; width: min(660px, 100%); max-height: 86vh;
  overflow-y: auto; border-radius: 3px; text-align: left;
  padding: clamp(24px,4vh,40px) clamp(22px,3.4vw,44px);
  background: var(--fha-glass);
  -webkit-backdrop-filter: blur(18px) saturate(1.25); backdrop-filter: blur(18px) saturate(1.25);
  border: 1px solid var(--fha-glass-edge); box-shadow: var(--fha-glass-lift);
  transform: translateY(10px); transition: transform .28s ease; }
.ngSheet.open .ngSheetIn { transform: none; }
.ngSheetIn h4 { margin: 0 0 8px; color: var(--fha-aqua);
  font-family: 'Playfair Display', serif; font-weight: 700; letter-spacing: .1em;
  font-size: clamp(16px,1.5vw,22px); text-shadow: 0 1px 1px rgba(2,44,68,.55); }
.ngSheetIn .note { margin: 0 0 16px; color: var(--fha-pale);
  font-family: 'Raleway', sans-serif; font-weight: 500; line-height: 1.5;
  font-size: clamp(12.5px,.95vw,15px); }
.ngSheetIn .ngTicks { list-style: none; margin: 0; padding: 0;
  color: var(--fha-bright); font-family: 'Raleway', sans-serif; font-weight: 500;
  font-size: clamp(12.5px,.95vw,15px); }
/* the shell's legacy `li` rules draw a rule under every list item — not wanted here */
.ngSheetIn .ngTicks li { position: relative; padding: 6px 0 6px 22px; line-height: 1.45;
  border: 0; background: none; list-style: none; }
.ngSheetIn .ngTicks li::before { content: ''; position: absolute; left: 2px; top: .95em;
  width: 9px; height: 9px; border-radius: 50%;
  background: rgba(162,231,232,.55); box-shadow: 0 1px 1px rgba(2,44,68,.5); }
.ngSheetIn .send { display: inline-flex; align-items: center; gap: 10px;
  margin-top: 20px; padding: 12px 22px; border-radius: 2px; text-decoration: none;
  background: rgba(162,231,232,.14); border: 1px solid rgba(162,231,232,.5);
  color: var(--fha-aqua); font-family: 'Playfair Display', serif; letter-spacing: .14em;
  font-size: clamp(13px,1.05vw,16px);
  transition: background .25s ease, color .25s ease; }
.ngSheetIn .send:hover { background: rgba(162,231,232,.26); color: #fff; }
.ngX { position: absolute; top: 8px; right: 12px; width: 34px; height: 34px;
  -webkit-appearance: none; appearance: none; background: none; border: 0;
  cursor: pointer; color: var(--fha-pale); font-size: 26px; line-height: 1;
  transition: color .2s ease; }
.ngX:hover { color: #fff; }
@media (prefers-reduced-motion: reduce) {
  .ngSheet, .ngSheetIn { transition: none; }
}

/* ---- NEXT GEN on mobile: the same page, in the pane ---------------------- */
#fhaMobile.ngm .ngTitle .t { display: block; text-align: center; color: var(--fha-aqua);
  font-family: 'Coldiac Free', 'Playfair Display', serif; letter-spacing: .04em;
  font-size: 19px; line-height: 1.12; text-shadow: 0 2px 1px rgba(2,44,68,.6); }
#fhaMobile.ngm .ngScript .t { display: block; text-align: center; color: var(--fha-pale);
  font-family: 'Distant Stroke', 'Playfair Display', serif; font-weight: 500;
  font-size: 20px; line-height: 1.2; margin: 2px 0 12px; }
#fhaMobile.ngm .ngm-body .ngWrap { display: block; background: none; border-radius: 2px; }
#fhaMobile.ngm .ngm-body .ngWrap::before { display: none; }
#fhaMobile.ngm .ngm-body .ngSec { padding: 26px 0 0; max-width: none; }
#fhaMobile.ngm .ngm-body .ngRule { margin: 26px 0 0; }
#fhaMobile.ngm .ngm-body h2 { font-size: 24px; }
#fhaMobile.ngm .ngm-body p { font-size: 13.5px; line-height: 1.5; max-width: none; }
#fhaMobile.ngm .ngm-body p.lead { font-size: 15.5px; }
#fhaMobile.ngm .ngm-body .ngSplit { grid-template-columns: 1fr; gap: 20px; }
#fhaMobile.ngm .ngm-body .ngSplit .spine { width: auto; height: 1px; align-self: auto;
  background: linear-gradient(90deg, transparent, rgba(162,231,232,.55), transparent); }
#fhaMobile.ngm .ngm-body .ngSide.r { text-align: left; }
#fhaMobile.ngm .ngm-body .ngSide.r p { margin-left: 0; }
#fhaMobile.ngm .ngm-body .ngSide .who { font-size: 26px; }
#fhaMobile.ngm .ngm-body .ngSide li { font-size: 17px; }
#fhaMobile.ngm .ngm-body .ngPair span { font-size: 13px; letter-spacing: .16em; }
#fhaMobile.ngm .ngm-body .ngResolve .word { font-size: 62px; }
#fhaMobile.ngm .ngm-body .ngQuote { padding: 24px 18px; }
#fhaMobile.ngm .ngm-body .ngQuote q { font-size: 25px; }
#fhaMobile.ngm .ngm-body .ngCols { column-count: 1; }
#fhaMobile.ngm .ngm-body .ngCare .big { font-size: 24px; }
#fhaMobile.ngm .ngm-body .ngBtn { font-size: 14px; padding: 13px 22px; letter-spacing: .14em; }
#fhaMobile.ngm .colInner p.mis { text-align: center; }

/* No max-height tiers are needed any more: the bio is flex:1 inside the scroll
   box, so on a short viewport it simply receives less height and scrolls sooner —
   the title stack and the CTA never give ground. Padding still trims. */
@media (min-width: 992px) and (max-height: 800px) {
  .s3 .s3bio { padding: clamp(8px,1.1vh,12px) 14px; }
}

/* NEXT GEN short-viewport tier. His own browser is ~830px inner (see the mobile
   round's @max-height:860px tier), and at that height the enlarged couplet tipped
   27px past the panel — the one line on the page that must never be scrolled to.
   Everything else gives ground first; the couplet steps down least. */
@media (min-width: 992px) and (max-height: 880px) {
  .ng .s3bio.ngOne { padding: 9px clamp(14px,1.5vw,20px); }
  .ng.theme-teal .banner .banner-detail-container .details .s3bio.ngOne p {
    font-size: clamp(13px, .96vw, 15.5px); line-height: 1.4; margin-bottom: .55em; }
  .ng.theme-teal .banner .banner-detail-container .details .s3bio.ngOne .ngLead {
    font-size: clamp(15px, 1.2vw, 19px); margin-bottom: .5em; line-height: 1.24; }
  .ng.theme-teal .banner .banner-detail-container .details .s3bio.ngOne .ngClose {
    font-size: clamp(17px, 1.44vw, 23px); margin-top: .72em; padding-top: .68em; }
  .ng .ngAsk { margin-top: clamp(7px,1.1vh,11px); }
}

/* ============================ MOBILE PARITY ============================== */
/* 1. The rolling header. Section 2 alternates Fairchild Hair Artistry with
   Service CATALOG; Section 3 alternates it with Artist Portrait, same 6s dwell,
   same mechanism (two faces in .rollCol, -50% at rest). Only the horizontal
   anchor is section-specific, because the two lockups carry their Coldiac word
   in different places:

     HAIR ARTISTRY caps centre           218.8px   (the fixed reference)
     CATALOG caps centre  = 66.43% of its art width
     PORTRAIT caps centre = 50.08% of its art width   <- measured, not assumed

   At the settled 62px: PORTRAIT art = 62 x 3.171 = 196.6px wide, caps centre
   98.4px in, so margin-left = 218.8 - 98.4 = 120.4px. At the 70px entrance the
   offset is 62% of that, 111.1px, expressed from the centre like Section 2's.
   Left edge lands at 120px, clear of the ambigram at 22..87. */
#fhaMobile.s3m .scriptWrap img.secFace,
#fhaMobile.ngm .scriptWrap img.secFace { height: 70px; width: auto;
  margin-left: calc(50% - 111.1px); }
#fhaMobile.s3m.settled .scriptWrap img.secFace,
#fhaMobile.ngm.settled .scriptWrap img.secFace { height: 62px; margin-left: 120.4px; }

/* 2. His name, as wide as the pane allows. The page-title arts in Section 2 are
   single words (MENU, PACKAGES) and fill a 26px box exactly. "STEVEN
   PRIOLA-FAIRCHILD" is 18.5:1, so inside the same 26px box at max-width 76% it
   was letterboxing down to a 12.5px cap band — half the size of PACKAGES. He
   asked for it wider; width is the only lever, since the art is already trimmed
   to its ink and he wants the name on ONE line (round 12).
   At 96% it draws ~16px instead of 12.5. A uniform 26px cap band would need
   481px of screen, which a 390px phone does not have — this is the honest
   ceiling, not a shortfall to fix later. */
#fhaMobile.s3m .ptitle { height: 30px; max-width: 96%; object-fit: contain; }
#fhaMobile.s3m .colInner .cc { padding-left: 6px; padding-right: 6px; }
