/* ------------------------------------------------------------- */
/* Tokens                                                         */
/* ------------------------------------------------------------- */
:root{
  --bg:#1B1B18;
  --bg-deep:#242420;
  --text:#F2EFE6;
  --text-soft:#B8B2A4;
  --accent:#E8B04B;
  --line:#38362F;
  --radius:2px;
}

*{margin:0;padding:0;box-sizing:border-box;}
html,body{height:100%;}

body{
  background:var(--bg);
  color:var(--text);
  font-family:'Inter',sans-serif;
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
  position:relative;
  /* Bottom padding reserves room for the fixed one-line footer so the
     chat window's max-height (below) has a real floor to be measured
     against — since .site-footer is position:fixed (out of flow), it
     can't reserve its own space, and centering .chat-window in the raw
     viewport would otherwise only give it half of any vh-based reserve
     as clearance. */
  padding:20px 16px 88px;
  padding-bottom:calc(88px + env(safe-area-inset-bottom, 0px));
  transition:background 0.4s ease, color 0.4s ease;
}

/* ------------------------------------------------------------- */
/* Ambient background: drifting blueprint grid + mouse glow       */
/* ------------------------------------------------------------- */
.grid{
  position:fixed;
  inset:-64px;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size:64px 64px;
  opacity:0.35;
  mask-image:radial-gradient(ellipse at center, black 0%, transparent 72%);
  -webkit-mask-image:radial-gradient(ellipse at center, black 0%, transparent 72%);
  transition:background-image 0.4s ease;
  animation:drift 40s linear infinite;
  will-change:transform;
}

.glow{
  position:fixed;
  top:0; left:0;
  width:520px;
  height:520px;
  border-radius:50%;
  background:radial-gradient(circle, var(--accent) 0%, transparent 70%);
  opacity:0.06;
  pointer-events:none;
  transform:translate(-50%,-50%);
  transition:opacity 0.4s ease, background 0.4s ease;
  z-index:1;
  will-change:transform;
}

@keyframes drift{
  from{ transform:translate(0,0); }
  to{ transform:translate(-64px,-64px); }
}

/* ------------------------------------------------------------- */
/* Chat window                                                    */
/* ------------------------------------------------------------- */
.chat-window{
  position:relative;
  z-index:2;
  width:min(420px, 92vw);
  background:var(--bg);
  border:1px solid var(--line);
  border-radius:18px;
  box-shadow:0 24px 60px -24px rgba(0,0,0,0.25);
  display:flex;
  flex-direction:column;
  overflow:hidden;
  opacity:0;
  animation:rise 0.8s ease forwards 0.1s;
  max-height:100%;
}

/* Disappear effect — triggered from js/chat.js a fixed 5s after the
   header goes offline, if enabled via /admin. pointer-events is dropped
   immediately (can't interact with a window that's leaving); visibility
   only flips at the animation's final step so the motion is still seen. */
.chat-window[class*="disappear-"]{
  pointer-events:none;
}

.disappear-fade{ animation:disappearFade 1.1s ease forwards; }
.disappear-shrink{ animation:disappearShrink 1s ease-in forwards; }
.disappear-slideDown{ animation:disappearSlideDown 1s ease-in forwards; }
.disappear-blur{ animation:disappearBlur 1.1s ease-in forwards; }

.chat-header{
  display:flex;
  align-items:center;
  gap:12px;
  padding:16px 20px;
  border-bottom:1px solid var(--line);
}

.avatar{
  flex:none;
  width:38px;
  height:38px;
  border-radius:50%;
  background:var(--accent);
  overflow:hidden;
  display:flex;
  align-items:center;
  justify-content:center;
}

.avatar img{
  width:100%;
  height:100%;
  object-fit:cover;
}

.name-row{
  display:flex;
  align-items:baseline;
  gap:6px;
  flex-wrap:wrap;
}

.chat-title .name{
  font-family:'Inter',sans-serif;
  font-weight:600;
  font-size:14px;
  color:var(--text);
}

.chat-title .status{
  display:flex;
  align-items:center;
  gap:6px;
  font-size:11.5px;
  color:var(--text-soft);
}

.chat-title .status .dot{
  width:6px;
  height:6px;
  border-radius:50%;
  background:#5FA463;
  transition:background 0.4s ease;
}

.chat-title .status.offline .dot{
  background:var(--text-soft);
}

/* Optional tagline (e.g. a short quote) — hidden entirely (via the
   `hidden` attribute) unless admin sets tagline text. Color is set inline
   by js/theme.js from config, not this default, since it's independently
   admin-editable rather than tied to a theme token. js/theme.js also
   moves this element to one of three spots per config.statusTagline.position
   (see index.html: #nameRow / #statusRow / #chatTitle) — the block/inline
   treatment below just needs to fit wherever it lands. */
.status-tagline{
  font-size:11px;
  color:var(--text-soft);
  margin-top:2px;
  overflow-wrap:break-word;
}

/* Beside-the-name placement: sits inline in #nameRow next to .name instead
   of on its own line, so it drops the block spacing and gets a leading
   separator instead. */
.status-tagline--inline{
  margin-top:0;
  font-weight:400;
}

