/*
 * Copy-code toolbar — lives INSIDE the <pre> as the first child, so
 * the pre's own background + radius + padding wrap the toolbar + the
 * code as one block. No seam, no cascade fight with per-surface `pre`
 * margin rules.
 *
 * The wrap itself has no background, no margin, and no padding (the
 * pre's padding gives the button breathing room from the code below).
 * It's just a flex line that right-aligns the button.
 *
 * Lives in this lib stylesheet (not in a page stylesheet) because
 * decorateCodeBlocks() runs on every surface that renders rendered
 * markdown — post body, comment body, course-lesson body — and the
 * styling has to be identical wherever it's mounted. Pulling the CSS
 * in via the lib's TS module guarantees they ship together.
 */

.copy-code-wrap {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  margin: 0;
  padding: 0;
  background: transparent;
  /* Negative top margin pulls the button up into the pre's top
     padding so the row above the code doesn't visibly take vertical
     space — the button overlays the empty top-right corner of the
     fence rather than pushing the code down. */
  margin-top: -0.25rem;
}

/* Framework button.css gives every <button> a 36px height, ink color,
   and light-fill :hover/:active/:focus backgrounds. None of those apply
   on a dark <pre>: the framework's --bg-soft / --bg-panel fills turn
   the pill BRIGHT WHITE on tap (and on mobile the :focus state lingers,
   so the pill stays white and the dim-white label becomes unreadable).
   Override every interactive state explicitly to keep the pill flat
   and the label legible. */
.copy-code-btn,
.copy-code-btn:hover,
.copy-code-btn:active,
.copy-code-btn:focus,
.copy-code-btn:focus-visible {
  /* Square, sized to the icon. The old pill was sized to the word "Copy" and
     then had to grow for "✓ Copied", which moved the button under the
     pointer that had just clicked it. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 26px;
  width: 26px;
  min-height: 0;
  padding: 0;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-sm);
  cursor: pointer;
  outline: none;
  box-shadow: none;
  transform: none;
  transition: color 100ms, border-color 100ms;
}

.copy-code-btn {
  color: rgba(255, 255, 255, 0.7);
}
.copy-code-btn:hover {
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.4);
}
.copy-code-btn:active,
.copy-code-btn:focus,
.copy-code-btn:focus-visible {
  color: rgba(255, 255, 255, 0.7);
  border-color: rgba(255, 255, 255, 0.18);
}

.copy-code-btn.is-copied,
.copy-code-btn.is-copied:hover,
.copy-code-btn.is-copied:active,
.copy-code-btn.is-copied:focus,
.copy-code-btn.is-copied:focus-visible {
  color: var(--success);
  border-color: rgba(90, 197, 88, 0.55);
}


/* The file a snippet belongs to, pulled out of the code by the renderer and
   set as a bar across the top of the block. It sits on the block's own dark
   surface, separated from the code by a hairline that runs edge to edge, and
   the copy button joins it at the right. Each block sets --pre-pad-y and
   --pre-pad-x with its padding so the bar can reach past it. */
pre.has-file > .code-file {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin: calc(-1 * var(--pre-pad-y, 0.75rem)) calc(-1 * var(--pre-pad-x, 1rem)) var(--pre-pad-y, 0.75rem);
  padding: 0.5rem var(--pre-pad-x, 1rem);
  /* The copy button sets the bar's 43px height where decorateCodeBlocks
     runs; this holds it where it does not, such as an issue body. */
  box-sizing: border-box;
  min-height: 43px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.62);
}
/* A path too long for the bar scrolls on its own, so all of it can be read.
   Only the text scrolls: the icon before it and the copy button stay put. */
pre.has-file > .code-file .code-file-label {
  display: flex;
  align-items: center;
  min-width: 0;
  white-space: nowrap;
}
pre.has-file > .code-file .code-file-label::before {
  flex: none;
}
pre.has-file > .code-file .code-file-path {
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
}
pre.has-file > .code-file .code-file-path::-webkit-scrollbar {
  display: none;
}
pre.has-file > .code-file .code-file-note {
  flex: none;
}

/* The code scrolls, not the block, so a long line never takes the title bar
   and copy button with it. The code reaches the block's edges and carries
   the padding itself, so lines scroll right to the edge, and its bottom
   padding is where an overlay scrollbar lands, under the last line. */
