/* 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.
   It is over every window and every part of the page (the notifications,
   the palette, the study room, the menus, Settings), never under one; only
   the short messages that come and go (toasts) stay over it. */
.sb { position: fixed; left: 0; top: 0; z-index: calc(var(--z-modal, 20000) + 10); 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%; isolation: isolate; }
/* What it drew and carries (buddy.js setProp): placed against its figure. */
.sb__prop { position: absolute; left: 50%; translate: -50% 0; line-height: 0; pointer-events: none; }
.sb__prop svg { display: block; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .18)); }
.sb__prop.is-under { top: 62%; z-index: 1; }
.sb__prop.is-over { bottom: 88%; }
.sb__prop.is-hand { left: 82%; top: 50%; translate: 0 -50%; z-index: 1; }
.sb__prop.is-behind { top: 50%; translate: -50% -50%; z-index: -1; }
.sb__prop.is-front { top: 50%; translate: -50% -50%; z-index: 1; }
.sb__prop.is-xy { translate: none; z-index: 1; }
.sb__prop.is-xy.is-back { z-index: -1; }
/* What it has become for now (buddy.js setBecome): its own drawing hidden, this one standing on its ground. */
.sb__fig.is-become .sb-av { visibility: hidden; }
.sb__become { position: absolute; left: 50%; bottom: 0; translate: -50% 0; line-height: 0; pointer-events: none; }
.sb__become svg { display: block; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .18)); }
.sb__bbody { transform-origin: 50% 100%; }
/* Its two frames take turns as it goes (legs, wheels, wings); a flier flaps and hovers all the time. */
.sb__become .sb__f2 { display: none; }
.sb.is-walking .sb__become.has-2 .sb__f1, .sb__become.m-fly.has-2 .sb__f1 { animation: sb-frame-a .3s steps(1, end) infinite; }
.sb.is-walking .sb__become.has-2 .sb__f2, .sb__become.m-fly.has-2 .sb__f2 { display: block; position: absolute; left: 0; top: 0; animation: sb-frame-b .3s steps(1, end) infinite; }
.sb__become.has-2 .sb__bbody { position: relative; }
@keyframes sb-frame-a { 0% { opacity: 1; } 50% { opacity: 0; } }
@keyframes sb-frame-b { 0% { opacity: 0; } 50% { opacity: 1; } }
/* How it goes about: a car rolls with no bob (a little rumble), a frog hops, a fish or a ghost glides, a bird hovers. */
.sb.is-walking .sb__become.m-roll .sb__bbody { animation: sb-step .12s steps(1, end) infinite; }
.sb.is-walking .sb__become.m-hop .sb__bbody { animation: sb-hopstep .36s steps(3, end) infinite; }
.sb.is-walking .sb__become.m-glide .sb__bbody { animation: sb-hover 1.2s steps(4, end) infinite; }
.sb__become.m-fly { bottom: 6px; }
.sb__become.m-fly .sb__bbody, .sb.is-walking .sb__become.m-fly .sb__bbody { animation: sb-hover 1s steps(4, end) infinite; }
.sb__become.m-glide .sb__bbody { animation: sb-hover 2s steps(4, end) infinite; }
@keyframes sb-hopstep { 0% { transform: translateY(0) scaleY(1); } 33% { transform: translateY(-6px) scaleY(1.06); } 66% { transform: translateY(-2px); } 100% { transform: translateY(0) scale(1.06, .92); } }
@keyframes sb-hover { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
/* A thing of its own on the screen (buddy.js thingOf): drawn over the page, never in the way of a press. */
.sb-thing { position: fixed; left: 0; top: 0; z-index: calc(var(--z-modal, 20000) + 9); pointer-events: none; line-height: 0; will-change: transform; }
.sb-thing svg { display: block; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .18)); }
/* At its sketchbook while a drawing it was asked for is made (buddy.js SKETCH): the lines come
   one by one and the pencil scribbles over them; with less motion, the page stands drawn. */
