/* What ALY's answers are made of: links and code boxes.
   Written for BOTH surfaces that render a reply through aly-render.js — the
   conversation (.aly-message-body) and the workspace's chat history
   (.workspace-chat-history-content) — because one renderer producing two
   different-looking code boxes is worse than either.
   Semantic tokens only, per the ALYSSIUN design contract. The code card is
   deliberately ink in BOTH atmospheres — the values below are the Infinite Void
   surfaces already declared in aly-theme.css, not new colours — because code is
   read as code, and a light code card in Ceramic Mist loses the one contrast
   that tells a reader where the prose stops. */
:root {
  --aly-code-bg: #16161c;
  --aly-code-ink: #e9e8ef;
  --aly-code-line: rgba(255, 255, 255, 0.10);
  --aly-code-muted: rgba(233, 232, 239, 0.58);
  --aly-tok-com: #7b8794;
  --aly-tok-str: #9ad39a;
  --aly-tok-num: #e0b083;
  --aly-tok-kw: #8fbcf5;
  --aly-tok-fn: #d6b6f0;
  --aly-tok-tag: #8fbcf5;
  --aly-tok-attr: #e3c88a;
  --aly-tok-var: #f1948a;
}

/* ---- Links ---------------------------------------------------------------
   Inline inside a sentence, a chip when the link is the whole line. Both are
   real anchors: target="_blank" with rel="noopener noreferrer" is set by the
   renderer, never here. */
:is(.aly-message-body, .workspace-chat-history-content) .aly-link {
  color: var(--aly-accent-ink);
  text-decoration: underline;
  text-decoration-color: var(--aly-accent-line);
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  overflow-wrap: anywhere;
}
:is(.aly-message-body, .workspace-chat-history-content) .aly-link:hover { text-decoration-color: currentColor; }
.aly-link-arrow {
  font-size: 0.78em; margin-left: 2px; opacity: 0.72;
  vertical-align: 0.08em; display: inline-block;
}

:is(.aly-message-body, .workspace-chat-history-content) .aly-link-chip {
  display: flex; align-items: center; gap: 10px;
  max-width: 100%; min-width: 0; margin: 0 0 6px;
  padding: 9px 12px;
  border: 1px solid var(--hair-2); border-radius: var(--radius);
  background: var(--glass-2);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  color: var(--text); text-decoration: none;
  transition: transform 120ms ease, background 120ms ease, border-color 120ms ease;
}
:is(.aly-message-body, .workspace-chat-history-content) .aly-link-chip:hover {
  background: var(--surface); border-color: var(--aly-accent-line); text-decoration: none;
}
:is(.aly-message-body, .workspace-chat-history-content) .aly-link-chip:active { transform: scale(0.985); background: var(--surface-2); }
:is(.aly-message-body, .workspace-chat-history-content) .aly-link-chip .aly-link-arrow { margin-left: auto; flex: 0 0 auto; opacity: 0.6; }

/* The favicon slot holds the REAL icon or nothing. There is no globe drawn
   underneath any more: aly-link-fav.js removes the image AND this slot when the
   icon fails to load, so the chip closes up and reads as title + domain.
   Nothing is drawn here that could survive as a placeholder. */
.aly-link-fav {
  position: relative; flex: 0 0 auto;
  width: 22px; height: 22px; border-radius: 6px;
  display: inline-block; overflow: hidden;
}
/* Belt and braces for the instant before the script runs, and for any path
   that empties the slot without removing it. */
