/* ═══════════════════════════════════════════════════════════════════
   wabi.css — the real wabi.ai chrome.

   Ported from the production site (sotabot/website-v1):
     nav          src/features/marketing/components/header.tsx
     hero copy    src/features/marketing/app.tsx  (the centre layout)
     footer       src/components/footer.tsx
     blur-in      src/features/marketing/app.tsx
     glass button src/components/ui/glassmorphic-button + header.tsx

   These are wabi.ai's numbers, not new ones. If the site changes, re-port
   rather than nudging values here — the point of this file is that the top
   and bottom of the page are indistinguishable from wabi.ai.
   ═══════════════════════════════════════════════════════════════════ */

@property --angle-1 { syntax: '<angle>'; inherits: false; initial-value: -75deg; }
@property --angle-2 { syntax: '<angle>'; inherits: false; initial-value: -45deg; }

:root{
  /* wabi.ai's page colours, exactly */
  --paper:#f0f0f0;
  --ink:#191919;
  --ink-70:rgba(25,25,25,.70);
  --ink-60:rgba(25,25,25,.60);
  --ink-40:rgba(25,25,25,.40);
  --ink-14:rgba(25,25,25,.14);
  --ink-07:rgba(25,25,25,.07);
  --grey-500:#737373;
  --ease-wabi:cubic-bezier(0.25, 1, 0.5, 1);
  --ease-expo:cubic-bezier(0.22, 1, 0.36, 1);
}

/* ── the site's entrance: everything arrives out of blur ──────────── */
@keyframes blur-in{
  0%   { opacity:0; filter:blur(14px); transform:translateY(12px); }
  99%  { opacity:1; filter:blur(0);    transform:translateY(0); }
  100% { opacity:1; filter:none;       transform:translateY(0); }
}
.blur-in{ animation:blur-in 1.05s var(--ease-expo) both; will-change:opacity, filter; }
@media (prefers-reduced-motion:reduce){ .blur-in{ animation:none; } }

/* ── nav ──────────────────────────────────────────────────────────── */
.orb-nav{
  display:flex; align-items:center; justify-content:space-between;
  padding:24px; position:relative; z-index:200; overflow:visible;
  pointer-events:none;                 /* the empty middle must not eat clicks */
}
.orb-nav-logo, .orb-nav-right{ pointer-events:auto; }
/* Fixed at ALL widths. Below 1025px it scrolled away after the first screen,
   which left a phone with no App Store link for 9,700px — eleven screens — on
   the platform this ships on first. */
