/* Vanity Ink: inner pages (v2 flow). Same canvas as Home, nothing is banded; the only boxes left are functional
   (the booking form and the sticky asides), in smoked glass instead of solid grey.
   Heroes sit on their own black base (like Home) so the marble never mixes into the photo: the photo fades into
   solid black, and only the black feathers into the marble, over the bottom --feather. */
.page-hero{position:relative;padding:210px 0 140px;isolation:isolate;--feather:140px;
  background:linear-gradient(180deg,var(--black) 0,var(--black) calc(100% - var(--f-bot,var(--feather))),rgba(6,6,7,0) 100%)}
/* Rhythm (round 3, 09-29, Home's system on every page): a black hero; the river comes up right under it (lifted into
   the hero's fade-out) and runs through the page in flows, outer wrappers around two sections, strongest behind the
   text sections and faint beneath the photo sections; the pre-footer's finale rises out of black at the end.
   Stages no longer paint black, so they use the normal section spacing (the old padding cleared a feather). */
.section.stage{padding:var(--section-y) 0}
/* The flows, page by page (cuts: tools/imagegen/cut_canvas.py; stops tuned at 1440, from the top of the lifted layer).
   Each first flow starts with the soft entry (below). Full behind the text sections, at --m-dim beneath photos
   (10-02, Home's "less dark" pass rolled out: was about 40%, now .72 like Home's Meet, the knob in vanity.css; a first
   step down goes halfway, --m-mid). The underlays (.m-under) read --m-under (was .8 / .85, now .75 of a brighter cut).
   Elementor: outer container, background image top center / 100% auto, a gradient overlay with the same stops. */
/* The soft entry (About, Carlos 09-29: the river "starts too soon" under the hero and the join felt disconnected; on
   every inner page since 09-30): no lift, and a long, eased fade out of black, so the hero goes fully dark first and
   the marble then rises gradually around the first heading. --entry is that ramp (full strength at 380px); each first
   flow continues with its own stops. Elementor: the flow container's gradient overlay starts at solid #060607 and
   eases to transparent by ~380px. */
:root{--entry:transparent 0,rgba(0,0,0,.06) 60px,rgba(0,0,0,.2) 140px,rgba(0,0,0,.46) 220px,rgba(0,0,0,.76) 300px;
  --m-mid:calc((1 + var(--m-dim)) / 2)}
.flow-about{--mlift:0px;--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 890px,rgb(0 0 0/var(--m-mid)) 1030px,rgb(0 0 0/var(--m-dim)) 1230px,rgb(0 0 0/var(--m-dim)) 1580px,transparent 1780px)}
.c-about-people{--mt:180px;--mb:200px}
.flow-artists{--mlift:0px;--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 580px,rgb(0 0 0/var(--m-mid)) 780px,rgb(0 0 0/var(--m-dim)) 1330px,rgb(0 0 0/var(--m-mid)) 1530px,transparent 1787px)}
/* Book (10-05): the river under Tell Us, the form and What Happens Next is its own canvas cut (c-book-under-b, strip
   0-2500 mirrored, a top and a bottom fade baked in), anchored at the section's bottom, so What Happens Next (always the
   last ~500px) sits on the river's left-hand stretch at every width and the cut's baked fade ends it at the seam, where
   the Policies river rises. Was r2 at the top, masked out by 880px: since What Happens Next moved here (10-02) the
   section is 1370px tall and the bottom 490px were black. Elementor: background image bottom center, 100% auto (Mobile
   180%), overlay opacity = --m-under; the entry ramp as before. */
