/* =========================================================================
   ALLA NOVYTSKA  ·  Homes, seen in a different light.
   Light and refraction. A home is a prism.
   One world: CRYSTALLINE. Dark ground, light and refraction on top.
   ========================================================================= */

/* ---------- 1. TOKENS ---------- */
:root{
  /* fixed brand palette */
  --void:      #0B0C0F;
  --void-2:    #0F1116;
  --bone:      #EDE8DC;
  --bone-2:    #E2DBC9;
  --ink:       #181510;
  --violet:      #7F63C9;  /* noble violet, the one accent */
  --violet-lift: #A98CE8;  /* 7.1:1 on the void ground */
  --violet-deep: #4A2E7A;  /* 8.8:1 on the bone ground */
  --sea:       #6E9A93;
  --sea-deep:  #325A54;
  --champagne: #CDC4B2;
  --silver:    #D6DBDF;
  --red:       #B8452F;

  /* iridescent dispersion: accents and edges only, never large fills */
  --i1:#B57BEC; --i2:#8E6FE0; --i3:#C08BF0;
  --i4:#6FB8E8; --i5:#E8A0D8; --i6:#D8C4F5;

  /* Display: Syne. Micro type: Space Mono. */
  --display: "Syne", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --serif:   var(--display);
  --mono:    "Space Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --wrap: 1360px;
  --gut:  clamp(20px, 5vw, 72px);

  --ease: cubic-bezier(.22,.61,.36,1);
}

/* ---------- the one world: CRYSTALLINE ---------- */
body{
  --bg:        var(--void);
  --bg-2:      var(--void-2);
  --fg:        var(--bone);
  --fg-muted:  #A9AEB5;   /* 8.0:1 on --void */
  --fg-faint:  #6A7079;   /* decorative only */
  --rule:      rgba(237,232,220,.16);
  --rule-soft: rgba(237,232,220,.08);
  --accent:      var(--violet);
  --accent-text: #A98CE8;  /* 7.1:1 on --void */
  --field-bg:  rgba(237,232,220,.045);
  --shadow:    0 30px 90px rgba(0,0,0,.55);
}

/* ---------- 2. RESET AND BASE ---------- */
*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
html,body{ overflow-x:clip; }

body{
  margin:0;
  background:var(--bg);
  color:var(--fg);
  font-family:var(--display);
  font-size:clamp(18px,1.15vw,20px);
  line-height:1.62;
  font-weight:400;
  -webkit-font-smoothing:antialiased;
}

img,picture,svg,video{ display:block; max-width:100%; }
img{ height:auto; }
a{ color:inherit; }
h1,h2,h3,p,figure,blockquote,ul{ margin:0; }
ul{ padding:0; list-style:none; }

::selection{ background:var(--accent); color:var(--bg); }

/* focus: never removed, always replaced */
:focus-visible{
  outline:2px solid var(--accent-text);
  outline-offset:3px;
  border-radius:2px;
}

.wrap{ width:100%; max-width:var(--wrap); margin-inline:auto; padding-inline:var(--gut); }

.skip-link{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--bg); color:var(--fg);
  padding:14px 20px; font-family:var(--mono); font-size:14px;
  letter-spacing:.16em; text-transform:uppercase; text-decoration:none;
  border:1px solid var(--rule);
}
.skip-link:focus{ left:12px; top:12px; }

/* ---------- 3. MICRO TYPE (HUD / labels) ---------- */
.hud,.sec-label,.eyebrow,.img-note,.grid-caption,
.btn,.foot-nav a,.hero-side-label,.legal-line,.legal-eho,.legal-ai,
.legal-fine,.legal-copy,.form-note,.contact-office,label,.quote-meta{
  font-family:var(--mono);
}

.hud,.sec-label,.eyebrow{
  font-size:clamp(10px,.76vw,11.5px);
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--fg-muted);
  line-height:1.9;
}
/* the hero HUD sits over moving footage, so it is lifted above the body tone
   and given a soft ground of its own */

.hero .hud-clock{ color:var(--fg); }
.hud-dot{ color:var(--accent-text); padding-inline:.25em; }
.reg-r{ font-size:.72em; vertical-align:.42em; letter-spacing:0; }

.sec-label{
  color:var(--accent-text);
  letter-spacing:.2em;
  margin-bottom:clamp(18px,2vw,30px);
}

/* AI captions: fine print by intent. Small and quiet, but still legible,
   because an unreadable disclosure is not a disclosure (B&P §10140.8). */
.img-note,.grid-caption{
  font-size:8.5px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--fg-muted); line-height:1.6; margin-top:10px;
}
.grid-caption{ margin-top:clamp(26px,3vw,40px); }

/* ---------- 4. DISPLAY TYPE ---------- */
.h-display{
  font-family:var(--display);
  font-weight:600;
  font-size:clamp(2.05rem,4vw,3.3rem);
  line-height:1.05;
  letter-spacing:-.022em;
  text-wrap:balance;
}
.h-display-lg{ font-size:clamp(2.25rem,4.9vw,4.1rem); }

.section p{ max-width:62ch; }

/* ---------- 5. BUTTONS AND LINKS ---------- */
.btn{
  display:inline-flex; align-items:center; gap:.7em;
  min-height:48px; padding:14px 26px;
  font-size:12px; letter-spacing:.14em; text-transform:uppercase;
  text-decoration:none; border:1px solid var(--rule);
  color:var(--fg); background:transparent;
  transition:border-color 320ms var(--ease), color 320ms var(--ease),
             background-color 320ms var(--ease), transform 320ms var(--ease);
  cursor:pointer;
}
.btn-primary{ position:relative; }
.btn-primary::after{
  content:""; position:absolute; inset:-1px; pointer-events:none;
  background:linear-gradient(100deg,var(--i1),var(--i2),var(--i3),var(--i4),var(--i5));
  opacity:0; transition:opacity 320ms var(--ease);
  -webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  padding:1px;
}
.btn:hover{ color:var(--fg); border-color:transparent; transform:translateY(-1px); }
.btn:hover::after{ opacity:.95; }

