/* core/fabric.css — the "liquid fabric" surface primitive.
   ---------------------------------------------------------------------------
   ONE hook you can drop on any layer:

       <div data-fabric>            surface
       <div data-fabric="tilt">     surface + 3D tilt toward the pointer
       <div data-fabric="flat">     surface WITHOUT the backdrop blur
       <div data-fabric="none">     opt a child back out

   Reach for "flat" on big structural layers such as <main id="content">.
   backdrop-filter establishes a containing block, so a blurred #content would
   re-anchor every position:fixed descendant inside it to the panel instead of
   the viewport. "flat" keeps the film and the light and skips the blur.

   Behaviour:
     Liquid OFF  a very subtle glow that follows the pointer. Nothing else —
                 no blur, no tilt cost.
     Liquid ON   the layer becomes a very thin transparent liquid fabric:
                 a translucent film over a blurred backdrop, with a specular
                 highlight that tracks the pointer.

   Per-layer knobs (set them inline or in a component rule — they are LOCAL
   custom properties, never :root, because app.css owns :root):
     --fab-tint     film strength            default 2%
     --fab-blur     backdrop blur            default 10px
     --fab-light    pointer-light strength   default 7%
     --fab-radius   light radius             default 170px
     --fab-weave    thread contrast          default 4%
     --fab-thread   weave period             default 4px
     --fab-max      max tilt in degrees      default 4

   Pointer position (--fab-x/--fab-y) and tilt (--fab-rx/--fab-ry) are written
   by core/fabric.js.

   NOTE: deliberately no `isolation: isolate` here. Isolating would make every
   fabric layer a backdrop root and blind the backdrop-filter of any fabric
   nested inside it (the same trap documented on #sbFlyout). The film therefore
   lives in the element's own background rather than in a ::before, and only the
   light — which should fall on top of content anyway — uses a pseudo element.

   WHAT THIS FILE MUST NEVER SET ON A HOST
   ---------------------------------------
   `border` and `box-shadow` used to live in the rule below. Because the selector
   scores (0,3,1) it beat every `.u-*` utility and every component rule, so any
   layer that opted into fabric silently LOST its own edge: `.avsw`'s
   `border: var(--line)` vanished, the Web-Elements preview lost
   `u-bd--line` + `u-bs[...]`, and `#content` — a purely structural layer —
   gained a 1px border plus a `0 10px 30px` drop shadow it never asked for.
   That is what "damages the skeleton and many other things" was.

   The glass edge is therefore painted as a background LAYER (the top rim
   highlight below), not as a border or a shadow. `background-image` is safe to
   own here: `u-bg--strans` and friends compile to the `background` SHORTHAND,
   which sets `background-image: none` and `background-color: <token>` as
   separate longhands — so overriding only `background-image` leaves the host's
   colour intact. A host that paints its own background-IMAGE (a real texture,
   e.g. `u-bgi[...]`) must not use `data-fabric`; use a fabric wrapper instead.

   WHY A WEAVE
   -----------
   The old film was a 140deg two-stop wash, which reads as cheap gloss, not
   cloth. What makes a surface read as woven is a fine cross-hatch: a warp of
   light vertical threads over a weft of dark horizontal ones, at a period small
   enough to resolve as texture rather than as stripes. Both weave layers repeat;
   everything else is sized to the box and must stay `no-repeat` or it tiles and
   leaves a hard rectangular seam.
*/

[data-fabric] {
  position: relative;

  --fab-x: 50%;
  --fab-y: 50%;
  --fab-tint: 2%;
  --fab-blur: 10px;
  --fab-light: 7%;
  --fab-radius: 170px;
  --fab-weave: 4%;
  --fab-thread: 4px;
  --fab-max: 4;

  /* 0 → 1, driven by :hover so the light can ease in and out */
  --fab-glow: 0;
}

[data-fabric="none"] { --fab-glow: 0 !important; }

/* ---- the pointer light (both modes) --------------------------------------
   Sits above content: a specular highlight lands on what it illuminates. */
[data-fabric]:not([data-fabric="none"])::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  pointer-events: none;
  opacity: var(--fab-glow);
  transition: opacity var(--ui-motion-med, 240ms) ease;
  background: radial-gradient(
    var(--fab-radius) circle at var(--fab-x) var(--fab-y),
    color-mix(in srgb, var(--primary) 10%, transparent),
    transparent 68%
  );
}

[data-fabric]:not([data-fabric="none"]):hover { --fab-glow: 1; }

