/* The animated Quinine Q (q-anim.js). Size with width or font-size (the mark is 1em wide and
   keeps the official 456:412 proportion); colour with `color` (the settled mark is currentColor).
   Trace and pulse colours come from tokens.css (--q-trace, --q-pulse, --q-ambient) and fall back
   to the mark's own colour and signal citron where tokens.css is not loaded (the dashboard).
   Motion: stroke-dashoffset, opacity and transform only. Reduced motion: settled mark, no motion. */

.qmark {
  --qmark-ink: currentColor;
  --qmark-trace: var(--q-trace, currentColor);
  --qmark-pulse: var(--q-pulse, #CEDC76);
  --qmark-ambient: var(--q-ambient, #B49A6B);
  display: inline-block;
  flex: 0 0 auto;
  width: 1em;
  height: auto;
  aspect-ratio: 456 / 412;
  vertical-align: -0.12em;
  line-height: 0;
  position: relative;
}
.qmark__svg { display: block; width: 100%; height: 100%; overflow: visible; }
.qmark__fill { fill: var(--qmark-ink); stroke: none; }
.qmark__line, .qmark__pulse {
  fill: none; stroke-linecap: round; stroke-linejoin: round;
}
.qmark__line { stroke: var(--qmark-trace); stroke-dasharray: 1; stroke-dashoffset: 1; }
.qmark__pulse { stroke: var(--qmark-pulse); stroke-dasharray: 0.1 0.9; stroke-dashoffset: 0; opacity: 0; }
.qmark__lines { opacity: 0; }

/* Before q-anim.js mounts (or without JS): the solid official Q from q-mark.svg as a mask. */
.qmark:not([data-q-mounted]) {
  background: var(--qmark-ink);
  -webkit-mask: url("/q-mark.svg") center / contain no-repeat;
  mask: url("/q-mark.svg") center / contain no-repeat;
}
.qmark[data-q="watermark"]:not([data-q-mounted]) { opacity: 0.08; }
@media (prefers-reduced-motion: no-preference) {
  /* Marks that open with an intro stay blank for the few ms before the module runs, so the solid
     fallback does not flash first. If the module never runs they appear anyway after 1.2 s. */
  .js .qmark[data-q="nav"]:not([data-q-mounted]),
  .js .qmark[data-q="once"]:not([data-q-mounted]) { opacity: 0; animation: qmark-fallback 0.2s linear 1.2s forwards; }
}

/* ------------------------------------------------------------------ intro (nav, once) */
.qmark[data-q-state="armed"] .qmark__fill { fill-opacity: 0; }
.qmark[data-q-state="intro"] .qmark__fill { fill-opacity: 0; animation: qmark-solid 0.42s var(--ease-out, ease-out) 1.18s forwards; }
.qmark[data-q-state="intro"] .qmark__lines { opacity: 1; animation: qmark-fade-out 0.32s ease-out 1.5s forwards; }
.qmark[data-q-state="intro"] .qmark__outer { animation: qmark-draw 0.56s var(--ease-trace, ease-in-out) 0.04s forwards; }
.qmark[data-q-state="intro"] .qmark__inner { animation: qmark-draw 0.38s var(--ease-trace, ease-in-out) 0.5s forwards; }
.qmark[data-q-state="intro"] .qmark__tail { animation: qmark-draw 0.24s ease-out 0.82s forwards; }
.qmark[data-q-state="intro"] .qmark__pulse { animation: qmark-run 0.62s ease-in-out 1.02s both; }

/* Hover / focus of the surrounding link or button (nav): one short light pulse. */
.qmark--trace .qmark__pulse { animation: qmark-hover 0.7s ease-in-out both; }

/* ------------------------------------------------------------------ loader */
.qmark[data-q="loader"] .qmark__fill { fill-opacity: 0.12; }
.qmark[data-q="loader"] .qmark__lines { opacity: 1; }
.qmark[data-q="loader"] .qmark__outer { animation: qmark-loop-outer var(--dur-q-loop, 2.4s) var(--ease-trace, ease-in-out) infinite; }
.qmark[data-q="loader"] .qmark__inner { animation: qmark-loop-inner var(--dur-q-loop, 2.4s) var(--ease-trace, ease-in-out) infinite; }
.qmark[data-q="loader"] .qmark__tail { animation: qmark-loop-tail var(--dur-q-loop, 2.4s) ease-out infinite; }
.qmark[data-q="loader"] .qmark__pulse { animation: qmark-loop-pulse var(--dur-q-loop, 2.4s) ease-in-out infinite; }

/* ------------------------------------------------------------------ footer */
/* A very slow, low-contrast brass pulse every 9 s. q-anim.js adds .qmark--ambient for one 5.4 s
   run per period (the old 9 s loop's visible part, same curve), so nothing animates in between. */
.qmark[data-q="footer"].qmark--ambient .qmark__pulse {
  stroke: var(--qmark-ambient); stroke-dasharray: 0.16 0.84;
  animation: qmark-footer-ambient 5.4s linear both;
}

/* ------------------------------------------------------------------ launcher (chat button) */
/* Settled solid mark. A rare faint ambient trace runs once (first after 20 s, then every 30 s;
   timer-driven, held by data-q-hold="true", offscreen and in a hidden tab); hover/focus of its
   button gives the short light pulse (.qmark--trace) plus the outline illumination below;
   pulseQ() is the one-off attention cue. */
.qmark[data-q="launcher"].qmark--ambient .qmark__pulse {
  stroke: var(--qmark-ambient); stroke-dasharray: 0.18 0.82;
  animation: qmark-launcher-ambient 1.8s ease-in-out both;
}

/* Entrance (introQ, 2.4 s = LAUNCHER_INTRO_MS): the solid Q stays visible and eases back a
   little so a thin outline can trace the ring (outer, then inner), the tail completes, one
   restrained light pulse travels through the mark with a very slight lift, and it settles. The
   fill's animation is the whole sequence; its animationend is the end q-anim.js waits for. */
.qmark[data-q="launcher"][data-q-state="entrance"] .qmark__fill { animation: qmark-entrance-fill 2.4s var(--ease-in-out, ease-in-out) both; }
.qmark[data-q="launcher"][data-q-state="entrance"] .qmark__lines { animation: qmark-entrance-lines 2.4s linear both; }
.qmark[data-q="launcher"][data-q-state="entrance"] .qmark__outer { animation: qmark-draw 0.72s var(--ease-trace, ease-in-out) 0.14s both; }
.qmark[data-q="launcher"][data-q-state="entrance"] .qmark__inner { animation: qmark-draw 0.6s var(--ease-trace, ease-in-out) 0.42s both; }
.qmark[data-q="launcher"][data-q-state="entrance"] .qmark__tail { animation: qmark-draw 0.3s var(--ease-out, ease-out) 0.96s both; }
.qmark[data-q="launcher"][data-q-state="entrance"] .qmark__pulse {
  stroke: var(--qmark-pulse); stroke-dasharray: 0.14 0.86;
  animation: qmark-entrance-pulse 0.86s ease-in-out 1.28s both;
}
.qmark[data-q="launcher"][data-q-state="entrance"] .qmark__svg { animation: qmark-entrance-lift 0.86s var(--ease-out, ease-out) 1.28s both; }

/* Hover / keyboard focus of the launcher button (.qchat-launcher): the outline lights up
   briefly in the pulse colour, then rests as a faint ring while the pointer or focus stays.
   Keyed on the button so it works whatever the button's other children are. Only on settled
   marks, so it never interrupts the entrance. Reduced motion: a static highlight (below). */
.qchat-launcher:focus-visible .qmark[data-q="launcher"] .qmark__line,
.qchat-launcher:hover .qmark[data-q="launcher"] .qmark__line { stroke: var(--qmark-pulse); }
@media (hover: hover) and (prefers-reduced-motion: no-preference) {
  .qchat-launcher:hover .qmark[data-q="launcher"][data-q-state="settled"] .qmark__line { stroke-dashoffset: 0; }
  .qchat-launcher:hover .qmark[data-q="launcher"][data-q-state="settled"] .qmark__lines { animation: qmark-illuminate 1s var(--ease-out, ease-out) both; }
  .qchat-launcher:hover .qmark[data-q="launcher"][data-q-state="settled"] .qmark__fill { animation: qmark-illuminate-fill 1s var(--ease-out, ease-out) both; }
}
@media (prefers-reduced-motion: no-preference) {
  .qchat-launcher:focus-visible .qmark[data-q="launcher"][data-q-state="settled"] .qmark__line { stroke-dashoffset: 0; }
  .qchat-launcher:focus-visible .qmark[data-q="launcher"][data-q-state="settled"] .qmark__lines { animation: qmark-illuminate 1s var(--ease-out, ease-out) both; }
  .qchat-launcher:focus-visible .qmark[data-q="launcher"][data-q-state="settled"] .qmark__fill { animation: qmark-illuminate-fill 1s var(--ease-out, ease-out) both; }
}

/* ------------------------------------------------------------------ thinking (typing indicator) */
/* Built for 16-20 px inline: faint silhouette, the ring traces, then the tail sweeps; 1.2 s loop. */
.qmark[data-q="thinking"] .qmark__fill { fill-opacity: 0.18; }
.qmark[data-q="thinking"] .qmark__lines { opacity: 1; }
.qmark[data-q="thinking"] .qmark__pulse { display: none; }
.qmark[data-q="thinking"] .qmark__outer { animation: qmark-think-outer 1.2s var(--ease-trace, ease-in-out) infinite; }
.qmark[data-q="thinking"] .qmark__inner { animation: qmark-think-inner 1.2s var(--ease-trace, ease-in-out) infinite; }
.qmark[data-q="thinking"] .qmark__tail { animation: qmark-think-tail 1.2s ease-out infinite; }

/* header (chat panel): the nav intro, armed until the mark is visible (see "intro" above). */

/* ------------------------------------------------------------------ watermark */
.qmark[data-q="watermark"] { opacity: 1; pointer-events: none; }
.qmark[data-q="watermark"] .qmark__fill { fill: none; stroke: var(--qmark-ink); stroke-opacity: 0.14; }
.qmark[data-q="watermark"] .qmark__pulse {
  stroke: var(--qmark-ambient); stroke-dasharray: 0.22 0.78;
  animation: qmark-watermark 18s linear infinite;
}

/* ------------------------------------------------------------------ static / settled */
.qmark[data-q="static"] .qmark__lines, .qmark[data-q="static"] .qmark__pulse { display: none; }

/* Confirmation pulse (pulseQ), any mode: a citron pulse runs the whole outline once over the
   settled mark, which lifts very slightly. Two identical keyframes let a repeat restart cleanly. */
.qmark.qmark--pulse-a[data-q] .qmark__pulse, .qmark.qmark--pulse-b[data-q] .qmark__pulse {
  stroke: var(--qmark-pulse); stroke-dasharray: 0.12 0.88;
}
.qmark.qmark--pulse-a[data-q] .qmark__pulse { animation: qmark-pulse-a 0.9s ease-in-out both; }
.qmark.qmark--pulse-b[data-q] .qmark__pulse { animation: qmark-pulse-b 0.9s ease-in-out both; }
.qmark.qmark--pulse-a[data-q] .qmark__svg { animation: qmark-lift 0.9s ease-out both; }
.qmark.qmark--pulse-b[data-q] .qmark__svg { animation: qmark-lift-b 0.9s ease-out both; }

/* Offscreen loops and loops in a hidden tab hold still (q-anim.js toggles data-q-offscreen via
   IntersectionObserver and data-q-paused on visibilitychange). !important: the per-mode
   `animation` shorthands would otherwise reset the play state. */
.qmark[data-q-offscreen] .qmark__svg, .qmark[data-q-offscreen] .qmark__svg *,
.qmark[data-q-paused] .qmark__svg, .qmark[data-q-paused] .qmark__svg * { animation-play-state: paused !important; }

/* ------------------------------------------------------------------ brand slots */
.site-brand .qmark { width: 34px; color: inherit; }
.site-brand--footer .qmark { width: 30px; }
.sb-brand .qmark.sb-mark { width: 32px; }
.signin-mark .qmark { width: 40px; }
.footer-brand .qmark { width: 18px; }

@keyframes qmark-fallback { to { opacity: 1; } }
@keyframes qmark-draw { to { stroke-dashoffset: 0; } }
@keyframes qmark-solid { to { fill-opacity: 1; } }
@keyframes qmark-fade-out { to { opacity: 0; } }
@keyframes qmark-run { 0% { opacity: 0; stroke-dashoffset: 0; } 18%, 78% { opacity: 0.95; } 100% { opacity: 0; stroke-dashoffset: -1; } }
@keyframes qmark-hover { 0% { opacity: 0; stroke-dashoffset: 0; } 20%, 70% { opacity: 0.9; } 100% { opacity: 0; stroke-dashoffset: -0.6; } }
@keyframes qmark-pulse-a { 0% { opacity: 0; stroke-dashoffset: 0; } 15%, 80% { opacity: 1; } 100% { opacity: 0; stroke-dashoffset: -1; } }
@keyframes qmark-pulse-b { 0% { opacity: 0; stroke-dashoffset: 0; } 15%, 80% { opacity: 1; } 100% { opacity: 0; stroke-dashoffset: -1; } }
@keyframes qmark-lift { 0%, 100% { transform: none; } 35% { transform: scale(1.04); } }
@keyframes qmark-lift-b { 0%, 100% { transform: none; } 35% { transform: scale(1.04); } }
@keyframes qmark-loop-outer { 0% { stroke-dashoffset: 1; opacity: 1; } 28% { stroke-dashoffset: 0; } 80% { stroke-dashoffset: 0; opacity: 1; } 92%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes qmark-loop-inner { 0%, 20% { stroke-dashoffset: 1; opacity: 1; } 44% { stroke-dashoffset: 0; } 80% { stroke-dashoffset: 0; opacity: 1; } 92%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes qmark-loop-tail { 0%, 40% { stroke-dashoffset: 1; opacity: 1; } 54% { stroke-dashoffset: 0; } 80% { stroke-dashoffset: 0; opacity: 1; } 92%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes qmark-loop-pulse { 0%, 54% { opacity: 0; stroke-dashoffset: 0; } 62%, 78% { opacity: 0.95; } 88%, 100% { opacity: 0; stroke-dashoffset: -1; } }
@keyframes qmark-footer-ambient { 0% { opacity: 0; stroke-dashoffset: 0; } 33.333%, 75% { opacity: 0.32; } 100% { opacity: 0; stroke-dashoffset: -1; } }
@keyframes qmark-entrance-fill { 0% { fill-opacity: 1; } 12%, 78% { fill-opacity: 0.8; } 100% { fill-opacity: 1; } }
@keyframes qmark-entrance-lines { 0% { opacity: 0; } 6%, 52% { opacity: 1; } 60%, 76% { opacity: 0.5; } 100% { opacity: 0; } }
@keyframes qmark-entrance-pulse { 0% { opacity: 0; stroke-dashoffset: 0; } 20%, 75% { opacity: 0.95; } 100% { opacity: 0; stroke-dashoffset: -1; } }
@keyframes qmark-entrance-lift { 0%, 100% { transform: none; } 40% { transform: scale(1.03); } }
@keyframes qmark-illuminate { 0% { opacity: 0; } 30% { opacity: 0.95; } 100% { opacity: 0.4; } }
@keyframes qmark-illuminate-fill { 0%, 100% { fill-opacity: 1; } 30% { fill-opacity: 0.84; } }
@keyframes qmark-launcher-ambient { 0% { opacity: 0; stroke-dashoffset: 0; } 25%, 70% { opacity: 0.55; } 100% { opacity: 0; stroke-dashoffset: -1; } }
@keyframes qmark-think-outer { 0% { stroke-dashoffset: 1; opacity: 1; } 45% { stroke-dashoffset: 0; } 72% { stroke-dashoffset: 0; opacity: 1; } 88%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes qmark-think-inner { 0%, 8% { stroke-dashoffset: 1; opacity: 1; } 48% { stroke-dashoffset: 0; } 72% { stroke-dashoffset: 0; opacity: 1; } 88%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes qmark-think-tail { 0%, 42% { stroke-dashoffset: 1; opacity: 1; } 62% { stroke-dashoffset: 0; } 72% { stroke-dashoffset: 0; opacity: 1; } 88%, 100% { stroke-dashoffset: 0; opacity: 0; } }
@keyframes qmark-watermark { 0% { opacity: 0; stroke-dashoffset: 0; } 15%, 70% { opacity: 0.3; } 85%, 100% { opacity: 0; stroke-dashoffset: -1; } }

@media (prefers-reduced-motion: reduce) {
  .qmark, .qmark *, .qmark__svg { animation: none !important; transition: none !important; }
  .qmark .qmark__lines, .qmark .qmark__pulse { display: none; }
  .qmark .qmark__fill { fill-opacity: 1 !important; }
  .qmark[data-q="watermark"] .qmark__fill { fill-opacity: 0 !important; }
  .qmark:not([data-q-mounted]) { opacity: 1; }
  .qmark[data-q="watermark"]:not([data-q-mounted]) { opacity: 0.08; }
  /* Launcher hover / keyboard focus: a static highlighted outline instead of the illumination. */
  .qchat-launcher:hover .qmark[data-q="launcher"] .qmark__lines,
  .qchat-launcher:focus-visible .qmark[data-q="launcher"] .qmark__lines { display: inline; opacity: 0.6; }
  .qchat-launcher:hover .qmark[data-q="launcher"] .qmark__line,
  .qchat-launcher:focus-visible .qmark[data-q="launcher"] .qmark__line { stroke-dashoffset: 0; }
}
@media (forced-colors: active) {
  .qmark__fill { fill: CanvasText; }
  .qmark[data-q="watermark"] .qmark__fill { fill: none; stroke: CanvasText; }
  .qmark__line { stroke: CanvasText; }
  .qmark__pulse { display: none; }
  .qmark:not([data-q-mounted]) { background: CanvasText; }
  .qchat-launcher:focus-visible .qmark[data-q="launcher"] .qmark__line,
  .qchat-launcher:hover .qmark[data-q="launcher"] .qmark__line { stroke: Highlight; }
}
