/* Chata-gata — portfolio assistant
   A searchable index that borrows the site's publication language: rules,
   source IDs and a single vermillion signal instead of generic chat chrome. */

.ts-ask-launcher,
.ts-ask-panel,
.ts-ask-panel * { box-sizing: border-box; }

.ts-ask-launcher {
  position: fixed;
  right: var(--pad-x);
  bottom: calc(var(--bar-h) + var(--s-4));
  z-index: 400;
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 44px;
  padding: 0 var(--s-4);
  border: 1px solid var(--ink);
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  font: 500 var(--t-small)/1 var(--font-sans);
  cursor: pointer;
  box-shadow: 0 10px 32px rgba(22, 21, 15, .16);
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.ts-ask-launcher::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 18%, transparent);
}

/* At rest it gets out of the way.
   A solid black pill with a lit dot, parked over the corner of a case study,
   competes with the work for the whole length of the read -- and a portfolio
   that argues for editorial restraint should not ship a permanent floating
   badge. Resting translucent keeps it findable without it being the loudest
   thing on a page of someone else's reading, and any intent to use it --
   hover, focus, keyboard -- brings it straight back to full strength. */
.ts-ask-launcher {
  opacity: .46;
  box-shadow: none;
  transition: transform var(--dur-fast) var(--ease),
              opacity var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.ts-ask-launcher:hover,
.ts-ask-launcher:focus-visible {
  opacity: 1;
  box-shadow: 0 10px 32px rgba(22, 21, 15, .16);
}
.ts-ask-launcher:hover { transform: translateY(-2px); }
.ts-ask-launcher[aria-expanded='true'] { opacity: 0; pointer-events: none; transform: translateY(6px); }

.ts-ask-scrim {
  position: fixed;
  inset: 0;
  z-index: 449;
  background: rgba(20, 20, 20, .18);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}

.ts-ask-scrim.is-open {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}

.ts-ask-panel {
  position: fixed;
  top: var(--bar-h);
  right: 0;
  bottom: var(--bar-h);
  z-index: 450;
  width: min(460px, calc(100vw - 32px));
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  border-left: 1px solid var(--rule);
  background-color: var(--paper);
  color: var(--ink);
  transform: translateX(102%);
  visibility: hidden;
  box-shadow: -24px 0 72px rgba(22, 21, 15, .12);
  transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur);
}

.ts-ask-panel.is-open {
  transform: translateX(0);
  visibility: visible;
  transition-delay: 0s;
}

.ts-ask-head {
  min-height: 64px;
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: center;
  gap: var(--s-2);
  padding: 0 var(--s-5);
  border-bottom: 1px solid var(--rule);
  background: var(--paper);
}

.ts-ask-wordmark {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  min-width: 0;
}

.ts-ask-name {
  font: 500 var(--t-small)/1 var(--font-mono);
  letter-spacing: .08em;
}

.ts-ask-icon {
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-70);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.ts-ask-icon:hover { background: var(--paper-2); color: var(--ink); }
.ts-ask-icon svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.6; }

.ts-ask-scroll {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--rule) transparent;
}

.ts-ask-welcome {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--s-9);
  padding: var(--s-5);
}

.ts-ask-note {
  max-width: 38ch;
  padding: var(--s-4);
  border: 1px solid var(--rule);
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  color: var(--ink-70);
  font: 400 var(--t-small)/1.45 var(--font-sans);
}

.ts-ask-note strong { color: var(--ink); font-weight: 500; }

/* Two modes, one panel. The display heading that used to sit here belonged
   to a panel that only did one thing; with navigation above and questions
   below, two 4rem headings would fight each other and push the actual
   controls off a phone screen. Mono section labels are the site's own way
   of naming a group without shouting. */
.ts-ask-block { display: grid; gap: var(--s-4); }

.ts-ask-block-title {
  margin: 0;
  font: 500 var(--t-label)/1 var(--font-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-40);
}

/* Shortcuts read as objects you pick up; questions read as sentences you
   say. Keeping them visually distinct is what stops the panel feeling like
   two widgets stacked, because the difference is now meaning rather than
   two separate launchers. */
.ts-ask-chips { display: flex; flex-wrap: wrap; gap: var(--s-2); }