.link-quiet{
  font-family:var(--mono); font-size:12.5px; letter-spacing:.2em;
  text-transform:uppercase; text-decoration:none;
  color:var(--fg-muted);
  border-bottom:1px solid var(--rule);
  padding-bottom:3px;
  transition:color 300ms var(--ease), border-color 300ms var(--ease);
}
.link-quiet:hover{ color:var(--fg); border-color:var(--accent-text); }

/* ---------- 6. REGISTRATION MARKS ---------- */
.reg{ position:fixed; inset:0; pointer-events:none; z-index:90; }
.reg-mark{ position:absolute; width:16px; height:16px; opacity:.5; }
.reg-mark::before,.reg-mark::after{
  content:""; position:absolute; background:var(--fg-faint);
}
.reg-mark::before{ width:100%; height:1px; top:0; }
.reg-mark::after{ width:1px; height:100%; left:0; }
.reg-tl{ top:16px; left:16px; }
.reg-tr{ top:16px; right:16px; transform:scaleX(-1); }
.reg-bl{ bottom:16px; left:16px; transform:scaleY(-1); }
.reg-br{ bottom:16px; right:16px; transform:scale(-1); }

/* ---------- 7. HEADER ---------- */
/* The first screen belongs to the name alone: the bar is not there at all
   until the hero has been scrolled past. Keyboard users get it back the
   moment anything inside it takes focus. */
.site-head{
  /* opacity rather than visibility: an element hidden with visibility cannot
     take focus at all, so :focus-within below would never fire and the nav
     would be unreachable by keyboard over the hero. pointer-events keeps it
     from catching clicks while it is invisible. */
  opacity:0; pointer-events:none; transform:translateY(-10px);
  transition:opacity 460ms var(--ease), transform 460ms var(--ease);
  position:sticky; top:0; z-index:100;
  display:flex; align-items:center; justify-content:space-between;
  gap:24px;
  padding:18px var(--gut);
  background:linear-gradient(to bottom,var(--bg) 0%,color-mix(in srgb,var(--bg) 74%,transparent) 62%,transparent 100%);
}
@supports not (background:color-mix(in srgb,red 50%,blue)){
  .site-head{ background:var(--bg); }
}
/* once past the hero the bar arrives, and it is solid so nothing shows
   through it */
.site-head.is-scrolled,
.site-head:focus-within{
  opacity:1; pointer-events:auto; transform:none;
  background:var(--bg);
  border-bottom:1px solid var(--rule-soft);
}

.brand{ display:block; line-height:0; flex:0 0 auto; }
.brand-mark{ width:clamp(132px,13vw,188px); height:auto; }
.foot-mark{ width:clamp(112px,10vw,148px); height:auto; }

.site-nav{ display:flex; gap:clamp(16px,2.2vw,34px); }
.site-nav a{
  font-family:var(--mono); font-size:11px; letter-spacing:.16em;
  text-transform:uppercase; text-decoration:none; color:var(--fg-muted);
  padding:14px 2px; min-height:44px; display:inline-flex; align-items:center;
  transition:color 300ms var(--ease);
}
.site-nav a:hover{ color:var(--fg); }

/* ---------- 8. HERO ---------- */
.hero{ position:relative; }
.hero-stage{
  position:relative;
  isolation:isolate;                 /* required for mix-blend-mode below */
  background-color:var(--bg);        /* blends need an opaque parent */
  z-index:0;
  min-height:100vh;
  min-height:100svh;
  overflow:hidden;
  margin-top:calc(-1 * (18px + clamp(132px,13vw,188px) * .53 + 18px));
  padding-top:calc(18px + clamp(132px,13vw,188px) * .53 + 18px);
}

.hero-bg{ position:absolute; inset:0; z-index:0; }

/* Section background video. Never preloaded: main.js starts a loop only on a
   device that can carry it, and only while it is actually on screen. */
.bg-video{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  opacity:0; transition:opacity 1100ms var(--ease);
  pointer-events:none;
}
.bg-video.is-playing{ opacity:.66; filter:saturate(.85) contrast(1.04); }

/* On a phone the loops stay off, except the one a loop was asked for:
   a video marked data-mobile-ok is small enough to carry and main.js
   still refuses it on save-data, 2g and reduced motion. */
@media (max-width:820px){ .bg-video:not([data-mobile-ok]){ display:none; } }
@media (prefers-reduced-motion:reduce){ .bg-video{ display:none; } }

.hero-bg picture,.hero-bg img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
}

/* The lens draws whatever the background currently is, so it wears the same
   treatment as that source: swapping one for the other changes nothing about
   the look, only about whether it answers the pointer. */
.bg-crystal,.lens-canvas{ opacity:.52; filter:saturate(.7) contrast(1.06); }
html.has-lens-video .lens-canvas{ opacity:.66; filter:saturate(.85) contrast(1.04); }
.lens-canvas{
  /* z-index 0, not 1: the scrim above has to stay above, or the loop washes
     out the type it is there to protect */
  position:absolute; inset:0; z-index:0;
  width:100%; height:100%;
  display:none;
}
/* Only once the shader has put a first frame on screen does what is underneath
   step aside, so there is never a blank moment. The loop keeps playing while
   invisible, because it is the shader's texture. */
