/* ==========================================================================
   Liquid Glass
   ==========================================================================
   A reusable recreation of Apple's iOS 26 / macOS Tahoe "Liquid Glass" material,
   as opposed to flat glassmorphism (backdrop-filter: blur() + rgba background).
   Loaded after custom.css so it wins on the selectors it shares with it.

   What each of the 8 traits from the brief maps to, in CSS terms:
     1. Blur + saturation             -> --lg-blur / --lg-saturate (base rule)
     2. Refraction / lensing          -> ONE shared, static SVG displacement
                                          filter (img/liquid-glass-filters.svg),
                                          applied via backdrop-filter: url(...).
                                          It uses primitiveUnits="objectBoundingBox",
                                          so the same cached filter resource
                                          scales correctly to any element's own
                                          size/shape - no per-element JS
                                          measuring or rebuilding needed.
                                          Chromium-only; plain blur/saturate
                                          elsewhere.
     3. Specular edge highlight       -> layered box-shadow (works everywhere,
                                          incl. ::before/::after) + an optional
                                          gradient-ring ::after on real elements
     4. Adaptive light/dark tint      -> --lg-tint-* driven by the site's
                                          existing [color-scheme] attribute
     5. Corner radius                 -> left as-is per component (main.css) -
                                          not overridden here, by request
     6. Depth (outer shadow + inner glow) -> combined in the same box-shadow stack
     7. Spring hover/active response,
        cursor-following highlight    -> --lg-spring cubic-bezier + --lg-mx/--lg-my
                                          custom properties (set by js/liquid-glass.js)
     8. Graceful degradation          -> @supports fallbacks throughout, and the
                                          box-shadow/tint alone already reads as
                                          "glass" with zero JS/filter support
   ========================================================================== */

:root {
  --lg-blur: 20px;
  --lg-saturate: 180%;
  --lg-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Light backdrop behind the glass -> same alpha values as dark mode below (per request: the
   glass should be equally translucent in both themes), just recolored for a light backdrop -
   white where dark mode uses white/dark-gray, the site's navy brand tone where dark mode
   uses black, since a literal black shadow/tint would read as dirty on a white surface. */
:root[color-scheme="light"] {
  --lg-tint: rgba(255, 255, 255, 0.40);
  --lg-tint-strong: rgba(255, 255, 255, 0.80);
  --lg-specular-top: rgba(255, 255, 255, 0.45);
  --lg-specular-bottom: rgba(16, 52, 100, 0.02);
  --lg-inner-top: rgba(255, 255, 255, 0.16);
  --lg-inner-bottom: rgba(16, 52, 100, 0.40);
  --lg-ambient: rgba(16, 52, 100, 0.45);
  --lg-fallback-bg: rgba(255, 255, 255, 0.86);
}

/* Dark backdrop behind the glass -> lighter, brighter tint (matches trait 4) */
:root[color-scheme="dark"] {
  --lg-tint: rgba(32, 32, 34, 0.40);
  --lg-tint-strong: rgba(24, 24, 26, 0.80);
  --lg-specular-top: rgba(255, 255, 255, 0.45);
  --lg-specular-bottom: rgba(255, 255, 255, 0.02);
  --lg-inner-top: rgba(255, 255, 255, 0.16);
  --lg-inner-bottom: rgba(0, 0, 0, 0.40);
  --lg-ambient: rgba(0, 0, 0, 0.45);
  --lg-fallback-bg: rgba(24, 24, 26, 0.86);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --lg-spring: ease;
  }
}

/* --------------------------------------------------------------------------
   Base material - blur, saturation, adaptive tint, layered depth shadow.
   This alone (no JS, no SVG filter, no Paint Worklet) already reads as glass,
   which is the fallback tier for browsers that support none of the enhancements.
   -------------------------------------------------------------------------- */
/* position: relative only where the element isn't already positioned.
   Two kinds of exception here, both already "positioned" per main.css:
   - .mxd-hero-05-videoblock__descr (doubled up as .mxd-attorney-hero__descr
     in custom.css) relies on position: absolute to pin itself to the bottom
     of its parallax photo - forcing `relative` here would win the cascade
     (this file loads after custom.css) and silently break that anchor.
   - The five ::before selectors (marquee/partners/tech-stack-v1&v2/team
     career) are each main.css's "glass background fill" pseudo-element:
     position: absolute; inset 0; z-index: -1, sized to cover its real parent
     while staying out of flow. Forcing `relative` on THEM turned each one
     from an invisible absolute backdrop into a real in-flow block - and
     since their parent is `display: flex`, that block became an actual
     (empty, blank) flex item sitting before the logo/text, squeezing both
     into the remaining space. That's what showed up as a blank pill floating
     next to the Education/Admissions/Partners/Team cards.
   `absolute` already counts as "positioned" for the ::after/::before
   pseudo-elements below, so none of these six need this rule at all. */
