/* ============================================================
   card.css
   The profile card itself. Identity block is deliberately offset
   to the left rather than centred, so the composition is not a
   dead-centre stack.
   ============================================================ */

/* The card stays completely hidden behind the gate. The gate is a
   vignette rather than a solid fill, so without this the card was
   visible through it on the welcome screen. */
.stage{
  position:relative;
  z-index:var(--z-page);
  min-height:100dvh;
  display:grid;
  place-items:center;
  padding:clamp(1rem,4vw,2.5rem);
  opacity:0;
  transition:opacity .7s var(--ease);
}
.stage.is-live{ opacity:1 }

.card{
  position:relative;
  width:100%;
  max-width:480px;
  border:1px solid var(--line);
  border-radius:var(--r-card);
  background:linear-gradient(180deg, rgba(255,255,255,.055), rgba(255,255,255,.018));
  backdrop-filter:blur(26px) saturate(130%);
  -webkit-backdrop-filter:blur(26px) saturate(130%);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.10),
    0 30px 80px rgba(0,0,0,.55);
  overflow:hidden;
  isolation:isolate;
}

/* Box highlight: a spotlight that tracks the cursor.
   Driven by --mx / --my from js/spotlight.js, so it never
   re-renders anything. */
.card::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:3;
  pointer-events:none;
  border-radius:inherit;
  opacity:0;
  transition:opacity var(--dur-mid) var(--ease);
  background:radial-gradient(
    260px circle at var(--mx,50%) var(--my,0%),
    rgba(255,255,255,.10),
    transparent 62%
  );
}
.card:hover::after{ opacity:1 }

/* Running border. A conic gradient rotates behind the card and a mask
   clips it down to the 1.5px ring, so only the edge is ever painted.
   Registering --angle as a real angle type is what makes it animate;
   browsers without @property simply show the ring standing still. */
@property --angle{
  syntax:"<angle>";
  initial-value:0deg;
  inherits:false;
}

.card::before{
  content:"";
  position:absolute;
  inset:-1px;                                /* sit on the border, not inside it */
  z-index:4;
  padding:1.5px;
  border-radius:calc(var(--r-card) + 1px);
  pointer-events:none;
  background:conic-gradient(
    from var(--angle),
    rgba(255,255,255,0)   0deg,
    rgba(255,255,255,.95) 42deg,
    rgba(255,255,255,.18) 78deg,
    rgba(255,255,255,0)   140deg,
    rgba(255,255,255,0)   190deg,
    rgba(255,255,255,.72) 232deg,
    rgba(255,255,255,.14) 268deg,
    rgba(255,255,255,0)   330deg
  );
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor;
  mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite:exclude;
}

@media (prefers-reduced-motion: no-preference){
  .card::before{ animation:orbit 7s linear infinite }
}

@keyframes orbit{ to{ --angle:360deg } }

@media (prefers-reduced-transparency: reduce){
  .card{
    background:var(--surface-solid);
    backdrop-filter:none;
    -webkit-backdrop-filter:none;
  }
}

/* --- load-in choreography, staggered by --i --- */
.reveal{ opacity:0; transform:translateY(18px) }

.is-live .reveal{
  opacity:1;
  transform:none;
  transition:opacity .8s var(--ease), transform .8s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms + 120ms);
}