.status-tagline--inline::before{
  content:'· ';
}

.chat-body{
  padding:20px;
  display:flex;
  flex-direction:column;
  gap:10px;
  flex:1;
  min-height:220px;
  overflow-y:auto;
  scroll-behavior:smooth;
  -webkit-overflow-scrolling:touch;
}

.bubble{
  align-self:flex-start;
  max-width:80%;
  padding:10px 14px;
  border-radius:16px;
  border-bottom-left-radius:4px;
  background:var(--bg-deep);
  color:var(--text);
  font-size:14.5px;
  line-height:1.5;
  overflow-wrap:break-word;
  opacity:0;
  transform:translateY(6px);
  animation:bubbleIn 0.35s ease forwards;
  /* Keeps WebKit from dropping this element's paint layer mid-animation
     while the container it's in is being scrolled programmatically. */
  will-change:opacity, transform;
  -webkit-backface-visibility:hidden;
  backface-visibility:hidden;
}

.bubble a{
  color:var(--accent);
  font-weight:600;
  text-decoration:underline;
  text-underline-offset:2px;
}

.bubble.outgoing{
  align-self:flex-end;
  background:var(--text);
  color:var(--bg);
  border-bottom-left-radius:16px;
  border-bottom-right-radius:4px;
}

/* Rich link-preview bubble, used for the LinkedIn invite */
.bubble.link-embed{
  padding:0;
  background:transparent;
}

.link-embed-card{
  display:flex;
  align-items:center;
  gap:12px;
  min-width:0;
  padding:12px 14px;
  background:var(--bg-deep);
  border:1px solid var(--line);
  border-radius:16px;
  border-bottom-left-radius:4px;
  text-decoration:none;
  color:var(--text);
  transition:background 0.2s ease, transform 0.2s ease;
}

.link-embed-card:hover{
  background:var(--line);
  transform:translateY(-1px);
}

.link-embed-icon{
  flex:none;
  width:34px;
  height:34px;
  border-radius:8px;
  background:var(--text);
  color:var(--bg);
  display:flex;
  align-items:center;
  justify-content:center;
}

.link-embed-icon svg{
  width:16px;
  height:16px;
  fill:currentColor;
}

.link-embed-text{
  min-width:0;
}

.link-embed-text .link-embed-title{
  font-weight:600;
  font-size:14px;
  overflow-wrap:break-word;
}

.link-embed-text .link-embed-domain{
  font-size:12px;
  color:var(--text-soft);
}

/* GIF message bubble — capped at a small display size regardless of the
   source file's actual dimensions, both so it can't blow up the chat
   window's layout and to keep the rendering/decoding cost trivial. The
   file itself still needs to be pre-compressed before it's committed to
   img/ (see README) — this only bounds what's paid on the layout side. */
.bubble.gif-bubble{
  padding:0;
  background:transparent;
}

.bubble.gif-bubble img{
  display:block;
  max-width:220px;
  max-height:220px;
  width:auto;
  height:auto;
  border-radius:16px;
  border-bottom-left-radius:4px;
}

.typing-indicator{
  align-self:flex-start;
  display:flex;
  align-items:center;
  gap:4px;
  padding:13px 16px;
  border-radius:16px;
  border-bottom-left-radius:4px;
  background:var(--bg-deep);
  opacity:0;
  transform:translateY(6px);
  animation:bubbleIn 0.3s ease forwards;
  will-change:opacity, transform;
  -webkit-backface-visibility:hidden;
  backface-visibility:hidden;
}

.typing-indicator span{
  width:6px;
  height:6px;
  border-radius:50%;
  background:var(--text-soft);
  animation:typingBounce 1.2s ease-in-out infinite;
}

.typing-indicator span:nth-child(2){ animation-delay:0.15s; }
.typing-indicator span:nth-child(3){ animation-delay:0.3s; }

.chat-input{
  flex:none;
  display:flex;
  align-items:center;
  gap:10px;
  padding:14px 16px calc(14px + env(safe-area-inset-bottom, 0px));
  border-top:1px solid var(--line);
  background:var(--bg);
  opacity:0;
  transform:translateY(6px);
  transition:opacity 0.35s ease, transform 0.35s ease;
}

.chat-input.visible{
  opacity:1;
  transform:translateY(0);
}

.chat-input-field{
  flex:1;
  min-width:0;
  font-family:'Inter',sans-serif;
  font-size:15px;
  color:var(--text);
  background:var(--bg-deep);
  border:1px solid var(--line);
  border-radius:999px;
  padding:12px 18px;
  outline:none;
  transition:border-color 0.2s ease;
}

.chat-input-field::placeholder{
  color:var(--text-soft);
}

.chat-input-field:focus{
  border-color:var(--accent);
}

.send-btn{
  flex:none;
  width:42px;
  height:42px;
  border-radius:50%;
  border:none;
  background:var(--text);
  color:var(--bg);
  display:flex;
  align-items:center;
  justify-content:center;
  cursor:pointer;
  transition:background 0.2s ease, transform 0.2s ease, opacity 0.2s ease;
}

.send-btn:hover{
  background:var(--accent);
  transform:translateY(-1px);
}