html.has-lens .lens-canvas{ display:block; }
html.has-lens .bg-crystal{ opacity:0; }
html.has-lens #hero-video.is-playing{ opacity:0; }

.hero-scrim{
  position:absolute; inset:0;
  background:
    radial-gradient(118% 80% at 50% 46%, transparent 0%, var(--bg) 84%),
    linear-gradient(to bottom, var(--bg) 0%, color-mix(in srgb,var(--bg) 74%,transparent) 18%, color-mix(in srgb,var(--bg) 26%,transparent) 46%, color-mix(in srgb,var(--bg) 92%,transparent) 100%);
}
/* a soft ground so the figure is never floating on a flat field */
.hero-seat{ position:absolute; inset:0; }
.hero-seat{
  background:radial-gradient(26% 46% at 57% 62%, rgba(214,219,223,.10), transparent 72%);
}

@supports not (background:color-mix(in srgb,red 50%,blue)){
  .hero-scrim{ background:radial-gradient(120% 78% at 50% 22%, transparent 0%, var(--bg) 78%); }
}

/* iridescent bloom: accent only, kept very low in opacity */
.hero-bloom{
  position:absolute; inset:-10%;
  mix-blend-mode:screen;             /* isolated by .hero-stage */
  opacity:.32;
  background:
    radial-gradient(38% 30% at 22% 62%, rgba(150,110,225,.38), transparent 70%),
    radial-gradient(34% 28% at 78% 30%, rgba(111,150,232,.26), transparent 70%),
    radial-gradient(30% 26% at 60% 82%, rgba(192,139,240,.24), transparent 70%);
  animation:drift 26s var(--ease) infinite alternate;
}

@keyframes drift{
  from{ transform:translate3d(-1.4%,1%,0) scale(1); }
  to  { transform:translate3d(1.6%,-1.2%,0) scale(1.06); }
}

.grain{
  position:absolute; inset:0; pointer-events:none; opacity:.22;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
}

/* --- the name is the hero --- */
.wordmark{
  position:static;                   /* no stacking context: children order freely */
  margin:0; font-weight:700;
  text-transform:uppercase;
  line-height:.84;
  color:var(--fg);
}
.wm-alla,.wm-novytska{
  position:absolute; left:50%; transform:translateX(-50%);
  white-space:nowrap; display:block;
  /* The loop behind the name is chrome: at some points in its cycle a white
     highlight passes straight under a letter. Measured against the painted
     pixels, a single soft glow was not enough, so the name carries its own
     dark halo and never depends on the scrim alone. */
  text-shadow:
    0 0 16px var(--bg),
    0 0 34px var(--bg),
    0 0 90px color-mix(in srgb,var(--bg) 88%,transparent);
}
@supports not (color:color-mix(in srgb,red 50%,blue)){
  .wm-alla,.wm-novytska{ text-shadow:0 0 16px var(--bg),0 0 34px var(--bg),0 0 90px var(--bg); }
}
.wm-alla{
  /* sits clear of her head: the name never crosses her face */
  top:8%;
  z-index:3;
  font-size:clamp(3.1rem,12vw,10.8rem);
  letter-spacing:-.012em;
}
.wm-novytska{
  /* Measured against the cut-out, not guessed. Across her arms the
     silhouette is 92% of the image wide and swallows half the word; at
     72-79% of her height it narrows to 20%, so the name crosses her legs
     and only a single letter is ever behind her. */
  top:74%;
  z-index:1;                          /* behind the figure: they interlock */
  font-size:clamp(2.1rem,8.6vw,8rem);
  /* opened up so the strip her legs take out falls between letters
     rather than through the middle of one */
  letter-spacing:.012em;
  color:color-mix(in srgb,var(--fg) 88%,transparent);
}

@supports not (color:color-mix(in srgb,red 50%,blue)){
  .wm-novytska{ color:var(--fg); }
  .wm-alla{ text-shadow:none; }
}

.hero-figure{
  position:absolute; z-index:2;
  left:57%; bottom:0; transform:translateX(-50%);
  height:74%; width:auto; margin:0;
}
.hero-figure picture,.hero-figure img{ height:100%; width:auto; object-fit:contain; }
.hero-figure img{
  filter:drop-shadow(0 40px 60px rgba(0,0,0,.45));
}

/* --- the prism band: a slab of optical glass standing on her raised hand,
       positioned by main.js against the figure rather than the viewport --- */