.orb-nav{
  position:fixed; top:0; left:0; right:0;
  background:rgba(240,240,240,.72);
  backdrop-filter:blur(20px) saturate(1.4);
  -webkit-backdrop-filter:blur(20px) saturate(1.4);
}
body[data-chrome="dark"] .orb-nav{ background:rgba(9,9,10,.55); }
@media (min-width:1025px){ .orb-nav{ padding:32px; } }
.orb-nav-logo{
  display:flex; align-items:center; text-decoration:none;
  position:relative; top:0; min-width:140px; min-height:50px;
}
.orb-nav-logo .wabi-logo-svg{
  height:30px; width:auto; display:block;
  transition:height .6s var(--ease-wabi);
}
.orb-nav-logo .wabi-logo-svg .logo-circles{ opacity:.3; transition:opacity .4s ease; }
.orb-nav-logo .wabi-logo-svg .logo-text{ opacity:0; transition:opacity .15s ease; }
.orb-nav-logo .logo-letter{ transition:transform .2s ease, opacity .2s ease; }
.orb-nav-logo .logo-w{ transform:translateX(-35px); }
.orb-nav-logo .logo-a{ transform:translateX(-65px); }
.orb-nav-logo .logo-b{ transform:translateX(-90px); }
.orb-nav-logo .logo-i{ transform:translateX(-110px); }
.orb-nav-logo:hover .logo-letter,
.orb-nav-logo.is-settled .logo-letter{
  transform:translateX(0);
  transition:transform .5s var(--ease-wabi) .3s, opacity .4s ease .3s;
}
.orb-nav-logo:hover .logo-a, .orb-nav-logo.is-settled .logo-a{ transition-delay:.32s; }
.orb-nav-logo:hover .logo-b, .orb-nav-logo.is-settled .logo-b{ transition-delay:.34s; }
.orb-nav-logo:hover .logo-i, .orb-nav-logo.is-settled .logo-i{ transition-delay:.36s; }
.orb-nav-logo:hover .wabi-logo-svg{ height:18px; transition:height .6s var(--ease-wabi); }
.orb-nav-logo.is-settled .wabi-logo-svg{ height:24px; }
.orb-nav-logo:hover .wabi-logo-svg .logo-circles,
.orb-nav-logo.is-settled .wabi-logo-svg .logo-circles{ opacity:.6; }
.orb-nav-logo:hover .wabi-logo-svg .logo-text,
.orb-nav-logo.is-settled .wabi-logo-svg .logo-text{ opacity:.6; transition:opacity .4s ease .45s; }
@media (min-width:1025px){
  .orb-nav-logo{ top:-4px; min-width:200px; min-height:60px; }
  .orb-nav-logo .wabi-logo-svg{ height:33.6px; }
  .orb-nav-logo:hover .wabi-logo-svg{ height:20.8px; }
  .orb-nav-logo.is-settled .wabi-logo-svg{ height:26.88px; }
}
.orb-nav-right{ display:flex; align-items:center; gap:36px; }
.orb-nav-manifesto{ display:none; }
@media (min-width:1025px){
  .orb-nav-manifesto{
    display:inline-flex; align-items:center;
    font-size:15px; font-weight:500; letter-spacing:-0.19px;
    color:var(--ink); text-decoration:none; opacity:.7;
    transition:opacity 200ms ease; white-space:nowrap;
  }
  .orb-nav-manifesto:hover{ opacity:1; }
}

