/* Flow & Define — design tokens */
:root{
  --cream: #f6f0e6;
  --cream-2: #efe6d6;
  --ink: #241c16;
  --ink-soft: #443627;
  --rust: #5a3ec8;
  --rust-dark: #402a96;
  --moss: #7c8a5e;
  --brass: #b6924f;
  /* Sampled straight out of images/logo-mark.png (#513BC0 / #513BBF on the
     solid strokes). Deliberately kept separate from --rust: this token is the
     literal logo purple, --rust is the site accent. They are close but not the
     same, so never swap one for the other to "tidy up". */
  --logo-purple: #513AC1;

  --sh-1: 0 1px 2px rgba(64,42,32,0.10), 0 1px 1px rgba(64,42,32,0.06);
  --sh-2: 0 8px 20px rgba(64,42,32,0.14), 0 2px 6px rgba(64,42,32,0.08);
  --sh-3: 0 20px 44px rgba(64,42,32,0.20), 0 6px 14px rgba(64,42,32,0.10);

  --z-nav: 100;
  --z-toast: 900;

  --font-display: 'Instrument Serif', Georgia, serif;
  --font-body: 'Inter', system-ui, sans-serif;
}

*{box-sizing:border-box}
/* smooth scroll is a vestibular trigger, so it has to be opt-out (WCAG 2.3.3).
   Gating it here rather than in the block at the bottom keeps it next to the
   thing it overrides. */
@media(prefers-reduced-motion:no-preference){
  html{scroll-behavior:smooth}
}
body{
  margin:0;
  background:var(--cream);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit}

.wrap{max-width:1180px;margin:0 auto;padding:0 20px}

.skip-link{
  position:absolute;left:-999px;top:0;background:var(--ink);color:var(--cream);
  padding:12px 18px;z-index:var(--z-toast);
}
.skip-link:focus{left:20px;top:20px}

/* grain overlay, applied per-section via ::after */
.hero::after, .about::after, .cta::after{
  content:"";
  position:absolute;inset:0;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
  mix-blend-mode:multiply;
  pointer-events:none;
}

/* header */
header{
  position:sticky; top:0; z-index:var(--z-nav);
  background:rgba(246,240,230,0.92);
  backdrop-filter:blur(8px);
  border-bottom:1px solid rgba(36,28,22,0.08);
}
.nav{display:flex;align-items:center;justify-content:space-between;height:76px}
.wordmark{
  display:flex;
  align-items:center;
  gap:10px;
  font-family:var(--font-display);
  font-size:1.6rem;
  letter-spacing:-0.02em;
  text-decoration:none;
  color:var(--ink);
}
.wordmark .amp{color:var(--rust);font-style:italic}
.wordmark.small{font-size:1.3rem;color:var(--cream)}
.wordmark .mark{height:44px;width:auto;display:block}
.wordmark.small .mark{height:34px}
.navlinks{display:none;align-items:center;gap:28px}
.navlinks a{
  text-decoration:none;
  font-size:0.95rem;
  font-weight:500;
  color:var(--ink-soft);
}
.navlinks a:hover{color:var(--ink)}
/* The header CTA is an <a class="btn"> INSIDE .navlinks, so `.navlinks a`
   (0,1,1) outranks `.btn` (0,1,0) and stole its cream text: the button
   rendered #443627 on #241c16 = 1.44:1, effectively invisible. Both rules
   below must stay more specific than `.navlinks a` / `.navlinks a:hover`. */
.navlinks a.btn{color:var(--cream)}
.navlinks a.btn:hover{color:var(--cream)}
.navtoggle{
  background:none;border:0;font-size:1.4rem;cursor:pointer;
  min-width:44px;min-height:44px;
}
@media(min-width:860px){
  .navlinks{display:flex}
  .navtoggle{display:none}
}
.navlinks.open{
  display:flex;flex-direction:column;position:absolute;top:76px;left:0;right:0;
  background:var(--cream);padding:12px 20px;gap:4px;box-shadow:var(--sh-2);
}
/* Open-menu links were 24px tall: above the WCAG 2.5.8 floor but well under
   Apple's 44px target, which is fiddly to hit one-handed. */
.navlinks.open a{
  display:flex;align-items:center;min-height:44px;
}