.prism{
  position:absolute;                 /* never fixed: iOS scroll jank */
  z-index:4;
  top:-6%; height:112%;
  left:45%; width:6vw; min-width:66px; max-width:104px;
  transform:rotate(5deg);
  pointer-events:none;
  /* literal px values: CSS custom properties do not work inside
     -webkit-backdrop-filter in Safari */
  -webkit-backdrop-filter:blur(9px) hue-rotate(24deg) saturate(1.6) brightness(1.12);
          backdrop-filter:blur(9px) hue-rotate(24deg) saturate(1.6) brightness(1.12);
  /* no flat tint: the band must read as glass, not as a coloured slab */
  -webkit-mask-image:linear-gradient(to bottom,transparent 0%,#000 30%,#000 72%,transparent 100%);
          mask-image:linear-gradient(to bottom,transparent 0%,#000 30%,#000 72%,transparent 100%);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .prism{ background:linear-gradient(100deg,rgba(181,123,236,.15),rgba(111,150,232,.11)); }
}

.prism-edge{ position:absolute; top:0; bottom:0; width:1px; }

.prism-edge-l{ left:0;  background:linear-gradient(to bottom,transparent,rgba(181,123,236,.60),rgba(142,111,224,.42),transparent); }
.prism-edge-r{ right:0; background:linear-gradient(to bottom,transparent,rgba(192,139,240,.52),rgba(111,184,232,.34),transparent); }

@keyframes float{
  from{ transform:translate3d(0,0,0) rotate(-5deg); }
  to  { transform:translate3d(0,-22px,0) rotate(4deg); }
}

/* --- HUD placement --- */
.hud-clock{ display:block; color:var(--fg); letter-spacing:.16em; font-variant-numeric:tabular-nums; }

/* --- the side mark: a hairline standing on one word, bottom left --- */
.hero-side{
  position:absolute; z-index:5;
  left:var(--gut); bottom:clamp(30px,7vh,84px);
  margin:0; display:flex; flex-direction:column; align-items:center;
  gap:clamp(14px,2vh,22px);
}
.hero-side-line{
  width:1px; height:clamp(72px,16vh,180px);
  background:linear-gradient(to bottom,
    transparent 0%,
    color-mix(in srgb,var(--accent-text) 70%,transparent) 42%,
    color-mix(in srgb,var(--accent-text) 70%,transparent) 74%,
    transparent 100%);
}
@supports not (color:color-mix(in srgb,red 50%,blue)){
  .hero-side-line{ background:linear-gradient(to bottom,transparent,var(--accent-text) 50%,transparent); }
}
.hero-side-label{
  writing-mode:vertical-rl; transform:rotate(180deg);   /* reads upward */
  font-family:var(--mono);
  font-size:clamp(11.5px,.94vw,13.8px);
  letter-spacing:.46em; text-transform:uppercase;
  color:#D6DBDF;
  text-shadow:0 1px 12px rgba(11,12,15,.85);
}

.eyebrow{ margin-bottom:14px; }
.tagline{
  font-family:var(--display); font-style:normal; font-weight:500;
  font-size:clamp(1.35rem,2.6vw,2.4rem);
  letter-spacing:-.015em;
  line-height:1.22; color:var(--fg); margin-bottom:30px;
}
.hero-cta{ display:flex; align-items:center; gap:clamp(14px,2vw,26px); flex-wrap:wrap; }

/* --- the opening band, one screen below the name --- */
/* The loop that used to sit behind Approach lives here now, so the band needs
   room underneath it: the scrim resolves to solid ground at its own bottom
   edge and that fade needs somewhere to land. */
.section-open{ padding-block:clamp(78px,13vh,170px) clamp(56px,8vh,104px); }
/* the wrap itself keeps the page's gutter so this lines up with every other
   section; only the copy inside it is held to a readable measure */
.section-open .open-grid > *{ max-width:min(760px,100%); }
.open-meta{ margin-top:clamp(34px,5vh,60px); }
.open-meta > span{ display:block; }

.scroll-cue{
  position:absolute; z-index:5; left:50%; transform:translateX(-50%);
  bottom:20px; display:flex; flex-direction:column; align-items:center; gap:10px;
  text-decoration:none; padding:10px 16px; min-height:44px;
}
.scroll-cue-line{
  width:1px; height:34px; background:linear-gradient(to bottom,var(--fg-faint),transparent);
  animation:cue 2.6s var(--ease) infinite;
}
@keyframes cue{ 0%,100%{ transform:scaleY(.5); transform-origin:top; } 50%{ transform:scaleY(1); transform-origin:top; } }

/* ---------- 9. SECTIONS ---------- */
.section{
  position:relative;
  padding-block:clamp(80px,11vw,168px);
  border-top:1px solid var(--rule-soft);
}
.section-about{ border-top:0; }

/* No portrait here any more: the section is a single editorial text block,
   the heading held in a narrow left column and the prose set wide beside it. */
.about-grid{
  display:grid; gap:clamp(28px,4vw,72px);
  grid-template-columns:minmax(0,.72fr) minmax(0,1fr);
  align-items:start;
}
.about-head .h-display{ margin-bottom:0; }
.about-text p{ margin-bottom:1.15em; color:var(--fg); max-width:56ch; }
.about-lead{
  font-size:clamp(1.2rem,1.72vw,1.52rem);
  line-height:1.5; letter-spacing:-.012em;
}
.about-meta{ margin-top:26px; display:flex; align-items:center; gap:10px; flex-wrap:wrap; }

.approach-grid{
  display:grid; gap:clamp(32px,5vw,84px);
  grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  align-items:start;
  margin-top:clamp(34px,4vw,60px);
}
.approach-item{ padding-block:clamp(22px,2.4vw,34px); border-top:1px solid var(--rule-soft); }
.approach-item:first-child{ border-top:0; padding-top:0; }
.approach-item h3{
  font-family:var(--mono); font-size:12px; letter-spacing:.18em;
  text-transform:uppercase; color:var(--accent-text); font-weight:500;
  margin-bottom:14px;
}
.approach-item p{ color:var(--fg); }
.approach-figure img{ width:100%; }

.hood-grid{
  display:grid; gap:clamp(26px,3.2vw,46px);
  grid-template-columns:repeat(3,minmax(0,1fr));
  margin-top:clamp(34px,4vw,60px);
}
.hood figure{ margin:0 0 22px; }
.hood img{ width:100%; aspect-ratio:16/9; object-fit:cover; }
.hood h3{
  font-family:var(--display); font-weight:600; letter-spacing:-.02em;
  font-size:clamp(1.5rem,2.3vw,2.07rem); line-height:1.08; margin-bottom:12px;
}
.hood p{ color:var(--fg); font-size:.96em; }

/* ---------- SERVICE AREA MAP ----------
   A drawn map, not an embed: no API key, no third-party cookie, no tile
   request. The city names are real HTML text in the legend, so a search
   engine and a language model both read them as words rather than pixels.
   The plate itself carries only the numerals, which stay legible at any
   width because two digits can never collide with anything. */
.map-block{
  display:grid; gap:clamp(28px,3.6vw,64px);
  grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  align-items:start;
  margin-top:clamp(48px,6vw,92px);
  padding-top:clamp(40px,5vw,72px);
  border-top:1px solid var(--rule-soft);
}
.map-plate{
  margin:0; position:relative;
  border:1px solid var(--rule-soft);
  background:
    radial-gradient(120% 90% at 30% 20%, rgba(127,99,201,.10), transparent 70%),
    var(--bg-2);
}
.svc-map{ width:100%; height:auto; display:block; }

.svc-ridge{ fill:none; stroke:var(--fg-faint); stroke-width:1.4; opacity:.62; }
.svc-ridge-far{ opacity:.28; }
.svc-fwy{ fill:none; stroke:rgba(237,232,220,.16); stroke-width:1.2; }
.svc-fwy-major{ stroke:rgba(237,232,220,.24); }

.svc-ring{ fill:none; stroke:var(--accent-text); stroke-width:1.1; opacity:.5; }
.svc-ring-office{ opacity:.32; }
.svc-node{ fill:var(--accent-text); }

.svc-num{
  font-family:var(--mono); font-weight:700;
  font-size:19px; letter-spacing:.06em;
  fill:var(--fg);
}
.svc-terrain,.svc-fwy-label{
  font-family:var(--mono); font-size:14px; letter-spacing:.22em;
  text-transform:uppercase; fill:var(--fg-faint);
}
.svc-fwy-label{ letter-spacing:.1em; }
.svc-scale{ stroke:var(--fg-faint); stroke-width:1.2; fill:none; }

/* The plate scales with its column, so the numerals are stepped to land at
   roughly the same optical size on every width rather than shrinking away. */
@media (max-width:1100px){
  .svc-num{ font-size:25px; }
  .svc-terrain,.svc-fwy-label{ font-size:19px; }
}
@media (max-width:900px){
  .map-block{ grid-template-columns:minmax(0,1fr); }
  .svc-num{ font-size:21px; }
  /* freeway numerals and chrome go, but the ranges stay: without their
     names the plate reads as an empty dark field rather than as terrain */
  .svc-fwy-label,.svc-chrome,.svc-terrain-minor{ display:none; }
  .svc-terrain{ font-size:24px; }
}
@media (max-width:760px){ .svc-num{ font-size:26px; } .svc-terrain{ font-size:28px; } }
@media (max-width:600px){ .svc-num{ font-size:32px; } .svc-terrain{ font-size:34px; } }
@media (max-width:460px){ .svc-num{ font-size:41px; } .svc-terrain{ font-size:42px; } }

.map-side h3{
  font-family:var(--display); font-weight:600; letter-spacing:-.02em;
  font-size:clamp(1.5rem,2.3vw,2.07rem); line-height:1.08; margin-bottom:14px;
}
.map-side p{ color:var(--fg); margin-bottom:26px; }

.map-legend{
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:2px 18px;
  margin:0; padding:0; list-style:none;   /* ol is not covered by the base reset */
}
@media (max-width:520px){ .map-legend{ grid-template-columns:minmax(0,1fr); } }
.map-legend li{
  display:flex; align-items:baseline; gap:10px;
  padding-block:7px;
  border-top:1px solid var(--rule-soft);
}
.map-legend .lg-n{
  font-family:var(--mono); font-size:11.5px; letter-spacing:.1em;
  color:var(--accent-text); flex:0 0 auto;
}
.map-legend .lg-c{ font-size:.94em; }
.map-office{
  margin-top:22px;
  font-family:var(--mono); font-size:11.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--fg-muted); line-height:1.8;
}

/* ---------- SECTION BACKDROPS ----------
   A loop behind a section, always under a scrim that keeps the text side
   solid. The video never fights the copy: the scrim is opaque where the
   words are and clears where they are not. */
.section-listings,.section-open,.section-contact{ position:relative; overflow:hidden; }
.sec-bg,.listings-bg{ position:absolute; inset:0; z-index:0; }
.sec-bg .bg-video,.listings-bg .bg-video{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
}
.sec-bg .bg-video.is-playing,.listings-bg .bg-video.is-playing{ opacity:.5; }

.sec-scrim,.listings-scrim{ position:absolute; inset:0; }
.listings-scrim,.sec-scrim-right{
  background:
    linear-gradient(100deg, var(--bg) 0%, color-mix(in srgb,var(--bg) 78%,transparent) 46%, color-mix(in srgb,var(--bg) 34%,transparent) 100%),
    linear-gradient(to bottom, var(--bg) 0%, transparent 22%, transparent 78%, var(--bg) 100%);
}
.sec-scrim-left{
  background:
    linear-gradient(260deg, var(--bg) 0%, color-mix(in srgb,var(--bg) 76%,transparent) 44%, color-mix(in srgb,var(--bg) 30%,transparent) 100%),
    linear-gradient(to bottom, var(--bg) 0%, transparent 20%, transparent 80%, var(--bg) 100%);
}
@supports not (background:color-mix(in srgb,red 50%,blue)){
  .listings-scrim,.sec-scrim-right{ background:linear-gradient(100deg,var(--bg) 0%,rgba(11,12,15,.6) 60%,transparent 100%); }
  .sec-scrim-left{ background:linear-gradient(260deg,var(--bg) 0%,rgba(11,12,15,.6) 60%,transparent 100%); }
}
.section-listings .listings-inner,
.section-open .wrap,
.section-contact .wrap{ position:relative; z-index:1; }
.listings-body{ margin-block:clamp(20px,2.4vw,32px) clamp(26px,3vw,40px); color:var(--fg); }

.contact-grid{
  display:grid; gap:clamp(34px,5vw,84px);
  grid-template-columns:minmax(0,.85fr) minmax(0,1fr);
  align-items:start;
}
.contact-body{ margin-block:clamp(20px,2.4vw,32px) clamp(24px,3vw,36px); }
.contact-list{ display:flex; flex-direction:column; gap:10px; margin-bottom:26px; }
.contact-list a{
  font-family:var(--mono); font-size:14px; letter-spacing:.14em;
  text-decoration:none; color:var(--fg); border-bottom:1px solid var(--rule);
  padding-bottom:4px; display:inline-block;
  transition:border-color 300ms var(--ease);
}
.contact-list a:hover{ border-color:var(--accent-text); }
.contact-office{
  font-size:12.5px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--fg-muted); line-height:2;
}