.liquid-glass,
.mxd-hero-05__worksblock,
.footer-blocks__card,
.mxd-hero-06__mark,
.hero-09-objects__item,
.mxd-article__block.block-table-of-contents,
.mxd-article-author,
.mxd-demo-list__item,
.mxd-demo-cards__item,
.demo-swiper-slide__image,
.mxd-pinned__img-wrap,
.mxd-pinned__img-mobile,
.marquee__component,
.mxd-tech-stack-cards__inner-v3,
.mxd-pricing-table__inner,
.bg-base-tint,
.btn-mobile-icon,
.btn-outline {
  position: relative;
}
/* .btn-to-top is deliberately NOT in the list above: main.css already gives
   it position: fixed (to pin it to the viewport corner) plus its own right/
   bottom offsets. "fixed" already counts as positioned for the ::after ring
   below, same as the absolute-positioned exceptions noted above - forcing
   position: relative here (equal specificity, this file loads later, so it
   would win) downgraded it from a fixed, viewport-pinned button to an
   in-flow relatively-positioned one, which is why it was rendering off-
   screen near the bottom of the page instead of floating over the content. */
.liquid-glass,
.mxd-hero-05__worksblock,
.footer-blocks__card,
.mxd-hero-06__mark,
.hero-09-objects__item,
.mxd-article__block.block-table-of-contents,
.mxd-article-author,
.mxd-demo-list__item,
.mxd-demo-cards__item,
.demo-swiper-slide__image,
.mxd-pinned__img-wrap,
.mxd-pinned__img-mobile,
.marquee__item.item-partners::before,
.marquee__component,
.mxd-partners-cards__inner::before,
.mxd-tech-stack-cards__inner::before,
.mxd-tech-stack-cards__inner-v2::before,
.mxd-tech-stack-cards__inner-v3,
.mxd-pricing-table__inner,
.mxd-team-cards__career::before,
.mxd-hero-05-videoblock__descr,
.hamburger__base,
.bg-base-tint,
.btn-to-top,
.btn-mobile-icon,
.btn-outline,
.tag-outline,
.tag-outline-medium,
.tag-outline-opposite,
.tag-outline-permanent {
  background-color: var(--lg-tint);
  -webkit-backdrop-filter: blur(var(--lg-blur)) saturate(var(--lg-saturate));
          backdrop-filter: blur(var(--lg-blur)) saturate(var(--lg-saturate));
  border: 1px solid transparent;
  box-shadow:
    0 1px 0 var(--lg-inner-top) inset,
    0 -14px 22px -16px var(--lg-inner-bottom) inset,
    0 18px 46px -14px var(--lg-ambient);
  transition:
    box-shadow 0.5s var(--lg-spring),
    background-color 0.5s var(--lg-spring),
    -webkit-backdrop-filter 0.4s ease;
  transition:
    box-shadow 0.5s var(--lg-spring),
    background-color 0.5s var(--lg-spring),
    backdrop-filter 0.4s ease;
}

/* Buttons/tags: only the transparent, bordered variants (.btn-outline and the
   .tag-outline* family) are given the glass treatment here - they already
   read as "a border around empty space", which is exactly what glass fills.
   The solid brand-color fills (.btn-accent/.btn-additional/.btn-opposite/
   .btn-base/.btn-permanent and their .tag- equivalents) are left alone on
   purpose: layering a translucent tint over them would just mute the brand
   color, working against the whole point of a solid CTA. .btn-outline is
   also the template's dominant button style (used on almost every CTA
   across the site), so this covers the vast majority of buttons/tags without
   touching the highlighted ones. */

/* No backdrop-filter support at all -> raise the fill opacity so the panel is
   still legible as a distinct surface instead of near-invisible (trait 8). */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .liquid-glass,
  .mxd-hero-05__worksblock,
  .footer-blocks__card,
  .mxd-hero-06__mark,
  .hero-09-objects__item,
  .mxd-article__block.block-table-of-contents,
  .mxd-article-author,
  .mxd-demo-list__item,
  .mxd-demo-cards__item,
  .demo-swiper-slide__image,
  .mxd-pinned__img-wrap,
  .mxd-pinned__img-mobile,
  .marquee__item.item-partners::before,
  .marquee__component,
  .mxd-partners-cards__inner::before,
  .mxd-tech-stack-cards__inner::before,
  .mxd-tech-stack-cards__inner-v2::before,
  .mxd-tech-stack-cards__inner-v3,
  .mxd-pricing-table__inner,
  .mxd-team-cards__career::before,
  .mxd-hero-05-videoblock__descr,
  .bg-base-tint,
  .btn-to-top,
  .btn-mobile-icon,
  .btn-outline,
  .tag-outline,
  .tag-outline-medium,
  .tag-outline-opposite,
  .tag-outline-permanent {
    background-color: var(--lg-fallback-bg);
  }
}