.btn, .btn-dark, .btn-out{
  display:inline-flex;align-items:center;justify-content:center;
  padding:12px 22px;
  border-radius:999px;
  font-weight:600;
  font-size:0.95rem;
  text-decoration:none;
  min-height:44px;
  transition:transform 160ms ease-out, box-shadow 160ms ease-out, background 160ms ease-out;
}
.btn{background:var(--ink);color:var(--cream);box-shadow:var(--sh-1)}
.btn:hover{transform:translateY(-2px);box-shadow:var(--sh-2)}
.btn:active{transform:scale(0.97)}

.btn-dark{background:var(--ink);color:var(--cream);box-shadow:var(--sh-2)}
.btn-dark:hover{transform:translateY(-3px);box-shadow:var(--sh-3);background:var(--ink-soft)}
.btn-dark:active{transform:scale(0.97) translateY(-1px)}

/* 0.55 alpha, not 0.30: btn-out has no background, so this border is the only
   thing identifying it as a control, which puts it under WCAG 1.4.11's 3:1
   floor. At 0.30 it measured 1.89:1. Now 3.66:1. */
.btn-out{background:transparent;color:var(--ink);border:1.5px solid rgba(36,28,22,0.55)}
.btn-out:hover{transform:translateY(-3px);border-color:var(--ink);box-shadow:var(--sh-1)}
.btn-out:active{transform:scale(0.97)}

/* hero */
.hero{
  position:relative;
  min-height:88svh;
  display:flex;
  align-items:center;
  overflow:hidden;
  background:linear-gradient(180deg, var(--cream) 0%, var(--cream-2) 100%);
}
.hero-flow{position:absolute;inset:0;opacity:0.5}
.hero-flow svg{width:100%;height:100%}
.flow-line{fill:none;stroke-width:3;stroke-linecap:round}
.f1{stroke:var(--rust);opacity:0.35;animation:drift 22s ease-in-out infinite}
.f2{stroke:var(--moss);opacity:0.3;animation:drift 26s ease-in-out infinite reverse}
.f3{stroke:var(--brass);opacity:0.28;animation:drift 30s ease-in-out infinite}
@keyframes drift{
  0%,100%{transform:translateX(0)}
  50%{transform:translateX(-40px)}
}
@media(prefers-reduced-motion:reduce){
  .flow-line{animation:none}
}

.hero-grid{
  position:relative;z-index:1;
  display:grid;grid-template-columns:1fr;gap:44px;
  padding:60px 0 40px;
}
@media(min-width:900px){
  .hero-grid{grid-template-columns:1.1fr 0.9fr;align-items:center;gap:40px}
}

.hero-eyebrow{display:flex;align-items:center;gap:10px;font-size:0.85rem;color:var(--ink-soft);margin-bottom:18px}
.pill{background:var(--rust);color:var(--cream);padding:4px 12px;border-radius:999px;font-weight:600;font-size:0.78rem}

h1{
  font-family:var(--font-display);
  font-weight:400;
  font-size:clamp(2.6rem, 6vw, 4.6rem);
  line-height:1.02;
  letter-spacing:-0.02em;
  margin:0 0 20px;
  color:var(--ink);
}
.ital{font-style:italic;color:var(--rust-dark)}

.lede{
  font-size:1.15rem;
  color:var(--ink-soft);
  max-width:52ch;
  margin:0 0 30px;
}
.hero-cta{display:flex;flex-wrap:wrap;gap:14px}

.hero-mark{position:relative}
.mark-frame{
  position:relative;
  aspect-ratio:4/5;
}
.mark-inner{
  position:absolute;inset:18px;
  display:flex;align-items:center;justify-content:center;
}
.mark-glyph{
  /* constrain by HEIGHT: the mark is ~3:1 tall, so sizing by width overflows the hero */
  height:92%;width:auto;max-width:100%;
  filter:drop-shadow(0 14px 30px rgba(64,42,32,0.16));
}
.sticker{
  margin:18px auto 0;
  max-width:340px;
  background:var(--cream-2);
  border:1px solid rgba(36,28,22,0.08);
  border-radius:14px;
  padding:12px 16px;
  font-size:0.82rem;
  color:var(--ink-soft);
  text-align:center;
}

/* strip */
.strip{background:var(--ink);color:var(--cream);padding:36px 0}
.strip-grid{display:flex;flex-direction:column;gap:22px}
@media(min-width:700px){.strip-grid{flex-direction:row;justify-content:space-between}}
.strip-item{display:flex;flex-direction:column;gap:4px}
.strip-item strong{font-family:var(--font-display);font-size:1.2rem;font-weight:400}
.strip-item span{font-size:0.88rem;color:rgba(246,240,230,0.7)}