.ts-ask-chip {
  padding: .5em .85em;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-70);
  font: 400 var(--t-small)/1 var(--font-sans);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

.ts-ask-chip:hover { border-color: var(--accent); color: var(--accent-text); }
.ts-ask-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.ts-ask-prompts { display: grid; border-top: 1px solid var(--rule); }

.ts-ask-prompt {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--s-3);
  align-items: start;
  width: 100%;
  padding: var(--s-4) 0;
  border: 0;
  border-bottom: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-70);
  text-align: left;
  font: 400 var(--t-small)/1.4 var(--font-sans);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease), padding var(--dur-fast) var(--ease);
}

.ts-ask-prompt::before { content: '↳'; color: var(--accent-text); font-family: var(--font-mono); }
.ts-ask-prompt::after { content: '→'; opacity: 0; transition: opacity var(--dur-fast) var(--ease); }
.ts-ask-prompt:hover { color: var(--ink); padding-left: var(--s-2); }
.ts-ask-prompt:hover::after { opacity: 1; }

.ts-ask-thread { display: grid; gap: var(--s-7); padding: var(--s-5); }
.ts-ask-turn { display: grid; gap: var(--s-3); }

.ts-ask-question {
  max-width: 88%;
  justify-self: end;
  padding: var(--s-3) var(--s-4);
  border-radius: 18px 18px 3px 18px;
  background: var(--ink);
  color: var(--paper);
  font: 400 var(--t-small)/1.45 var(--font-sans);
}

.ts-ask-answer { display: grid; gap: var(--s-4); font: 400 var(--t-body)/1.55 var(--font-sans); }
.ts-ask-answer p { margin: 0; max-width: 42ch; }

.ts-ask-answer.is-loading p {
  color: var(--ink-40);
  animation: ts-ask-pulse 1.4s ease-in-out infinite;
}

@keyframes ts-ask-pulse { 50% { opacity: .42; } }

.ts-ask-sources { display: grid; border-top: 1px solid var(--rule); }

/* Routes are an answer, sources are a citation, and they use the same row
   because they are the same gesture — go to this page. The accent rule on
   the left is the only separation they need: it marks the rows the
   navigator chose, which are also the rows that still work when the model
   does not. */
.ts-ask-routes { border-top-color: var(--accent); }
.ts-ask-route { border-left: 2px solid var(--accent); padding-left: var(--s-3); }
.ts-ask-route:hover { padding-left: calc(var(--s-3) + var(--s-2)); }

.ts-ask-source {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--s-3);
  min-height: 58px;
  padding: var(--s-2) 0;
  border-bottom: 1px solid var(--rule);
  color: var(--ink);
  text-decoration: none;
  transition: padding var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}

.ts-ask-source:hover { padding-left: var(--s-2); background: color-mix(in srgb, var(--paper-2) 58%, transparent); }
.ts-ask-source-title { font: 500 var(--t-small)/1.25 var(--font-sans); }
.ts-ask-source-meta { display: block; margin-top: 3px; color: var(--ink-40); font: 400 var(--t-micro)/1.2 var(--font-mono); text-transform: uppercase; letter-spacing: .06em; }
.ts-ask-source-arrow { color: var(--ink-40); }

.ts-ask-empty {
  padding: var(--s-5);
  border: 1px solid var(--rule);
  color: var(--ink-70);
  font: 400 var(--t-small)/1.5 var(--font-sans);
}

.ts-ask-compose {
  padding: var(--s-4) var(--s-5) var(--s-5);
  border-top: 1px solid var(--rule);
  background: var(--paper);
}

.ts-ask-form {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: var(--s-2);
  min-height: 52px;
  padding: var(--s-2) var(--s-2) var(--s-2) var(--s-4);
  border: 1px solid var(--rule);
  background: var(--paper);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}

.ts-ask-form:focus-within { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 18%, transparent); }

.ts-ask-input {
  width: 100%;
  max-height: 110px;
  resize: none;
  overflow-y: auto;
  padding: 8px 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--ink);
  font: 400 16px/1.4 var(--font-sans);
}

.ts-ask-input::placeholder { color: var(--ink-40); }

.ts-ask-send {
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}

.ts-ask-send:hover { transform: translateY(-1px); }
.ts-ask-send:disabled { opacity: .32; cursor: default; transform: none; }
.ts-ask-send svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.8; }