/* ── the glass button ─────────────────────────────────────────────── */
.glass-btn-wrap{
  position:relative; z-index:2; border-radius:999vw; background:transparent;
  pointer-events:none; transition:all 400ms var(--ease-wabi);
}
.glass-btn-shadow{
  position:absolute;
  width:calc(100% + 0.5em); height:calc(100% + 0.5em);
  top:calc(0% - 0.25em); left:calc(0% - 0.25em);
  filter:blur(clamp(0.5px, 0.0313em, 3px));
  overflow:visible; pointer-events:none; z-index:1;
}
.glass-btn-shadow::after{
  content:''; position:absolute; z-index:0; inset:0; border-radius:999vw;
  background:linear-gradient(180deg, rgba(0,0,0,.015), rgba(0,0,0,.0075));
  width:calc(100% - 0.5em - 0.0625em); height:calc(100% - 0.5em - 0.0625em);
  top:calc(0.5em - 0.125em); left:calc(0.5em - 0.21875em);
  padding:.125em; box-sizing:border-box;
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  transition:all 400ms var(--ease-wabi); opacity:1;
}
.glass-btn{
  all:unset; cursor:pointer; position:relative;
  -webkit-tap-highlight-color:rgba(0,0,0,0);
  pointer-events:auto; z-index:3;
  background:linear-gradient(-75deg, rgba(255,255,255,.05), rgba(255,255,255,.2), rgba(255,255,255,.05));
  border-radius:999vw;
  box-shadow:
    inset 0 .125em .125em rgba(0,0,0,.035),
    inset 0 -.125em .125em rgba(255,255,255,.5),
    0 .25em .125em -.125em rgba(0,0,0,.1),
    0 0 .1em .25em inset rgba(255,255,255,.2),
    0 0 0 0 rgba(255,255,255,1);
  backdrop-filter:blur(clamp(1px, .125em, 4px));
  -webkit-backdrop-filter:blur(clamp(1px, .125em, 4px));
  transition:all 400ms var(--ease-wabi);
  display:flex; align-items:center; justify-content:center;
  height:46px; font-family:inherit;
}
.glass-btn:hover{
  transform:scale(.975);
  box-shadow:
    inset 0 .125em .125em rgba(0,0,0,.035),
    inset 0 -.125em .125em rgba(255,255,255,.5),
    0 .075em .025em -.1em rgba(0,0,0,.25),
    0 0 .05em .1em inset rgba(255,255,255,.5),
    0 0 0 0 rgba(255,255,255,1);
}
.glass-btn span{
  position:relative; width:100%; height:100%;
  display:flex; align-items:center; justify-content:center; user-select:none;
  color:rgba(50,50,50,1); text-shadow:0 .05em .05em rgba(0,0,0,.05);
  transition:all 400ms var(--ease-wabi);
  padding-inline:1.75em; font-size:16px; font-weight:500;
  letter-spacing:-0.18px; white-space:nowrap;
}
.glass-btn span::after{                       /* the travelling shine */
  content:''; display:block; position:absolute; z-index:3;
  width:calc(100% - clamp(1px,.0625em,4px)); height:calc(100% - clamp(1px,.0625em,4px));
  top:calc(0% + clamp(1px,.0625em,4px) / 2); left:calc(0% + clamp(1px,.0625em,4px) / 2);
  border-radius:999vw; overflow:clip;
  background:linear-gradient(var(--angle-2),
    rgba(255,255,255,0) 0%, rgba(255,255,255,.5) 40% 50%, rgba(255,255,255,0) 55%);
  mix-blend-mode:screen; pointer-events:none;
  background-size:200% 200%; background-position:0% 50%; background-repeat:no-repeat;
  transition:background-position 500ms var(--ease-wabi), --angle-2 500ms var(--ease-wabi);
}
.glass-btn:hover span::after{ background-position:25% 50%; }
.glass-btn::after{                            /* the conic edge */
  content:''; position:absolute; z-index:1; inset:0; border-radius:999vw;
  width:calc(100% + clamp(1px,.0625em,4px)); height:calc(100% + clamp(1px,.0625em,4px));
  top:calc(0% - clamp(1px,.0625em,4px) / 2); left:calc(0% - clamp(1px,.0625em,4px) / 2);
  padding:clamp(1px,.0625em,4px); box-sizing:border-box;
  background:
    conic-gradient(from var(--angle-1) at 50% 50%,
      rgba(0,0,0,.5), rgba(0,0,0,0) 5% 40%, rgba(0,0,0,.5) 50%, rgba(0,0,0,0) 60% 95%, rgba(0,0,0,.5)),
    linear-gradient(180deg, rgba(255,255,255,.5), rgba(255,255,255,.5));
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  transition:all 400ms var(--ease-wabi), --angle-1 500ms ease;
  box-shadow:inset 0 0 0 calc(clamp(1px,.0625em,4px) / 2) rgba(255,255,255,.35);
}
.glass-btn:hover::after{ --angle-1:-125deg; }
.glass-btn-wrap:has(button:hover) .glass-btn-shadow,
.glass-btn-wrap:has(a:hover) .glass-btn-shadow{ filter:blur(clamp(.25px,.0156em,1.5px)); }
.glass-btn-wrap:has(button:active) { transform:rotate3d(1,0,0,25deg); }

/* header variant — the bright pill */
.glass-btn-wrap--header{ width:140px; }
.glass-btn-wrap--header .glass-btn{
  width:140px; height:40px;
  background:
    linear-gradient(-75deg, rgba(255,255,255,.10), rgba(255,255,255,.30), rgba(255,255,255,.10)),
    rgba(255,255,255,.55);
  border:1px solid rgba(255,255,255,.9);
  box-shadow:
    inset 0 1px 4px rgba(255,255,255,.665),
    inset 0 -4px 4px rgba(255,255,255,.85),
    inset 0 0 14px rgba(229,229,229,.55),
    0 11px 28px rgba(0,0,0,.07),
    0 23px 31px rgba(0,0,0,.05);
  backdrop-filter:blur(clamp(4px,.5em,14px));
  -webkit-backdrop-filter:blur(clamp(4px,.5em,14px));
}
.glass-btn-wrap--header .glass-btn span{
  font-size:13px; font-weight:400; letter-spacing:-0.14px; color:#363636;
  padding-inline:.65em; display:inline-flex; align-items:center; gap:5px;
}
.glass-btn-wrap--header .glass-btn span svg{ display:none; }
@media (min-width:1025px){
  .glass-btn-wrap--header{ width:200px; }
  .glass-btn-wrap--header .glass-btn{ width:200px; height:56px; }
  .glass-btn-wrap--header .glass-btn span{
    font-size:19px; letter-spacing:-0.19px; padding-inline:.7em; gap:7px;
  }
  .glass-btn-shadow{
    width:calc(100% + 1em); height:calc(100% + 1em);
    top:calc(0% - .5em); left:calc(0% - .5em);
    filter:blur(clamp(1px,.0625em,6px));
  }
  .glass-btn-shadow::after{
    background:linear-gradient(180deg, rgba(0,0,0,.03), rgba(0,0,0,.015));
    width:calc(100% - 1em - .125em); height:calc(100% - 1em - .125em);
    top:calc(1em - .25em); left:calc(1em - .4375em);
  }
}
/* icon variant — the footer's social buttons */
.glass-btn-wrap--icon{ width:32px; }
.glass-btn-wrap--icon .glass-btn{ width:32px; height:32px; }
.glass-btn-wrap--icon .glass-btn span{ padding-inline:0; }
.glass-btn-wrap--icon svg{ width:16px; height:16px; color:var(--grey-500); }

