/* ============================================================================
   Websonance — Lens logo. THE source of truth.
   ----------------------------------------------------------------------------
   Every glass rendering of the logo (site, app, exports) comes from this file.
   Do not redraw the logo, re-derive its numbers, or rebuild it in SVG.
   To get a PNG, run scripts/export-lens.sh (it screenshots master.html).
   Rules and usage: Docs/brand/lens/README.md.

   Construction (1em = the mark's box):
     o     ring, outer diameter .5625em, stroke .09375em, center (.375em, .625em)
     pane  rounded square .53125em, radius .15625em, top-left (.375em, .09375em)
     rule  the pane's bottom-left corner sits exactly on the o's center, so it
           covers the o's top-right quadrant.
   ========================================================================= */

@font-face{
  font-family:"Figtree WS";
  src:url("fonts/Figtree-latin-var.woff2") format("woff2");
  font-weight:300 900;
  font-display:block;
}

:root{
  --ws-violet:#A597F2;        /* the o, on dark grounds */
  --ws-violet-soft:#C9C0FA;   /* travelling ring */
  --ws-violet-deep:#7A6BDB;   /* the o, on light grounds (flat versions) */
  --ws-abyss:#090A0F;         /* ground */
  --ws-frost:#ECEEF6;         /* ink on dark */
  --ws-ink:#1D2130;           /* ink on light */
  --ws-porcelain:#EDEFF5;     /* light ground */
}

/* ---------- glass material (shared by the mark pane and the wordmark pane) */
.ws-glass{
  -webkit-backdrop-filter:blur(.055em) saturate(160%) brightness(1);
  backdrop-filter:blur(.055em) saturate(160%) brightness(1);
  box-shadow:inset 0 max(1px,.0045em) 0 rgba(255,255,255,.5),
             inset 0 0 0 max(1px,.0045em) rgba(255,255,255,.16);
}
.ws-glass::before{
  content:"";position:absolute;inset:0;border-radius:inherit;
  background:linear-gradient(150deg,rgba(255,255,255,.24) 0%,rgba(255,255,255,.07) 48%,rgba(255,255,255,.04) 72%,rgba(255,255,255,.10) 100%);
}

/* ---------- mark
   <span class="ws-lens" role="img" aria-label="Websonance">
     <span class="ws-lens-o"></span><span class="ws-lens-ring"></span><span class="ws-lens-pane ws-glass"></span>
   </span>
   Size it with font-size (font-size: 64px = a 64px mark). Needs a dark ground. */
.ws-lens{position:relative;display:inline-block;width:1em;height:1em;flex:none;vertical-align:middle}
.ws-lens>span{position:absolute;box-sizing:border-box}
.ws-lens-o{
  left:.09375em;top:.34375em;width:.5625em;height:.5625em;border-radius:50%;
  border:.09375em solid var(--ws-violet);
  box-shadow:0 0 .12em rgba(165,151,242,.45),inset 0 0 .08em rgba(165,151,242,.35);
}
.ws-lens-ring{
  left:.09375em;top:.34375em;width:.5625em;height:.5625em;border-radius:50%;
  border:max(1px,.012em) solid var(--ws-violet-soft);opacity:0;pointer-events:none;
}
.ws-lens-pane{left:.375em;top:.09375em;width:.53125em;height:.53125em;border-radius:.15625em}

/* ---------- wordmark
   <span class="ws-word" role="img" aria-label="Websonance">webs<span class="ws-word-o"><span class="ws-word-glyph">o</span><span class="ws-word-ring"></span><span class="ws-word-pane ws-glass"></span></span>nance</span>
   The pane is the flat family's .3608em, bottom-left fixed at (.22em,.54em) (A2, Zach 2026-09-25).
   Size it with font-size. The o's numbers are measured from Figtree 620 — if the
   typeface ever changes, re-measure; don't eyeball. */
.ws-word{font-family:"Figtree WS",ui-sans-serif,system-ui,sans-serif;font-weight:620;letter-spacing:-.03em;line-height:1;color:var(--ws-frost);white-space:nowrap}
.ws-word-o{position:relative;display:inline-block}
.ws-word-glyph{display:inline-block;color:var(--ws-violet);text-shadow:0 0 .1em rgba(165,151,242,.35)}
.ws-word-ring{position:absolute;left:.0334em;top:.343em;width:.514em;height:.514em;box-sizing:border-box;border-radius:50%;border:max(1px,.03em) solid var(--ws-violet-soft);opacity:0;pointer-events:none}
.ws-word-pane{position:absolute;left:.22em;top:.1792em;width:.3608em;height:.3608em;border-radius:.1066em}

/* ---------- app icon (square; the platform rounds the corners)
   <span class="ws-appicon"><span class="ws-lens">…</span></span>  size with --ws-icon */
.ws-appicon{
  --ws-icon:180px;
  position:relative;display:grid;place-items:center;overflow:hidden;
  width:var(--ws-icon);height:var(--ws-icon);
  background:radial-gradient(90% 70% at 22% 8%,rgba(165,151,242,.30),transparent 62%),linear-gradient(165deg,#171A2B,#08090E);
}
.ws-appicon .ws-lens{font-size:calc(var(--ws-icon) * .74)}
.ws-appicon::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(180deg,rgba(255,255,255,.08),transparent 42%)}

