/* ==========================================================================
   samisee.design, WALLPAPER (night)
   Reads tokens.css. Built by wallpaper.js, which adds the stars, glints and
   the zone positions. Layers, back to front:

     sky       night gradient, lifted toward the top left
     aurora    a slow lilac/ice band across the middle (from the live site)
     orbs      two soft lights: lilac top right, ice bottom left
     emanate   the live site's blue/violet orbs, blooming from the signature
     scan      1px scanlines at almost nothing
     grid      the drafting grid, in opacity zones (see below)
     stars     the live site's 80 hand-placed stars: 3 sizes = 3 depths,
               mouse parallax by depth, slow drift, 18 twinkle
     glints    4 opal stars that catch light when the cursor comes near
     plate     the signature at rest + the hero tagline (js/tagline.js)
     grain     film grain, very low
     fade      a soft floor under the dock

   GRID ZONES. One grid, one colour; a mask decides where it shows.
     hero   strongest, centred on the signature, with a finer minor grid
            inside it, like graph paper under a drafting pen
     echo   a smaller, softer zone diagonally opposite, so the eye has a
            second landing point on its way from the dock to the icons
     base   faint everywhere else
   The frame mask then pulls the grid back where UI already gives structure:
   under the menubar, behind the icon column, around the dock, at the edges.
   ========================================================================== */