/* ── hero — REMOVED ───────────────────────────────────────────────────
   era's own hero component lived here: `.hero`, `.hero-visual`, `.hero-copy`,
   `.props`, `.dcard-*`. None of it is used on this page, and `.hero` COLLIDED:
   it sets `height:100vh; overflow:hidden`, which is not a minimum, so this
   page's own hero — a different object with the same class name — was capped at
   one screen and clipped the moment its content grew past it. The headline sat
   102px above the top of the window and nothing in app.css could be blamed for
   it. A ported stylesheet's generic class names are the risk you take; the fix
   is to ship only the parts you actually port. What is kept below is the nav,
   the glass button, the facepile, the cycling word and the footer. */

/* ── facepile — the four friends, inline on line 3 of the subhead ───── */
.facepile{
  display:inline-flex; align-items:center; gap:0;
  vertical-align:-0.24em; margin-left:.16em;
  filter:drop-shadow(0 6px 14px rgba(0,0,0,.084)) drop-shadow(0 24px 50px rgba(0,0,0,.154));
}
.facepile .av{
  /* 20% off wabi.ai's own 1.235em — the pile reads as jewellery beside a
     fitted headline that can reach 200px */
  position:relative; width:0.988em; height:0.988em; border-radius:50%;
  overflow:hidden; background:#ddd; cursor:pointer; flex:none;
  /* stroked in the PAGE colour so the rings read as cut-outs, not white outlines */
  box-shadow:0 0 0 3px #fff;
  transform:translateY(var(--shift, 0px)) scale(var(--scale-active, 1));
  transform-origin:center;
  opacity:0; --reveal-zoom:1.22;
  transition:
    transform var(--av-dur, 320ms) var(--avatar-tf, cubic-bezier(0.34,1.56,0.64,1)),
    opacity .82s cubic-bezier(0.33,1,0.68,1) var(--reveal-delay, 0ms);
}
.facepile.revealed .av{ opacity:1; --reveal-zoom:1; }
.facepile .av + .av{ margin-left:-0.3em; }
/* ⚠ TWO STACKED LAYERS, one showing. See facepile() in js/chrome.js: a shuffle
   cross-fades between them, so both have to be present and positioned — swapping one
   `src` would show an empty circle for as long as the new file takes to decode. The
   incoming layer also comes up 6% large, which is what makes a swap read as a face
   arriving rather than a picture blinking. */
.facepile .av .av-img{
  position:absolute; inset:0;
  width:100%; height:100%; object-fit:cover; display:block;
  pointer-events:none; user-select:none;
  opacity:0;
  transform:scale(calc(var(--reveal-zoom, 1) * 1.06)); transform-origin:center;
  transition:opacity 460ms cubic-bezier(0.33,1,0.68,1),
             transform 620ms cubic-bezier(0.16,1,0.3,1);
}
.facepile .av .av-img.on{
  opacity:1;
  transform:scale(var(--reveal-zoom, 1));
  /* the reveal's own slow zoom, on the layer that is showing */
  transition:opacity 460ms cubic-bezier(0.33,1,0.68,1),
             transform .95s cubic-bezier(0.16,1,0.3,1) var(--reveal-delay, 0ms);
}
@media (prefers-reduced-motion:reduce){
  .facepile .av .av-img{ transition:none; }
}
/* Neighbours are tinted toward the page colour rather than faded — an opacity
   dim ghosts through wherever the circles overlap. */