/* about */
.about{position:relative;background:var(--cream-2);padding:88px 0}
.about-grid{display:grid;grid-template-columns:1fr;gap:44px;position:relative;z-index:1}
@media(min-width:860px){.about-grid{grid-template-columns:0.85fr 1.15fr;align-items:center;gap:56px}}
.frame{
  position:relative;
  background:var(--logo-purple);
  border-radius:22px;
  padding:14px;
  transform:rotate(1.4deg);
  box-shadow:var(--sh-3);
}
.frame-photo{
  display:block;
  width:100%;
  /* height:auto is required: the width/height HTML attributes (there for
     layout-shift prevention) otherwise win and aspect-ratio never applies. */
  height:auto;
  aspect-ratio:4/5;
  object-fit:cover;
  object-position:50% 22%;   /* keep her face in frame on the 4/5 crop */
  border-radius:14px;
  background:var(--cream-2);
}
.eyebrow{
  display:inline-block;font-size:0.82rem;font-weight:600;letter-spacing:0.04em;
  text-transform:uppercase;color:var(--rust-dark);margin-bottom:12px;
}
h2{
  font-family:var(--font-display);
  font-weight:400;
  font-size:clamp(2rem, 3.6vw, 2.9rem);
  letter-spacing:-0.02em;
  margin:0 0 18px;
}
.about-copy p{max-width:64ch;color:var(--ink-soft);font-size:1.05rem}
.todo-note{
  font-size:0.85rem;
  color:var(--rust-dark);
  /* 90,62,200 == --rust (#5a3ec8). Literal because rgba() can't take a var() colour directly. */
  background:rgba(90,62,200,0.09);
  border:1px dashed rgba(90,62,200,0.38);
  border-radius:10px;
  padding:10px 14px;
  max-width:60ch;
}

/* services */
.services{padding:88px 0;background:var(--cream)}
.service-grid{display:flex;flex-direction:column;gap:26px;margin-top:36px}
@media(min-width:760px){.service-grid{flex-direction:row}}
.service-item{
  flex:1;
  background:var(--cream-2);
  border-radius:20px;
  padding:28px 26px;
  box-shadow:var(--sh-1);
  transition:transform 200ms ease-out, box-shadow 200ms ease-out;
}
.service-item:hover{transform:translateY(-6px);box-shadow:var(--sh-2)}
.service-item h3{font-family:var(--font-display);font-weight:400;font-size:1.4rem;margin:0 0 6px}
.service-item p{color:var(--ink-soft);font-size:0.98rem;max-width:38ch}
.service-meta{
  display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;
  margin:0 0 12px;padding-bottom:12px;
  border-bottom:1px solid rgba(36,28,22,0.12);
}
.service-price{font-family:var(--font-display);font-size:1.75rem;line-height:1;color:var(--rust)}
.service-time{font-size:0.86rem;letter-spacing:0.06em;text-transform:uppercase;color:var(--ink-soft)}

/* results */
.results{padding:88px 0;background:var(--ink);color:var(--cream)}
.results .eyebrow{color:var(--brass)}
.results h2{color:var(--cream)}
.results-copy{max-width:64ch;color:rgba(246,240,230,0.75)}
.results-grid{display:flex;flex-direction:column;gap:34px;margin-top:32px}
@media(min-width:860px){.results-grid{flex-direction:row;gap:28px}}
.result{flex:1;margin:0}
.result-pair{display:flex;flex-direction:column;gap:8px}
.result-shot{position:relative;border-radius:14px;overflow:hidden;background:rgba(246,240,230,0.06)}
.result-shot img{width:100%;height:auto;display:block}
/* The burned-in Instagram captions were cropped out with the room clutter, so
   the label is rendered here instead. It is also what keeps a tight body crop
   reading as clinical documentation rather than just a photo of someone. */
.result-tag{
  position:absolute;left:12px;top:12px;
  background:rgba(36,28,22,0.72);
  /* backdrop-filter is progressive enhancement: the 0.72 background alone
     already clears 4.5:1, so this stays legible where it is unsupported. */
  backdrop-filter:blur(6px);
  color:var(--cream);
  font-size:0.72rem;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;
  padding:5px 11px;border-radius:999px;
}
.result figcaption{
  margin-top:14px;
  font-size:0.9rem;
  color:rgba(246,240,230,0.75);
}