.wp {
  /* tune here */
  --wp-cell: 96px;                 /* major grid, an 8pt multiple */
  --wp-minor: 24px;                /* minor grid, hero zone only */
  --wp-grid-ink: color-mix(in oklch, var(--os-ink) 6%, transparent);
  --wp-grid-minor-ink: color-mix(in oklch, var(--os-ink) 2.6%, transparent);
  --wp-base: 0.2;                  /* base zone strength, 0 to 1 */
  --wp-echo: 0.55;                 /* echo zone strength */
  --wp-echo-x: 27%;  --wp-echo-y: 73%;
  --wp-echo-w: 28vw; --wp-echo-h: 26vh;
  /* hero zone and emanate follow the signature; wallpaper.js sets these */
  --wp-hero-x: 66.7%; --wp-hero-y: 56%;
  --wp-hero-w: 30vw;  --wp-hero-h: 30vh;
  --wp-grid-x: 0px;   --wp-grid-y: 0px;

  position: fixed;
  inset: 0;
  z-index: var(--z-sky);
  overflow: hidden;
  pointer-events: none;
  /* srgb on purpose: blending toward near-black in oklch swings the hue (black
     has none) and painted a hard brown diagonal across the lower half */
  background: linear-gradient(160deg,
    var(--os-sky-stop-2) 0%,
    var(--os-sky-stop-1) 55%,
    color-mix(in srgb, var(--os-sky-stop-3) 82%, #000) 100%);
}
.wp > * { position: absolute; }

/* ---- aurora and orbs: the live site's, recoloured to lilac and ice ---- */
.wp__aurora {
  left: -20%; right: -20%; top: 30%; height: 22%;
  background: radial-gradient(ellipse 60% 100% at 50% 50%,
    color-mix(in oklch, var(--os-accent-2) 70%, var(--os-accent)) 0%, transparent 100%);
  filter: blur(32px);
  opacity: 0.04;
  animation: wp-aurora 24s ease-in-out infinite;
}
.wp__orb { border-radius: 50%; filter: blur(70px); }
.wp__orb--lilac {
  width: 72vw; aspect-ratio: 1; top: -22%; right: -12%;
  background: radial-gradient(circle, color-mix(in oklch, var(--os-accent) 13%, transparent) 0%, transparent 68%);
  animation: wp-orb-a 24s ease-in-out infinite;
}
.wp__orb--ice {
  width: 70vw; aspect-ratio: 1; bottom: -38%; left: -14%;
  background: radial-gradient(circle, color-mix(in oklch, var(--os-accent-2) 9%, transparent) 0%, transparent 68%);
  animation: wp-orb-b 28s ease-in-out infinite;
}

/* ---- emanate: the live site's "selected work" light, behind the signature.
   A soft ambient glow, a faint core, and 23 orbs that bloom outward from the
   signature's centre at their own pace (9 size tiers, staggered so it never
   pulses in sync). Ice and lilac, like the original's blue and violet. ---- */
.wp__emanate {
  left: var(--wp-hero-x); top: var(--wp-hero-y);
  width: 0; height: 0;
  opacity: 0;
  /* blurred as a group so the blooming orbs never show a hard circular edge;
     saturated as a group too, or the ice and lilac pastels average out to a
     washed lavender white instead of reading as blue into lilac */
  filter: blur(28px) saturate(1.35);
  transition: opacity 2.4s var(--ease-standard);
}
.wp.is-settled .wp__emanate { opacity: var(--wp-emanate, .22); }
.wp__emanate > * { position: absolute; left: 0; top: 0; translate: -50% -50%; border-radius: 50%; }
.wp__ambient {
  width: min(88vw, 640px); aspect-ratio: 1;
  background: radial-gradient(circle, color-mix(in srgb, var(--os-accent-2) 20%, transparent) 0%, color-mix(in srgb, var(--os-accent) 8%, transparent) 48%, transparent 70%);
  filter: blur(52px);
  animation: wp-breathe 12s ease-in-out infinite;
}
.wp__core {
  width: 110px; aspect-ratio: 1;
  background: radial-gradient(circle, color-mix(in srgb, var(--os-accent-2) 55%, transparent) 0%, color-mix(in srgb, var(--os-accent) 25%, transparent) 40%, transparent 70%);
  filter: blur(8px);
  opacity: .5;
}
.wp__orbit { width: var(--sz); aspect-ratio: 1; animation: wp-emanate var(--dur) ease-out var(--delay) infinite; transform: scale(.05); opacity: 0; }

.wp__scan {
  inset: 0;
  background-image: repeating-linear-gradient(0deg,
    color-mix(in oklch, var(--os-ink) 0.6%, transparent) 0 1px, transparent 1px 3px);
}

/* ---- grid: frame mask (where UI lives) x zone mask (where the eye goes) ---- */
.wp__grid-frame {
  inset: 0;
  opacity: 0;
  transition: opacity 1.6s var(--ease-standard);
  -webkit-mask:
    linear-gradient(to bottom, transparent 0 30px, #000 128px),
    linear-gradient(to right, rgb(0 0 0 / .25) 0 132px, #000 300px),
    radial-gradient(ellipse 420px 150px at 50% 100%, rgb(0 0 0 / .2) 0%, #000 100%),
    radial-gradient(ellipse 78% 82% at 50% 50%, #000 58%, transparent 100%);
  -webkit-mask-composite: source-in;
          mask:
    linear-gradient(to bottom, transparent 0 30px, #000 128px),
    linear-gradient(to right, rgb(0 0 0 / .25) 0 132px, #000 300px),
    radial-gradient(ellipse 420px 150px at 50% 100%, rgb(0 0 0 / .2) 0%, #000 100%),
    radial-gradient(ellipse 78% 82% at 50% 50%, #000 58%, transparent 100%);
          mask-composite: intersect;
}
.wp.is-settled .wp__grid-frame { opacity: 1; }
.wp__grid, .wp__grid-minor { position: absolute; inset: 0; }
.wp__grid {
  background-image:
    linear-gradient(var(--wp-grid-ink) 1px, transparent 1px),
    linear-gradient(90deg, var(--wp-grid-ink) 1px, transparent 1px);
  background-size: var(--wp-cell) var(--wp-cell);
  background-position: var(--wp-grid-x) var(--wp-grid-y);
  -webkit-mask:
    radial-gradient(ellipse var(--wp-hero-w) var(--wp-hero-h) at var(--wp-hero-x) var(--wp-hero-y), #000 0%, transparent 72%),
    radial-gradient(ellipse var(--wp-echo-w) var(--wp-echo-h) at var(--wp-echo-x) var(--wp-echo-y), rgb(0 0 0 / var(--wp-echo)) 0%, transparent 72%),
    linear-gradient(rgb(0 0 0 / var(--wp-base)), rgb(0 0 0 / var(--wp-base)));
          mask:
    radial-gradient(ellipse var(--wp-hero-w) var(--wp-hero-h) at var(--wp-hero-x) var(--wp-hero-y), #000 0%, transparent 72%),
    radial-gradient(ellipse var(--wp-echo-w) var(--wp-echo-h) at var(--wp-echo-x) var(--wp-echo-y), rgb(0 0 0 / var(--wp-echo)) 0%, transparent 72%),
    linear-gradient(rgb(0 0 0 / var(--wp-base)), rgb(0 0 0 / var(--wp-base)));
}
.wp__grid-minor {
  background-image:
    linear-gradient(var(--wp-grid-minor-ink) 1px, transparent 1px),
    linear-gradient(90deg, var(--wp-grid-minor-ink) 1px, transparent 1px);
  background-size: var(--wp-minor) var(--wp-minor);
  background-position: var(--wp-grid-x) var(--wp-grid-y);
  -webkit-mask: radial-gradient(ellipse calc(var(--wp-hero-w) * .8) calc(var(--wp-hero-h) * .8) at var(--wp-hero-x) var(--wp-hero-y), #000 0%, transparent 70%);
          mask: radial-gradient(ellipse calc(var(--wp-hero-w) * .8) calc(var(--wp-hero-h) * .8) at var(--wp-hero-x) var(--wp-hero-y), #000 0%, transparent 70%);
}

/* ---- stars ---- */
.wp__stars { inset: 0; }
.wp__star { position: absolute; animation: wp-drift linear infinite; }
.wp__dot {
  display: block;
  border-radius: 50%;
  background: var(--os-ink);
  opacity: var(--op);
  will-change: transform;
}
.wp__dot.is-warm { background: color-mix(in oklch, var(--os-accent-3) 55%, var(--os-ink)); }
.wp__dot.is-twinkle { animation: wp-twinkle var(--tdur) ease-in-out var(--td) infinite; }

/* ---- glints: opal sparkles that answer the cursor ---- */
.wp__glint {
  width: var(--s, 18px); aspect-ratio: 1;
  translate: -50% -50%;
  opacity: calc(.2 + var(--g, 0) * .8);
  transform: scale(calc(.72 + var(--g, 0) * .6)) rotate(calc(var(--g, 0) * 30deg));
  filter: drop-shadow(0 0 calc(var(--g, 0) * 9px) color-mix(in oklch, var(--opal-warm) 80%, transparent));
  transition: opacity .3s, transform .45s cubic-bezier(.3, 1.5, .5, 1);
}
.wp__glint i {
  display: block; width: 100%; height: 100%;
  background: linear-gradient(115deg in oklch, var(--opal-silver), var(--os-accent-2), var(--os-accent), var(--os-accent-3), var(--opal-warm), var(--opal-silver));
  background-size: 300% 300%;
  background-position: calc(20% + var(--g, 0) * 60%) 50%;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 0C10.6 6.4 13.6 9.4 20 10C13.6 10.6 10.6 13.6 10 20C9.4 13.6 6.4 10.6 0 10C6.4 9.4 9.4 6.4 10 0Z'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M10 0C10.6 6.4 13.6 9.4 20 10C13.6 10.6 10.6 13.6 10 20C9.4 13.6 6.4 10.6 0 10C6.4 9.4 9.4 6.4 10 0Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ---- the signature at rest ---- */
.wp-plate {
  position: fixed;
  z-index: var(--z-decor);
  pointer-events: none;
  /* the resting spot: on the right-third line, just below centre */
  left: 66.67%; top: 56%;
  width: min(34vw, 600px);
  translate: -50% -50%;
  /* a size container: the tagline is sized in cqw, so it holds at any plate width */
  container-type: inline-size;
}
/* tablets held upright: a third of the width is too small a signature, and there's room below the widget */
@media (min-width: 701px) and (max-width: 1100px) and (orientation: portrait) {
  .wp-plate { left: 60%; width: min(50vw, 600px); }
}
.wp-plate .sig { display: block; width: 100%; height: auto; overflow: visible; }
/* .sig__ink colour and glow live in looks.css (plum ink by day, warm white at sunset) */

/* ---- the hero tagline: a justified lockup, each line exactly the signature's width ---- */
.tag {
  position: absolute; left: 0; right: 0; top: 100%;
  margin-top: 4.5cqw;
  font-family: var(--font-display); font-weight: var(--weight-display);
  line-height: .98; letter-spacing: -.015em;
}
.tag__line { display: block; width: max-content; white-space: nowrap; }
.tag__line--1 { color: var(--os-ink); }
.tag__line--2 { color: var(--os-accent); margin-top: .06em; }
.tag__ch, .tag__dot { display: inline-block; }
.tag__pulse { position: relative; display: inline-block; isolation: isolate; }
/* the glow "pulse" sits in, beating on the shared heartbeat (js/heartbeat.js) */
.tag__glow {
  position: absolute; inset: -55% -30%; z-index: -1; border-radius: 50%; opacity: 0;
  background: radial-gradient(ellipse, color-mix(in srgb, var(--os-accent-2) 60%, transparent) 0%, color-mix(in srgb, var(--os-accent) 22%, transparent) 45%, transparent 72%);
  filter: blur(14px);
}
/* the closing period is a dot that swells on the same two thumps */
.tag__dot { width: .17em; height: .17em; margin-left: .05em; border-radius: 50%; background: var(--os-accent); box-shadow: 0 0 .25em var(--os-accent); }
/* the live site's wide glow behind the whole line, on the same beat */
.tag__aura {
  position: absolute; left: -12%; right: -12%; top: 100%; height: 22cqw; opacity: 0; pointer-events: none;
  background: radial-gradient(ellipse 50% 100% at 50% 50%, color-mix(in srgb, var(--os-accent-2) 18%, transparent) 0%, transparent 100%);
  filter: blur(40px);
}

/* reveal: the letters resolve out of a blur as the signature lands */
.tag__ch, .tag__dot {
  opacity: 0; filter: blur(8px); transform: translateY(.3em);
  transition: opacity .7s var(--ease-enter), filter .7s var(--ease-enter), transform .7s var(--ease-enter);
  transition-delay: calc(var(--i) * 20ms + 150ms);
}
.wp-plate.is-settled .tag__ch, .wp-plate.is-settled .tag__dot { opacity: 1; filter: none; transform: none; }
/* before the script builds it, the tagline is plain text in the page: keep it out of sight
   until the signature has landed, so a reload never flashes it ahead of the boot or lock screen */
.wp-plate:not(.is-settled) .tag { visibility: hidden; }

.wp__grain {
  inset: -20%;
  opacity: .06;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: wp-grain 1s steps(3) infinite;
}
.wp__fade {
  inset: 0;
  background: linear-gradient(to top, color-mix(in oklch, var(--os-sky-stop-1) 70%, transparent) 0%, transparent 30%);
}

/* ---- motion ---- */
@keyframes wp-aurora { 0%, 100% { transform: translateX(-15%) scaleX(.88); opacity: .028; } 50% { transform: translateX(12%) scaleX(1.12); opacity: .055; } }
@keyframes wp-orb-a { 0%, 100% { transform: translate(0, 0) scale(1); } 40% { transform: translate(55px, -42px) scale(1.1); } 70% { transform: translate(-28px, 30px) scale(.93); } }
@keyframes wp-orb-b { 0%, 100% { transform: translate(0, 0) scale(1); } 38% { transform: translate(-60px, 35px) scale(1.08); } 74% { transform: translate(42px, -48px) scale(.91); } }
@keyframes wp-breathe { 0%, 100% { scale: 1; } 50% { scale: 1.06; } }
/* the live site scaled to 10x; on a desktop that reads as a lit disk, so the bloom stops at 5.5x */
@keyframes wp-emanate { 0% { transform: scale(.05); opacity: .82; } 60% { opacity: .5; } 85% { opacity: .1; } 100% { transform: scale(5.5); opacity: 0; } }
@keyframes wp-drift { 0% { transform: translate(0, 0); opacity: 0; } 3% { opacity: 1; } 94% { opacity: 1; } 99% { opacity: 0; } 100% { transform: translate(160px, 55px); opacity: 0; } }
@keyframes wp-twinkle { 0%, 100% { opacity: var(--op); } 40% { opacity: calc(var(--op) * .12); } 75% { opacity: var(--op); } }
@keyframes wp-grain { 33% { transform: translate(-2%, 3%); } 66% { transform: translate(3%, -2%); } }

@media (prefers-reduced-motion: reduce) {
  .wp *, .wp-plate * { animation: none !important; transition: none !important; }
  .tag__ch, .tag__dot { opacity: 1; filter: none; transform: none; }
  .wp__grid-frame { opacity: 1; }
  .wp__emanate { opacity: var(--wp-emanate, .22); }
  .wp__orbit { display: none; }
}