/* ---- liquid on: thin transparent fabric ----------------------------------- */
html[data-liquid-on] [data-fabric]:not([data-fabric="none"]) {
  /* Paint order, top layer first:
       1  top rim highlight  — the glass edge (see header: NOT a border)
       2  pointer sheen      — tracks --fab-x/--fab-y
       3  warp               — light vertical threads   (repeats)
       4  weft               — dark horizontal threads  (repeats)
       5  base film          — flat tint             */
  background-image:
    linear-gradient(color-mix(in srgb, #fff 9%, transparent), transparent),
    radial-gradient(88% 72% at var(--fab-x) var(--fab-y),
      color-mix(in srgb, #fff var(--fab-light), transparent), transparent 58%),
    repeating-linear-gradient(90deg,
      color-mix(in srgb, #fff var(--fab-weave), transparent) 0 1px,
      transparent 1px var(--fab-thread)),
    repeating-linear-gradient(0deg,
      color-mix(in srgb, #000 var(--fab-weave), transparent) 0 1px,
      transparent 1px var(--fab-thread)),
    linear-gradient(color-mix(in srgb, var(--text) var(--fab-tint), transparent),
      color-mix(in srgb, var(--text) var(--fab-tint), transparent));
  /* Only the weave repeats. The rim and the sheen are sized in % of the box, so
     without an explicit no-repeat they tile and leave hard seams. */
  background-repeat: no-repeat, no-repeat, repeat, repeat, no-repeat;
  background-size: 100% 1.5px, 100% 100%, auto, auto, 100% 100%;
  background-position: 0 0;
  transition: background-position var(--ui-motion-fast, 160ms) ease;
}

/* The blur is opt-out, because it establishes a containing block (see "flat").
   NOTE `tilt` is deliberately NOT in this list. An element with both `transform`
   and `backdrop-filter` samples the UNtransformed backdrop, so a tilting card
   blurs a slice of the page that no longer lines up with where the card is drawn
   — it reads as a smear that slides the wrong way as you move the pointer. Tilt
   cards get the film, the weave and the rotation; no blur. */
html[data-liquid-on] [data-fabric=""] {
  -webkit-backdrop-filter: blur(var(--fab-blur)) saturate(120%);
  backdrop-filter: blur(var(--fab-blur)) saturate(120%);
}

/* Inside a top-layer <dialog> (every Utilities.openBaseDialog modal, so the
   Settings modal and #settingsProfile with it) the backdrop root is the top
   layer, not the page — so a blurred fabric panel samples the wrong thing and
   renders as a flat grey slab that no component rule can style its way out of.
   The film and the weave still read correctly there; only the blur is dropped. */
html[data-liquid-on] dialog [data-fabric] {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* The pointer light is already in the film above, so keep the overlay faint
   rather than doubling it. */
html[data-liquid-on] [data-fabric]:not([data-fabric="none"])::after {
  background: radial-gradient(
    var(--fab-radius) circle at var(--fab-x) var(--fab-y),
    color-mix(in srgb, var(--primary) 5%, transparent),
    transparent 70%
  );
}

/* ---- structural layers: cloth, but no spotlight ---------------------------
   `flat` is for big layers like <main id="content">. A pointer-tracked sheen and
   a roaming --fab-radius spotlight are fine on a card you can see the edges of;
   spread across the entire route area they just look like a smear following the
   mouse over every page, and the ::after (z-index:1, inset:0) puts that smear
   ON TOP of all route content. So structural layers keep the weave and the flat
   tint — the parts that actually read as fabric — and drop both light layers. */
html[data-liquid-on] [data-fabric="flat"] {
  background-image:
    repeating-linear-gradient(90deg,
      color-mix(in srgb, #fff var(--fab-weave), transparent) 0 1px,
      transparent 1px var(--fab-thread)),
    repeating-linear-gradient(0deg,
      color-mix(in srgb, #000 var(--fab-weave), transparent) 0 1px,
      transparent 1px var(--fab-thread)),
    linear-gradient(color-mix(in srgb, var(--text) var(--fab-tint), transparent),
      color-mix(in srgb, var(--text) var(--fab-tint), transparent));
  background-repeat: repeat, repeat, no-repeat;
  background-size: auto, auto, 100% 100%;
  transition: none;
}

/* No overlay pseudo at all on structural layers — nothing to paint over content. */
[data-fabric="flat"]::after { content: none; }

/* Lite tier keeps the film but drops the (expensive) backdrop blur. */
html[data-liquid-tier="lite"] [data-fabric]:not([data-fabric="none"]) {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* ---- 3D tilt --------------------------------------------------------------
   `transform-style: preserve-3d` used to be here and it does not belong: there
   are no 3D children to preserve, and it promotes every descendant onto its own
   3D plane, which is what made text inside a tilting card render soft/crunchy
   and made absolutely-positioned children (`.avsw-check`) stack unpredictably.
   `flat` keeps the parent's own rotation and renders children normally.

   `will-change: transform` is also gone. It creates a containing block AND a
   backdrop root, so a tilting card would blind the backdrop-filter of any fabric
   nested inside it — the #sbFlyout trap again. The transform alone already gets
   its own compositor layer while animating. */
[data-fabric="tilt"] {
  --fab-rx: 0deg;
  --fab-ry: 0deg;
  transform: perspective(900px) rotateX(var(--fab-rx)) rotateY(var(--fab-ry));
  transform-style: flat;
  /* Slow, springy return; the JS shortens this while the pointer is inside so
     the card tracks rather than lags. */
  transition: transform 420ms cubic-bezier(.16, 1, .3, 1);
}

[data-fabric="tilt"].is-tilting { transition-duration: 90ms; }

@media (prefers-reduced-motion: reduce) {
  [data-fabric="tilt"] {
    transform: none !important;
    transition: none;
  }

  [data-fabric]::after { transition: none; }
}