.under-book{--mlift:0px;--mop:var(--m-under);--mpos:center bottom;--mmask:linear-gradient(180deg,var(--entry),#000 380px);--mmask-m:var(--mmask)}
.flow-book{--mmask:linear-gradient(180deg,transparent 0,#000 150px,#000 650px,rgb(0 0 0/var(--m-mid)) 820px,rgb(0 0 0/var(--m-dim)) 1100px,rgb(0 0 0/var(--m-dim)) 1400px,transparent 100%)}
.flow-care{--mlift:0px;--msize:cover;--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 calc(100% - 947px),rgb(0 0 0/var(--m-mid)) calc(100% - 767px),rgb(0 0 0/var(--m-dim)) calc(100% - 547px),rgb(0 0 0/var(--m-dim)) calc(100% - 147px),transparent 100%)}
.flow-heal{--mmask:linear-gradient(180deg,transparent 0,#000 150px,#000 400px,rgb(0 0 0/var(--m-mid)) 560px,rgb(0 0 0/var(--m-dim)) 800px,rgb(0 0 0/var(--m-dim)) 1050px,transparent 100%)}
.under-faq{--mlift:0px;--mop:var(--m-under);--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 500px,rgb(0 0 0/var(--m-mid)) 780px,rgb(0 0 0/var(--m-dim)) 1380px,transparent 1722px)}
.flow-contact{--mlift:0px;--mmask:linear-gradient(180deg,var(--entry),rgb(0 0 0/var(--m-mid)) 360px,rgb(0 0 0/var(--m-dim)) 520px,transparent 100%)} /* 09-30: one section now (Finding the Studio moved under the map), so the river fades out by the wrapper's own end */
/* Jeremy's hero (Carlos 10-06: "too black... literally just a black background and then the white text"; bring some
   of the purple texture back, slightly, not a revamp). A faint river behind the profile: a stretch his page never shows
   (Aftercare's healing cut, mirrored), held dim, eased in under the header and out before the portfolio's own underlay
   rises. Elementor: the hero container's background image (the -b file, top center, 100% auto) with a black gradient
   overlay; or route A, the fades baked into a dedicated file. */
.c-jeremy-hero{--mimg:url(../assets/marble/c-aftercare-time-b.webp);--mpos:center 14%;--mop:.62;--mlift:0px;
  --mmask:linear-gradient(180deg,transparent 0,rgba(0,0,0,.45) 150px,#000 330px,#000 calc(100% - 300px),rgba(0,0,0,.4) calc(100% - 120px),transparent 100%);
  --mmask-m:linear-gradient(180deg,transparent 0,rgba(0,0,0,.5) 120px,#000 260px,#000 calc(100% - 200px),transparent 100%)}
.c-jeremy{--mlift:0px;--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 700px,rgb(0 0 0/var(--m-dim)) 1100px,rgb(0 0 0/var(--m-dim)) calc(100% - 520px),transparent 100%)}
/* Jeremy, 10-01 (Carlos, from the 09-30 meeting: visitors want the work first, the text is mostly for SEO): the
   portfolio moved up under the hero, so it is the page's first flow. A faint underlay (like FAQ's and Book's) eases in
   out of the hero beneath the portfolio heading and the first rows, then fades out; the river then rises again behind
   the text (c-jeremy, unchanged: its entry ramp works after the gallery's black bottom as it did after the hero).
   The fade ends before the image does on desktops and tablets (1800px cut: 960px tall at 1024 wide, 720 at 768), so
   tablets and phones get a shorter fade. On phones the cut shows at 180% since 10-02 (vanity.css): 540px tall on a 320
   phone, 658 on a 390 one, so there the cut's own baked end fade closes it just before the mask does (no line).
   Artist pages (Kain's too) lead with the work. */
.under-jeremy{--mlift:0px;--mop:var(--m-under);--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 520px,rgb(0 0 0/var(--m-dim)) 720px,transparent 900px);
  --mmask-m:linear-gradient(180deg,var(--entry),#000 380px,rgb(0 0 0/var(--m-dim)) 560px,transparent 680px)}
/* hero photo: a .page-hero-img element with an inline background-image (a url() inside a custom property resolves
   against the stylesheet in Chrome, which broke the paths). It stops where the feather starts.
   Elementor: container background (black → transparent gradient) + inner container with the image, overlay and a gradient mask. */
.page-hero-img{position:absolute;inset:0 0 var(--feather);z-index:-2;background-position:center 35%;background-size:cover;background-repeat:no-repeat;opacity:.85;
  -webkit-mask-image:linear-gradient(180deg,#000 45%,transparent 100%);mask-image:linear-gradient(180deg,#000 45%,transparent 100%)}
.page-hero-img.hero-hand{background-size:auto 100%;background-position:right center}
/* A tall inner hero (About, Carlos 09-29: on a laptop the short, dark hero plus the black under it read as "empty and
   weird"). It fills the first screen, so the room itself is the visual: lighter, dark only behind the text, the floor
   and the front desk's honeycomb visible, ending in solid black; the page's river then rises below the fold.
   Elementor: container min-height 100vh, background image + gradient overlays (left for the text, bottom to black). */
.page-hero.tall{min-height:min(100svh,1000px);--feather:0px}
/* the honeycomb in About's hero (Carlos 09-29, final after 12 rounds): honeycomb-about.svg, the sweep ("how it goes
   sideways down") with only its main cluster (no faint strays) and three small grouped clusters where Carlos marked
   them: one above and right of the band, stretched sideways, two just under its left end; 09-30 ("fill the gaps"): the
   gaps between the band and those groups are filled with slightly fainter cells, so it reads as one piece of wall
   stencil. It bleeds off the left edge just under the button, slopes gently
   down to the right and thins out by about a third of the page, crossing the hero's bottom into the black below. Nothing
   clips it (the hero doesn't crop overflow), so it fades on every side; the next section's marble covers its tail.
   09-30: the same sweep on every tall inner hero (About, Artists, Book, Aftercare, FAQ, Contact): each has the same empty
   black under its text, which is the corner the sweep fills on About. It now hangs from the text block (inside the
   container) instead of a fixed 560px, so it clears the words however tall they run: 22px above the button's bottom,
   exactly where About's sat. Left edge 80px past the viewport; behind the text (z-index -1 in the container).
   Elementor: an Image widget (the SVG) inside the hero's text container, Position Absolute, top 100% - 22px. */
.page-hero .container>.hex-sweep{left:calc(50% - 50vw - 80px);top:calc(100% - 22px);z-index:-1;--hex-w:min(70vw,1060px);--hex-op:.45}
/* 09-30, later: hidden on every inner hero, About included (Carlos: "still not fully satisfied with its placement", to be
   worked out in a separate session). The markup and the rule above stay, so deleting this one line brings it back.
   On FAQ it had also run down behind the side menu. The footer badge's halo is unaffected. */
.page-hero .hex-sweep{display:none}
.page-hero.tall .page-hero-img{inset:0;opacity:1;background-position:center 60%;-webkit-mask-image:none;mask-image:none}
/* 09-30, the tall hero on every inner page with a photo (Carlos: "the same issue will persist"), each photo placed so
   its subject sits right of the text. Where the photo is busy behind the text (a portrait, the studio's floor, the
   machine's needle), it becomes a panel down the right side (.side) that fades in from the black under the text.
   Artists: the portrait in black and white (like every artist portrait), cropped in on the honeycomb scalp.
   Elementor: a second inner container, width 58%, right aligned, with the image and a left-to-right gradient mask. */
.page-hero.tall .page-hero-img.side{left:auto;width:min(58%,880px);
  -webkit-mask-image:linear-gradient(90deg,transparent 0,rgba(0,0,0,.55) 22%,#000 46%);mask-image:linear-gradient(90deg,transparent 0,rgba(0,0,0,.55) 22%,#000 46%)}
.page-hero.tall .page-hero-img.hero-artist{background-size:128% auto;background-position:0 24%;filter:contrast(1.08) brightness(.78)}
.page-hero.tall .page-hero-img.hero-contact{background-position:75% 60%}
.page-hero.tall .page-hero-img.hero-faq{background-position:right 58%}
.page-hero.tall .page-hero-img.hero-hand{background-size:auto 100%;background-position:right top}
.page-hero.tall .page-hero-img.hero-care{background-position:center 72%}
/* 10-01 trial (Carlos: inner heroes like Aftercare's and FAQ's): About, Artists, Book and Contact get generated still
   lifes on dark marble, probes until the finals, each in a right-hand panel like FAQ's. Desktop: the image is sized
   by the panel's width (a little shorter than the hero) and anchored bottom right, so it sits under the H1 and clear
   of the subhead. Each export eases its top 14% into #060607 (the panel's top edge never shows) and is tone-matched
   to FAQ's level. Tablets and phones: exactly like FAQ's (Cover and a position). Elementor: the side panel's
   background image; Desktop Display Size Custom (the widths below), Position Bottom Right; Tablet and Mobile Cover. */
.page-hero.tall .page-hero-img.hero-mirror,.page-hero.tall .page-hero-img.hero-kit,.page-hero.tall .page-hero-img.hero-sketch,.page-hero.tall .page-hero-img.hero-letter{background-position:right 58%}
@media (min-width:1024px){
  .page-hero.tall .page-hero-img.hero-mirror,.page-hero.tall .page-hero-img.hero-kit{background-size:132% auto;background-position:right bottom}
  .page-hero.tall .page-hero-img.hero-sketch{background-size:129% auto;background-position:right bottom}
  .page-hero.tall .page-hero-img.hero-letter{background-size:135% auto;background-position:right bottom}
}
/* from 1600 the panel stops growing (880px), so a width-based size would shrink the still life against a taller hero;
   here its height follows the hero instead (checked at 1600x900, 1680x1050, 1728x1117, 1920x1080). Elementor: not a
   native control; one line of custom CSS, or the native fallback: a custom breakpoint at 1600 with Custom about 150%. */
@media (min-width:1600px){
  .page-hero.tall .page-hero-img.hero-mirror,.page-hero.tall .page-hero-img.hero-kit,.page-hero.tall .page-hero-img.hero-sketch,.page-hero.tall .page-hero-img.hero-letter{background-size:auto 96%}
}
.page-hero.has-img::before{content:"";position:absolute;inset:0 0 var(--feather);z-index:-1;pointer-events:none;
  background:linear-gradient(90deg,rgba(6,6,7,.88) 20%,rgba(6,6,7,.35) 85%),linear-gradient(180deg,rgba(6,6,7,.55),rgba(6,6,7,0) 55%)}
.page-hero.tall.has-img::before{inset:0;background:
  linear-gradient(90deg,rgba(6,6,7,.9) 0%,rgba(6,6,7,.74) 32%,rgba(6,6,7,.28) 62%,rgba(6,6,7,.14) 100%),
  linear-gradient(180deg,rgba(6,6,7,.62) 0%,rgba(6,6,7,0) 28%,rgba(6,6,7,0) 60%,rgba(6,6,7,.78) 86%,var(--black) 100%)}
.page-hero .tex-hex{right:-140px;top:-80px;width:620px;opacity:.1}
.page-hero .container{position:relative;z-index:2}
.crumbs{display:none}
.page-hero h1{max-width:860px;margin-bottom:28px}
.page-hero .sub{max-width:640px;font-size:var(--body);color:var(--text-muted);text-wrap:pretty}
.page-hero .actions{margin-top:36px;display:flex;gap:16px;flex-wrap:wrap}
/* Contact's hero (10-02): the button, then the phone link under it, the stacked actions of Home's artists. On tablets
   and phones the button hides (the booking bar is there), so the phone link alone follows the subhead.
   Elementor: Button (hidden on Tablet and Mobile), then an Icon List item, in a column container, gap 14. */
.page-hero .actions.stacked{flex-direction:column;align-items:flex-start;gap:14px}
/* smoked glass for the boxes that stay */
.glass,.form-wrap,.aside .card,.note-box{background:rgba(14,13,17,.66);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border:1px solid var(--line-soft)}
/* prose block */
.prose{max-width:680px}
.prose h2{margin-bottom:18px}
.prose h3{font-size:var(--h3-sm);margin:28px 0 10px;color:var(--text)}
.prose p{text-wrap:pretty}
.prose ul.list{display:flex;flex-direction:column;gap:12px;margin:8px 0 20px}
.prose ul.list li{display:grid;grid-template-columns:18px 1fr;gap:14px;align-items:start}
.prose ul.list li::before{content:"";width:6px;height:6px;margin:10px 0 0 4px;background:var(--purple);transform:rotate(45deg)}
.prose ul.list b{color:var(--text);font-weight:600}
/* story rows (About, Book): text beside a photo that melts at its outer edge */
.story{display:grid;grid-template-columns:1fr 1fr;gap:72px;align-items:center}
.story.rev .txt{order:2}
.story .txt{max-width:520px;position:relative;isolation:isolate}
.story .txt::before{content:"";position:absolute;inset:-14% -12%;z-index:-1;background:radial-gradient(closest-side,rgba(6,6,7,.9),rgba(6,6,7,.75) 55%,rgba(6,6,7,0))}
.story.rev .txt{margin-left:auto}
.story .ph,.story .shot{aspect-ratio:4/5;width:100%;max-width:520px}
.story:not(.rev) .shot,.story:not(.rev) .ph{justify-self:end}
.story+.story{margin-top:var(--section-y)}
.story .txt p{text-wrap:pretty}
/* Aftercare, Questions and Touch-Ups: the healed tattoo large, the same piece fresh as an inset over its corner (Home's
   cover-up pattern, no captions). Elementor: two Image widgets; the inset Position Absolute + offsets, z-index, shadow. */
.heal-pair{position:relative;width:min(100%,440px);margin-right:110px}
.story .heal-pair .shot{max-width:none}
.heal-pair .heal-before{position:absolute;right:-110px;bottom:-56px;width:clamp(150px,13vw,200px);z-index:3;box-shadow:0 0 50px #000}
.heal-pair .heal-before::before{border-color:rgba(200,200,204,.35)}
/* About, A Place to Spend a Few Hours (the shared studio section, site.css; 10-02 late: a registered bleed): the words
   left (Time for the Drawing before it is photo-left), the photo right, out to the right edge, its top edge on the
   H2's cap line, ending inside the section. Its river (c-about-studio: strip 6300-8100, tools/imagegen/cut_studio.py)
   picks up where the Name and Drawing river leaves off. */
.about-studio{--mimg:url(../assets/marble/c-about-studio.webp);--s-pos:100% 50%}
@media (min-width:768px){.about-studio{--s-up:220px;--s-in:320px;--s-out:280px}}
/* 48px under the photo: The People Behind the Work's portraits start high on the same side, so without the old hang
   the two photos would sit 87px apart; now 135px. People's own river rises across the seam, so this one needs no
   tail. */
@media (min-width:1024px){.about-studio{--s-pb:48px;--s-shade:73% 50%}}
/* team strip */
.team-strip{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center}
.team-strip .row{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.team-strip .row.two{grid-template-columns:repeat(2,1fr);gap:16px}
.team-strip .row .ph,.team-strip .row .shot{aspect-ratio:4/5}
.team-strip .row>:first-child{margin-top:48px}
/* two column with sticky aside */
.two-col{display:grid;grid-template-columns:minmax(0,1fr) 380px;gap:80px;align-items:start}
.aside{position:sticky;top:110px;display:flex;flex-direction:column;gap:24px}
.aside .card{padding:28px}
.aside .card h4,.aside .card .card-h{font-family:var(--sans);font-weight:600;font-size:11px;line-height:1.4;letter-spacing:.22em;text-transform:uppercase;color:var(--purple-light);margin:0 0 16px;background:none;-webkit-text-fill-color:currentColor;filter:none}
.aside .card p{font-size:var(--body-sm)}
.aside .card ul{display:flex;flex-direction:column;gap:10px;font-size:var(--body-sm)}
.aside .card li{display:flex;gap:12px;align-items:flex-start}
.aside .card li svg{width:16px;height:16px;flex:none;color:var(--purple-light);margin-top:4px}
.aside .card .btn{width:100%;margin-top:6px}
.aside .card .tok{color:var(--text)}
.aside .card .n{font:400 30px/1 var(--display);color:var(--text);display:block;margin-bottom:6px}
/* sections stack */
.stack>section{padding:var(--section-y) 0;border-top:1px solid var(--line-soft)}
.stack>section:first-child{border-top:0;padding-top:0}
/* artist profile (Jeremy) */
.profile{display:grid;grid-template-columns:440px minmax(0,1fr);gap:72px;align-items:end}
.profile .ph,.profile .shot{aspect-ratio:4/5}
.styles-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--card-gap);margin:32px 0}
.style-tile{display:flex;flex-direction:column;gap:14px}
.style-tile .ph,.style-tile .shot{aspect-ratio:1/1;border:0}
.style-tile span{font:400 15px/1.3 var(--display);text-transform:uppercase;letter-spacing:.08em;color:var(--text)}
.gallery{display:grid;grid-template-columns:repeat(4,1fr);grid-auto-rows:220px;grid-auto-flow:dense;gap:12px;margin-top:40px}
.gallery .ph,.gallery .shot{aspect-ratio:auto;height:100%}
.gallery .tall{grid-row:span 2}.gallery .wide{grid-column:span 2}
.gallery-note{margin-top:20px;font-size:14px}
/* artists page */
.guest-sec{padding:96px 0}
.guest{display:flex;flex-direction:column;align-items:center;text-align:center;max-width:620px;margin:0 auto}
.guest .eyebrow{margin-bottom:14px}
.guest h2{font-size:var(--h2-sm);margin-bottom:14px}
.guest p{font-size:var(--body-sm);text-wrap:pretty;margin:0}
/* book form */
.form{display:grid;grid-template-columns:1fr 1fr;gap:20px 24px}
.form .full{grid-column:1/-1}
.field{display:flex;flex-direction:column;gap:8px}
.field label{font:500 11px/1 var(--sans);letter-spacing:.2em;text-transform:uppercase;color:var(--text)}
.field label em{font-style:normal;color:var(--purple-light);margin-left:4px}
.field input,.field select,.field textarea{width:100%;background:rgba(6,6,7,.8);border:1px solid var(--line);color:var(--text);font:400 15px/1.5 var(--sans);padding:14px 16px;transition:border-color .2s;-webkit-appearance:none;appearance:none;border-radius:0}
.field input:focus,.field select:focus,.field textarea:focus{outline:0;border-color:var(--purple)}
.field ::placeholder{color:#86868C;opacity:1}
.field textarea{min-height:140px;resize:vertical}
.field select{background-image:linear-gradient(45deg,transparent 50%,var(--text-muted) 50%),linear-gradient(135deg,var(--text-muted) 50%,transparent 50%);background-position:calc(100% - 20px) 50%,calc(100% - 15px) 50%;background-size:5px 5px;background-repeat:no-repeat;padding-right:44px}
.field .hint{font-size:13px;color:var(--text-muted)}
.drop{border:1px dashed var(--line);padding:28px;text-align:center;font-size:14px;color:var(--text-muted);background:rgba(6,6,7,.8)}
.drop b{display:block;color:var(--text);font-weight:500;margin-bottom:4px}
.form-foot{grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;gap:20px 32px;margin-top:8px}
.form-foot .btn{border-color:var(--purple);background:var(--purple);color:#fff}
.form-foot .btn:hover{background:var(--purple-dark);border-color:var(--purple-dark)}
.form-foot .dep{font-size:14px;color:var(--text-muted);max-width:480px}
.form-foot .dep b{color:var(--text);font-weight:600}
.form-wrap{padding:48px}
.form-wrap h2{font-size:var(--h2-sm);margin-bottom:8px}
.form-wrap .lead{margin-bottom:36px;font-size:var(--body-sm)}
.consent{display:flex;gap:12px;align-items:flex-start;font-size:14px;color:var(--text-muted)}
.consent input{width:18px;height:18px;margin-top:3px;accent-color:var(--purple);flex:none;padding:0}
/* Book's request (09-30, Carlos: "simplify it to how it looks on the old site", keep our styling): the old Schedule form's
   fields (name, phone, email, a deposit checkbox) plus one box for the idea, because the copy asks people to include the
   details with their request. What to include sits on the left as plain text, beside the box it describes; the short
   form is on the right in its glass card. The hero's button jumps to the form (#request).
   10-02 (Carlos, on What Happens Next spread under both columns: "the text to the right is offset and it just looks
   weird"): it moves into the left column, under Tell Us About the Tattoo and its list, at the same width, after the
   policy cards' hairline. On desktop the form card is sticky, 110px down like Jeremy's aside, so the right column never
   reads empty while the left one runs on; it lets go where What Happens Next ends. Only in a window at least 810px
   tall, so Send Request (795px down while the card is stuck) is never held below the fold; under 844px the card's
   bottom padding runs just past it. Shorter laptop windows (768, 720 tall) keep the card in place. Tablets and phones: one column, Tell Us, the form, then What Happens Next (after the form it
   reads as "after you send it").
   Elementor (build spec 6.6): a Grid container, 2 columns (1fr 560px), the form's container spanning 2 rows, so What
   Happens Next falls under Tell Us; the form's container Sticky Top, offset 110, Desktop, Stay In Column. Tablet and
   Mobile: 1 column, in source order. */
.book-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,560px);grid-template-areas:"guide form" "next form";column-gap:88px;align-items:start}
.book-guide{grid-area:guide}
.guide-list{display:flex;flex-direction:column;gap:14px;margin-top:22px}
.guide-list li{display:flex;gap:12px;align-items:flex-start}
.guide-list li svg{width:16px;height:16px;flex:none;color:var(--purple-light);margin-top:5px}
.guide-list b{color:var(--text);font-weight:600}
.book-guide .guide-foot{margin-top:22px}
.book-form{grid-area:form;scroll-margin-top:110px}
@media (min-width:1024px) and (min-height:810px){
  .book-form{position:sticky;top:110px}
}
.req{color:var(--purple-light);font-style:normal}
.book-next{grid-area:next;position:relative;margin-top:64px;padding-top:56px}
.book-next::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:linear-gradient(90deg,rgba(200,200,204,.55),rgba(136,88,184,.35) 45%,transparent 85%)}
.book-next p{text-wrap:pretty}
/* What Happens Next as steps (10-06; the 09-30 call, Carlos: "That'd be cool"): the copy's two paragraphs, word for word,
   split at their own sentence breaks into four steps (the consultation; the deposit once the date is set; the drawing
   and the check-in; the design on the day) on the house light trail, as on Home's process and Aftercare's routine: a 1px
   line down the left edge, a hexagon marker on it level with each step's first line, the step's numeral in Cinzel violet
   beside the marker, the words to the right (about 516px wide at 1512). No cards, no headings, no eyebrow; the numerals
   are design labels, drawn by CSS (a counter) so the copy reads exactly as written. The line is static (beside the sticky
   form a draw would be a second moving thing). Under 1200px: the numeral above its words (below).
   Elementor: a column container (gap 40, 32 under 1200; 32 under the H2), per step a row container (left: an Image widget with
   hex-node.svg, 24px, and a Heading widget, tag p, the numeral in Cinzel 500 26px #A98AD6; right: Text Editor with the
   sentences); the line a 1px container, Position Absolute, left 11.5, top 14, bottom 0, background gradient
   #A98AD6 to transparent (the Divider widget is horizontal, so not a Divider). Not an Icon List (no numerals, no line). */
.next-steps{--ns-x:12px;--ns-in:76px;--ns-lh:calc(var(--body) * 1.7);position:relative;display:flex;flex-direction:column;gap:40px;margin-top:32px;counter-reset:step}
.next-steps::before{content:"";position:absolute;left:calc(var(--ns-x) - .5px);top:calc(var(--ns-lh) / 2);bottom:0;width:1px;opacity:.85;pointer-events:none;
  background:linear-gradient(180deg,#A98AD6,#EFD6CB 45%,#8858B8 85%,rgba(136,88,184,0))}
.next-steps li{position:relative;padding-left:var(--ns-in);counter-increment:step}
.next-steps li::before{content:counter(step);position:absolute;left:42px;top:0;font:500 26px/var(--ns-lh) var(--display);color:var(--purple-light)}
.next-steps li::after{content:"";position:absolute;left:calc(var(--ns-x) - 12px);top:calc((var(--ns-lh) - 24px) / 2);z-index:1;width:24px;height:24px;
  background:url(../assets/brand/hex-node.svg) center/contain no-repeat}
/* under 1200 (the left column is 328px at 1024; tablets and phones): the numeral above its words, its marker level with
   it, the line 5.5px in and the words 34px in, as on Aftercare's phone routine. Elementor: Tablet and Mobile (its Tablet
   breakpoint already covers 1024), the step's row container set to Column; 1025 to 1199 can keep the row. */
@media (max-width:1199px){
  .next-steps{--ns-x:5.5px;--ns-in:34px;gap:32px;margin-top:28px}
  .next-steps::before{top:13px}
  .next-steps li::before{position:static;display:block;margin-bottom:6px;font-size:24px;line-height:26px}
  .next-steps li::after{top:1px}
}
/* 10-06 (later), Carlos: the dots on the line sat "too close together in two and three" and the numbered look felt odd.
   Now three steps (the deposit sentence back in step 1), the Cinzel numeral alone at the left of each step, no line and
   no markers. Elementor: a row container per step, a Heading (the numeral) + Text Editor; no absolute line. */
.next-steps{--ns-in:52px}
.next-steps::before,.next-steps li::after{display:none}
.next-steps li::before{left:0}
@media (max-width:1199px){.next-steps{--ns-in:0}}

/* policies: three unboxed columns under a hairline each, like Home's "What You Can Expect" rows (no cards) */
.policy{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:56px}
.policy .card{position:relative;padding:36px 0 0;display:flex;flex-direction:column;gap:12px}
.policy .card::before{content:"";position:absolute;left:0;right:0;top:0;height:1px;background:linear-gradient(90deg,rgba(200,200,204,.55),rgba(136,88,184,.35) 45%,transparent 85%)}
.policy .card .n{font:400 34px/1.15 var(--display);background-image:var(--chrome);background-size:100% 1lh;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.policy .card h3{font-size:var(--h3-sm)}
.policy .card p{font-size:var(--body-sm)}
/* Aftercare routine, vertical (10-01; the 09-30 meeting: the three columns read text-heavy, "a vertical layout with
   large step numbers or week labels to the left" that scans at a glance; Carlos 10-01: numbers like Healing Takes Time,
   "to the side of these sections/steps"). Each stage is a row: its label on the left, set in the Healing stat's recipe
   (the figure large in chrome, the words small in violet; the same words as before), its heading and copy on the right,
   in the same column as Healing Takes Time's text. Home's light trail runs down the left edge, a hexagon marker level
   with each figure, and draws itself as you read down; on desktop each label (with its marker) stays in view while its
   stage scrolls past. Tablets keep the rows with the line static; phones keep today's layout (below).
   Elementor: a column container with a two-column container per stage (left: a container with the label, a Heading
   widget, tag p, the small words in spans as on the stat, and the marker, the hexagon SVG in an Image widget, Position
   Absolute; right: Heading h2, Heading h3, Text Editor); the line is a 1px absolute container with a 2-stop gradient;
   the draw is a little CSS (7.5). */
.timeline{--tl-x:12px;--tl-in:64px;--when-size:clamp(56px,5.4vw,80px);--tl-h2:30px;
  /* the label's cap top level with the heading's (Cinzel caps: .089em under a 1.0 line box, .164em under the h2's 1.15) */
  --tl-lift:calc(var(--tl-h2) * .164 - var(--when-size) * .089);
  /* each marker level with the middle of its figure (cap middle .447em down a 1.0 line box) */
  --tl-m:calc(var(--tl-lift) + var(--when-size) * .447 - 12px);
  position:relative;display:flex;flex-direction:column;gap:120px;view-timeline:--trail block}
/* the line, from the first marker down past the last stage, fading out at its end */
.timeline::before{content:"";position:absolute;left:calc(var(--tl-x) - .5px);top:calc(var(--tl-m) + 12px);bottom:0;width:1px;opacity:.85;transform-origin:top;
  background:linear-gradient(180deg,#A98AD6,#EFD6CB 45%,#8858B8 85%,rgba(136,88,184,0))}
.tl{position:relative;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);column-gap:64px;align-items:start}
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference) and (min-width:1024px){
    /* the tip stays about 70% down the screen: it starts when the routine's top reaches that point and ends when its
       bottom does, so each marker is reached as its stage comes up */
    .timeline::before{animation:trail-draw linear both;animation-timeline:--trail;animation-range:cover 30vh exit 30vh}
  }
}
@keyframes trail-draw{from{transform:scaleY(0)}to{transform:scaleY(1)}}
/* the label: the stat's figure (.stat .num) at this size; "to" and the small words fall into Cinzel's small caps */
.tl-when{position:relative;isolation:isolate;justify-self:start;padding-left:var(--tl-in)}
.tl .when{margin:var(--tl-lift) 0 0;white-space:nowrap;font:400 var(--when-size)/1 var(--display);letter-spacing:.02em;
  background-image:var(--chrome);background-size:100% 1lh;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.tl .when .unit{font-size:.36em;letter-spacing:.06em;text-transform:lowercase;color:var(--purple-light);-webkit-text-fill-color:var(--purple-light)}
/* the routine's markers: the same hexagon as Home's process (09-30), centred on the line; each rides with its label */
.tl-when::after{content:"";position:absolute;left:calc(var(--tl-x) - 12px);top:var(--tl-m);z-index:1;width:24px;height:24px;
  background:url(../assets/brand/hex-node.svg) center/contain no-repeat}
/* soft ink pools behind the label and behind the copy (as behind Home's process steps), so nothing sits on bright marble */
.tl-when::before,.tl-body::before{content:"";position:absolute;z-index:-1;pointer-events:none;background:radial-gradient(closest-side,rgba(6,6,7,.86),rgba(6,6,7,0))}
.tl-when::before{inset:-70% -16% -70% calc(var(--tl-in) * .5)}
.tl-body{position:relative;isolation:isolate}
.tl-body::before{inset:-6% -12%;background:radial-gradient(closest-side,rgba(6,6,7,.88),rgba(6,6,7,0))}
.tl h2{font-size:var(--tl-h2);margin-bottom:22px}
.tl h3{margin:30px 0 10px;color:var(--text);font-family:var(--sans);font-weight:600;letter-spacing:.06em;font-size:13px;line-height:1.5}
.tl p{font-size:var(--body-sm);text-wrap:pretty}
/* desktop: each label stays in view while its stage scrolls past, 110px from the top like Jeremy's aside and the FAQ
   links, its marker travelling down the line with it, and lets go at the end of its own row.
   Elementor: the label's container, Motion Effects > Sticky Top, offset 110, Stay In Column, desktop only. */
@media (min-width:1024px){
  .tl-when{position:sticky;top:110px}
}
.avoid{display:grid;grid-template-columns:1fr 1fr;gap:72px;align-items:center}
.avoid ul{display:flex;flex-direction:column}
.avoid li{display:grid;grid-template-columns:24px 1fr;gap:16px;padding:18px 0;border-bottom:1px solid var(--line-soft);color:var(--text)}
.avoid li:first-child{border-top:1px solid var(--line-soft)}
.avoid li svg{width:18px;height:18px;color:var(--purple-light);margin-top:3px}
.avoid .ph,.avoid .shot{aspect-ratio:4/5;max-width:480px;justify-self:end}
.big-stat{display:grid;grid-template-columns:1fr 1fr;gap:64px;align-items:center}
/* Healing Takes Time (09-30; Carlos: "2 to 3" over a small caps line read like a stray number with an eyebrow): two
   facts that explain themselves, the unit on the number's line (smaller, inside the chrome) and a plain caption under
   it, the second fact smaller. The column still balances the heading and text on the right. The time units are violet
   (taste-skill pass, 09-30: the section was the only one on the page without the accent; violet marks time on this
   page, like the routine's "Week 1" labels); "up to" stays chrome.
   Elementor: two Heading widgets (the unit in a <span> with the smaller size) + Text Editor captions. */
.stats{display:flex;flex-direction:column;gap:40px}
.stat{margin:0;display:flex;flex-direction:column;gap:12px}
.stat .num{display:block;font:400 104px/1.05 var(--display);letter-spacing:.02em;background-image:var(--chrome);background-size:100% 1lh;-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.stat .unit{font-size:.36em;letter-spacing:.06em;color:var(--purple-light);-webkit-text-fill-color:var(--purple-light)}
.stat .unit.pre{-webkit-text-fill-color:transparent}
.stat.sm .num{font-size:62px}
.stat .cap{font:400 16px/1.5 var(--sans);color:var(--text-muted)}
/* FAQ */
.faq-grid{display:grid;grid-template-columns:260px minmax(0,1fr);gap:80px;align-items:start}
.faq-nav{position:sticky;top:110px;display:flex;flex-direction:column;gap:4px}
.faq-nav a{font:500 12px/1 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--text-muted);padding:12px 0 12px 16px;border-left:1px solid var(--line)}
.faq-nav a:hover,.faq-nav a.on{color:var(--text);border-left-color:var(--purple)}
.faq-group-title{font:600 14px/1.15 var(--sans);letter-spacing:.24em;text-transform:uppercase;color:var(--purple-light);margin:0 0 8px}
.faq-group+.faq-group{margin-top:56px}
/* in-page links (side nav, deep links to a question) land below the fixed header */
.faq-group,.faq .acc-item{scroll-margin-top:120px}
.faq .acc-btn{grid-template-columns:1fr 30px;padding:24px 0}
/* questions are H2 (per the copy) but read as quiet sans text, not chrome display type */
.faq .acc-h{margin:0;font:500 19px/1.4 var(--sans);text-transform:none;letter-spacing:0;color:var(--text);background:none;-webkit-text-fill-color:currentColor;filter:none}
.faq .acc-panel{padding:0 46px 28px 0}
.faq .acc-panel p{font-size:var(--body-sm)}
.faq .acc-item,.faq .acc{border-color:var(--line-soft)}
/* contact */
.contact{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.2fr);gap:64px;align-items:stretch}
/* 09-30 (Carlos: the details felt heavier than the map, and Finding the Studio's lone link repeated the map): Finding
   the Studio sits under the map in the right column (still an H2, set smaller), its "Map to" link is gone (the map
   and Get Directions cover it), and the map fills whatever height is left so the two columns end together. When Jeremy sends
   the parking and entrance note (#13), it shows here. Elementor: the right column is a container with the Google
   Maps widget, a Heading and a Text Editor. */
.contact-side{display:flex;flex-direction:column}
.contact-side .map-frame{aspect-ratio:auto;flex:1;min-height:320px}
.contact-finding{margin-top:40px;max-width:600px}
.contact-finding h2{font-size:var(--h2-sm);margin-bottom:14px}
.contact-finding p{text-wrap:pretty}
/* Contact's details: the block Home's Visit shares (site.css, "the visit details", 10-02 late; the meeting's "contact
   info card as a table", now one table on both pages, without Instagram) */
.note-box{padding:24px 28px;font-size:var(--body-sm);margin-top:32px}
.note-box b{color:var(--text);font-weight:600}
/* inner-page pre-footer: unboxed, straight on the canvas (no band, no border) */
.cta-strip{padding:calc(var(--section-y) + 24px) 0}
.cta-strip,.cta-strip.on-band{background:none;border:0}
.strip{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:32px 72px;align-items:center;position:relative;isolation:isolate}
.strip::before{content:"";position:absolute;inset:-30% -8%;z-index:-1;background:radial-gradient(closest-side,rgba(6,6,7,.88),rgba(6,6,7,0))}
.strip h2{max-width:680px}
.strip p{margin:0;max-width:560px;text-wrap:pretty}
.strip .btn{padding:16px 32px}
/* 10-02: the inner pages keep their own ending (Carlos, after they briefly ended like Home: "it feels almost a bit too
   similar... I kind of liked how our last section on the inner pages was different than the Home"). The logo's
   separator marks the threshold instead of sitting under a heading: centred on the strip's top seam, the section break
   between the page's body and its closing strip, where the finale starts to rise out of black. Home keeps it under its
   centred heading. The button has the phone link under it (.cta-actions, .call-link: site.css).
   Elementor: an Image widget, the pre-footer container's first child: Position Absolute, Top 0, Left 50%, Transform
   Offset X -50% / Y -50%, Z-Index 1, width 360 / 300 / 240. */
.cta-strip .seam{position:absolute;left:50%;top:0;z-index:1;width:360px;margin:0;transform:translate(-50%,-50%)}
/* generic center CTA inside pages */
.inline-cta{text-align:center;max-width:640px;margin:0 auto}
.inline-cta p{margin:16px auto 32px;text-wrap:pretty}

@media (max-width:1023px){
  .page-hero{padding:150px 0 96px;--feather:96px}
  .two-col{grid-template-columns:1fr;gap:48px}
  /* Book: one column, Tell Us, the form, then What Happens Next */
  .book-grid{grid-template-columns:minmax(0,1fr);grid-template-areas:"guide" "form" "next";row-gap:56px}
  .cta-strip .seam{width:300px}
  .book-next{margin-top:24px;padding-top:48px}
  .aside{position:static}
  .profile{grid-template-columns:1fr;gap:40px}
  .profile .ph,.profile .shot{max-width:420px}
  .gallery{grid-template-columns:repeat(3,1fr);grid-auto-rows:200px}
  .under-jeremy{--mmask:var(--mmask-m)}
  .faq-grid{grid-template-columns:1fr;gap:40px}
  .faq-nav{position:static;flex-direction:row;flex-wrap:wrap;gap:8px 20px}
  .faq-nav a{border-left:0;padding:8px 0;border-bottom:1px solid transparent}
  .faq-nav a.on{border-bottom-color:var(--purple)}
  .contact{grid-template-columns:1fr;gap:40px}
  .contact-side .map-frame{flex:none;min-height:0;aspect-ratio:16/11}
  /* tablets: the same rows, a narrower label column and smaller figures; the line static */
  .timeline{--tl-in:48px;--when-size:clamp(40px,5.2vw,50px);--tl-h2:24px;gap:88px}
  .tl{grid-template-columns:minmax(0,1fr) minmax(0,2fr);column-gap:40px}
  .policy{gap:40px}
  .policy{grid-template-columns:1fr}
  .story,.team-strip,.avoid,.big-stat{gap:40px}
  .stat .num{font-size:76px}
  .stat.sm .num{font-size:48px}
}
@media (max-width:767px){
  .page-hero{padding:130px 0 80px;--feather:80px}
  /* phones keep today's routine (Carlos 10-01: mobile was "already solid"): the small violet caps label above the
     heading, the line 5px in and the text 34px in, 15px copy and the old spacing (the stage was a 16px-gap column).
     Elementor: a second, phone-only Heading widget for the small label; the figure's widget hidden on mobile. */
  .timeline{--tl-x:5.5px;--tl-in:34px;--tl-h2:24px;--tl-m:-2.5px;gap:44px}
  .tl{display:block;padding-left:var(--tl-in)}
  .tl-when{width:fit-content;padding-left:0;margin-bottom:16px}
  .tl-when::before{display:none}
  .tl-when::after{left:calc(var(--tl-x) - 12px - var(--tl-in))}
  .tl .when{margin:0;font:500 11px/1 var(--sans);letter-spacing:.22em;text-transform:uppercase;color:var(--purple-light);
    background:none;-webkit-text-fill-color:var(--purple-light)}
  .tl .when .unit{font-size:1em;letter-spacing:inherit;text-transform:inherit}
  .tl-body{display:flex;flex-direction:column;gap:16px}
  .tl h2{margin-bottom:24px}
  .tl h3{margin:8px 0 0;line-height:1.15}
  /* the tall hero on a phone: the text runs full width, so the top half stays dark and the floor shows below it */
  .page-hero.tall{padding-bottom:0}
  .page-hero.tall .page-hero-img{background-position:38% 72%}
  .page-hero.tall .page-hero-img.side{left:0;width:auto;-webkit-mask-image:none;mask-image:none}
  .page-hero.tall .page-hero-img.hero-artist{background-size:cover;background-position:30% 30%}
  .page-hero.tall .page-hero-img.hero-hand{background-size:cover;background-position:62% 30%}
  .page-hero.tall .page-hero-img.hero-care{background-position:78% 70%}
  .page-hero.tall .page-hero-img.hero-faq{background-position:72% 60%}
  .page-hero.tall .page-hero-img.hero-contact{background-position:70% 70%}
  .page-hero.tall .page-hero-img.hero-mirror{background-position:80% 50%}
  .page-hero.tall .page-hero-img.hero-kit{background-position:88% 50%}
  .page-hero.tall .page-hero-img.hero-sketch{background-position:76% 50%}
  .page-hero.tall .page-hero-img.hero-letter{background-position:76% 50%}
  .page-hero.tall.has-img::before{background:linear-gradient(180deg,rgba(6,6,7,.84) 0%,rgba(6,6,7,.74) 50%,rgba(6,6,7,.22) 72%,rgba(6,6,7,.5) 88%,var(--black) 100%)}
  .page-hero .hex-accent{display:none}
  .section.stage{--feather:90px}
  .strip{grid-template-columns:1fr}
  /* the strip on phones: the button full width as before, the phone link centred under it */
  .strip .cta-actions{align-items:stretch}
  .strip .call-link{align-self:center}
  .cta-strip .seam{width:240px}
  .story,.story.rev,.team-strip,.avoid,.big-stat{grid-template-columns:1fr}
  .story.rev .txt{order:0;margin-left:0}
  .story .ph,.story .shot{order:-1;justify-self:stretch;max-width:none;aspect-ratio:4/3}
  .heal-pair{order:-1;width:auto;margin:0 24px 40px 0}
  .story .heal-pair .heal-after{aspect-ratio:4/5}
  .story .heal-pair .heal-before{aspect-ratio:4/5;right:-24px;bottom:-40px;width:38vw}
  .team-strip .row>:first-child{margin-top:0}
  .styles-grid{grid-template-columns:1fr 1fr;gap:12px}
  .gallery{grid-template-columns:1fr 1fr;grid-auto-rows:160px}
  .form{grid-template-columns:1fr}
  .form-wrap{padding:28px 20px}
  .contact-side .map-frame{aspect-ratio:1/1}
  .avoid .ph,.avoid .shot{aspect-ratio:3/2;justify-self:stretch;max-width:none}
}

/* 10-06: Send Request's hover: the chrome with a dark label and light border, like every button (it kept white words
   and a purple edge over the chrome). Elementor: Form widget > Button > Hover, the same gradient, text #060607. */
.form-foot .btn:hover{color:#060607;border-color:#EDECF1}
/* 10-06: Aftercare's What to Avoid: ticks beside things not to do read wrong (Carlos), so the process hexagon marks
   the rows instead, 12px, centred on the first line; hairline rows unchanged. Book's and Jeremy's tick lists stay.
   Elementor: Icon List, custom SVG icon hex-node.svg, size 12, vertical align top. */
.avoid li::before{content:"";width:10px;height:1px;margin-top:calc((1.7em - 1px)/2);margin-top:calc((1lh - 1px)/2);background:var(--purple-light)}  /* 10-06: a hairline dash, not a tick (Carlos: a tick beside "No pools" reads wrong); the hexagon was the other option */

/* ===== 10-06 black (Carlos: Contact and FAQ "too much black", Artists' "weird gap on the right") =====
   Contact's details (#details in .flow-contact): its own cut (c-contact-details-b, strip 3200-5440, vanity.css),
   top-anchored, and full strength from the end of the soft entry to near the seam. The old stops dimmed it to
   --m-mid at 360px and --m-dim at 520px and faded it out over the whole section, so the address and the map sat on a
   dark, dying river. Now: the entry (rule 1b), full from 380px, eased out over the last 140px into the seam, where the
   finale rises. Phones: the same mask; the cut (820px tall at 390) covers the heading, the details and the map's top,
   then its baked fade closes it before Finding the Studio (no unused stretch is long enough for a 1337px phone section).
   Elementor: the wrapper container's background image top center, 100% auto (Mobile 180%); overlay gradient = the
   mask's stops (route B, 7.2) or the fades baked in (route A). */
.flow-contact{--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 calc(100% - 140px),rgba(0,0,0,.5) calc(100% - 70px),transparent 100%);--mmask-m:var(--mmask)}
/* FAQ's body (#questions.under-faq): one taller cut (c-faq-body-b, strip 2560-6400: 3024px tall at 1512, 2048 at 1024,
   1405 on a 390 phone), so the river runs under all three groups at every desktop width. Full behind the side links and
   the left margin; under the accordion column it eases down to --m-under (.75): a second, horizontal mask layer
   intersected with the vertical one, tied to the grid (the accordion starts 340px into the 1240 container), so it
   follows the column at any width. Vertical: the entry, full from 380px, eased out over the last 200px into the seam
   (was --m-dim from 1380px and gone by 1722px, which left the lower groups on black). Tablets and phones (one
   column): the whole layer at --m-under, vertical mask only.
   Elementor: the section container's background image top center, 100% auto (Mobile 180%); the two-layer mask is
   route B (one CSS line, 7.2). Native fallback: the image with Background Overlay opacity .75 (= --m-under) and the
   vertical gradient, which loses only the full-strength strip down the side links. */
.under-faq{--mop:1;
  --mmask-v:linear-gradient(180deg,var(--entry),#000 380px,#000 calc(100% - 200px),rgba(0,0,0,.5) calc(100% - 100px),transparent 100%);
  --mmask:var(--mmask-v),linear-gradient(90deg,#000 0,#000 calc(max(24px,(100% - 1240px) / 2) + 260px),rgb(0 0 0/var(--m-under)) calc(max(24px,(100% - 1240px) / 2) + 400px));
  --mmask-m:var(--mmask-v)}
.under-faq::after{-webkit-mask-composite:source-in;mask-composite:intersect}
@media (max-width:1023px){.under-faq{--mop:var(--m-under);--mmask:var(--mmask-v)}}
/* Artists' Our Team: the two cards fill the content width. They were two 440px columns aligned left (site.css
   `.sec-head+.cards` + `.sec-head.stack+.cards`), 944px of a 1240px row, so 296px sat empty on the right at 1512
   (288 at 1280). Now two equal columns, gap 64: the portraits grow to about 588 x 735 at 1512, the card design is
   unchanged (portrait, role, name, bio, then the button and the Instagram link right under the bio). Tablets keep the
   gap 40; phones stay one column (site.css). Elementor: the cards' Grid container, 2 columns 1fr, gap 64. */
@media (min-width:768px){#team .cards{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* Artists' river with the taller cards: the wrapper grows about 160px (1958 at 1512), so the old absolute end stops
   (--m-mid at 1530px, gone by 1787px) left Guest Artist Inquiries on black. The same stops, now counted from the
   wrapper's end (as .flow-care does), so the river keeps its place under Guest whatever the cards' height: full behind
   the heading and lead, --m-dim beneath the cards, back to --m-mid behind Guest, out at the seam. The cut is
   c-artists-team-b (c-artists-flow's stretch run on to strip 8960, vanity.css): at 1280 c-artists-flow was 1680px
   tall, about 270px short of the wrapper. Elementor: the same overlay gradient, its last three stops set from the
   bottom (route B, 7.2), or baked in (route A). */
.flow-artists{--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 580px,rgb(0 0 0/var(--m-mid)) 780px,rgb(0 0 0/var(--m-dim)) calc(100% - 468px),rgb(0 0 0/var(--m-mid)) calc(100% - 268px),transparent calc(100% - 11px))}
/* Contact's pools (the details, and Finding the Studio's, new 10-06: its paragraph fell to 4.45:1 on the river without
   one), one step lighter (10-06): with the river now full behind the address, the house pool (.94 at
   its centre) blacked out most of the left column; the details text keeps AA with room to spare on this lighter pool
   (measured: the table and address 14:1 and up, the area line and "Phone"/"Hours" labels above 4.5:1 at the 99th
   percentile). Elementor: the details container's radial gradient, the same stops. */
.flow-contact .pool::before{background:radial-gradient(closest-side,rgba(6,6,7,.8),rgba(6,6,7,.6) 55%,rgba(6,6,7,0))}

/* ===== 10-06 river (the 10-06 river QA: where the river read as "chopped"; measured as row means at 1512) =====
   Book, Tell Us to Policies: Tell Us's river ends in its baked fade at the section's bottom, and the Policies river came
   back 150px later across the full width (6 to 13 in 75 rows, the steepest re-entry on any page). Now the Policies
   river starts under Tell Us's bottom padding (--mlift = the section padding, so it never reaches the text) and eases in
   with the entry ramp, so the two rivers cross-fade instead of meeting at black. Its later stops move down by the lift,
   so they keep their places beside Deposits and Age. Phones keep the default fades.
   Elementor: the Policies wrapper container's margin-top and padding-top = minus / plus the section padding (120px
   Desktop, 96px Tablet; Mobile none), the overlay gradient = these stops (route B, 7.2). */
@media (min-width:768px){
  .flow-book{--mlift:var(--section-y);--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 calc(650px + var(--mlift)),rgb(0 0 0/var(--m-mid)) calc(820px + var(--mlift)),rgb(0 0 0/var(--m-dim)) calc(1100px + var(--mlift)),rgb(0 0 0/var(--m-dim)) calc(1400px + var(--mlift)),transparent 100%)}
}
/* Contact's details: the bright band ran to the box bottom and was cut by a 140px fade (a flat edge across the full
   width, 17 to 6 in about 165 rows). Now an eased 380px fade into the seam, where the finale rises. Phones follow
   (--mmask-m reads --mmask). Elementor: the wrapper's overlay gradient, the same stops. */
.flow-contact{--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 calc(100% - 380px),rgba(0,0,0,.86) calc(100% - 300px),rgba(0,0,0,.5) calc(100% - 200px),rgba(0,0,0,.16) calc(100% - 90px),transparent 100%)}
/* About, A Place to Spend a Few Hours: the studio's cut had the old inner grade (gamma 1.55, vgain .85; row means 7 to
   9), so the river dropped out between the brighter Name/Drawing and People rivers. Now the same stretch (strip
   6300-8100) with the brighter step (gamma 1.35, vgain 1, like Home's studio; tools/imagegen/cut_studio.py), q95.
   Elementor: replace the studio container's background image. */
.about-studio{--mimg:url(../assets/marble/c-about-studio-b.webp)}
/* Jeremy's portfolio: the underlay faded out at 900px, so the gutters and the gaps between the photos were flat black
   for about 2000px (rule 1b: faint beneath photos, never flat black). Desktop: the cut holds --m-dim to its own end
   (1417px at 1512), and a second faint layer (div.under-jeremy-low, first child of #portfolio) runs under the grid's
   lower half: c-book-under-b, strip 0-2500 mirrored (A, B mirrored: views this page never shows; Jeremy's cuts are
   B, A, C and D unmirrored), its top and bottom fades baked in, at Cover (100% wide from about 1400 up; below that it
   scales up to fill the taller grid, as Aftercare's flow does, instead of running out). It starts 1000px into the
   section at 1512 (66vw: the first cut is 93.75vw tall, so the hand-off stays in step at every desktop width), rising
   while the first cut fades, and runs 120px past the section's end, fading out while Meet Jeremy's
   river rises (no black band at the seam). Tablets and phones keep the short underlay. Elementor: a second container inside the portfolio
   container, Position Absolute (top 66vw, bottom -120px, left/right 0), Z-Index -1, the image top center / Cover,
   Background Overlay opacity .75 (= --m-under), and the gradient stops (route B, 7.2). */
@media (min-width:1024px){
  .under-jeremy{--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 520px,rgb(0 0 0/var(--m-dim)) 720px,rgb(0 0 0/var(--m-dim)) 1250px,transparent 1417px)}
  .under-jeremy-low{position:absolute;top:66vw;right:0;bottom:-120px;left:0;z-index:-1;pointer-events:none;--mlift:0px;--mop:var(--m-under);--msize:cover;
    --mmask:linear-gradient(180deg,transparent 0,rgba(0,0,0,.1) 100px,rgba(0,0,0,.38) 220px,rgb(0 0 0/var(--m-dim)) 380px,rgb(0 0 0/var(--m-dim)) calc(100% - 420px),rgba(0,0,0,.36) calc(100% - 200px),transparent 100%)}
}
@media (max-width:1023px){.under-jeremy-low{display:none}}
/* FAQ's body: the river was still full at the box bottom and cut by a 200px fade (a near-horizontal edge before the
   finale). Now eased from 420px above the seam. --mmask and --mmask-m both read --mmask-v, so every width follows.
   Elementor: the vertical overlay gradient, the same stops. */
.under-faq{--mmask-v:linear-gradient(180deg,var(--entry),#000 380px,#000 calc(100% - 420px),rgba(0,0,0,.84) calc(100% - 320px),rgba(0,0,0,.5) calc(100% - 200px),rgba(0,0,0,.16) calc(100% - 90px),transparent 100%)}
/* Aftercare, Healing Takes Time: its river came in over 150px; now an eased 300px rise (the default fade's stops). No
   lift here: this cut already runs out above the finale at 1280 and below, and a lift would move its end up with it.
   Elementor: the wrapper's overlay gradient, the first stops. */
.flow-heal{--mmask:linear-gradient(180deg,transparent 0,rgba(0,0,0,.12) 78px,rgba(0,0,0,.5) 156px,rgba(0,0,0,.88) 234px,#000 300px,#000 400px,rgb(0 0 0/var(--m-mid)) 560px,rgb(0 0 0/var(--m-dim)) 800px,rgb(0 0 0/var(--m-dim)) 1050px,transparent 100%)}
/* Privacy and 404: the river ran on under the footer's top (the footer overlaps the page by 120px, site.css); now it
   is gone by the footer's top edge. Privacy: its column is 720px at every desktop width, so the flow is about 1514px
   tall, and the old stops (--m-dim at 1800px, the 420px fade after it) sat past its end: the river ran at about .82
   into the footer. Now the plateau and the step down are capped from the end (min()), with an eased fade of about
   400px. 404: the same entry, full at 340px, out by the footer's top. legal.css loads after this file, so these carry
   .marble for the extra weight. Phones keep their own fades (the footer's top gradient covers the overlap there).
   Elementor: the overlay gradients' stops. */
.marble.flow-legal{--mmask:linear-gradient(180deg,var(--entry),#000 380px,#000 min(1100px,calc(100% - 520px)),rgb(0 0 0/var(--m-mid)) min(1400px,calc(100% - 380px)),rgba(0,0,0,.4) calc(100% - 230px),transparent calc(100% - 120px))}
.marble.flow-404{--mmask:linear-gradient(180deg,var(--entry),#000 340px,rgba(0,0,0,.88) calc(100% - 245px),rgba(0,0,0,.5) calc(100% - 195px),rgba(0,0,0,.12) calc(100% - 150px),transparent calc(100% - 120px))}

/* ===== 10-06 legible: the house pool (--pool, vanity.css) under the text that sat on bright marble =====
   The closing strip (all seven inner pages, by the shared class): the pool is the house one, so the phone link and
   the button's outline in the right-hand cell sit on its depth, not its feather (it was a straight .88-to-0 falloff). */
.strip::before{background:var(--pool)}
/* The other pools that drew their own, weaker recipe now paint the house one: the story rows' text (About, Book,
   Aftercare) and Aftercare's routine copy and labels. */
.story .txt::before,.tl-body::before,.tl-when::before{background:var(--pool)}
/* Book's What Happens Next (its ::before is the hairline, so the pool is on ::after): the house pool under the steps,
   the heading and the numerals. Tell Us About the Tattoo above it carries .pool (book.html). Elementor: the column
   container's radial gradient, as every pool. */
.book-next{isolation:isolate}
.book-next::after{content:"";position:absolute;inset:-18% -14%;z-index:-1;pointer-events:none;background:var(--pool)}
/* FAQ's group titles (Booking, Your Appointment, Healing and Cover-Ups): the river's vein crosses "Your Appointment" at
   desktop widths (4.29:1 at 1512 against 4.5). A small house pool behind each title line, all three alike; the
   accordion column keeps the river as the 10-06 pass left it. The title shrinks to its words so the pool centres on
   them (no layout change: one left-aligned line). Elementor: the title's Heading widget inside a container with the
   radial gradient, width Inline (auto). */
.faq-group-title{width:fit-content;position:relative;isolation:isolate}
.faq-group-title::before{content:"";position:absolute;inset:-120% -14%;z-index:-1;pointer-events:none;background:var(--pool)}
/* Aftercare's routine labels on phones ("Week 1", 11px violet caps, 5.4:1 over the river): the label pool returns,
   sized to the one line like FAQ's titles (on desktop it is the larger pool above). */
@media (max-width:767px){.tl-when::before{display:block;inset:-120% -14%}}

/* Netlify Forms (10-19, launch): spam protection is invisible (Tannis: no visible reCAPTCHA): the honeypot field stays
   hidden from people (the hidden attribute), bots fill it in and are dropped; Netlify's spam filter runs on the rest. */
.form .hp{display:none}
