/* ai.heart — silk material. One file, one link, one material.
   HK 2026-08-05. Reference: a limited-edition Art of War printed on
   silk-finish cream stock — warm ivory, a broad low-angle sheen, and a
   fibre mottle you notice only once you look for it.

   Physical spec (researched, governed answer from gpt-5.5):
     · hue ~40°, saturation 20–45%, lightness 82–96% — never yellow, never grey
     · silk sits between matte and gloss: the highlight is BROAD and shallow,
       not a narrow white stripe. Narrow stripes are what make fake silk cheap.
     · dark silk is not dark paper: the sheen survives and reads cool and
       smoky (blue-grey), never metallic, never warm.

   No images. Gradients plus one inline feTurbulence layer, so nothing extra
   is fetched. Body text stays >12:1 in light and >15:1 in dark.

   Applied to <body> by default. Any element can opt in with .silk, and a
   page can opt out entirely with <html data-no-silk>. */

:root, :root[data-theme="light"] {
  --silk-hi:   #faf7ef;
  --silk-lit:  #f5eedf;
  --silk-base: #eee4cf;
  --silk-mid:  #e3d4b7;
  --silk-low:  #d1bc94;
  --silk-ink:  #211c14;
}

:root[data-theme="dark"] {
  --silk-hi:   #10243a;
  --silk-lit:  #0a1422;
  --silk-base: #0a1422;
  --silk-mid:  #060b13;
  --silk-low:  #060b13;
  --silk-ink:  #f4efe4;
}

/* ── the material ──────────────────────────────────────────────────────
   ::before carries the fine lengthwise grain, ::after the fibre mottle.
   Both are fixed to the viewport so the sheen does not slide as you
   scroll — a sheet of paper does not have a moving highlight. */

/* The material floats ABOVE the page's own backgrounds, not beneath them.
   Sections like .hero paint an opaque colour of their own; a sheen sitting
   under those would be invisible on exactly the surfaces that need it.
   z-index 2147483000 with pointer-events:none means it overlays everything
   visually while remaining completely inert to clicks, focus and selection. */
body::before,
body::after,
.silk::before,
.silk::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  pointer-events: none;
}

/* Photographs are NOT silk. A sheen and a fibre mottle belong on paper;
   laid over a photograph they read as haze and flatten it (HK 2026-08-05).
   Anything marked .nosilk punches a hole in the overlay so the image is
   seen at full clarity — the material stops at the picture's edge, the way
   a photographic plate tipped into a book sits proud of the page. */
.nosilk { isolation: isolate; z-index: 2147483001; position: relative; }

.silk { position: relative; isolation: isolate; }
.silk::before, .silk::after { position: absolute; }
.silk > * { position: relative; z-index: 2; }

/* Broad, low-angle sheen only.
   The 1px repeating-linear-gradients that used to live here are GONE
   (HK 2026-08-05): under the estate's 1.333 zoom a 1-on-4px pattern lands
   on fractional device pixels and beats against the display grid, so the
   page read as graph paper rather than silk. Real silk-finish stock has no
   visible weave anyway — the fibre comes from the turbulence layer below,
   which is resolution-independent and cannot alias. */
body::before, .silk::before {
  background-image:
    linear-gradient(118deg,
      rgba(255,255,255,0)   0%,
      rgba(255,255,255,.045) 30%,
      rgba(255,255,255,.10)  47%,
      rgba(255,255,255,.03)  63%,
      rgba(255,255,255,0)   100%),
    radial-gradient(ellipse at 22% 12%,
      rgba(255,251,240,.26) 0%, rgba(255,251,240,.07) 36%, rgba(255,251,240,0) 68%),
    radial-gradient(ellipse at 82% 88%,
      rgba(176,141,84,.12) 0%, rgba(176,141,84,.04) 40%, rgba(176,141,84,0) 74%),
    /* The OG weave, back but faint (HK 2026-08-05). The earlier version used
       1px lines on a 4-5px pitch: under the estate's 1.333 zoom those landed
       on fractional device pixels and beat against the display grid — graph
       paper, not silk. This one is a 3px line on a 24px pitch, which stays a
       whole number of device pixels at 1x, 1.333x and 2x, and the alpha is
       roughly a third of before. Felt, not read. */
    repeating-linear-gradient(90deg,
      rgba(90,70,35,.014) 0 3px, transparent 3px 24px),
    repeating-linear-gradient(0deg,
      rgba(90,70,35,.010) 0 3px, transparent 3px 24px);
}

/* dark: the sheen stays, but cool and smoky */
:root[data-theme="dark"] body::before,
:root[data-theme="dark"] .silk::before {
  background-image:
    linear-gradient(114deg,
      rgba(255,255,255,0)  0%,
      rgba(95,135,175,.06) 33%,
      rgba(185,215,245,.11) 48%,
      rgba(72,112,152,.04) 63%,
      rgba(255,255,255,0) 100%),
    radial-gradient(ellipse at 26% 12%,
      rgba(70,112,152,.14) 0%, rgba(70,112,152,.04) 44%, rgba(70,112,152,0) 72%),
    /* same 3-on-24 weave, lifted rather than darkened so dark silk keeps
       its satin rather than turning matte */
    repeating-linear-gradient(90deg,
      rgba(255,255,255,.016) 0 3px, transparent 3px 24px),
    repeating-linear-gradient(0deg,
      rgba(255,255,255,.011) 0 3px, transparent 3px 24px);
}

/* Fibre mottle — the layer that stops the eye reading it as a gradient.
   Softened from .075 to .04 (HK 2026-08-05): `multiply` at the old value
   darkened the whole page, which is why the site had lost its brightness.
   Fibre should be felt, not seen. */
body::after, .silk::after {
  opacity: .04;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='0.45'/%3E%3C/svg%3E");
}

:root[data-theme="dark"] body::after,
:root[data-theme="dark"] .silk::after {
  opacity: .05;
  mix-blend-mode: overlay;
}

/* Deliberately no `body > * { position:relative }` here. Forcing a stacking
   context onto every top-level element broke fixed bars and sticky headers
   on pages that already manage their own z-order. The overlay is above
   everything by z-index alone, and inert, so content needs no lifting. */

/* ── opt-outs ──────────────────────────────────────────────────────────
   A page opts out wholesale; a viewer who has asked their system for less
   transparency gets the flat sheet, which is the accessible default. */
html[data-no-silk] body::before,
html[data-no-silk] body::after { display: none; }

@media (prefers-reduced-transparency: reduce) {
  body::before, body::after,
  .silk::before, .silk::after { display: none; }
}