pre.has-file.code-fence:not(.is-prompt) {
  overflow: hidden;
}
pre.has-file.code-fence:not(.is-prompt) > code {
  display: block;
  white-space: pre;
  overflow-x: auto;
  margin: 0 calc(-1 * var(--pre-pad-x, 1rem)) calc(-1 * var(--pre-pad-y, 0.75rem));
  padding: 0 var(--pre-pad-x, 1rem) var(--pre-pad-y, 0.75rem);
}
pre.has-file > .code-file .code-file-note {
  margin-left: 0.6rem;
  color: rgba(255, 255, 255, 0.4);
}
pre.has-file > .code-file .copy-code-btn { flex: none; }


/* A prompt to paste into an AI agent: a light input box with the agent's
   window bar above it, so it reads as a
   prompt and not as a shell command. Lines scroll rather than wrap, with
   the same fade on the right as every other box on the site. */
pre.is-prompt,
pre.is-prompt.code-fence {
  position: relative;
  background: var(--bg, #ffffff);
  color: var(--ink, #10283d);
  border: 1px solid var(--rule, rgba(16, 40, 61, 0.12));
  border-radius: 10px;
  box-shadow: 0 1px 2px rgba(16, 40, 61, 0.04), 0 12px 32px rgba(16, 40, 61, 0.10);
  --pre-pad-y: 1rem;
  --pre-pad-x: 1.25rem;
  padding: var(--pre-pad-y) var(--pre-pad-x);
}
pre.is-prompt > .code-file {
  border-bottom: 1px solid rgba(31, 30, 27, 0.10);
  /* The warm off-white agent apps use, shared with the agent terminal. */
  background: #f3f1ec;
  border-radius: 10px 10px 0 0;
  color: var(--ink-soft, #4b5d6e);
  font-family: var(--font-sans, inherit);
  font-size: 0.75rem;
  letter-spacing: 0;
}
/* Panes inside an agent app carry the pane's own icon, a speech bubble for
   the chat and a prompt for the terminal, rather than window dots: they are
   parts of one app, not separate windows. */
pre.is-prompt > .code-file .code-file-label::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 0.5rem;
  vertical-align: -2px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linejoin='round'%3E%3Cpath d='M2.5 3.5h11v7h-6l-3 2.5v-2.5h-2z'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linejoin='round'%3E%3Cpath d='M2.5 3.5h11v7h-6l-3 2.5v-2.5h-2z'/%3E%3C/svg%3E") center / contain no-repeat;
}
pre.is-agent-terminal > .code-file .code-file-label::before {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6.5 8 3 11.5M8.5 11.5h4.5'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6.5 8 3 11.5M8.5 11.5h4.5'/%3E%3C/svg%3E");
}
pre.is-prompt,
pre.is-prompt.code-fence {
  overflow: visible;
}
/* The code scrolls inside the box, not the box itself, so the fade stays on
   the right edge and the title bar stays put. */
pre.is-prompt code {
  display: block;
  color: inherit;
  white-space: pre;
  overflow-x: auto;

  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent);
          mask-image: linear-gradient(to right, #000 calc(100% - 56px), transparent);
}
pre.is-prompt .copy-code-btn,
pre.is-prompt .copy-code-btn:active,
pre.is-prompt .copy-code-btn:focus,
pre.is-prompt .copy-code-btn:focus-visible {
  color: var(--ink-soft, #4b5d6e);
  border-color: var(--rule, rgba(16, 40, 61, 0.18));
}
pre.is-prompt .copy-code-btn:hover {
  color: var(--ink, #10283d);
  border-color: var(--ink-soft, #4b5d6e);
}

/* The scrollbar goes under the last line, never over it. The code element
   is the scroller, so its bottom padding is where an overlay scrollbar
   lands; the box keeps a little padding of its own below that. Qualified
   with .post-body to win over the lesson body's pre and code rules, which
   reset padding. */
.post-body pre.is-prompt,
.post-body pre.is-prompt.code-fence {
  padding-bottom: 0.5rem;
}
.post-body pre.is-prompt code,
.post-body pre.is-prompt.code-fence code {
  padding: 0 0 1.25rem;
}

/* A copied block takes the same accent ring and fading wash as every other
   copyable surface on the site (.is-copyable.is-copied in site.css). */
pre.is-copied {
  position: relative;
  animation: copyable-ring 1s ease-out forwards;
}
pre.is-copied::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
  background: var(--accent);
  pointer-events: none;
  animation: copyable-wash 1s ease-out forwards;
}
@media (prefers-reduced-motion: reduce) {
  pre.is-copied::before { animation: none; opacity: 0.15; }
}

/* Click anywhere on a block to copy it; see decorateCodeBlocks. */
pre.is-click-copy {
  cursor: pointer;
}

/* A terminal pane inside an agent app (```text agent-terminal) is drawn
   exactly like the Agent Chat box, white under the same warm title bar, the
   way the panes look side by side in the app. The title tells them apart. */
.post-body pre.is-agent-terminal,
.post-body pre.is-agent-terminal.code-fence {
  color: #1f1e1b;
}

/* A shell block titled Terminal carries the terminal icon, the same mark as
   the Agent Terminal and the terminal widget. The browser console is a
   prompt too, not a file, so it carries the same mark. */
pre.is-terminal-block > .code-file .code-file-label::before,
pre.is-console > .code-file .code-file-label::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 0.5rem;
  vertical-align: -2px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6.5 8 3 11.5M8.5 11.5h4.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3 4.5 6.5 8 3 11.5M8.5 11.5h4.5'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Every titled block sits in the lesson boxes' rounded frame, and its title
   carries the icon of what it is: a page for a file, a prompt for a
   terminal. Commands for a shell are drawn as the lesson's Terminal box,
   the title in the sans face on a lighter bar; a file keeps its path in
   mono, so the two read apart. */
pre.has-file,
pre.has-file.code-fence {
  border-radius: 10px;
}
pre.has-file > .code-file {
  border-radius: 10px 10px 0 0;
}
pre.has-file:not(.is-prompt):not(.is-terminal-block):not(.is-console) > .code-file .code-file-label::before {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-right: 0.5rem;
  vertical-align: -2px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.4' stroke-linejoin='round'%3E%3Cpath d='M4 1.75h5.25L12.5 5v9.25H4z'/%3E%3Cpath d='M9 1.75V5.25h3.5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.4' stroke-linejoin='round'%3E%3Cpath d='M4 1.75h5.25L12.5 5v9.25H4z'/%3E%3Cpath d='M9 1.75V5.25h3.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
pre.is-terminal-block,
pre.is-terminal-block.code-fence {
  box-shadow: 0 1px 2px rgba(7, 12, 19, 0.06), 0 12px 32px rgba(7, 12, 19, 0.18);
}
/* Every dark block's title bar takes the same faint tint, whether it names a
   file or says Terminal, so they read as one family. The light agent boxes
   set their own beige above. */
pre.has-file:not(.is-prompt) > .code-file {
  background: rgba(255, 255, 255, 0.04);
}
pre.is-terminal-block > .code-file {
  font-family: var(--font-sans, inherit);
  letter-spacing: 0;
}

/* Selected text stays readable. The global ::selection sets color to the
   page's dark ink, which on a dark code block paints dark glyphs on the wash
   and the text vanishes. Dark blocks keep light glyphs on a blue wash, the
   same as the home page and install panel; the light agent boxes keep dark
   glyphs on the pale accent. An explicit colour, never `inherit`, which on
   ::selection resolves to the global rule's dark ink. */
pre.code-fence:not(.is-prompt)::selection,
pre.code-fence:not(.is-prompt) ::selection {
  background: rgba(73, 169, 231, 0.42);
  color: #f2f7fb;
}
pre.is-prompt::selection,
pre.is-prompt ::selection {
  background: var(--accent-soft, #ebf6fc);
  color: #10283d;
}

/* On a phone the block's padding is too much to spend on the bar's ends.
   Both sit close to the edge and look even: the icon's own whitespace and
   the button's border make equal padding read as uneven, so the left is a
   little less. */
@media (max-width: 640px) {
  pre.has-file > .code-file {
    padding-left: 0.5rem;
    padding-right: 0.625rem;
  }
}
