/* ═══════════════════════════════════════════════════════════════════════════
   lg.css — the Liquid Glass material, one CSS layer per optical behaviour
   ───────────────────────────────────────────────────────────────────────────
   lg-core.js injects four spans into every [data-lg] host. Nothing here knows
   about the page; the material is a component you drop onto anything.

     .lg        HOST — carries the backdrop pass itself (see below)
     .lg__tint   adaptive tint + the vertical brightness ramp
     .lg__spec   generated specular rim, plus-lighter            (from JS)
     .lg__edge   1px inner hairline, bright at the top

   Every layer answers to a --lg-show-* switch so any one of them can be pulled
   out of the stack while the page keeps running. That is what lab.html drives.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* Material constants. Overridable per host. */
  --lg-radius:22px;
  --lg-spec-boost:1;
  --lg-spec-opacity:.72;
  --lg-edge-top:.55;        /* hairline brightness where the light hits      */
  --lg-edge-bottom:.14;     /* …and where it does not                        */
  --lg-tint-dark:.055;      /* white veil when the glass sits over dark art  */
  --lg-tint-light:.52;      /* pale-grey veil when it sits over bright art   */

  /* Apple's shadows are not decoration: they scale with the apparent
     thickness of the element and deepen over text. Three presets. */
  --lg-shadow-sm:0 1px 2px rgba(0,0,0,.10), 0 4px 12px -2px rgba(0,0,0,.22);
  --lg-shadow-md:0 2px 6px rgba(0,0,0,.12), 0 12px 32px -8px rgba(0,0,0,.34);
  --lg-shadow-lg:0 4px 14px rgba(0,0,0,.14), 0 30px 70px -18px rgba(0,0,0,.46);
}

/* ─────────────────────────────────────────────────────────────────────────
   THE HOST — and the one rule that decides whether any of this works
   ─────────────────────────────────────────────────────────────────────────
   The backdrop pass lives on the HOST, not on a child.

   That is not a style choice. `isolation:isolate`, `will-change`,
   `mix-blend-mode` and friends each make an element a BACKDROP ROOT, and a
   backdrop-filter only ever samples what was painted inside its nearest
   backdrop root. Put the filter on a child of an isolated host and it has
   nothing left to look at — in Chromium it does not fail cleanly either, it
   half-renders: a band of the element filters and the rest passes straight
   through, which reads like a blur that "sometimes" works.

   So: filter on the host, no isolation, no will-change. backdrop-filter
   already establishes a stacking context, which is all plus-lighter on
   .lg__spec needs to stay contained.
   ───────────────────────────────────────────────────────────────────────── */
.lg{
  position:relative;
  border-radius:var(--lg-radius);
  box-shadow:var(--lg-shadow, var(--lg-shadow-md));
  /* backdrop-filter: written by lg-core.js — an SVG url() where the engine
     supports it, a blur() chain where it does not. */
}
html[data-lg-hide-lens] .lg{ backdrop-filter:none !important;
                             -webkit-backdrop-filter:none !important; }

.lg > .lg__tint,
.lg > .lg__spec,
.lg > .lg__edge,
.lg > .lg__touch{
  position:absolute;
  inset:0;
  border-radius:inherit;
  pointer-events:none;
  display:block;
}

/* 2 ── TINT ──────────────────────────────────────────────────────────────
   Two jobs. A flat veil that lifts contrast for whatever sits on the glass,
   and a top-to-bottom ramp: light arrives from above, so the upper half of a
   real slab is brighter than the lower. Without the ramp the panel reads as a
   sticker rather than as a solid. */
