/* Study buddy (public/js/buddy.js): the study-room creature on the study
   screens. It moves as one composited layer and lets every click through. */
.sb { position: fixed; left: 0; top: 0; z-index: calc(var(--z-drawer, 1500) - 100); width: 46px; height: 38px;
  pointer-events: none; will-change: transform; image-rendering: pixelated; }
.sb[hidden] { display: none; }
.sb__fig { position: relative; width: 100%; height: 100%; }
.sb__fig .cs-av { width: 46px; height: 38px; }
.sb__fig svg { filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .18)); }

/* Breathing while it stands, little steps while it walks (one pixel, in
   whole frames, as on an old console). */
.sb .sb-av svg { animation: sb-breathe 1.6s steps(1, end) infinite; transform-origin: 50% 100%; }
.sb.is-walking .sb-av svg { animation: sb-bob .34s steps(1, end) infinite; }
.sb.is-walking .cs-leg--l { animation: sb-step .34s steps(1, end) infinite; }
.sb.is-walking .cs-leg--r { animation: sb-step .34s steps(1, end) infinite reverse; animation-delay: -.17s; }
.sb.is-air .sb-av svg { animation: none; transform: scaleY(1.06); }
.sb.is-land .sb-av svg { animation: sb-land .25s steps(2, end); }
/* Right answer: a happy wiggle. Wrong answer: it droops and stays still. */
.sb.is-happy .sb-av svg { animation: sb-happy .4s steps(2, end) infinite; transform-origin: 50% 100%; }
.sb.is-sad .sb-av svg { animation: none; transform: translateY(3px) scaleY(.86); transform-origin: 50% 100%; filter: saturate(.55) brightness(.9); }
.sb.is-sad .cs-eyes { transform: translateY(1px); }
.sb.is-dizzy .sb-av svg { animation: sb-dizzy .5s steps(4, end) infinite; transform-origin: 50% 60%; }

/* Tripped: it falls flat on its face in the direction it was walking, in
   three whole frames like an old sprite, and lies on the floor. The
   separate rotate/translate properties leave its facing (transform) alone. */
.sb__fig { transform-origin: 50% 100%; transition: rotate .24s steps(3, end), translate .24s steps(3, end); }
.sb.is-trip-r .sb__fig { rotate: 90deg; translate: 0 -21px; }
.sb.is-trip-l .sb__fig { rotate: -90deg; translate: 0 -21px; }
.sb.is-trip .sb-av svg { animation: none; }

/* Asleep: eyes shut and a slow z. */
.sb.is-sleeping .cs-eyes { display: none; }
.sb.is-sleeping .cs-eyes-shut { display: inline; }
.sb.is-sleeping .cs-zz { display: block; animation: cs-zz 2.6s ease-in-out infinite; }
.sb.is-sleeping .sb-av svg { animation: sb-breathe 2.8s steps(1, end) infinite; }

.sb__shadow { position: absolute; left: 50%; bottom: -5px; width: 30px; height: 4px; margin-left: -15px; border-radius: 2px;
  background: rgba(0, 0, 0, .16); transition: transform .15s steps(2), opacity .15s steps(2); }
.sb.is-air .sb__shadow { display: none; }

/* Thinking over a question: a slow nod. */
.sb.is-thinking .sb-av svg { animation: sb-breathe .9s steps(1, end) infinite; }

/* The question box: retro like the buddy (square corners, a 2px pixel
   frame, a small hard shadow, a pixel-style title) but quiet: the site's own
   colours, no frames around the messages, only one line between parts. */