/* ---------- 10. FORM ---------- */
.contact-form{ border:1px solid var(--rule); padding:clamp(22px,3vw,42px); background:var(--field-bg); }
.field{ margin-bottom:20px; }
.field label{
  display:block; font-size:11px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--fg-muted); margin-bottom:9px;
}
.field input,.field textarea{
  width:100%; min-height:48px; padding:13px 14px;
  font-family:var(--mono); font-size:16px; color:var(--fg);
  background:transparent; border:1px solid var(--rule); border-radius:0;
  transition:border-color 300ms var(--ease);
}
.field textarea{ resize:vertical; min-height:132px; line-height:1.6; }
.field input:hover,.field textarea:hover{ border-color:var(--fg-faint); }
.field input:focus,.field textarea:focus{ border-color:var(--accent-text); }
.cf-turnstile{ margin-top:22px; min-height:65px; }
.field-actions{ margin-top:26px; }
.form-note{ margin-top:20px; font-size:11.5px; letter-spacing:.1em; color:var(--fg-muted); line-height:1.9; }
.form-note a{ color:var(--fg); }
.hp-field{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }

/* ---------- 11. FOOTER ---------- */
.site-foot{
  border-top:1px solid var(--rule);
  padding-block:clamp(52px,7vw,96px) clamp(40px,5vw,64px);
  background:var(--bg-2);
}
.foot-grid{ display:grid; gap:clamp(34px,4vw,64px); grid-template-columns:auto 1fr; align-items:start; }
.foot-brand{ display:flex; flex-direction:column; gap:18px; }
.foot-tag{ font-family:var(--display); font-weight:500; font-size:1.1rem; letter-spacing:-.01em; color:var(--fg-muted); }
.foot-cols{ display:flex; flex-wrap:wrap; gap:clamp(28px,5vw,80px); justify-content:flex-end; }
@media (max-width:900px){ .foot-cols{ justify-content:flex-start; } }
.foot-nav{ display:flex; flex-direction:column; gap:8px; }
.foot-nav a{
  font-size:11.5px; letter-spacing:.2em; text-transform:uppercase;
  text-decoration:none; color:var(--fg-muted); padding:7px 0;
  transition:color 300ms var(--ease);
}
.foot-nav a:hover{ color:var(--fg); }
.foot-contact{ display:flex; flex-direction:column; gap:8px; }
.foot-contact a{
  font-family:var(--mono); font-size:12.5px; letter-spacing:.12em;
  color:var(--fg-muted); text-decoration:none; padding:7px 0;
  transition:color 300ms var(--ease);
}
.foot-contact a:hover{ color:var(--fg); }