.facepile .av::after{
  content:''; position:absolute; inset:0; border-radius:inherit;
  background:rgba(240,240,240, calc(var(--dim, 0) * .5));
  pointer-events:none; transition:background 260ms var(--ease-expo);
}
@media (max-width:640px){ .facepile .av{ box-shadow:0 0 0 2.25px #fff; } }
@media (prefers-reduced-motion:reduce){
  .facepile .av{ opacity:1; --reveal-zoom:1; transition:none; transform:none; }
}

/* cycling word — used by the loop's prompt line */
.cw-wrap{
  display:inline-flex; align-items:baseline; vertical-align:baseline;
  position:relative; overflow:visible; pointer-events:auto;
  /* ⚠ The width has to settle WITH the letters, not after them. At .45s against a
     .36s letter animation the slot was still resizing once the new word had landed,
     which is the part that read as not flowing — the words were done and the line
     was still moving. The whole swap is out (.36) + offset (.19) + in (.36), so the
     width takes the same span and the same curve. */
  transition:width .62s var(--ease-expo); padding-inline:.05em;
}
.cw-current{ display:inline-flex; align-items:baseline; white-space:nowrap; }
.cw-prev{
  position:absolute; left:0; top:0; display:inline-flex; align-items:baseline;
  white-space:nowrap; pointer-events:none;
}
.cw-measure{ position:absolute; opacity:0; pointer-events:none; white-space:nowrap; left:0; top:0; }
@keyframes cw-letter-in{
  0%   { opacity:0; transform:translateY(0.35em); filter:blur(4px); }
  60%  { opacity:1; filter:blur(0.6px); }
  100% { opacity:1; transform:translateY(0); filter:blur(0); }
}
@keyframes cw-letter-out{
  0%   { opacity:1; transform:translateY(0); filter:blur(0); }
  100% { opacity:0; transform:translateY(-0.35em); filter:blur(4px); }
}
.cw-letter{ display:inline-block; animation:cw-letter-in .36s var(--ease-expo) both; }
.cw-letter-out{ display:inline-block; animation:cw-letter-out .3s var(--ease-expo) both; }
@media (prefers-reduced-motion:reduce){ .cw-letter, .cw-letter-out{ animation:none; } }

/* ── footer ───────────────────────────────────────────────────────── */
.foot{
  position:relative; z-index:10;
  display:flex; align-items:center; justify-content:space-between;
  /* 14.5px, not the live site's 12px — this page carries no tiny text */
  padding:18px 24px; font-size:14.5px; color:var(--grey-500);
}
.foot-mark{ display:flex; align-items:center; color:var(--ink); }
.foot-mark svg{ display:block; }
.foot-legal{ display:none; align-items:center; gap:24px; }
@media (min-width:768px){ .foot-legal{ display:flex; } }
.foot-legal a{ color:inherit; text-decoration:none; transition:color .2s ease; }
.foot-legal a:hover{ color:#525252; }
.foot-legal .dot{ color:#a3a3a3; }
.foot-social{ display:flex; align-items:center; justify-content:flex-end; gap:8px; }
.foot-social a{ transition:opacity .2s ease; }
.foot-social a:hover{ opacity:.8; }


/* ── NOT PORTED: the footer's mark on a phone ───────────────────────────────
   See the note in js/chrome.js. The full wordmark above 700px, the five orbs
   below it — and the orbs are the NAV's mark with its lettering hidden, so the two
   are the same drawing in the same ink. */
.foot-mark--orbs { display:none; }
.foot-mark--orbs .wabi-logo-svg { width:auto; height:20px; }
.foot-mark--orbs .logo-text { display:none; }
/* ⚠ the mark's viewBox is 611 wide and the circles end at 168, so showing only the
   circles leaves 443 units of empty box to the right — the row would keep a gap
   where the lettering was. Cropping the viewBox is what actually removes it. */
@media (max-width:700px) {
  .foot-mark--full { display:none; }
  .foot-mark--orbs { display:flex; align-items:center; }
}