/* ============================================================================
   Motion. Put the class on .ws-lens or .ws-word. Four approved moves:
     .ws-publish  Ring-out — one shot, when a frame goes live   (remove on animationend)
     .ws-loading  Focus    — loops while something is working
     .ws-intro    Settle   — one shot, first load / splash
     .ws-ambient  Hum      — loops on screens the logo sits on for a long time
   Sympathy was cut (2026-09-13: too exaggerated).
   ========================================================================= */
@media (prefers-reduced-motion: no-preference){
  /* Ring-out */
  .ws-publish .ws-lens-ring,.ws-publish .ws-word-ring{animation:ws-ring 1.82s cubic-bezier(.15,.55,.3,1) both}
  .ws-publish .ws-lens-o{animation:ws-glow 1.52s ease-out both}
  .ws-publish .ws-word-glyph{animation:ws-glow-text 1.52s ease-out both}
  /* Focus */
  .ws-loading .ws-lens-pane,.ws-loading .ws-word-pane{animation:ws-focus 4.6s cubic-bezier(.45,0,.2,1) infinite}
  .ws-loading .ws-lens-pane::before,.ws-loading .ws-word-pane::before{animation:ws-focus-fill 4.6s cubic-bezier(.45,0,.2,1) infinite}
  /* Settle */
  .ws-intro .ws-lens-pane,.ws-intro .ws-word-pane{animation:ws-settle 1.57s cubic-bezier(.2,.8,.25,1) both}
  .ws-intro .ws-lens-ring,.ws-intro .ws-word-ring{animation:ws-settle-ring 2.27s cubic-bezier(.15,.55,.3,1) .86s both}
  /* Hum */
  .ws-ambient .ws-lens-o{animation:ws-hum 6s ease-in-out infinite}
  .ws-ambient .ws-word-glyph{animation:ws-hum-text 6s ease-in-out infinite}
  .ws-ambient .ws-lens-pane,.ws-ambient .ws-word-pane{animation:ws-hum-pane 6s ease-in-out infinite}
}

@keyframes ws-ring{0%{transform:scale(1);opacity:0}6%{opacity:.8}100%{transform:scale(1.9);opacity:0}}
@keyframes ws-glow{
  0%{box-shadow:0 0 .12em rgba(165,151,242,.45),inset 0 0 .08em rgba(165,151,242,.35)}
  15%{box-shadow:0 0 .2em rgba(165,151,242,.75),inset 0 0 .1em rgba(201,192,250,.5)}
  100%{box-shadow:0 0 .12em rgba(165,151,242,.45),inset 0 0 .08em rgba(165,151,242,.35)}}
@keyframes ws-glow-text{0%{text-shadow:0 0 .1em rgba(165,151,242,.35)}15%{text-shadow:0 0 .22em rgba(165,151,242,.8)}100%{text-shadow:0 0 .1em rgba(165,151,242,.35)}}
@keyframes ws-focus{
  0%,10%{-webkit-backdrop-filter:blur(.055em) saturate(160%) brightness(1);backdrop-filter:blur(.055em) saturate(160%) brightness(1)}
  24%,34%{-webkit-backdrop-filter:blur(.004em) saturate(115%) brightness(1.05);backdrop-filter:blur(.004em) saturate(115%) brightness(1.05)}
  62%,100%{-webkit-backdrop-filter:blur(.055em) saturate(160%) brightness(1);backdrop-filter:blur(.055em) saturate(160%) brightness(1)}}
@keyframes ws-focus-fill{0%,10%{opacity:1}24%,34%{opacity:.3}62%,100%{opacity:1}}
@keyframes ws-settle{0%{transform:translate(.16em,-.16em);opacity:0}17%{opacity:1}62%{transform:translate(-.014em,.014em)}83%{transform:translate(.004em,-.004em)}100%{transform:translate(0,0);opacity:1}}
@keyframes ws-settle-ring{0%{transform:scale(1);opacity:0}7%{opacity:.6}100%{transform:scale(1.7);opacity:0}}
@keyframes ws-hum{
  0%,100%{box-shadow:0 0 .12em rgba(165,151,242,.45),inset 0 0 .08em rgba(165,151,242,.35)}
  45%{box-shadow:0 0 .19em rgba(165,151,242,.68),inset 0 0 .1em rgba(201,192,250,.45)}}
@keyframes ws-hum-text{0%,100%{text-shadow:0 0 .1em rgba(165,151,242,.35)}45%{text-shadow:0 0 .22em rgba(165,151,242,.75)}}
@keyframes ws-hum-pane{
  0%,100%{-webkit-backdrop-filter:blur(.055em) saturate(160%) brightness(1);backdrop-filter:blur(.055em) saturate(160%) brightness(1)}
  58%{-webkit-backdrop-filter:blur(.055em) saturate(178%) brightness(1.22);backdrop-filter:blur(.055em) saturate(178%) brightness(1.22)}}