.sb-chat { position: fixed; z-index: calc(var(--z-drawer, 1500) - 99); display: flex; flex-direction: column; max-height: min(400px, 58vh);
  background: var(--s2, var(--surface-2, #14304f)); color: var(--text-primary, #e8eef7);
  border: 2px solid var(--line-strong, rgba(255, 255, 255, .22)); border-radius: 0;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, .28);
  font: 14px/1.5 var(--font-ui, system-ui); animation: sb-pop .2s steps(3, end); }
.sb-chat[hidden] { display: none; }
.sb-chat__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 7px 6px 3px 12px; }
.sb-chat__title { font: 700 11.5px/1.3 var(--font-mono, ui-monospace, monospace); letter-spacing: .02em; color: var(--text-secondary, rgba(232, 238, 247, .72)); }
.sb-chat__title::before { content: '▸ '; color: var(--accent, #c9a45c); }
.sb-chat__x { border: 0; background: none; color: var(--text-muted, rgba(232, 238, 247, .5)); font: 700 14px/1 var(--font-mono, ui-monospace, monospace);
  cursor: pointer; padding: 3px 6px; border-radius: 0; }
.sb-chat__x:hover { color: var(--text-primary, #e8eef7); }
@keyframes sb-blink { 50% { opacity: 0; } }
.sb-chat__form { display: flex; align-items: stretch; gap: 6px; padding: 4px 10px 10px; }
.sb-chat__in { flex: 1; resize: none; min-height: 34px; max-height: 96px; padding: 6px 9px; border-radius: 0;
  border: 2px solid var(--line, rgba(255, 255, 255, .1)); background: var(--bg-input, var(--surface-3, rgba(0, 0, 0, .2)));
  color: inherit; font: 13px/1.4 var(--font-mono, ui-monospace, monospace); }
.sb-chat__in::placeholder { font: inherit; opacity: .7; }
.sb-chat__in:focus { outline: none; border-color: var(--accent, #c9a45c); }
.sb-chat__send { flex: none; padding: 0 12px; border: 0; border-radius: 0; cursor: pointer;
  background: var(--accent, #c9a45c); color: var(--accent-contrast, #1a1206); font: 700 12px var(--font-mono, ui-monospace, monospace);
  box-shadow: 2px 2px 0 rgba(0, 0, 0, .3); }
.sb-chat__send:active { transform: translate(2px, 2px); box-shadow: none; }

/* Pixel speech bubble. */
.sb__bubble { position: absolute; bottom: calc(100% + 10px); left: var(--bx, 0px); transform: none; width: max-content; max-width: 220px;
  padding: 5px 9px; border: 2px solid #2A1C16; border-radius: 0; background: #FFF8F0; color: #2A1C16;
  box-shadow: 3px 3px 0 rgba(42, 28, 22, .35); font: 700 12px/1.3 var(--font-mono, ui-monospace, monospace); text-align: center;
  transform-origin: var(--ax, 50%) 100%; animation: sb-pop .3s steps(3, end); }
.sb__bubble::after { content: ''; position: absolute; top: 100%; left: var(--ax, 50%); margin-left: -4px; width: 8px; height: 6px;
  background: #FFF8F0; border: 2px solid #2A1C16; border-top: 0; clip-path: polygon(0 0, 100% 0, 50% 100%); }
/* Placed by buddy.js: centred on the buddy, slid along only as far as the
   screen edge needs, its tail (--ax) always pointing at the buddy's middle and
   the pop growing from that same point. */
.sb__bubble[hidden] { display: none; }
/* An answer to a question: wider, in the reading font, left-aligned, still
   the same pixel bubble. While it thinks, a blinking cursor. */
.sb__bubble.is-long { max-width: 300px; padding: 7px 11px; font: 500 13px/1.45 var(--font-ui, system-ui); text-align: left; white-space: pre-line; }
.sb__bubble.is-wait { font: 700 12px/1.3 var(--font-mono, ui-monospace, monospace); }
.sb__bubble.is-wait::before { content: ''; }
:root[data-theme="dark"] .sb__bubble, :root[data-theme="dark"] .sb__bubble::after { background: #1F2A3D; color: #F5EDE3; border-color: #F5EDE3; }

@keyframes sb-in { 0% { opacity: 0; } 100% { opacity: 1; } }
@keyframes sb-happy { 0% { transform: rotate(-6deg) scaleY(1.04); } 50% { transform: rotate(6deg) scaleY(1.04); } }
@keyframes sb-breathe { 0% { transform: scaleY(1); } 50% { transform: scaleY(.96); } }
@keyframes sb-bob { 0% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes sb-step { 0% { transform: translateY(0); } 50% { transform: translateY(-1px); } }
@keyframes sb-land { 0% { transform: scale(1.12, .84); } 100% { transform: scale(1, 1); } }
@keyframes sb-dizzy { 0% { transform: rotate(0); } 25% { transform: rotate(-8deg); } 75% { transform: rotate(8deg); } }
/* The pop only scales (the separate `scale` property), so it never touches
   the `transform` that places a bubble: centred, or pinned to one side near
   a screen edge. Animating transform here moved the bubble half its width
   for the length of the pop, then it jumped into place. */
@keyframes sb-pop { 0% { scale: .6; } 100% { scale: 1; } }

/* The switch in the study room lobby. */
.cs-buddy { display: flex; align-items: center; gap: 10px; margin: 6px auto 0; padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px;
  background: none; color: var(--text-secondary); font: inherit; font-size: 13px; cursor: pointer; }
.cs-buddy:hover { background: var(--fill-hover); color: var(--text-primary); }
.cs-buddy__dot { width: 28px; height: 16px; border-radius: 8px; background: var(--line); position: relative; flex: none; }
.cs-buddy__dot::after { content: ''; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: #fff; transition: left .15s; }
.cs-buddy[aria-pressed="true"] .cs-buddy__dot { background: var(--accent); }
.cs-buddy[aria-pressed="true"] .cs-buddy__dot::after { left: 14px; }

@media (prefers-reduced-motion: reduce) {
  .sb, .sb *, .sb__bubble, .sb-chat { animation: none !important; transition: none !important; }
  .sb.is-sleeping .cs-zz { opacity: 1; }
}

/* Phones and tablets: it lives in the top bar, so it speaks downwards. */
.sb.is-top .sb__bubble { bottom: auto; top: calc(100% + 10px); }
.sb.is-top .sb__bubble::after { top: auto; bottom: 100%; border-top: 2px solid #2A1C16; border-bottom: 0; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
:root[data-theme="dark"] .sb.is-top .sb__bubble::after { border-top-color: #F5EDE3; }
.sb.is-top .sb__bubble { transform-origin: var(--ax, 50%) 0; }
.sb.is-top .sb__shadow { display: none; }
/* A double tap on the bar is for the buddy, not for zooming the page. */
.topnav { touch-action: manipulation; }

/* "Anything still unclear?" under an answer: two small pixel buttons. The
   bubble takes taps only while it carries them (the buddy itself never does). */
.sb__bubble.has-acts { pointer-events: auto; }
.sb__acts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.sb__acts button { border: 2px solid #2A1C16; border-radius: 0; background: transparent; color: inherit; cursor: pointer;
  padding: 3px 8px; font: 700 11.5px/1.3 var(--font-mono, ui-monospace, monospace); box-shadow: 2px 2px 0 rgba(42, 28, 22, .25); }
.sb__acts button.is-primary { background: #E8A33D; }
.sb__acts button:active { transform: translate(2px, 2px); box-shadow: none; }
:root[data-theme="dark"] .sb__acts button { border-color: #F5EDE3; }
:root[data-theme="dark"] .sb__acts button.is-primary { color: #1F2A3D; }
/* Phones zoom into a field typed in under 16px; the retro face stays. */
@media (pointer: coarse) { .sb-chat__in { font-size: 16px; } }

/* Showing the way / the part of the page an answer is about: it leaves its
   floor and stands on the thing, above the menus and the drawer it may be
   pointing into, and bobs as if to say "here!". */
.sb.is-away { z-index: calc(var(--z-overlay, 2000) + 10); }
.sb.is-away .sb__shadow { display: none; }
.sb.is-point:not(.is-air) .sb__fig { animation: sb-point .7s steps(1, end) infinite; }
@keyframes sb-point { 0% { translate: 0 0; } 50% { translate: 0 -4px; } }
.sb-chat { z-index: calc(var(--z-overlay, 2000) + 11); }
/* What is left of a question's length, shown only near the end. */
.sb-chat__count { margin-left: auto; margin-right: 4px; font: 700 11px var(--font-mono, ui-monospace, monospace); color: var(--text-muted, rgba(232, 238, 247, .5)); }
.sb-chat__count.is-out { color: var(--danger, #e5484d); }

/* The box's microphone: a small pixel button beside "Sor". */
.sb-chat__mic { flex: none; width: 34px; display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: pointer;
  border: 2px solid var(--line-strong, rgba(255, 255, 255, .22)); border-radius: 0; background: transparent; color: var(--text-secondary, rgba(232, 238, 247, .72)); }
.sb-chat__mic:hover { color: var(--accent, #c9a45c); border-color: var(--accent, #c9a45c); }
.sb-chat__mic:active { transform: translate(2px, 2px); }

/* Listening: it stands still, leans in a pixel, and four pixel bars beside
   it move with the voice (their heights are set from the microphone level,
   in whole 2px steps). */
.sb.is-listening .sb-av svg { animation: none; transform: translateY(-1px); }
.sb__ears { position: absolute; left: calc(100% + 4px); bottom: 6px; display: none; align-items: flex-end; gap: 2px; height: 14px; }
.sb.is-listening .sb__ears { display: flex; }
.sb__ears i { display: block; width: 3px; height: 2px; background: var(--accent, #E8A33D); box-shadow: 1px 1px 0 rgba(0, 0, 0, .25); }
.sb.is-top .sb__ears { bottom: 10px; }

/* Over the buddy the pointer stays the plain arrow, whatever is under it. */
html.sb-over, html.sb-over * { cursor: default !important; }