/* .mxd-hero-05-videoblock__descr is shared by two different cards: the
   homepage hero (Eric's photo + the awards row) and the attorney-bio page's
   name/role card (custom.css adds .mxd-attorney-hero__descr on top there,
   which floats over a different photo per attorney). Both now use the same
   shared recipe (base rule above: --lg-tint, standard shadow) so the glass
   opacity reads identically everywhere in the site, per request - there used
   to be a firmer, non-adaptive tint/shadow here scoped to the attorney-bio
   variant (tuned so the card stayed legible over an unpredictably bright
   photo), but that made this one card visibly more opaque than every other
   glass panel. If a future attorney photo turns out too bright for the
   shared --lg-tint to read against, fix it on that photo (an overlay/darken)
   rather than reintroducing a page-specific opacity here. */

/* The full-screen nav menu's "panel" isn't .mxd-menu__base (that one carries
   no background at all) - it's .hamburger__base, the small circle behind the
   hamburger icon, which app.js Flip-animates from that button into
   .mxd-menu__contain to become the whole menu surface. main.css originally
   made this panel (and its text: --t-opp-bright etc., see the override
   below) deliberately invert against the page - dark menu on the light
   theme, light menu on the dark theme. Per request the menu now matches the
   theme like every other glass surface instead: .hamburger__base is in the
   shared selector list above, so it already gets the normal (matching)
   tint and specular/inner/ambient tokens for the current scheme - nothing
   extra needed here. No SVG refraction on purpose - it's the one glass
   surface that can span the full viewport, and that's too much backdrop
   for a per-pixel filter. */

/* Un-invert the menu's text/icon colors to match the background above: every
   "opposite" text/font-weight custom property (main.css) that
   .hamburger__line, .main-menu__link, .submenu__item a, .mxd-menu__caption,
   .mxd-menu__data and .menu-promo__caption read from is redefined here,
   scoped to the menu's wrapper, to equal its non-opposite counterpart - so
   every one of those rules keeps working unmodified, it just resolves to
   the matching color now. */
.mxd-nav__wrap {
  --t-opp-bright: var(--t-bright);
  --t-opp-medium: var(--t-medium);
  --t-opp-muted: var(--t-muted);
  --fw-regular-opp: var(--fw-regular);
  --fw-medium-opp: var(--fw-medium);
}

/* Corner radius is intentionally left untouched here - every selector above
   keeps whatever border-radius it already had from main.css (circle for the
   two floating buttons, each card's own radius otherwise). The ::after
   specular ring below uses border-radius: inherit, so it automatically
   follows whatever that turns out to be. */

/* --------------------------------------------------------------------------
   Refraction / lensing (trait 2) - one shared, static SVG filter per variant
   (img/liquid-glass-filters.svg), only on the prominent, visually-relevant
   panels named in the brief (hero/footer/article/pricing cards, nav floating
   buttons). Left off small repeating tiles (marquee items, tech-stack/partner
   grid cells, demo list rows) on purpose: an SVG feDisplacementMap sample per
   backdrop pixel is real GPU/CPU cost, and Apple's own effect is never applied
   to dozens of small tiles at once either. Both filters use
   primitiveUnits="objectBoundingBox" so the exact same cached filter resource
   is reused correctly-scaled on every element that references it - no
   per-element JavaScript, no rebuilding anything on resize/scroll.
   -------------------------------------------------------------------------- */
@supports (backdrop-filter: url(x)) {
  .liquid-glass--distort,
  .mxd-hero-05__worksblock,
  .footer-blocks__card,
  .mxd-article-author,
  .mxd-pricing-table__inner,
  .mxd-hero-05-videoblock__descr {
    -webkit-backdrop-filter: url("../img/liquid-glass-filters.svg#liquid-glass-distortion-lg") blur(calc(var(--lg-blur) * 0.6)) saturate(var(--lg-saturate));
            backdrop-filter: url("../img/liquid-glass-filters.svg#liquid-glass-distortion-lg") blur(calc(var(--lg-blur) * 0.6)) saturate(var(--lg-saturate));
  }
  .btn-to-top,
  .btn-mobile-icon,
  .btn-outline {
    -webkit-backdrop-filter: url("../img/liquid-glass-filters.svg#liquid-glass-distortion") blur(calc(var(--lg-blur) * 0.4)) saturate(var(--lg-saturate));
            backdrop-filter: url("../img/liquid-glass-filters.svg#liquid-glass-distortion") blur(calc(var(--lg-blur) * 0.4)) saturate(var(--lg-saturate));
  }
}