.send-btn:active{
  transform:translateY(0);
}

.send-btn:disabled{
  opacity:0.35;
  cursor:default;
  pointer-events:none;
}

.send-btn svg{
  width:18px;
  height:18px;
  fill:currentColor;
  margin-left:2px;
}

.site-footer{
  position:fixed;
  bottom:34px;
  z-index:2;
  opacity:0;
  animation:fadeInFooter 1s ease forwards 1.4s;
  max-width:90vw;
}

/* Alignment (admin-editable — js/theme.js sets this from config.footer.align)
   repositions the whole fixed block, not just the text inside it: since
   .site-footer shrink-wraps to its one line of content, text-align alone
   would have no visible box to align within. Defaults to center via the
   data-align="center" already on the element in index.html, so there's
   no flash of misplaced footer before config.js resolves. */
.site-footer[data-align="center"]{ left:50%; right:auto; transform:translateX(-50%); text-align:center; }
.site-footer[data-align="left"]{ left:16px; right:auto; transform:none; text-align:left; }
.site-footer[data-align="right"]{ left:auto; right:16px; transform:none; text-align:right; }

.footer-line{
  font-size:var(--footer-font-size, 11px);
  letter-spacing:0.14em;
  text-transform:uppercase;
  color:var(--text-soft);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}

.footer-line a{
  color:var(--text-soft);
  text-decoration:underline;
  text-underline-offset:2px;
  transition:color 0.2s ease;
}

.footer-line a:hover{
  color:var(--accent);
}

/* ------------------------------------------------------------- */
/* Keyframes                                                      */
/* ------------------------------------------------------------- */
@keyframes rise{
  from{ opacity:0; transform:translateY(10px); }
  to{ opacity:1; transform:translateY(0); }
}

@keyframes fadeInFooter{
  from{ opacity:0; }
  to{ opacity:0.6; }
}

@keyframes disappearFade{
  0%{ opacity:1; visibility:visible; }
  99%{ opacity:0; visibility:visible; }
  100%{ opacity:0; visibility:hidden; }
}

@keyframes disappearShrink{
  0%{ opacity:1; visibility:visible; transform:scale(1); }
  99%{ opacity:0; visibility:visible; transform:scale(0.85); }
  100%{ opacity:0; visibility:hidden; transform:scale(0.85); }
}

@keyframes disappearSlideDown{
  0%{ opacity:1; visibility:visible; transform:translateY(0); }
  99%{ opacity:0; visibility:visible; transform:translateY(40px); }
  100%{ opacity:0; visibility:hidden; transform:translateY(40px); }
}

@keyframes disappearBlur{
  0%{ opacity:1; visibility:visible; filter:blur(0); }
  99%{ opacity:0; visibility:visible; filter:blur(10px); }
  100%{ opacity:0; visibility:hidden; filter:blur(10px); }
}

@keyframes emphasisPulse{
  0%, 100%{ opacity:1; }
  50%{ opacity:0.72; }
}

@keyframes bubbleIn{
  from{ opacity:0; transform:translateY(6px); }
  to{ opacity:1; transform:translateY(0); }
}

@keyframes typingBounce{
  0%, 60%, 100%{ transform:translateY(0); opacity:0.4; }
  30%{ transform:translateY(-4px); opacity:1; }
}

/* ------------------------------------------------------------- */
/* Accessibility                                                  */
/* ------------------------------------------------------------- */
.link-embed-card:focus-visible,
.chat-input-field:focus-visible,
.send-btn:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
}

@media (prefers-reduced-motion: reduce){
  .chat-window, .site-footer{ animation:none !important; opacity:1 !important; }
  .bubble, .typing-indicator{ animation:none !important; opacity:1 !important; transform:none !important; }
  .chat-input{ transition:none !important; }
  .grid{ animation:none !important; }
  .glow{ display:none; }
  /* The disappear effect is a state change (not motion) — it still
     happens, just instantly instead of animated. Needs its own rule
     since it's more specific than the animation:none/opacity:1 above. */
  .chat-window[class*="disappear-"]{
    animation:none !important;
    opacity:0 !important;
    visibility:hidden !important;
    transform:none !important;
    filter:none !important;
  }
}

@media (max-width:480px){
  .glow{ display:none; }
  .chat-body{ min-height:180px; }
  body{
    padding:16px 12px 64px;
    padding-bottom:calc(64px + env(safe-area-inset-bottom, 0px));
  }
  .site-footer{ bottom:18px; max-width:94vw; }
  .site-footer[data-align="left"]{ left:12px; }
  .site-footer[data-align="right"]{ right:12px; }
  /* Scaled relative to the admin-configured size (default 11px * 0.82 ≈
     9px, verified to fit the default footer text on one line down to
     ~320px viewports) rather than a flat override, so a custom size from
     /admin still shrinks proportionally instead of being ignored on
     mobile. nowrap+ellipsis (inherited from .footer-line) stays as a
     safety net for text still too long at that scaled size. */
  .footer-line{
    font-size:calc(var(--footer-font-size, 11px) * 0.82);
    letter-spacing:0.02em;
  }
}