.legal{
  grid-column:1 / -1;
  border-top:1px solid var(--rule-soft);
  padding-top:clamp(28px,3.4vw,44px);
  display:flex; flex-direction:column; gap:9px;
}
.legal-line,.legal-eho,.legal-ai,.legal-fine,.legal-copy{
  font-size:12.5px; letter-spacing:.09em; line-height:1.85; color:var(--fg-muted);
}
.legal-line strong{ color:var(--fg); font-weight:500; letter-spacing:.14em; }
.legal-eho{ display:flex; align-items:center; gap:10px; color:var(--fg); margin-top:6px; text-transform:uppercase; letter-spacing:.16em; font-size:11.5px; }
.eho{ width:26px; height:26px; flex:0 0 auto; color:var(--fg); }
.legal-ai{ margin-top:10px; max-width:78ch; color:var(--fg-muted); font-size:10px; }
.legal-fine{ margin-top:6px; max-width:88ch; color:var(--fg-muted); font-size:11.5px; }
.legal-copy{ margin-top:12px; }
.legal-copy a{ color:var(--fg-muted); }

/* ---------- 12. PRIVACY PAGE ---------- */
.page-head{ padding-block:clamp(90px,12vw,150px) clamp(30px,4vw,54px); }
.prose h2{
  font-family:var(--display); font-weight:600; letter-spacing:-.02em;
  font-size:clamp(1.44rem,2.4vw,2rem); line-height:1.12;
  margin-block:clamp(34px,4vw,54px) 14px;
}
.prose p,.prose li{ color:var(--fg); margin-bottom:1em; max-width:70ch; }
.prose ul{ padding-left:1.1em; list-style:disc; }
.prose li{ margin-bottom:.5em; }
.prose a{ color:var(--fg); }

/* ---------- 13. REVEAL ---------- */
.reveal{ opacity:0; transform:translateY(22px); transition:opacity 900ms var(--ease), transform 900ms var(--ease); }
.reveal.is-in{ opacity:1; transform:none; }

