/* ═══════════════════════════════════════════════════════════════════════
   The line under the sphere — "this is a button, press it and talk"
   ───────────────────────────────────────────────────────────────────────
   A sphere of points has no edge, no shadow and no label. It breathes and
   it rotates, which is exactly what an ornament does, so the one place on
   the page where a visitor could simply start talking read as decoration
   and went unpressed. The glow under the pointer only helps somebody who
   already put a pointer on it, and on a phone there is no pointer at all.

   So under every sphere that opens a call there is one short line in
   words: a microphone and "Tap to talk" — "Click to talk" where there is
   a mouse, chosen by the pointer media query rather than by a script, so
   there is no wrong wording on the first frame and the wording that is
   not shown is display:none and therefore not read aloud either.

   While a call is up the line stops inviting and starts reporting —
   Connecting… / Listening… / Thinking… / Speaking… — with a pulsing dot
   in place of the microphone, and it goes back to inviting when the call
   ends. One element, one attribute (data-state), no second copy of the
   widget's state anywhere.

   Markup when the cue is its own control (use a span instead when it already
   sits inside the orb's button):

     <button class="fg-cue" type="button" data-state="idle">
       <svg class="fg-cue-ic" …a microphone…></svg>
       <i class="fg-cue-dot" aria-hidden="true"></i>
       <span class="fg-cue-t"
         ><span class="fg-cue-idle"
           ><span class="fg-cue-tap">Tap to talk</span
           ><span class="fg-cue-click">Click to talk</span
         ></span
         ><span class="fg-cue-live"></span
       ></span>
     </button>

   data-state:
     idle       invitation, microphone, breathing        (the wording above)
     again      invitation after a call, from .fg-cue-live
     connecting | listening | thinking | speaking        dot, no breathing
     trouble    a sentence, not a pill — it has to wrap

   Colours are the liquid orb's own: blue at rest, green while it is
   listening. Tokens are read with
   fallbacks, because the console pages and /p/<slug> each declare their
   own subset.
   ═══════════════════════════════════════════════════════════════════════ */

.fg-cue {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 7px 14px 7px 11px;
  border: 1px solid rgba(139, 180, 255, .2);
  border-radius: 999px;
  background: rgba(139, 180, 255, .06);
  color: rgba(234, 238, 247, .88);
  font: 500 13px/1.2 var(--sans, "Instrument Sans", "Inter", ui-sans-serif, system-ui, sans-serif);
  letter-spacing: -.005em;
  white-space: nowrap;
  vertical-align: middle;
  transition: border-color .25s ease, background-color .25s ease, color .25s ease;
  /* The breath. Two properties, three and a half seconds, no flashing: it
     is meant to be caught out of the corner of the eye, not to compete
     with the sphere it points at. */
  animation: fgCueBreathe 3.6s ease-in-out infinite;
}

/* When the cue sits beside the orb it is its own button; on compact surfaces
   (404 and the funnel) it lives inside the orb's button instead. Keep both
   versions visually identical, but make the standalone control unmistakably
   pressable and keyboard-visible. */