/* --------------------------------------------------------------------------
   Specular edge ring (trait 3, enhanced) - a 1px gradient border, bright at
   the top, faint at the bottom, cut out with a mask so only the ring shows.
   Real elements only: ::before/::after targets above (marquee/partners/tech-
   stack/team pseudo-fills) can't host their own ::after, and rely on the
   box-shadow inset highlight from the base rule instead - still a real
   specular edge, just without the gradient ring layered on top.
   -------------------------------------------------------------------------- */
.liquid-glass::after,
.mxd-hero-05__worksblock::after,
.footer-blocks__card::after,
.mxd-hero-06__mark::after,
.hero-09-objects__item::after,
.mxd-article__block.block-table-of-contents::after,
.mxd-article-author::after,
.mxd-demo-list__item::after,
.mxd-demo-cards__item::after,
.demo-swiper-slide__image::after,
.mxd-pinned__img-wrap::after,
.mxd-pinned__img-mobile::after,
.mxd-tech-stack-cards__inner-v3::after,
.mxd-pricing-table__inner::after,
.mxd-hero-05-videoblock__descr::after,
.hamburger__base::after,
.bg-base-tint::after,
.btn-to-top::after,
.btn-mobile-icon::after,
.btn-outline::after,
.tag-outline::after,
.tag-outline-medium::after,
.tag-outline-opposite::after,
.tag-outline-permanent::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(180deg, var(--lg-specular-top) 0%, transparent 40%, transparent 65%, var(--lg-specular-bottom) 100%);
  -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;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   Interactive response (trait 7) - spring hover/active + a cursor-following
   specular highlight. Applied to the panels people actually click/hover
   (demo/pricing/article cards, floating nav buttons); left off passive
   background fills (partners/tech-stack tiles, marquee, pinned imagery).
   -------------------------------------------------------------------------- */
.liquid-glass--interactive,
.mxd-demo-list__item,
.mxd-demo-cards__item,
.mxd-article-author,
.mxd-pricing-table__inner,
.btn-outline,
.tag-outline,
.tag-outline-medium,
.tag-outline-opposite,
.tag-outline-permanent {
  --lg-mx: 50%;
  --lg-my: 0%;
  transition:
    -webkit-transform 0.5s var(--lg-spring), box-shadow 0.5s var(--lg-spring), background-color 0.5s var(--lg-spring);
  transition:
    transform 0.5s var(--lg-spring), box-shadow 0.5s var(--lg-spring), background-color 0.5s var(--lg-spring);
}
.no-touch .liquid-glass--interactive:hover,
.no-touch .mxd-demo-list__item:hover,
.no-touch .mxd-demo-cards__item:hover,
.no-touch .mxd-article-author:hover,
.no-touch .mxd-pricing-table__inner:hover,
.no-touch .btn-outline:hover,
.no-touch .tag-outline:hover,
.no-touch .tag-outline-medium:hover,
.no-touch .tag-outline-opposite:hover,
.no-touch .tag-outline-permanent:hover {
  -webkit-transform: translateY(-3px) scale(1.012);
          transform: translateY(-3px) scale(1.012);
  will-change: transform;
}
.liquid-glass--interactive:active,
.mxd-demo-list__item:active,
.mxd-demo-cards__item:active,
.btn-outline:active,
.tag-outline:active,
.tag-outline-medium:active,
.tag-outline-opposite:active,
.tag-outline-permanent:active {
  -webkit-transform: scale(0.985);
          transform: scale(0.985);
  transition-duration: 0.2s;
}

.liquid-glass--interactive::before,
.mxd-demo-list__item::before,
.mxd-demo-cards__item::before,
.mxd-article-author::before,
.mxd-pricing-table__inner::before,
.btn-outline::before,
.tag-outline::before,
.tag-outline-medium::before,
.tag-outline-opposite::before,
.tag-outline-permanent::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at var(--lg-mx) var(--lg-my), var(--lg-specular-top), transparent 45%);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
  mix-blend-mode: overlay;
}
.no-touch .liquid-glass--interactive:hover::before,
.no-touch .mxd-demo-list__item:hover::before,
.no-touch .mxd-demo-cards__item:hover::before,
.no-touch .mxd-article-author:hover::before,
.no-touch .mxd-pricing-table__inner:hover::before,
.no-touch .btn-outline:hover::before,
.no-touch .tag-outline:hover::before,
.no-touch .tag-outline-medium:hover::before,
.no-touch .tag-outline-opposite:hover::before,
.no-touch .tag-outline-permanent:hover::before {
  opacity: 0.55;
}

/* The two floating nav controls keep their existing scale(1.04) hover from
   main.css (untouched) - this only adds the spring easing and cursor glow. */
.btn-to-top,
.btn-mobile-icon {
  --lg-mx: 50%;
  --lg-my: 50%;
}
.no-touch .btn-to-top:hover,
.no-touch .btn-mobile-icon:hover {
  transition-timing-function: var(--lg-spring);
}