.sb__sketch { position: absolute; left: 96%; bottom: 0; line-height: 0; display: none; }
.sb__sketch svg { display: block; filter: drop-shadow(0 2px 0 rgba(0, 0, 0, .18)); }
.sb.is-thinking.is-sketching .sb__sketch { display: block; }
.sb__line { animation: sb-line 2.4s steps(1, end) infinite; }
.sb__line:nth-of-type(2) { animation-name: sb-line2; }
.sb__line:nth-of-type(3) { animation-name: sb-line3; }
.sb__pencil { animation: sb-pencil 2.4s steps(1, end) infinite; }
@keyframes sb-line { 0%, 8% { opacity: 0; } 9%, 100% { opacity: 1; } }
@keyframes sb-line2 { 0%, 40% { opacity: 0; } 41%, 100% { opacity: 1; } }
@keyframes sb-line3 { 0%, 72% { opacity: 0; } 73%, 100% { opacity: 1; } }
@keyframes sb-pencil {
  0% { transform: translate(-6px, -2px); } 10% { transform: translate(-4px, -3px); } 20% { transform: translate(-5px, -2px); }
  33% { transform: translate(-7px, 0); } 43% { transform: translate(-4px, 0); } 53% { transform: translate(-2px, -1px); }
  66% { transform: translate(-5px, 2px); } 76% { transform: translate(-3px, 2px); } 86% { transform: translate(-2px, 1px); }
  100% { transform: translate(0, 0); }
}
.sb.is-sketching.is-thinking .sb-av svg, .sb.is-sketching.is-thinking .sb__bbody { animation: sb-breathe .5s steps(1, end) infinite; }
.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, .sb .sb__bbody { animation: sb-breathe 1.6s steps(1, end) infinite; transform-origin: 50% 100%; }
.sb.is-walking .sb-av svg, .sb.is-walking .sb__bbody { 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, .sb.is-air .sb__bbody { animation: none; transform: scaleY(1.06); }
/* Running somewhere (İ14): the same little steps, twice as quick. */
.sb.is-running .sb-av svg, .sb.is-running .sb__bbody { animation-duration: .18s; }
.sb.is-running .cs-leg--l, .sb.is-running .cs-leg--r { animation-duration: .18s; }
.sb.is-running .cs-leg--r { animation-delay: -.09s; }
/* Sorry: a small bow, forwards and back, in whole frames. */
.sb.is-bow .sb-av svg, .sb.is-bow .sb__bbody { animation: sb-bow .9s steps(3, end) both; transform-origin: 50% 100%; }
@keyframes sb-bow { 0% { transform: none; } 30%, 70% { transform: rotate(12deg) translateY(2px) scaleY(.94); } 100% { transform: none; } }
/* Waiting for their press: it taps a foot. */
.sb.is-wait .cs-leg--r { animation: sb-tap .6s steps(2, end) infinite; }
.sb.is-wait .sb-av svg, .sb.is-wait .sb__bbody { animation: sb-wait 1.2s steps(2, end) infinite; transform-origin: 50% 100%; }   /* a body with no legs too */
@keyframes sb-tap { 0% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes sb-wait { 0% { transform: none; } 50% { transform: rotate(-4deg); } }
/* Waiting on the site's «are you sure?»: a «!» over its head, popped in once. */
.sb.is-alert::before { content: ''; position: absolute; left: 50%; bottom: calc(100% + 4px); translate: -50% 0; width: 5px; height: 17px;
  background: linear-gradient(#E8A33D 0 11px, transparent 11px 13px, #E8A33D 13px); filter: drop-shadow(2px 2px 0 #2A1C16);
  animation: sb-pop .2s steps(2, end); pointer-events: none; }
.sb.is-alert.is-top::before { bottom: auto; top: calc(100% + 2px); }
.sb.is-land .sb-av svg, .sb.is-land .sb__bbody { 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, .sb.is-happy .sb__bbody { animation: sb-happy .4s steps(2, end) infinite; transform-origin: 50% 100%; }
.sb.is-sad .sb-av svg, .sb.is-sad .sb__bbody { 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, .sb.is-dizzy .sb__bbody { 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, .sb.is-trip .sb__bbody { animation: none; }
/* Knocked over by clicks: one bounce as it lands. */
.sb.is-knocked .sb__fig { animation: sb-knock-bounce .24s steps(2, end) .24s; }
@keyframes sb-knock-bounce { 0% { translate: 0 -21px; } 50% { translate: 0 -28px; } 100% { translate: 0 -21px; } }

/* Sitting down (its own pose): squatted onto its feet, a little lower and wider, breathing slowly; it sets into it
   and gets up again in whole frames (buddy.js phasePose('sit')). Its feet stay on its ground. */
.sb.is-sit-in .sb-av svg, .sb.is-sit-in .sb__bbody { animation: sb-sit .2s steps(2, end) both; transform-origin: 50% 100%; }
.sb.is-sit .sb-av svg, .sb.is-sit .sb__bbody { transform: scale(1.06, .84); transform-origin: 50% 100%; animation: none; }
.sb.is-sit-out .sb-av svg, .sb.is-sit-out .sb__bbody { animation: sb-sit .16s steps(2, end) reverse both; transform-origin: 50% 100%; }
@keyframes sb-sit { from { transform: none; } to { transform: scale(1.06, .84); } }
/* 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; }
/* Its z stays upright and reads the right way whatever the figure does: turned the other way (mirrored) or lying
   down in a play (rotated); it still rises up the screen. Mirrored, a rotation undone turns the other way. */
.sb .cs-zz { scale: var(--sb-flip, 1) 1; }
.sb.is-keys .cs-zz { rotate: calc(var(--sb-r, 0deg) * -1 * var(--sb-flip, 1)); }
.sb.is-sleeping .sb-av svg, .sb.is-sleeping .sb__bbody { 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. It sets into it (a look up, a pixel taller) and comes out of it (a little
   settle) in whole frames; buddy.js thinkStart/thinkEnd. */
.sb.is-thinking .sb-av svg, .sb.is-thinking .sb__bbody { animation: sb-breathe .9s steps(1, end) infinite; }
.sb.is-thinking.is-thinking-in .sb-av svg, .sb.is-thinking.is-thinking-in .sb__bbody { animation: sb-set-in .2s steps(2, end) both; }
.sb.is-thinking-out .sb-av svg, .sb.is-thinking-out .sb__bbody { animation: sb-set-out .16s steps(2, end) both; }
@keyframes sb-set-in { from { transform: translateY(0); } to { transform: translateY(-1px) scaleY(1.04); } }
@keyframes sb-set-out { 0% { transform: scaleY(.94); } 100% { transform: none; } }
/* Long poses (buddy.js phasePose): sitting down into it and getting up out of it; dozing off and stretching awake. */
.sb.is-point-in .sb__fig { animation: sb-crouch .2s steps(2, end) both; }
.sb.is-point-out .sb__fig { animation: sb-crouch .16s steps(2, end) reverse both; }
@keyframes sb-crouch { from { translate: 0 0; } to { translate: 0 3px; } }
.sb.is-sleeping-in .cs-eyes { display: none; }
.sb.is-sleeping-in .cs-eyes-shut { display: inline; }
.sb.is-sleeping-in .sb-av svg, .sb.is-sleeping-in .sb__bbody { animation: sb-doze .2s steps(2, end) both; }
.sb.is-sleeping-out .sb-av svg, .sb.is-sleeping-out .sb__bbody { animation: sb-stretch .16s steps(2, end) both; }
@keyframes sb-doze { from { transform: none; } to { transform: translateY(1px) scaleY(.95); } }
@keyframes sb-stretch { 0% { transform: scaleY(1.08); } 100% { transform: none; } }
/* Its head tilted, wondering (a curious answer, a moment of hanging around). */
.sb.is-tilt .sb-av svg, .sb.is-tilt .sb__bbody { animation: sb-tilt .9s steps(3, end) both; transform-origin: 50% 100%; }
@keyframes sb-tilt { 0% { rotate: 0deg; } 25%, 75% { rotate: -9deg; } 100% { rotate: 0deg; } }

/* 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-modal, 20000) + 11); display: flex; flex-direction: column; max-height: min(640px, 60vh); overflow: hidden;
  background: var(--surface-2, #1f3a33); 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; gap: 2px; padding: 4px 4px 2px 12px; }
.sb-chat__title { flex: 1 1 auto; min-width: 0; }
.sb-chat__title { font: 700 11.5px/1.3 var(--font-reti, 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-reti, monospace);
  cursor: pointer; padding: 3px 6px; border-radius: 0; }
.sb-chat__x:hover { color: var(--text-primary, #e8eef7); }
/* Its earlier answers: a small pixel clock beside the ×. */
.sb-chat__hist { display: inline-flex; align-items: center; justify-content: center; border: 0; background: none; padding: 3px 6px; border-radius: 0;
  color: var(--text-muted, rgba(232, 238, 247, .5)); cursor: pointer; }
.sb-chat__hist:hover { color: var(--accent, #c9a45c); }
.sb-chat__hist[hidden] { display: none; }
@keyframes sb-blink { 50% { opacity: 0; } }
/* One row: the field, then its buttons beside it, all 44px high; the field
   grows upwards with what is written (buddy.js, up to 30% of the screen).
   The note that Reti can be wrong is a quiet line under them. */
.sb-chat__form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 6px; padding: 4px 10px 8px; }
.sb-chat__in { flex: 1 1 0; min-width: 0; resize: none; min-height: 44px; max-height: 30vh; padding: 10px 10px; border-radius: 0; overflow-y: hidden;
  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: 16px/1.4 var(--font-ui, system-ui); }
.sb-chat__in::placeholder { font: inherit; opacity: .7; }
/* That Reti can be wrong, said once and quietly: in the free space left of the buttons, never a line of its own. */
.sb-chat__note { order: 9; flex: 1 0 100%; min-width: 0; font-size: 11.5px; line-height: 1.3;
  color: var(--text-muted, rgba(232, 238, 247, .5)); }
.sb-chat__in:focus { outline: none; border-color: var(--accent, #c9a45c); }
.sb-chat__send { flex: none; min-height: 44px; padding: 0 14px; border: 0; border-radius: 0; cursor: pointer;
  background: var(--accent, #c9a45c); color: var(--accent-contrast, #1a1206); font: 700 12px var(--font-reti, 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: 600 13px/1.35 var(--font-reti, 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: 600 13px/1.35 var(--font-reti, monospace); }
.sb__bubble.is-scroll { overflow-y: auto; overscroll-behavior: contain; pointer-events: auto; }   /* taller than the room: it scrolls */
.sb__bubble.is-scroll::after { display: none; }   /* its tail would scroll away with it */
.sb__bubble.is-wait::before { content: ''; }
/* The step it is taking (İ6): one word over its words, as a small line. */
.sb__bubble[data-phase]:not(.is-wait)::before { content: attr(data-phase); display: block; margin-bottom: 2px; text-align: left;
  font: 600 11px/1.3 var(--font-reti, monospace); opacity: .7; }
: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); } }
/* The ground under it scrolled: a startled sway, then still. */
.sb__fig.is-startled .sb-av svg, .sb__fig.is-startled .sb__bbody { animation: sb-startled .6s steps(4, end) 1; transform-origin: 50% 100%; }
@keyframes sb-startled { 0% { transform: rotate(0) translateY(0); } 25% { transform: rotate(-10deg) translateY(-3px); } 60% { transform: rotate(7deg); } 100% { transform: rotate(0); } }
@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-reti, 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; }
@media (pointer: coarse) { .sb__acts button { min-height: 44px; padding: 6px 12px; } }   /* a thumb's size on a phone */
:root[data-theme="dark"] .sb__acts button.is-primary { color: #1F2A3D; }
/* Phones zoom into a field typed in under 16px; the retro face stays. A
   finger needs 44px to hit the buttons. */
@media (pointer: coarse) { .sb-chat__in { font-size: 16px; } .sb-chat__send, .sb-chat__mic, .sb-chat__x, .sb-chat__hist { min-height: 44px; min-width: 44px; } }
/* A page to read, under an answer: a link of its own line, underlined. */
.sb__acts a.is-link { flex: 1 0 100%; display: block; padding: 4px 0; color: inherit; font: 700 12.5px/1.35 var(--font-ui, system-ui);
  text-decoration: underline; text-underline-offset: 3px; overflow-wrap: anywhere; }
.sb__acts a.is-link::before { content: '↗ '; text-decoration: none; display: inline-block; margin-right: 2px; }
@media (pointer: coarse) { .sb__acts a.is-link { padding: 12px 0; } }

/* Showing the way / the part of the page an answer is about: it leaves its
   floor and stands on the thing and bobs as if to say "here!". */
.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; } }
/* 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-reti, monospace); color: var(--text-muted, rgba(232, 238, 247, .5)); }
.sb-chat__count.is-out { color: var(--danger, #e5484d); }

/* The box's camera and microphone: small pixel buttons in its title row,
   beside its clock, so the field has the box's width. */
.sb-chat__mic { flex: none; width: 34px; min-height: 30px; display: inline-flex; align-items: center; justify-content: center; padding: 0; cursor: pointer;
  border: 0; border-radius: 0; background: transparent; color: var(--text-muted, rgba(232, 238, 247, .5)); }
.sb-chat__mic:hover { color: var(--accent, #c9a45c); }
.sb-chat__mic:active { transform: translate(2px, 2px); }

/* A photo going with the question: small, over the field, with its ×. */
.sb-chat__photo { position: relative; margin: 0 0 8px; width: 72px; }
.sb-chat__photo[hidden] { display: none; }
.sb-chat__photo img { display: block; width: 72px; height: 72px; object-fit: cover; border: 2px solid var(--line-strong, rgba(255, 255, 255, .22)); }
.sb-chat__unphoto { position: absolute; top: -8px; right: -8px; width: 22px; height: 22px; padding: 0; border: 2px solid var(--line-strong, rgba(255, 255, 255, .22));
  border-radius: 0; background: var(--bg-card, #1d2230); color: inherit; cursor: pointer; font: 700 14px/1 var(--font-reti, monospace); }

/* 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, .sb.is-listening .sb__bbody { 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; }
/* An answer's bubble can be tapped away (its words; its buttons do their own thing). */
.sb__bubble.is-long:not(.is-wait) { pointer-events: auto; cursor: pointer; }

/* What Reti shows the person to press: a dotted frame blinks round it. */
[data-reti-here] { outline: 2px dashed var(--accent, #E8A33D) !important; outline-offset: 3px; animation: sb-here 1s steps(1) infinite; }
@keyframes sb-here { 50% { outline-color: transparent; } }
@media (prefers-reduced-motion: reduce) { [data-reti-here] { animation: none; } }

/* Moves it makes when asked ("move" steps): a spin, a wave. */
@keyframes sb-spin { to { transform: rotate(360deg); } }
@keyframes sb-wave { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-14deg); } 75% { transform: rotate(14deg); } }
.sb.is-spin .sb-av, .sb.is-spin .sb__bbody { animation: sb-spin 0.65s linear infinite; }
.sb.is-wave .sb-av, .sb.is-wave .sb__bbody { animation: sb-wave 0.45s ease-in-out infinite; transform-origin: 50% 90%; }
/* A somersault («takla»): once round in the air, each jump (buddy.js MOVES.flip). */
@keyframes sb-flip { 0%, 12% { transform: rotate(0); } 88%, 100% { transform: rotate(-360deg); } }
.sb.is-flip .sb-av, .sb.is-flip .sb__bbody { animation: sb-flip 0.8s ease-in-out infinite; transform-origin: 50% 50%; }
@media (prefers-reduced-motion: reduce) { .sb.is-spin .sb-av, .sb.is-wave .sb-av, .sb.is-flip .sb-av, .sb .sb__bbody, .sb .sb__become svg { animation: none; } }

/* In a session (RetiHost.big): the same creature twice as large, wherever
   it wanders, its words above it. Its moves stay its own; only their
   distances double with it. */
.sb.is-stage .sb__fig { scale: 2; }
.sb.is-stage .sb__bubble { bottom: calc(200% + 16px); max-width: 240px; padding: 7px 11px; font-size: 13px; }
/* Big and near the top of the screen: its words go under it. With both
   edges set (the top from .is-top, the bottom from here) the bubble was
   squeezed to a sliver and its words spilled out of it. */
.sb.is-stage.is-top .sb__bubble { bottom: auto; top: calc(100% + 10px); }
.sb.is-stage .sb__shadow { width: 56px; margin-left: -28px; bottom: -6px; height: 5px; border-radius: 3px; }
.sb.is-stage.is-trip-r .sb__fig, .sb.is-stage.is-trip-l .sb__fig { translate: 0 -42px; }
.sb.is-stage.is-knocked .sb__fig { animation: sb-knock-bounce-stage .24s steps(2, end) .24s; }
@keyframes sb-knock-bounce-stage { 0% { translate: 0 -42px; } 50% { translate: 0 -56px; } 100% { translate: 0 -42px; } }
.sb.is-stage .sb__ears { left: calc(100% + 26px); bottom: 20px; }


/* Its body put together for what was asked ("keys" steps, buddy.js
   keysBody): any size, any turn, about its middle; frame by frame, so no
   transition stands in the way. */
.sb.is-keys .sb__fig { transform-origin: 50% 50%; transition: none; scale: var(--sb-s, 1); rotate: var(--sb-r, 0deg); opacity: var(--sb-o, 1); }
.sb.is-keys.is-stage .sb__fig { scale: var(--sb-s, 2); }
/* Something done to the page for a moment ("fx" steps): little marks
   flying out, or a frame over some letters. Never in the way of a press. */
.sb-fx { position: fixed; z-index: calc(var(--z-modal, 20000) + 12); pointer-events: none; font-weight: 700; line-height: 1; }
.sb-fx-box { position: fixed; z-index: calc(var(--z-modal, 20000) + 9); pointer-events: none; border-radius: 6px;
  outline: 2px solid var(--accent, #E8A33D); background: color-mix(in srgb, var(--accent, #E8A33D) 18%, transparent); }

/* "Eski haline dön": beside Reti while it is turned into something, carries something or wears something asked
   (buddy.js placeUndo). A real touch target, in Reti's own pixel style. */
.sb-undo { position: fixed; left: 0; top: 0; z-index: calc(var(--z-modal, 20000) + 11); min-height: 44px; padding: 0 12px;
  border: 2px solid #2A1C16; border-radius: 0; background: #FFF8F0; color: #2A1C16; box-shadow: 3px 3px 0 rgba(42, 28, 22, .35);
  font: 600 13px/1 var(--font-reti, monospace); cursor: pointer; white-space: nowrap; touch-action: manipulation; }
.sb-undo[hidden] { display: none; }
.sb-undo:focus-visible { outline: 2px solid var(--accent, #c9a45c); outline-offset: 2px; }
.sb-undo:active { translate: 1px 1px; box-shadow: 2px 2px 0 rgba(42, 28, 22, .35); }
@media (prefers-reduced-motion: reduce) { .sb-undo:active { translate: none; } }

/* Its button: the question box one press away, at the end of its floor
   (buddy.js placeAskBtn). A square of the box's own make, 44px; on a wide
   screen its name beside the icon. */
.sb-askbtn { position: fixed; z-index: calc(var(--z-modal, 20000) + 9); display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-width: 44px; height: 44px; padding: 0 12px; cursor: pointer; border-radius: 0;
  background: var(--surface-2, #1f3a33); color: var(--text-primary, #e8eef7);
  border: 2px solid var(--line-strong, rgba(255, 255, 255, .22)); box-shadow: 2px 2px 0 rgba(0, 0, 0, .25);
  font: 700 12px var(--font-reti, monospace); -webkit-tap-highlight-color: transparent; }
.sb-askbtn[hidden] { display: none; }
.sb-askbtn svg { flex: none; color: var(--accent, #c9a45c); }
.sb-askbtn:hover { border-color: var(--accent, #c9a45c); }
.sb-askbtn:active { transform: translate(2px, 2px); box-shadow: none; }
.sb-askbtn:focus-visible { outline: 2px solid var(--accent, #c9a45c); outline-offset: 2px; }
@media (max-width: 1023px) { .sb-askbtn { padding: 0; width: 44px; } .sb-askbtn__label { display: none; } }

/* What Reti shows on the screen (İ7): a box, a hand-drawn ring or an arrow in the accent, square like its own
   drawing, never a glow; over the page, under Reti, never in the way of a press. */
.sb-marks { position: fixed; inset: 0; pointer-events: none; z-index: calc(var(--z-modal, 20000) + 5); }
.sb-mark { position: fixed; pointer-events: none; }
.sb-mark--box { border: 3px solid var(--accent, #F2C48D); border-radius: 0; animation: sb-mark-in .3s steps(3, end); }
.sb-mark--svg { left: 0; top: 0; overflow: visible; }
.sb-mark--svg path { fill: none; stroke: var(--accent, #F2C48D); stroke-width: 3; stroke-linecap: square; stroke-linejoin: miter;
  stroke-dasharray: 2000; stroke-dashoffset: 0; animation: sb-mark-draw .5s steps(5, end); }
@keyframes sb-mark-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes sb-mark-draw { from { stroke-dashoffset: 2000; } to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .sb-mark--box, .sb-mark--svg path { animation: none; } }

/* An answer's words coming out one by one (İ8): every word in place from the start, shown in turn. */
.sb__w.is-off, .sb__acts.is-off { visibility: hidden; }

/* Words picked on the page (İ11): «Bunu sor» under them, and the words over its box. Reti's own pixel button. */
.sb-selask { position: fixed; z-index: calc(var(--z-modal, 20000) + 8); min-height: 44px; padding: 0 14px; border: 0; border-radius: 0;
  background: var(--accent, #c9a45c); color: var(--accent-contrast, #1a1206); font: 700 12px var(--font-reti, monospace);
  box-shadow: 2px 2px 0 rgba(0, 0, 0, .3); cursor: pointer; }
.sb-selask:active { transform: translate(2px, 2px); box-shadow: none; }
.sb-selask[hidden] { display: none; }
.sb-chat__sel { display: flex; align-items: flex-start; gap: 6px; margin: 0 0 8px; padding: 6px 8px; border-left: 3px solid var(--accent, #c9a45c);
  background: var(--surface-1, rgba(255, 255, 255, .06)); font-size: 13px; line-height: 1.4; }
.sb-chat__sel[hidden] { display: none; }
.sb-chat__seltext { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.sb-chat__unsel { flex: none; min-width: 44px; min-height: 44px; margin: -10px -8px -10px 0; border: 0; background: none; color: inherit; font-size: 18px; cursor: pointer; }