/* --- banner --- */
.banner{
  position:relative;
  aspect-ratio:16/4.4;
  min-height:104px;
  overflow:hidden;
  background:linear-gradient(122deg,#26282d 0%,#131418 52%,#0b0c0e 100%);
}
.banner img{ width:100%; height:100%; object-fit:cover }
.banner::after{
  content:"";
  position:absolute;
  inset:0;
  background:linear-gradient(180deg, rgba(8,9,10,0) 34%, rgba(8,9,10,.86) 100%);
}

/* --- identity --- */
.ident{
  position:relative;
  z-index:2;
  display:flex;
  align-items:flex-end;
  gap:1rem;
  margin-top:-46px;
  padding:0 var(--pad-x);
}

.avatar-wrap{
  position:relative;
  flex:0 0 auto;
  width:var(--avatar-size);
  height:var(--avatar-size);
}

.avatar{
  width:100%;
  height:100%;
  border-radius:50%;
  object-fit:cover;
  background:#1a1c20;
  box-shadow:0 0 0 var(--avatar-ring) var(--bg), 0 12px 30px rgba(0,0,0,.5);
}

/* The frame is centred on the avatar by translate rather than by
   percentage insets, so it stays concentric at any size. Its size and
   nudge come from tokens.css. `object-fit:contain` guards against an
   asset that is not perfectly square being stretched off centre.
   The dark ring is dropped whenever a frame is on, because the frame
   is the ring: leaving both on makes the photo read wider than it is
   and the frame then looks offset even when it is not. */
.deco{
  position:absolute;
  top:50%;
  left:50%;
  z-index:2;
  width:calc(100% * var(--deco-scale));
  height:calc(100% * var(--deco-scale));

  /* base.css sets `img{max-width:100%}`. That rule does not lose to the
     width above, it clamps it: the frame was pinned at 100% of the
     avatar no matter what --deco-scale said, while the height still
     grew, so the art stretched vertically and read as off centre.
     Both caps have to be lifted for the scale to mean anything. */
  max-width:none;
  max-height:none;

  display:none;
  object-fit:contain;
  transform:translate(-50%,-50%) translate(var(--deco-x),var(--deco-y));
  pointer-events:none;
}
.deco.is-on{ display:block }
.avatar-wrap.has-deco .avatar{ box-shadow:0 12px 30px rgba(0,0,0,.5) }

/* Straddles the avatar edge normally. With a decoration on, it moves
   inside the photo instead, so it does not land on top of the frame
   ring the way it did before. */
.presence{
  position:absolute;
  right:-2px;
  bottom:-2px;
  z-index:3;
  width:21px;
  height:21px;
  border-radius:50%;
  background:var(--offline);
  box-shadow:0 0 0 5px var(--bg);
  transition:background var(--dur-mid) var(--ease);
}
.avatar-wrap.has-deco .presence{
  right:5%;
  bottom:5%;
  box-shadow:0 0 0 4px var(--bg);
}

/* --- custom status, a chat balloon up and right of the avatar ---
   The tail is two shrinking circles rather than a triangle, the
   way a speech balloon reads in a comic panel. Both are drawn as
   pseudo elements so the markup stays a single paragraph. */
.bubble{
  position:absolute;
  bottom:calc(100% - 2px);
  left:calc(100% - 6px);
  z-index:3;
  display:none;
  align-items:center;
  gap:.42rem;
  max-width:min(300px,54vw);
  padding:.5rem .9rem;
  border-radius:var(--r-pill);
  background:var(--bubble-bg);
  box-shadow:0 10px 26px rgba(0,0,0,.45);
  font-size:.86rem;
  font-weight:450;
  line-height:1.35;
  color:var(--text);
  white-space:nowrap;
}
.bubble.is-on{ display:inline-flex }
.bubble img{ flex:0 0 auto; width:18px; height:18px }
.bubble span{ overflow:hidden; text-overflow:ellipsis }

/* tail, larger circle */
.bubble::before{
  content:"";
  position:absolute;
  top:calc(100% + 4px);
  left:16px;
  width:15px;
  height:15px;
  border-radius:50%;
  background:var(--bubble-bg);
}

/* tail, smaller circle */
.bubble::after{
  content:"";
  position:absolute;
  top:calc(100% + 23px);
  left:11px;
  width:9px;
  height:9px;
  border-radius:50%;
  background:var(--bubble-bg);
}

@media (prefers-reduced-motion: no-preference){
  .is-live .bubble.is-on{ animation:bubble-in .6s var(--ease) both .5s }
  .is-live .bubble.is-on::before{ animation:bubble-in .45s var(--ease) both .42s }
  .is-live .bubble.is-on::after { animation:bubble-in .45s var(--ease) both .34s }
}
@keyframes bubble-in{
  from{ opacity:0; transform:translateY(6px) scale(.86) }
  to  { opacity:1; transform:none }
}
.presence[data-status="online"]{ background:var(--online) }
.presence[data-status="idle"]  { background:var(--idle) }
.presence[data-status="dnd"]   { background:var(--dnd) }
.presence[data-status="offline"]{ background:var(--offline) }

.names{ min-width:0; padding-bottom:.35rem }

.names h1{
  font-size:clamp(1.35rem,5vw,1.7rem);
  font-weight:600;
  letter-spacing:-.03em;
  line-height:1.15;
  overflow-wrap:anywhere;
}

.names p{
  font-size:.82rem;
  color:var(--text-faint);
  overflow-wrap:anywhere;
}

/* --- panel --- */
.panel{ padding:1.15rem var(--pad-x) 0 }

.bio{
  font-size:.92rem;
  color:var(--text-dim);
  max-width:52ch;
}

/* --- activity --- */
.activity{
  display:none;
  margin-top:1.1rem;
  padding:.85rem;
  border:1px solid var(--line);
  border-radius:var(--r-inner);
  background:var(--surface);
}
.activity.is-on{ display:block }

.activity__label{
  margin-bottom:.7rem;
  font-size:.66rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--text-faint);
}

.activity__row{ display:flex; align-items:center; gap:.85rem }

.art{
  position:relative;
  flex:0 0 auto;
  width:60px;
  height:60px;
  border-radius:var(--r-art);
  overflow:hidden;
  background:rgba(255,255,255,.06);
}
.art img{ width:100%; height:100%; object-fit:cover }

.art__small{
  position:absolute;
  right:-4px;
  bottom:-4px;
  width:24px;
  height:24px;
  display:none;
  border:2px solid #16171a;
  border-radius:50%;
}
.art__small.is-on{ display:block }

.meta{ flex:1; min-width:0 }

.meta strong{
  display:block;
  font-size:.95rem;
  font-weight:500;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

.meta span{
  display:block;
  font-size:.82rem;
  color:var(--text-dim);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

.meta .elapsed{
  margin-top:.2rem;
  font-size:.76rem;
  color:var(--text-faint);
}

/* Progress animates transform only, never width. */
.track{
  display:none;
  height:3px;
  margin-top:.8rem;
  border-radius:var(--r-pill);
  background:rgba(255,255,255,.10);
  overflow:hidden;
}
.track.is-on{ display:block }

.track__fill{
  height:100%;
  border-radius:inherit;
  background:var(--text);
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform 1s linear;
}

.times{
  display:none;
  justify-content:space-between;
  margin-top:.35rem;
  font-size:.68rem;
  color:var(--text-faint);
}
.times.is-on{ display:flex }

/* --- links --- */
.links{
  display:flex;
  flex-wrap:wrap;
  gap:.5rem;
  padding:1.3rem var(--pad-x) clamp(1.3rem,4vw,1.6rem);
}

.links a{
  display:inline-flex;
  align-items:center;
  gap:.45rem;
  padding:.5rem .95rem;
  border:1px solid var(--line);
  border-radius:var(--r-pill);
  background:var(--surface-2);
  color:var(--text-dim);
  font-size:.8rem;
  text-decoration:none;
  transition:
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    background var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}

.links a:hover{
  color:var(--text);
  border-color:var(--line-strong);
  background:rgba(255,255,255,.09);
}

.links a:active{ transform:translateY(1px) }
.links i{ font-size:1rem }