/* ---------- 14. RESPONSIVE ---------- */
@media (max-width:1100px){
  .site-nav{ gap:14px; }
  .site-nav a{ font-size:10.5px; letter-spacing:.14em; }
}

@media (max-width:900px){
  .about-grid,.approach-grid,.contact-grid{ grid-template-columns:minmax(0,1fr); }
  .about-grid{ gap:clamp(20px,3vw,34px); }
  .hood-grid{ grid-template-columns:minmax(0,1fr); }
  .foot-grid{ grid-template-columns:minmax(0,1fr); }
}

/* Below 820px: drop the HUD, simplify the glass, keep it fast and flat.
   The nav stays: on a phone it becomes a slim second row under the mark,
   scrollable sideways if a translation ever makes the words longer. */
@media (max-width:820px){
  .site-head{
    flex-direction:column; align-items:flex-start; gap:2px;
    padding:12px var(--gut) 4px;
  }
  .brand-mark{ width:104px; }
  .site-nav{
    width:100%; gap:14px;
    overflow-x:auto; -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  .site-nav::-webkit-scrollbar{ display:none; }
  .site-nav a{ font-size:9.5px; letter-spacing:.12em; padding:12px 2px; min-height:44px; white-space:nowrap; }
  /* the compensation above is written against the desktop bar; this is the
     phone bar's real height, so the hero still starts under it exactly */
  .hero-stage{ margin-top:-128px; padding-top:128px; }
  .reg{ display:none; }
  .about-meta .hud-dot{ display:none; }
  /* One AI disclosure per section is enough on a phone: the three identical
     per-card notes fold into the single grid caption below them, which names
     AI explicitly. B&P §10140.8 disclosure stays: grid caption, the approach
     figure's own note, and the footer block all remain. */
  .hood .img-note{ display:none; }
  .hero-bloom{ animation:none; opacity:.22; }

  /* The prism keeps its desktop life here: resting on her raised hand,
     opening into the refracted scene on scroll. main.js measures the real
     geometry, so no repositioning is needed at this width. */

  .hero-stage{ min-height:96svh; }
  .wm-alla{ top:9%; font-size:clamp(2.6rem,16vw,5.4rem); }
  /* She stands full height to the floor of the hero, as on desktop, and the
     name crosses her legs at the same point of the silhouette. 78% here and
     74% on desktop land on the same narrow strip of the cut-out; the
     difference is only the ratio of type height to stage height. */
  .wm-novytska{ top:78%; font-size:clamp(1.6rem,10.4vw,3.6rem); }
  .hero-figure{ left:57%; height:74%; bottom:0; }
  .tagline{ margin-bottom:22px; }
  .hero-side{ left:16px; bottom:18px; }
  .hero-side-line{ height:clamp(52px,10vh,90px); }
  .scroll-cue{ display:none; }
  .section p{ max-width:none; }

  /* touch targets: 44px minimum on every interactive element */
  .link-quiet{ padding:14px 0 12px; }
  .contact-list a{ padding:13px 0 11px; }
  .foot-nav a,.foot-contact a{ padding:14px 0; }
  .legal-copy a,.form-note a,.prose a{ position:relative; display:inline-block; }
  .legal-copy a::after,.form-note a::after,.prose a::after{
    content:""; position:absolute; left:-6px; right:-6px; top:50%;
    transform:translateY(-50%); height:44px;
  }
}

@media (max-width:520px){
  .hero-cta{ gap:16px; }
  .btn{ padding:13px 20px; font-size:11.5px; }
  .wm-novytska{ font-size:clamp(1.4rem,8.8vw,2.6rem); }
  .hero-figure{ height:58%; bottom:19%; }
}

/* ---------- 15. ACCESSIBILITY AND PRINT ---------- */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  .hero-bloom,.scroll-cue-line{ animation:none; }
  .reveal{ opacity:1; transform:none; }
}

@media (prefers-reduced-transparency:reduce){
  .prism{
    -webkit-backdrop-filter:none; backdrop-filter:none;
    background:linear-gradient(100deg,rgba(181,123,236,.15),rgba(111,150,232,.11));
  }
  .hero-bloom{ opacity:.16; }
}

