/* `dyno-tip`: a CSS-only tooltip, authored against DaisyUI's markup contract.

   Plain CSS over custom properties, in the manner of `dev_chrome.css`, so the
   one file serves both frameworks: the Bootstrap dashboard and portal link it
   today, and a Tailwind page can link it unchanged. It replaces
   `javascript/bootstrap_init.html`, whose `DOMContentLoaded` /
   `htmx:beforeSwap` / `htmx:afterSwap` lifecycle had to re-instantiate every
   `bootstrap.Tooltip` after each swap. CSS needs none of that -- a partial
   that arrives over htmx is styled on arrival -- which is what lets the rest
   of the Bootstrap migration be markup-only.

   Why not DaisyUI's own `.tooltip` yet: Bootstrap's bundle is unlayered and
   sets `.tooltip { opacity: 0 }`, so it beats DaisyUI's layered rule of the
   same name regardless of source order and the bubble never appears. Hence a
   prefixed class until Bootstrap is gone.

   The names are deliberately DaisyUI's, so that switch is a substitution of
   `dyno-tip` -> `tooltip` and nothing else:

   - the text comes from a `data-tip` attribute, and an empty one shows
     nothing;
   - placement modifiers are `dyno-tip-{top,bottom,left,right}` against
     `tooltip-{top,bottom,left,right}`, with top the default;
   - `dyno-tip-open` forces the bubble open, as `tooltip-open` does;
   - the bubble colour is `--tt-bg`, spelled as DaisyUI spells it, so a theme
     overriding it keeps working across the rename.

   The one place it deviates on purpose: DaisyUI's `.tooltip` also sets
   `display: inline-block`, and this does not. Eight of the triggers are
   block-level (`<div>`, one `<h6>`) and still live on Bootstrap pages, where
   Bootstrap's tooltip never touched the trigger's `display`; copying that
   declaration would reflow them now. The bill comes due at the rename, not
   here.

   Geometry reproduces Bootstrap 5.3.8's tooltip -- 0.8rem x 0.4rem arrow,
   12.5rem max-width, 0.875rem text, `z-index: 1080` -- so converting a
   template is not also a visual change. The 200ms-in / 100ms-out delay is
   *not* Bootstrap's default, which is 0; it is the one
   `javascript/bootstrap_init.html` passed to every trigger it constructed, so
   it is what this repo's tooltips have always felt like. Don't go looking for
   it in Bootstrap's docs. */

.dyno-tip {
  --tt-bg: rgb(0 0 0 / 90%);

  /* `position` only. See the `display` note above. */
  position: relative;
}

.dyno-tip[data-tip]:not([data-tip=""])::before,
.dyno-tip[data-tip]:not([data-tip=""])::after {
  position: absolute;
  z-index: 1080;
  opacity: 0;
  transition: opacity 150ms ease-in-out;
  /* The delay on the hidden state is the *hide* delay. */
  transition-delay: 100ms;
  pointer-events: none;
}

.dyno-tip[data-tip]:not([data-tip=""])::before {
  box-sizing: border-box;
  width: max-content;
  max-width: 12.5rem;
  /* Popper did two jobs, and only one of them was placement: it also kept the
     bubble inside the viewport. CSS cannot flip or shift, so a long enough
     `data-tip` grows the box off-screen -- away from the trigger, because the
     edge nearest the trigger is the anchored one. That direction is the saving
     grace: capping the height clips the *end* of the text and keeps the start
     where it can be read, rather than pushing the start off the top. Prefer
     truncating the tip at its source (see `interactions/detail_cell.html`);
     this is the backstop for the tip nobody measured. */
  max-height: 50vh;
  overflow: hidden;
  padding: 0.25rem 0.5rem;
  border-radius: 0.375rem;
  background-color: var(--tt-bg);
  color: #fff;
  content: attr(data-tip);
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.25;
  text-align: center;
  white-space: normal;
}

.dyno-tip[data-tip]:not([data-tip=""])::after {
  border: 0.4rem solid transparent;
  content: "";
}

/* Placement. Top is the default, so `dyno-tip-top` only has to name it. */

.dyno-tip[data-tip]:not([data-tip=""])::before,
.dyno-tip-top[data-tip]:not([data-tip=""])::before {
  inset: auto auto calc(100% + 0.4rem) 50%;
  transform: translateX(-50%);
}

.dyno-tip[data-tip]:not([data-tip=""])::after,
.dyno-tip-top[data-tip]:not([data-tip=""])::after {
  inset: auto auto calc(100% - 0.4rem) 50%;
  border-top-color: var(--tt-bg);
  transform: translateX(-50%);
}

.dyno-tip-bottom[data-tip]:not([data-tip=""])::before {
  inset: calc(100% + 0.4rem) auto auto 50%;
  transform: translateX(-50%);
}

.dyno-tip-bottom[data-tip]:not([data-tip=""])::after {
  inset: calc(100% - 0.4rem) auto auto 50%;
  border-top-color: transparent;
  border-bottom-color: var(--tt-bg);
  transform: translateX(-50%);
}

.dyno-tip-left[data-tip]:not([data-tip=""])::before {
  inset: 50% calc(100% + 0.4rem) auto auto;
  transform: translateY(-50%);
}

.dyno-tip-left[data-tip]:not([data-tip=""])::after {
  inset: 50% calc(100% - 0.4rem) auto auto;
  border-top-color: transparent;
  border-left-color: var(--tt-bg);
  transform: translateY(-50%);
}

.dyno-tip-right[data-tip]:not([data-tip=""])::before {
  inset: 50% auto auto calc(100% + 0.4rem);
  transform: translateY(-50%);
}

.dyno-tip-right[data-tip]:not([data-tip=""])::after {
  inset: 50% auto auto calc(100% - 0.4rem);
  border-top-color: transparent;
  border-right-color: var(--tt-bg);
  transform: translateY(-50%);
}

/* Shown. `:focus-visible` matches a trigger that is itself focusable -- nine
   of them are `<button>` -- and `:has(:focus-visible)` a trigger wrapping one,
   which is DaisyUI's shape. Bootstrap's default trigger was `hover focus`, so
   both are needed to keep keyboard users where they are today.

   Neither reaches *upwards*, and there is no selector that does: a trigger
   nested **inside** the focusable element never lights up on focus, only on
   hover. So when a tooltip describes a button or a link, the class goes on
   that button or link, not on a `<span>` within it -- the three
   `partials/assessments/*reported_outcome*button.html` triggers were moved out
   onto their `<button>` for exactly this reason.

   The reverse nesting is fine and stays: on the four row-link surfaces
   (`home/my_tasks_card`, `home/recent_interactions_card`,
   `monitors/table_rows`, `patients/table_rows`) an `<a>` covers the whole row
   and the tooltips describe individual *cells* inside it. Hoisting those onto
   the row link would say the wrong thing and fire on the wrong focus. Judge by
   what the tip describes, not by the nesting. */

.dyno-tip[data-tip]:not([data-tip=""]):hover::before,
.dyno-tip[data-tip]:not([data-tip=""]):hover::after,
.dyno-tip[data-tip]:not([data-tip=""]):focus-visible::before,
.dyno-tip[data-tip]:not([data-tip=""]):focus-visible::after,
.dyno-tip[data-tip]:not([data-tip=""]):has(:focus-visible)::before,
.dyno-tip[data-tip]:not([data-tip=""]):has(:focus-visible)::after,
.dyno-tip-open[data-tip]:not([data-tip=""])::before,
.dyno-tip-open[data-tip]:not([data-tip=""])::after {
  opacity: 1;
  transition-delay: 200ms;
}