.lg > .lg__tint{
  /* NEGATIVE, and it has to be.
     Painting order inside a stacking context puts positioned descendants
     (z-index 0 or more) ABOVE in-flow content. A tint at z-index 1 therefore
     sits on top of the host's own label — invisible while the tint is a 5%
     white veil over a dark page, and a wash that eats the text the moment the
     material adapts to a light background. z-index:-1 paints it above the
     backdrop pass and below the content, which is where a tint belongs.
     Safe because the host is always a stacking context: it carries the
     backdrop-filter. */
  z-index:-1;
  background:
    linear-gradient(180deg,
      rgba(255,255,255,.10) 0%,
      rgba(255,255,255,.02) 42%,
      rgba(255,255,255,0)   68%,
      rgba(0,0,0,.05)      100%),
    rgba(255,255,255,var(--lg-tint-dark));
}

/* Adaptive tone. lg-core's adapt() writes data-lg-tone from what is actually
   under the element, so a pill crossing from a dark hero onto a white section
   flips exactly the way a system control does. */
.lg[data-lg-tone="light"]{
  --lg-shadow:0 1px 2px rgba(0,0,0,.05), 0 10px 30px -10px rgba(0,0,0,.20);
  --lg-spec-opacity:.34;      /* a white highlight on white is only noise */
  color:#1b1a21;
}
/* Over a bright backdrop the veil has to LOWER the value, not raise it, or the
   control disappears into the page. Apple's light glass reads as a pale grey
   pane, never as white-on-white. */
.lg[data-lg-tone="light"] > .lg__tint{
  background:
    linear-gradient(180deg,
      rgba(255,255,255,.42) 0%,
      rgba(255,255,255,.10) 46%,
      rgba(12,10,20,.045)  100%),
    rgba(246,245,250,var(--lg-tint-light));
}
/* …and the hairline has to be dark. A white rim on a white page is invisible,
   which is exactly the failure that makes most "adaptive" glass on the web
   look broken in light mode. */
.lg[data-lg-tone="light"] > .lg__edge{
  background:linear-gradient(
      var(--lg-edge-angle, 175deg),
      rgba(0,0,0,.10) 0%,
      rgba(0,0,0,.16) 44%,
      rgba(0,0,0,.20) 100%);
}

/* Clear variant — permanently transparent, no adaptive veil. Apple allow it
   only over media-rich content, with a dimming layer, and with bold bright
   content on top. The dim is part of the variant, not an afterthought. */
.lg[data-lg-variant="clear"] > .lg__tint{
  background:
    linear-gradient(180deg, rgba(255,255,255,.07), rgba(255,255,255,0) 60%),
    linear-gradient(0deg, rgba(0,0,0,.28), rgba(0,0,0,.12));
}

/* 3 ── SPECULAR ─────────────────────────────────────────────────────────
   A generated PNG: white, with alpha = Blinn-Phong intensity + Fresnel,
   evaluated against the same normal field that drove the refraction. It is
   ADDITIVE (plus-lighter), because a highlight is light arriving, not paint
   sitting on top. */
.lg > .lg__spec{
  /* Above the host's own content, not below it. The highlight lives on the TOP
     surface of the slab, so anything sitting inside the glass — a label, a
     thumbnail, an icon — is under it. It only ever touches the rim, so it never
     lands on type. Same for the hairline. */
  z-index:6;
  opacity:calc(var(--lg-spec-opacity) * var(--lg-spec-boost));
  mix-blend-mode:plus-lighter;
  background-repeat:no-repeat;
  background-size:100% 100%;
  transition:opacity .28s cubic-bezier(.32,.72,0,1);
}

/* 4 ── EDGE ─────────────────────────────────────────────────────────────
   The hairline where the glass meets the air. A gradient border, cut with the
   mask-composite trick so it stays exactly 1px and follows the radius. */