.ts-ask-footnote {
  margin: var(--s-3) 0 0;
  color: var(--ink-40);
  font: 400 var(--t-micro)/1.4 var(--font-mono);
  letter-spacing: .02em;
}

.ts-ask-icon:focus-visible,
.ts-ask-prompt:focus-visible,
.ts-ask-source:focus-visible,
.ts-ask-launcher:focus-visible,
.ts-ask-send:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

body.ts-ask-locked { overflow: hidden; }

@media (max-width: 700px) {
  .ts-ask-launcher {
    right: var(--margin);
    bottom: calc(var(--bar-h) + var(--s-3));
    min-height: 42px;
  }

  /* 42px is a deliberate visual size — a floating control on a phone should
     not be a slab — but it is under the 44px a thumb needs. The retired
     guide solved this and the fix comes with it: a transparent ::after
     overhangs the box by 2px top and bottom, so what you can hit is 46px
     while what you can see stays 42. The overhang costs 2 of the 12px the
     launcher already clears the status bar by, so it never reaches it. */
  .ts-ask-launcher::after {
    content: '';
    position: absolute;
    inset: -2px 0;
  }

  /* left/right 0, not 100vw: 100vw counts a desktop scrollbar, which pushed the
     panel 17px off the left edge in a narrow Firefox, Chrome or Edge window. */
  .ts-ask-panel {
    top: 0;
    bottom: 0;
    left: 0;
    width: auto;
    border-left: 0;
    grid-template-rows: auto minmax(0, 1fr) auto;
  }

  .ts-ask-head {
    min-height: calc(var(--bar-h) + env(safe-area-inset-top));
    padding: env(safe-area-inset-top) var(--s-4) 0;
  }

  .ts-ask-welcome,
  .ts-ask-thread { padding: var(--s-4); }

  .ts-ask-compose { padding: var(--s-3) var(--s-4) calc(var(--s-4) + env(safe-area-inset-bottom)); }
  .ts-ask-scrim { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ts-ask-launcher,
  .ts-ask-scrim,
  .ts-ask-panel,
  .ts-ask-prompt,
  .ts-ask-send,
  /* Both of these animate a padding shift on hover, which is exactly the
     kind of movement the setting asks us to drop. The source rows were
     already missing from this list before the merge; the chips arrived
     with it. */
  .ts-ask-chip,
  .ts-ask-source { transition: none; }
  .ts-ask-answer.is-loading p { animation: none; }
  /* Nothing should slide sideways under the pointer either. */
  .ts-ask-prompt:hover,
  .ts-ask-source:hover { padding-left: 0; }
  .ts-ask-route:hover { padding-left: var(--s-3); }
  .ts-ask-launcher:hover { transform: none; }
}


/* ---- Chata-gata: my face and a name -----------------------------------
   Docked in the top bar it reads as one more nav item, set like the nav,
   not a button shouting over it. Floating on a phone the face IS the
   button. The site's three colours: the accent for the disc, white for
   skin, black for ink. The ink is a literal, not var(--ink), because --ink
   turns white at night and the drawing would lose its outlines. */
.ts-ask-launcher::before { content: none; }
.ts-ask-face {
  display: block; flex: none;
  width: 22px; height: 22px;
  border-radius: 50%;
  overflow: hidden;              /* the head tilts inside the disc, not past it */
  background: var(--accent);
}
.ts-ask-face-lean,
.ts-ask-face svg {
  display: block;
  width: 100%; height: 100%;
  transform-origin: 50% 80%;     /* about the jaw, so it reads as a head tilt
                                    rather than a picture rotating on a pin */
}
.ts-ask-face svg { fill: #FFFFFF; }

/* The button's mark (2026-11-09): the Ask AI mark, small, in the site's orange. */
.ts-ask-mark { display: block; flex: none; width: 14px; height: 14px; color: var(--accent); }
.ts-ask-mark svg { display: block; width: 100%; height: 100%; fill: currentColor; }

/* At rest: every so often a curious tilt, a beat held like someone
   listening, then back past centre and settled. Most of the loop is still,
   so it is something you catch out of the corner of an eye rather than a
   thing that fidgets beside the nav for the whole read. */
@keyframes ts-ask-face-idle {
  0%, 50%   { transform: rotate(0deg); }
  56%       { transform: rotate(-12deg); }
  60%, 72%  { transform: rotate(-9deg); }
  79%       { transform: rotate(4deg); }
  84%       { transform: rotate(-1.5deg); }
  88%, 100% { transform: rotate(0deg); }
}
.ts-ask-launcher .ts-ask-face svg {
  animation: ts-ask-face-idle 8s cubic-bezier(.45, 0, .3, 1) infinite;
}

/* On hover it leans towards its name. The lean is a transition on the
   wrapper, the idle tilt pauses wherever it is, and the two add up, so
   arriving or leaving mid-tilt never jumps. */
.ts-ask-face-lean { transition: transform .5s cubic-bezier(.3, .7, .3, 1.4); }
.ts-ask-launcher:is(:hover, :focus-visible, :active) .ts-ask-face-lean { transform: rotate(14deg); }
.ts-ask-launcher:is(:hover, :focus-visible, :active) .ts-ask-face svg { animation-play-state: paused; }

/* Opening the panel: a quick hello from the face in its head. */
@keyframes ts-ask-face-hello {
  0%   { transform: rotate(0deg); }
  28%  { transform: rotate(-14deg); }
  52%  { transform: rotate(9deg); }
  74%  { transform: rotate(-4deg); }
  100% { transform: rotate(0deg); }
}
.ts-ask-panel.is-open .ts-ask-wordmark .ts-ask-face svg {
  animation: ts-ask-face-hello .9s .25s cubic-bezier(.45, 0, .3, 1) both;
}

@media (prefers-reduced-motion: reduce) {
  .ts-ask-face-lean,
  .ts-ask-face svg { animation: none !important; transition: none; transform: none !important; }
}

/* floating (phones): the face is the button */
.ts-ask-launcher:not(.is-docked) {
  opacity: 1;
  width: 48px; height: 48px; min-height: 0;
  padding: 0;
  justify-content: center;
  border: 0;
  background: var(--accent);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .24);
}
.ts-ask-launcher:not(.is-docked) .ts-ask-face { width: 48px; height: 48px; }
.ts-ask-launcher:not(.is-docked) .ts-ask-mark { width: 22px; height: 22px; color: #fff; }
.ts-ask-launcher:not(.is-docked) .ts-ask-launcher-label {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* docked (tablet and up): the last item in the nav, set like the nav */
.ts-ask-launcher.is-docked {
  position: relative;
  right: auto; bottom: auto;
  z-index: auto;
  flex: none;
  opacity: 1;
  min-height: 32px;
  gap: 8px;
  padding: 0 0 0 var(--s-4);
  border: 0;
  border-left: 1px solid var(--rule);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  box-shadow: none;
  font: inherit;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.ts-ask-launcher.is-docked:hover,
.ts-ask-launcher.is-docked:focus-visible {
  background: transparent;
  color: var(--accent-text);
  box-shadow: none;
  transform: none;
}
.ts-ask-launcher.is-docked[aria-expanded='true'] {
  opacity: 1; pointer-events: auto; transform: none;
  color: var(--accent-text);
}

/* The panel opens with the same face and name in the head, and a
   greeting in the first person before the page list and prompts. */
.ts-ask-wordmark { align-items: center; }
.ts-ask-wordmark .ts-ask-face { width: 28px; height: 28px; }
.ts-ask-hi { display: grid; gap: var(--s-3); }
.ts-ask-hello {
  margin: 0;
  font: 400 clamp(30px, 3vw, 40px)/1.02 var(--font-display);
  letter-spacing: -.01em;
  color: var(--ink);
}
.ts-ask-hi .ts-ask-note { margin: 0; }

/* Slimmer opening (user, 2026-10-27): greeting, one quiet line, three
   product questions and two chips, stacked at the top with even gaps
   instead of spread down the panel. */
.ts-ask-welcome { justify-content: flex-start; gap: 28px; min-height: 0; }
.ts-ask-hi { gap: 8px; }
.ts-ask-note { padding: 0; border: 0; background: none; max-width: 40ch; color: var(--ink-40); }
.ts-ask-block--quiet { margin-top: -8px; }
.ts-ask-chip { border-radius: 999px; padding: .55em 1em; }