.aly-link-fav:empty { display: none; }
.aly-link-fav-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  border-radius: 6px; object-fit: contain; background: transparent;
}
.aly-link-lines { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
.aly-link-title {
  font-size: 14px; line-height: 1.35; font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.aly-link-host {
  font-size: 11.5px; line-height: 1.3; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* A list of sources is a stack of chips, not a bulleted list. A chip is already
   a self-contained card, so the marker beside it is a second bullet for the same
   thing — and the 22px list indent pushes the whole stack off the text column.
   Both go, and the chips sit flush with the paragraph above them.
   `aly-chip-list` is set by the renderer when EVERY item in the list is a chip;
   `aly-link-item` covers a single chip inside an otherwise ordinary list, where
   the indent has to stay so the remaining bullets still line up. */
:is(.aly-message-body, .workspace-chat-history-content) ul.aly-chip-list,
:is(.aly-message-body, .workspace-chat-history-content) ol.aly-chip-list {
  list-style: none; padding-left: 0; margin: 0 0 12px;
}
:is(.aly-message-body, .workspace-chat-history-content) li.aly-link-item {
  list-style: none; margin-bottom: 0;
}
:is(.aly-message-body, .workspace-chat-history-content) li.aly-link-item::marker { content: none; }
/* The last chip in a stack carries no trailing gap — the list's own margin ends it. */
:is(.aly-message-body, .workspace-chat-history-content) .aly-chip-list > li:last-child .aly-link-chip {
  margin-bottom: 0;
}

@media (prefers-reduced-motion: reduce) {
  :is(.aly-message-body, .workspace-chat-history-content) .aly-link-chip { transition: none; }
  :is(.aly-message-body, .workspace-chat-history-content) .aly-link-chip:active { transform: none; }
}

/* ---- Code boxes ----------------------------------------------------------
   No top bar: no file name, no language label, no darker strip above the code.
   The figure carries the card, the <pre> carries the corners, and the only
   furniture is one floating copy circle over the top-right corner. The figure
   must NOT clip its overflow — clipping is what stops a sticky child from
   sticking. */
:is(.aly-message-body, .workspace-chat-history-content) .aly-code {
  --aly-code-tools-top: 8px;
  margin: 0 0 14px; min-width: 0;
  border: 1px solid var(--aly-code-line); border-radius: var(--radius);
  background: var(--aly-code-bg);
  box-shadow: 0 18px 40px -28px rgba(0, 0, 0, 0.85);
}
/* A zero-height sticky rail: it takes no room in the flow, so the code starts at
   the very top of the box, and the icon it carries stays in the corner however
   far down a long block the transcript has been scrolled. */
.aly-code-tools {
  position: sticky; top: var(--aly-code-tools-top); z-index: 2;
  height: 0; display: flex; justify-content: flex-end;
  pointer-events: none;
}
.aly-code-copy {
  pointer-events: auto;
  position: relative; margin: 8px 8px 0 0; flex: 0 0 auto;
  width: 30px; height: 30px; padding: 0;
  display: inline-grid; place-items: center;
  border: 1px solid var(--aly-code-line); border-radius: 50%;
  background: rgba(255, 255, 255, 0.06); color: var(--aly-code-muted);
  -webkit-backdrop-filter: blur(12px) saturate(140%); backdrop-filter: blur(12px) saturate(140%);
  font: inherit; font-size: 12px; line-height: 1; cursor: pointer;
  opacity: 0.8;
  transition: opacity 140ms ease, background-color 140ms ease, color 140ms ease;
}
.aly-code:hover .aly-code-copy, .aly-code-copy:focus-visible { opacity: 1; }
/* Nothing hovers on a phone, so the one control the box has is always there. */
@media (hover: none) { .aly-code-copy { opacity: 1; color: var(--aly-code-ink); } }
.aly-code-copy:hover { background: rgba(255, 255, 255, 0.12); color: var(--aly-code-ink); }
.aly-code-copy-icon::before { content: "⧉"; font-size: 14px; }
/* "Copied" is a small label beside the circle, never a bar behind it. */
.aly-code-copy-word {
  position: absolute; right: calc(100% + 6px); top: 50%;
  transform: translateY(-50%);
  padding: 3px 8px; border-radius: 999px;
  border: 1px solid var(--aly-code-line);
  background: rgba(255, 255, 255, 0.06); color: var(--aly-tok-str);
  -webkit-backdrop-filter: blur(12px) saturate(140%); backdrop-filter: blur(12px) saturate(140%);
  font-size: 11px; line-height: 1; white-space: nowrap;
  opacity: 0; visibility: hidden;
  transition: opacity 140ms ease;
}
.is-copied .aly-code-copy-icon::before { content: "✓"; }
.is-copied .aly-code-copy-word { opacity: 1; visibility: visible; }
.is-copied .aly-code-copy {
  opacity: 1;
  color: var(--aly-tok-str); border-color: var(--aly-tok-str);
  animation: aly-code-pulse 620ms ease-out;
}
.is-copy-failed .aly-code-copy-icon::before { content: "!"; }
.is-copy-failed .aly-code-copy { opacity: 1; color: var(--danger); border-color: var(--danger); }
@keyframes aly-code-pulse {
  from { box-shadow: 0 0 0 0 rgba(154, 211, 154, 0.45); }
  to { box-shadow: 0 0 0 12px rgba(154, 211, 154, 0); }
}
@media (prefers-reduced-motion: reduce) { .is-copied .aly-code-copy { animation: none; } }

:is(.aly-message-body, .workspace-chat-history-content) .aly-code-pre {
  margin: 0; padding: 13px 14px 15px;
  border: 0; border-radius: calc(var(--radius) - 1px);
  background: transparent; color: var(--aly-code-ink);
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  /* The one place in a reply where text must NOT wrap — and the one place iOS
     would otherwise inflate it, because a wide line looks like a column that
     needs enlarging. */
  white-space: pre; overflow-wrap: normal; word-break: normal;
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
  font-size: 13px; line-height: 1.65;
}
:is(.aly-message-body, .workspace-chat-history-content) .aly-code-pre code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: inherit; background: none; padding: 0; color: inherit;
}
.aly-code .tok-com { color: var(--aly-tok-com); font-style: italic; }
.aly-code .tok-str { color: var(--aly-tok-str); }
.aly-code .tok-num { color: var(--aly-tok-num); }
.aly-code .tok-kw { color: var(--aly-tok-kw); }
.aly-code .tok-fn { color: var(--aly-tok-fn); }
.aly-code .tok-tag { color: var(--aly-tok-tag); }
.aly-code .tok-attr { color: var(--aly-tok-attr); }
.aly-code .tok-var { color: var(--aly-tok-var); }

/* The orb hangs into the top of the TRANSCRIPT and the first 48px are masked,
   so the sticky copy icon parks below both rather than fading out under the
   orb. The workspace panel has its own header and keeps the small default
   offset. */
.aly-main:has(.aly-sphere-compact.has-sphere) .aly-transcript .aly-message-body .aly-code {
  --aly-code-tools-top: 52px;
}

@media (max-width: 520px) {
  /* A thumb still needs the target, so the circle keeps its size on a phone
     and only pulls in closer to the corner. */
  .aly-code-copy { margin: 6px 6px 0 0; }
  :is(.aly-message-body, .workspace-chat-history-content) .aly-code-pre { font-size: 12.5px; padding: 11px 12px 13px; }
}