.lg > .lg__edge{
  z-index:7;
  padding:1px;
  background:linear-gradient(
      var(--lg-edge-angle, 175deg),
      rgba(255,255,255,var(--lg-edge-top)) 0%,
      rgba(255,255,255,calc(var(--lg-edge-top) * .38)) 26%,
      rgba(255,255,255,calc(var(--lg-edge-bottom) * .9)) 62%,
      rgba(255,255,255,var(--lg-edge-bottom)) 100%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite:exclude;
}

/* ─────────────────────────────────────────────────────────────────────────
   WHILE THE BOX IS MOVING
   The specular map is a bitmap painted at 100% × 100% of the host, so any
   non-uniform resize squashes its rim — the visible "stretch" when a sidebar
   collapses. Hide it for the duration and let the hairline carry the edge:
   that one IS a CSS gradient, so it is redrawn correctly at every width.
   lg-core adds and removes this attribute around any animated resize.
   ───────────────────────────────────────────────────────────────────────── */
.lg[data-lg-resizing] > .lg__spec{ opacity:0; transition:opacity .1s linear; }
.lg[data-lg-resizing] > .lg__edge{ --lg-edge-top:.92; --lg-edge-bottom:.30; }
/* Coming back: the rim fades in rather than appearing, so the settle reads as
   the glass catching the light instead of a graphic popping on. */
.lg:not([data-lg-resizing]) > .lg__spec{ transition:opacity .34s cubic-bezier(.32,.72,0,1); }

/* Layer switches live on <html> as data attributes rather than as custom
   properties, because pulling the lens has to remove the backdrop-filter
   outright: an opacity of 0 would keep the (expensive) pass running AND keep
   the element a stacking context, so you would be dissecting something that
   still behaves differently from the real thing. */
html[data-lg-hide-tint] .lg > .lg__tint,
html[data-lg-hide-spec] .lg > .lg__spec,
html[data-lg-hide-edge] .lg > .lg__edge{ display:none; }

/* ─────────────────────────────────────────────────────────────────────────
   INTERACTION
   "Responds to interaction by instantly flexing and energizing with light."
   Press = the slab compresses slightly and the highlight blooms; release
   overshoots on a spring rather than easing, because glass is a gel here.
   ───────────────────────────────────────────────────────────────────────── */
.lg[data-lg-interactive]{
  transition:transform .34s cubic-bezier(.2,1.3,.35,1),
             box-shadow .34s cubic-bezier(.32,.72,0,1);
}
.lg[data-lg-interactive]:hover{ --lg-spec-opacity:.92; }
.lg[data-lg-interactive]:active{
  transform:scale(.972);
  --lg-spec-opacity:1.15;
  transition-duration:.09s;
}

/* The glow that spreads from a fingertip. A radial wash positioned by JS from
   the pointer, additive, clipped to the host. */
.lg > .lg__touch{
  position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  z-index:-1; mix-blend-mode:plus-lighter; opacity:0;
  background:radial-gradient(120px 120px at var(--lg-tx,50%) var(--lg-ty,50%),
             rgba(255,255,255,.30), rgba(255,255,255,0) 70%);
  transition:opacity .5s cubic-bezier(.32,.72,0,1);
}
.lg[data-lg-interactive]:hover > .lg__touch{ opacity:1; }

/* ─────────────────────────────────────────────────────────────────────────
   ACCESSIBILITY — the same three overrides the system applies
   ───────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-transparency: reduce){
  .lg{ backdrop-filter:blur(30px) saturate(1.2) !important;
       -webkit-backdrop-filter:blur(30px) saturate(1.2) !important; }
  .lg > .lg__tint{ background:rgba(20,18,28,.86) !important; }
  .lg[data-lg-tone="light"] > .lg__tint{ background:rgba(250,250,252,.94) !important; }
}
@media (prefers-contrast: more){
  .lg > .lg__tint{ background:rgba(12,10,18,.92) !important; }
  .lg > .lg__edge{ --lg-edge-top:1; --lg-edge-bottom:.7; }
  .lg > .lg__spec{ opacity:0 !important; }
}
@media (prefers-reduced-motion: reduce){
  .lg,.lg *{ transition-duration:.01ms !important; animation-duration:.01ms !important; }
}