@media (prefers-contrast:more){
  body{ --fg-muted:#D2D6DB; --rule:rgba(237,232,220,.4); }

}

@media print{
  .hero-bloom,.grain,.prism,.reg,.scroll-cue,  *{ mix-blend-mode:normal !important; -webkit-backdrop-filter:none !important; backdrop-filter:none !important; }
  body{ background:#fff; color:#000; }
  .hero-stage{ min-height:auto; }
}

/* ---------- 16. SCROLL BEAM ----------
   A thin ray of light along the top edge tracks reading progress.
   Its leading tip carries the iridescent dispersion accents; when the
   reader crosses into a new section the tip briefly flares into spectrum.
   Decorative only: pointer-events none, aria-hidden in the markup. */
.scroll-beam{
  position:fixed; top:0; left:0; width:100%; height:2px;
  z-index:140; pointer-events:none;
}
.scroll-beam__fill{
  position:absolute; inset:0;
  transform:translateX(-100%);
  will-change:transform;
  background:linear-gradient(90deg,
    transparent 0%,
    rgba(237,232,220,.30) 58%,
    var(--i3) 90%,
    var(--i4) 96%,
    var(--i6) 100%);
}

.scroll-beam__tip{
  position:absolute; right:0; top:50%;
  width:28px; height:28px;
  transform:translate(50%,-50%);
  border-radius:50%;
  opacity:.55;
  background:radial-gradient(closest-side,
    rgba(255,255,255,.60),
    rgba(111,184,232,.30) 38%,
    rgba(116,224,201,.16) 58%,
    rgba(242,192,123,.10) 68%,
    transparent 74%);
}

.scroll-beam.is-flare .scroll-beam__tip{
  animation:beam-flare 780ms var(--ease);
}
@keyframes beam-flare{
  0%   { transform:translate(50%,-50%) scale(.55); opacity:.95; }
  45%  { transform:translate(50%,-50%) scale(2.15); opacity:.85; }
  100% { transform:translate(50%,-50%) scale(1);   opacity:.55; }
}
@media (prefers-reduced-motion: reduce){
  .scroll-beam__tip{ opacity:.35; }
  .scroll-beam.is-flare .scroll-beam__tip{ animation:none; }
}
@media print{ .scroll-beam{ display:none; } }

/* ---------- 17. PRISM LENS ----------
   The band is a piece of optical glass standing on her raised hand. What
   you see through it is this same hero, thrown sideways and split into
   spectrum, and as the page scrolls the glass opens until the refraction
   fills the frame and settles back into a clean picture. The geometry is
   written by main.js; everything here is what it writes into. */
/* Geometry is derived from the band, not guessed: the band runs from
   -6% to 106% of the stage and its mask is solid between 30% and 72% of
   its own height, which lands at 28% to 74% of the stage. The hit area
   covers exactly that solid middle and nothing else. */
@media (max-width:820px){
  /* below 820 the band moves to left:26%/15vw, so the hit area follows it */
  }

/* The scroll handler writes transform every frame while the glass is
   opening and switches this off, so the easing only ever applies at rest. */
.prism{ transition:transform 500ms var(--ease); }

.prism-window{
  position:absolute; inset:0; display:block; overflow:hidden;
  /* the vertical fade lives on the band; this is the matching one across it,
     so the opened glass has no hard left or right edge either */
  -webkit-mask-image:linear-gradient(to right,transparent 0%,#000 6%,#000 94%,transparent 100%);
          mask-image:linear-gradient(to right,transparent 0%,#000 6%,#000 94%,transparent 100%);
}
/* The spectrum a real prism throws. Strongest through the narrow band and
   easing away as the glass opens, so the reveal lands on a clean picture. */
.prism-window::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(100deg,
    rgba(232,93,158,.22) 0%,
    rgba(181,123,236,.14) 32%,
    rgba(111,184,232,.15) 64%,
    rgba(116,224,201,.20) 100%);
  opacity:var(--disp,1);
}
/* Hidden until JS measures the hero and counter-rotates the scene.
   Without JS the prism simply stays the decorative glass it was. */
.prism-unrotate{
  position:absolute; display:none; will-change:transform;
  /* glass gathers the light that passes through it, which is what makes the
     band read as an object rather than as a smudge on a dark picture */
  filter:brightness(calc(1 + 0.30 * var(--disp,1))) saturate(calc(1 + 0.30 * var(--disp,1)));
}
.prism-unrotate > *{ display:block; }

.pw-bg{ position:absolute; inset:0; }
.prism-unrotate .pw-bg{ background:#0B0C0F; }
.pw-photo{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.prism-unrotate .pw-photo{ opacity:.52; filter:saturate(.7) contrast(1.06); }
.pw-scrim{ position:absolute; inset:0; }
.prism-unrotate .pw-scrim{
  background:
    radial-gradient(120% 78% at 50% 22%, transparent 0%, #0B0C0F 78%),
    linear-gradient(to bottom, rgba(11,12,15,.62) 0%, transparent 34%, rgba(11,12,15,.88) 100%);
}
.pw-wordmark{
  font-weight:600; text-transform:uppercase; line-height:.78;
}
.prism-unrotate .pw-wordmark{ color:#EDE8DC; }
.prism-unrotate .pw-wordmark .wm-alla,
.prism-unrotate .pw-wordmark .wm-novytska{
  text-shadow:
    var(--fringe,3px) 0 0 rgba(111,184,232,.5),
    calc(var(--fringe,3px) * -1) 0 0 rgba(216,120,236,.42),
    0 0 60px rgba(11,12,15,.7);
}
.prism-unrotate .pw-wordmark .wm-novytska{ color:rgba(237,232,220,.88); }
.pw-figure{
  position:absolute; z-index:2;
  left:57%; bottom:0; transform:translateX(-50%);
  height:74%; width:auto; object-fit:contain;
}
/* Chromatic fringing: glass does not bend every wavelength by the same
   amount, so through the band her edges carry a cyan and a magenta ghost.
   --fringe is written by the scroll handler and relaxes to nothing as the
   glass opens. */
.prism-unrotate .pw-figure{
  filter:
    drop-shadow(var(--fringe,3px) 0 0 rgba(111,184,232,.55))
    drop-shadow(calc(var(--fringe,3px) * -1) 0 0 rgba(216,120,236,.45))
    drop-shadow(0 40px 60px rgba(0,0,0,.45));
}
/* When the lens scene is live the band is fully covered, so the
   backdrop blur underneath would only waste GPU time. */
.prism.is-lens{ -webkit-backdrop-filter:none; backdrop-filter:none; }

/* The hero's labels, tagline and buttons live under the glass. As it opens
   the refracted picture would wash them out, so they dissolve with it and
   stop taking clicks well before they become hard to read.
   --reveal is written by the scroll handler; with no JS it is simply absent
   and everything below resolves to full opacity. */
.hero-side,.hero .scroll-cue{
  opacity:clamp(0, calc(1 - var(--reveal,0) * 1.6), 1);
}
.hero-stage.is-open .scroll-cue{ pointer-events:none; }