button.fg-cue {
  position: relative;
  appearance: none;
  cursor: pointer;
  text-align: inherit;
}
button.fg-cue:focus-visible {
  outline: 2px solid var(--blue-1, #8BB4FF);
  outline-offset: 3px;
}
/* The press itself, answered. Colour and not movement: the pill is breathing,
   and a transform here would be overridden by that animation half the time —
   a control that answers a press only on the up-beat is worse than one that
   does not answer at all. */
button.fg-cue:active,
/* The second selector is the same rule again, written to outrank the host's
   hover: a pointer that is pressing is also hovering, and without this the
   press would be answered with the hover colour it already had. */
.fg-cue-host:hover button.fg-cue:active {
  border-color: rgba(139, 180, 255, .5);
  background: rgba(139, 180, 255, .2);
  color: #fff;
  transition-duration: .06s;
}

/* A finger is not a cursor. The pill is set to be read, not to be aimed at:
   about 31px tall, which is a comfortable label and a poor target — a press
   that lands a few pixels high or low goes to the gap and nothing happens,
   which is exactly the complaint this control was built to answer. So on a
   touch screen the button keeps its drawn size and grows an invisible one:
   ~45px tall, and the reach stays inside the gap to the line underneath
   (9px there), so nothing below it loses a press to this. */
@media (pointer: coarse) {
  button.fg-cue::after {
    content: "";
    position: absolute;
    inset: -7px -6px;
  }
}

/* Under the pointer — or under the keyboard focus — the sphere and its line
   light up together, so it is clear they are one control and not a button
   with a caption. The host is whatever wraps the two (.hero-orb, .tester-orb,
   .orb-card …); marking it is what makes the pair work. */
/* :where() so this weighs the same as .fg-cue[data-state="…"] below and loses
   to it on order: the pointer that just pressed the pill is still on it (on a
   phone the hover sticks after the tap), and without this the line would sit
   in its pointer colour for the whole call while the sphere above it turned
   green. The invitation has no state colour of its own, so hover still lights
   it exactly as before. */
.fg-cue-host:where(:hover, :focus-within) .fg-cue {
  border-color: rgba(139, 180, 255, .42);
  background: rgba(139, 180, 255, .12);
  color: #fff;
}

.fg-cue-ic {
  flex: none;
  width: 15px;
  height: 15px;
  color: var(--blue-1, #8BB4FF);
}

/* The state light. Same green as the listening sphere, so the two agree. */
.fg-cue-dot {
  display: none;
  flex: none;
  width: 7px;
  height: 7px;
  margin: 0 4px;
  border-radius: 50%;
  background: currentColor;
  animation: fgCuePulse 1.6s ease-in-out infinite;
}

.fg-cue-live { display: none; }

/* ── Which half speaks ───────────────────────────────────────────────── */
.fg-cue-click { display: none; }
@media (hover: hover) and (pointer: fine) {
  .fg-cue-tap { display: none; }
  .fg-cue-click { display: inline; }
}

.fg-cue[data-state="again"] .fg-cue-idle,
.fg-cue[data-state="connecting"] .fg-cue-idle,
.fg-cue[data-state="listening"] .fg-cue-idle,
.fg-cue[data-state="thinking"] .fg-cue-idle,
.fg-cue[data-state="speaking"] .fg-cue-idle,
.fg-cue[data-state="trouble"] .fg-cue-idle { display: none; }

.fg-cue[data-state="again"] .fg-cue-live,
.fg-cue[data-state="connecting"] .fg-cue-live,
.fg-cue[data-state="listening"] .fg-cue-live,
.fg-cue[data-state="thinking"] .fg-cue-live,
.fg-cue[data-state="speaking"] .fg-cue-live,
.fg-cue[data-state="trouble"] .fg-cue-live { display: inline; }

/* ── In a call: the dot instead of the microphone, and no breathing ───── */
.fg-cue[data-state="connecting"],
.fg-cue[data-state="listening"],
.fg-cue[data-state="thinking"],
.fg-cue[data-state="speaking"],
.fg-cue[data-state="trouble"] { animation: none; }

.fg-cue[data-state="connecting"] .fg-cue-ic,
.fg-cue[data-state="listening"] .fg-cue-ic,
.fg-cue[data-state="thinking"] .fg-cue-ic,
.fg-cue[data-state="speaking"] .fg-cue-ic,
.fg-cue[data-state="trouble"] .fg-cue-ic { display: none; }

.fg-cue[data-state="connecting"] .fg-cue-dot,
.fg-cue[data-state="listening"] .fg-cue-dot,
.fg-cue[data-state="thinking"] .fg-cue-dot,
.fg-cue[data-state="speaking"] .fg-cue-dot,
.fg-cue[data-state="trouble"] .fg-cue-dot { display: block; }

.fg-cue[data-state="listening"] {
  border-color: rgba(113, 180, 54, .42);
  background: rgba(113, 180, 54, .1);
  color: #C6E8A4;
}
.fg-cue[data-state="speaking"] {
  border-color: rgba(139, 180, 255, .44);
  background: rgba(139, 180, 255, .12);
  color: #DCE8FF;
}

/* A call that never got off the ground says why, and a reason is a sentence:
   it may wrap, it is not centred on one line, and it is not a pill. */
.fg-cue[data-state="trouble"] {
  white-space: normal;
  text-align: left;
  align-items: flex-start;
  max-width: 34ch;
  border-radius: 14px;
  border-color: rgba(255, 186, 120, .32);
  background: rgba(255, 186, 120, .08);
  color: rgba(255, 226, 196, .92);
  line-height: 1.45;
}
.fg-cue[data-state="trouble"] .fg-cue-dot { margin-top: 4px; animation: none; }

@keyframes fgCueBreathe {
  0%, 100% { opacity: .8; transform: translateY(0); }
  50%      { opacity: 1;  transform: translateY(-2px); }
}
@keyframes fgCuePulse {
  0%, 100% { opacity: .45; }
  50%      { opacity: 1; }
}

/* Somebody who asked the system for less movement gets a line that does not
   move at all — it still says the same words. */
@media (prefers-reduced-motion: reduce) {
  .fg-cue, .fg-cue-dot { animation: none; }
  .fg-cue { opacity: 1; }
}

/* 320px is the floor the whole site is built to. The pill is the widest
   fixed thing under a sphere on a phone, so it gets to be smaller there
   rather than to push the page sideways. */
@media (max-width: 400px) {
  .fg-cue { font-size: 12.5px; padding: 6px 12px 6px 10px; gap: 7px; }
  .fg-cue-ic { width: 14px; height: 14px; }
}