/* reviews */
.reviews{padding:88px 0;background:var(--cream-2)}
.reviews-copy{max-width:64ch;color:var(--ink-soft)}
.review-empty{
  margin-top:30px;
  background:var(--cream);
  border-radius:18px;
  padding:36px;
  text-align:center;
  box-shadow:var(--sh-1);
  max-width:420px;
}
/* 0.70 alpha, not 0.35: at 0.35 this measured 1.43:1 on cream and failed WCAG. */
.star-row{color:rgba(90,62,200,0.70);font-size:1.6rem;letter-spacing:4px}
.review-empty p{color:var(--ink-soft);margin:10px 0 0;font-size:0.95rem}

/* cta */
.cta{position:relative;background:var(--rust);color:var(--cream);padding:76px 0}
.cta-grid{display:flex;flex-direction:column;gap:26px;position:relative;z-index:1}
@media(min-width:760px){.cta-grid{flex-direction:row;justify-content:space-between;align-items:center}}
.cta h2{font-family:var(--font-display);font-weight:400;color:var(--cream);margin:0 0 8px;font-size:clamp(1.8rem,3vw,2.4rem)}
.cta p{margin:0;color:rgba(246,240,230,0.85)}
/* same 1.4.11 issue on the purple ground: 0.50 measured 2.73:1, 0.70 is 3.91:1 */
.cta .btn-out{border-color:rgba(246,240,230,0.70);color:var(--cream)}
.cta .btn-out:hover{border-color:var(--cream)}
.cta-actions{display:flex;flex-wrap:wrap;gap:14px}

/* Footer depth, 2026-08-16. It was a flat ink bar butted straight against the
   purple CTA band. Four layers now, cheapest first:
   1. a vertical gradient so the bar is not one dead colour,
   2. an inset top shadow + 1px light hairline, so it reads as RECESSED under
      the CTA instead of stacked beside it,
   3. a purple radial bleeding down out of the CTA band, which ties the two
      sections together rather than hard-cutting between them,
   4. an oversized logo watermark. This is the first real use of
      logo-mark-light.png, the reversed-for-dark-grounds variant we have been
      shipping unused since 2026-08-15. */
footer{
  position:relative;
  overflow:hidden;
  background:linear-gradient(180deg, #2c2119 0%, var(--ink) 44%, #191310 100%);
  color:rgba(246,240,230,0.72);
  padding:54px 0 46px;
  box-shadow:
    inset 0 1px 0 rgba(246,240,230,0.11),
    inset 0 16px 30px -16px rgba(0,0,0,0.8);
}
footer::before{
  content:"";
  position:absolute; left:0; right:0; top:0; height:190%;
  background:radial-gradient(58% 62% at 20% 0%,
    rgba(81,58,193,0.40) 0%, rgba(81,58,193,0.13) 44%, transparent 72%);
  pointer-events:none;
}
footer::after{
  content:"";
  position:absolute; right:-26px; top:50%;
  width:250px; height:250px;
  transform:translateY(-50%) rotate(-8deg);
  background:url("/images/logo-mark-light.png") no-repeat center/contain;
  opacity:0.055;
  pointer-events:none;
}
/* Both pseudo-elements are decorative and must never sit over the links. */
.footer-grid{position:relative; z-index:1}
.footer-grid{display:flex;flex-direction:column;gap:16px}
@media(min-width:700px){.footer-grid{flex-direction:row;justify-content:space-between;align-items:center}}
.footer-meta{display:flex;flex-wrap:wrap;gap:6px 20px;font-size:0.9rem}
/* These were 23px tall with zero padding, under even the WCAG 24px floor, and
   one of them is the primary sms: booking link.
   The plain "Teaneck, NJ" <span> gets the same box: without it the flex parent
   stretched it to 44px with its text pinned to the TOP, so it floated 10px
   above the links next to it (2026-08-16).
   The `>` matters. `.footer-meta span` would also catch the wrapper span
   inside the Handled credit, turn it into a flex container, and collapse the
   space in "Site by Handled." all over again. Direct children only. */
.footer-meta > a,
.footer-meta > span{
  text-decoration:none;
  display:inline-flex;align-items:center;min-height:44px;
}
.footer-meta a:hover{color:var(--cream)}
/* "Site by Handled." - Handled itself is bold (Keegan, 2026-08-16). */
.footer-meta .credit strong{font-weight:700;color:var(--cream)}

/* reveal on scroll: visible by default, animation is enhancement only.
   Content must never depend on JS to become visible. */
@keyframes revealIn{
  from{opacity:0;transform:translateY(18px)}
  to{opacity:1;transform:translateY(0)}
}
.reveal.in{animation:revealIn 700ms ease-out}
@media(prefers-reduced-motion:reduce){
  .reveal.in{animation:none}
}
