/* neat-annotations — neat hand-drawn CSS annotations: arrows + handwritten labels.
   https://github.com/syabro/neat-annotations · MIT license.
   Labels look best with the Shantell Sans font (falls back to system cursive). */

.ann {
  --ann-color: oklch(0.62 0.005 30);
  --ann-mark: light-dark(color-mix(in oklch, var(--ann-color) 10%, transparent), oklch(from var(--ann-color) l calc(c * 1.35) h / 24%));
  --ann-font: 'Shantell Sans', cursive;
  --ann-target-gap: 5px;
  --ann-label-gap: 6px;
  --ann-lower-label-gap: -4px;
  --ann-label-max-width: 150px;
  /* set per element by the shell script: how far the arrow must travel from
     the target's edge to the margin line, and how wide the margin is */
  --ann-reach: 0px;
  --ann-room: 150px;
  --ann-arrow-x: 0px;
  --ann-text-x: 0px;
  --ann-arrow-y: 0px;
  --ann-text-y: 5px;
  --ann-rotate: -4deg;
  position: relative;
  display: inline-block;
  overflow: visible;
  line-height: 1.15;
  border-radius: 3px;
  background: var(--ann-mark);
  box-shadow:
    -0.3em 0 0 0 var(--ann-mark),
    0.3em 0 0 0 var(--ann-mark);
}

.ann::after {
  content: attr(data-note);
  position: absolute;
  z-index: 4;
  width: max-content;
  max-width: var(--ann-label-max-width);
  transform: rotate(var(--ann-rotate));
  font-family: var(--ann-font);
  font-size: 0.95rem;
  font-weight: 400;
  line-height: 1.05;
  color: var(--ann-color);
  opacity: .9;
  white-space: normal;
  overflow-wrap: anywhere;
  pointer-events: none;
}

.ann::before {
  content: "";
  position: absolute;
  z-index: 3;
  width: 46px;
  height: 38px;
  transform-origin: 50% 50%;
  -webkit-mask: var(--_ann-arrow-mask) center / contain no-repeat;
  mask: var(--_ann-arrow-mask) center / contain no-repeat;
  background: var(--ann-color);
  opacity: .9;
  pointer-events: none;
}

.ann:not([data-note])::before,
.ann:not([data-note])::after,
.ann[data-note=""]::before,
.ann[data-note=""]::after { display: none; }

.ann-amber { --ann-color: #b8751a; --ann-mark: light-dark(color-mix(in oklch, #ffb000 14%, transparent), color-mix(in oklch, #ffb000 22%, transparent)); }
.ann-blue { --ann-color: #3b72c4; }
.ann-green { --ann-color: #2f8f5b; }
.ann-red { --ann-color: #c45a38; }
.ann-purple { --ann-color: #8657c8; }
.ann-rainbow {
  --ann-color: oklch(0.65 0.28 var(--ann-rainbow-hue, 350deg));
}
.ann-no-mark { --ann-mark: transparent; }

@property --ann-rainbow-hue {
  syntax: "<angle>";
  inherits: false;
  initial-value: 350deg;
}

@keyframes ann-rainbow-cycle { to { --ann-rainbow-hue: 710deg; } }
@media (prefers-reduced-motion: no-preference) {
  .ann-rainbow { animation: ann-rainbow-cycle 3s linear infinite; }
}

@media (forced-colors: active) {
  .ann::before {
    background: CanvasText;
    forced-color-adjust: none;
  }
}

.ann-n::before {
  left: calc(50% - 23px + var(--ann-arrow-x));
  top: calc(100% + var(--ann-target-gap) - 4px + var(--ann-arrow-y));
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23 35 C22 26 22 15 23 4' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M17 10 L23 3 L29 10' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-n::after { left: calc(50% + var(--ann-text-x)); top: calc(100% + var(--ann-target-gap) + 31px + var(--ann-lower-label-gap) + var(--ann-text-y)); transform: translateX(-50%) rotate(var(--ann-rotate)); }

.ann-ne::before {
  left: calc(50% - 40px + var(--ann-arrow-x));
  top: calc(100% + var(--ann-target-gap) - 6px + var(--ann-arrow-y));
  transform: translateX(-10%);
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 32 C16 30 28 18 40 6' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M30 10 L40 6 L36 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-ne::after { left: calc(50% - 34px + var(--ann-text-x)); top: calc(100% + var(--ann-target-gap) + 26px + var(--ann-lower-label-gap) + var(--ann-text-y)); transform: translateX(-60%) rotate(var(--ann-rotate)); }

.ann-e::before {
  /* the arrow sits in the margin, pointing east at the column edge on the
     target's line. --ann-reach (set by the shell script) is the distance from
     the target to that edge; the highlight on the target carries the link */
  right: calc(100% + var(--ann-target-gap) - 3px + var(--ann-reach) - var(--ann-arrow-x));
  top: calc(50% - 19px + var(--ann-arrow-y));
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 19 C15 18 31 18 43 19' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M36 13 L43 19 L36 25' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-e::after {
  right: calc(100% + var(--ann-target-gap) + var(--ann-reach) + 39px + var(--ann-label-gap) - var(--ann-text-x));
  top: calc(50% - 5px + var(--ann-text-y));
  max-width: min(var(--ann-label-max-width), var(--ann-room));
  transform: translateY(-50%) rotate(var(--ann-rotate));
}

.ann-se::before {
  left: calc(50% - 40px + var(--ann-arrow-x));
  top: calc(-1 * var(--ann-target-gap) - 32px + var(--ann-arrow-y));
  transform: translateX(-10%);
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 6 C16 8 28 20 40 32' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M36 22 L40 32 L30 28' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-se::after { left: calc(50% - 34px + var(--ann-text-x)); bottom: calc(100% + var(--ann-target-gap) + 26px + var(--ann-label-gap) - var(--ann-text-y)); transform: translateX(-60%) rotate(var(--ann-rotate)); }

.ann-s::before {
  left: calc(50% - 23px + var(--ann-arrow-x));
  top: calc(-1 * var(--ann-target-gap) - 35px + var(--ann-arrow-y));
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M23 4 C22 13 22 24 23 35' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M17 29 L23 36 L29 29' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-s::after { left: calc(50% + var(--ann-text-x)); bottom: calc(100% + var(--ann-target-gap) + 31px + var(--ann-label-gap) - var(--ann-text-y)); transform: translateX(-50%) rotate(var(--ann-rotate)); }

.ann-sw::before {
  left: calc(50% - 6px + var(--ann-arrow-x));
  top: calc(-1 * var(--ann-target-gap) - 32px + var(--ann-arrow-y));
  transform: translateX(10%);
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M40 6 C30 8 18 20 6 32' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M10 22 L6 32 L16 28' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-sw::after { left: calc(50% + 34px + var(--ann-text-x)); bottom: calc(100% + var(--ann-target-gap) + 26px + var(--ann-label-gap) - var(--ann-text-y)); transform: translateX(-40%) rotate(var(--ann-rotate)); }

.ann-w::before {
  left: calc(100% + var(--ann-target-gap) - 3px + var(--ann-reach) + var(--ann-arrow-x));
  top: calc(50% - 19px + var(--ann-arrow-y));
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M43 19 C32 18 15 18 3 19' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M10 13 L3 19 L10 25' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-w::after {
  left: calc(100% + var(--ann-target-gap) + var(--ann-reach) + 40px + var(--ann-label-gap) + var(--ann-text-x));
  top: calc(50% - 5px + var(--ann-text-y));
  max-width: min(var(--ann-label-max-width), var(--ann-room));
  transform: translateY(-50%) rotate(var(--ann-rotate));
}

.ann-nw::before {
  left: calc(50% - 6px + var(--ann-arrow-x));
  top: calc(100% + var(--ann-target-gap) - 6px + var(--ann-arrow-y));
  transform: translateX(10%);
  --_ann-arrow-mask: url("data:image/svg+xml,%3Csvg width='46' height='38' viewBox='0 0 46 38' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M40 32 C30 30 18 18 6 6' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M16 10 L6 6 L10 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.ann-nw::after { left: calc(50% + 34px + var(--ann-text-x)); top: calc(100% + var(--ann-target-gap) + 26px + var(--ann-lower-label-gap) + var(--ann-text-y)); transform: translateX(-40%) rotate(var(--ann-rotate)); }

/* Narrow screens have no gutters to float the labels in. Below 1280px the
   arrow and label hide and the note opens on tap instead (the shell script
   in build.py wires this up): a highlighted word is the tap target; a card
   annotation (ann-no-mark wrapper, nothing to highlight) gets a small
   numbered marker on its corner. The note floats in a popover card next to
   what was tapped. Decision record: notes/mobile-decisions.md */
@media (min-width: 1280px) {
  .ann-e, .ann-w { --ann-label-max-width: 190px; }
  .ann-pm { display: none; }
}

@media (max-width: 1279px) {
  .ann::before, .ann::after { display: none; }
  .tip::before, .tip::after { display: none; }

  /* word notes: the mark stays, plus a hand-drawn underline in the note colour
     (rough-notation, drawn by the module script in build.py) says "tap me" */
  .ann.ann-tap, .tip.ann-tap {
    cursor: pointer;
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
  }
  .rough-annotation { pointer-events: none; opacity: 0.9; }
  .tip.ann-tap { --ann-color: var(--gray-1100, #62625f); }
  /* 44px hit area on a one-line target */
  .ann.ann-tap::before, .tip.ann-tap::before {
    display: block; content: ""; position: absolute; inset: -10px -4px; z-index: 1;
    -webkit-mask: none; mask: none; background: none; border: 0; opacity: 1;
    transform: none; visibility: visible; width: auto; height: auto;
  }
  .ann.ann-tap[aria-expanded="true"] {
    --ann-mark: color-mix(in oklch, var(--ann-color) 22%, transparent);
  }

  /* card notes: the wrapper becomes a block so a marker can sit on its corner */
  /* not the flow (node canvas) anchors: they sit absolutely over their card, and a
     canvas node gains its note on tap. As relative blocks they took 58px of
     flow and pushed everything below the canvas down. */
  .ann.ann-no-mark[data-note]:not([data-note=""]):not(.flow-anchor):not([class*="E-anchor"]) { display: block; position: relative; }
  .ann-pm {
    position: absolute; top: -11px; right: -4px; z-index: 5;
    width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%;
    background: var(--gray-100, #fcfcfc);
    box-shadow: 0 0 0 1.5px var(--ann-color);
    color: var(--ann-color);
    font: 500 14px/1 var(--ann-font);
    cursor: pointer; touch-action: manipulation; -webkit-tap-highlight-color: transparent;
    transition: transform 150ms ease-out, background-color 150ms ease-out, color 150ms ease-out;
  }
  .ann-pm::before { content: ""; position: absolute; inset: -10px; }
  .ann-pm:active { transform: scale(0.96); }
  .ann-pm[aria-expanded="true"] { background: var(--ann-color); color: var(--gray-100, #fcfcfc); }
  .ann-pm:focus-visible { outline: 2px solid var(--gray-1200, #1c1c1a); outline-offset: 2px; }

  /* the note, floated beside what was tapped */
  .ann-pv {
    position: absolute; z-index: 50;
    max-width: min(300px, calc(100vw - 32px));
    padding: 9px 13px 10px;
    border-radius: 12px;
    background: var(--surface, #fff);
    box-shadow:
      0 0 0 1px rgb(var(--shadow, 0 0 0) / 0.08),
      0 1px 3px rgb(var(--shadow, 0 0 0) / 0.06),
      0 8px 24px -8px rgb(var(--shadow, 0 0 0) / 0.18);
    font: 400 15px/1.3 'Shantell Sans', cursive;
    color: var(--ann-color);
    overflow-wrap: anywhere;
    opacity: 0; transform: scale(0.95);
    transition: opacity 150ms ease-out, transform 150ms ease-out;
  }
  .ann-pv[data-open] { opacity: 1; transform: none; }
  .ann-pv::before {
    content: ""; position: absolute; width: 10px; height: 10px;
    left: var(--ann-pv-arrow); margin-left: -5px;
    background: var(--surface, #fff); transform: rotate(45deg);
  }
  .ann-pv[data-side="below"]::before { top: -5px; box-shadow: -1px -1px 0 0 rgb(var(--shadow, 0 0 0) / 0.08); }
  .ann-pv[data-side="above"]::before { bottom: -5px; box-shadow: 1px 1px 0 0 rgb(var(--shadow, 0 0 0) / 0.08); }
}
@media (prefers-reduced-motion: reduce) {
  .ann-pm, .ann-pv { transition: none; }
}

/* hover tip: a highlighted word; hover or focus floats a small rounded note
   above it. Unlike .ann the note is a solid card, so it stays readable over
   the text it covers. The markdown is {target|note|tip}. */
.tip {
  position: relative;
  display: inline-block;
  border-radius: 3px;
  background: rgb(253 224 130 / 0.4);
  box-shadow:
    -0.15em 0 0 0 rgb(253 224 130 / 0.4),
    0.15em 0 0 0 rgb(253 224 130 / 0.4);
  text-decoration: underline dotted var(--gray-1000, #70706c);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  cursor: help;
}
.tip::before {
  content: "";
  position: absolute;
  z-index: 6;
  bottom: calc(100% - 5px);
  left: 50%;
  width: 10px;
  height: 10px;
  background: var(--surface);
  border-right: 1px solid var(--gray-400, #e6e6e3);
  border-bottom: 1px solid var(--gray-400, #e6e6e3);
  transform: translateX(-50%) rotate(45deg);
  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms ease-out, visibility 150ms;
  pointer-events: none;
}
.tip::after {
  content: attr(data-tip);
  position: absolute;
  z-index: 7;
  bottom: calc(100% + 9px);
  left: 50%;
  width: max-content;
  max-width: min(240px, 70vw);
  padding: 8px 12px;
  border: 1px solid var(--gray-400, #e6e6e3);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: 0 4px 16px rgb(var(--shadow) / 0.08);
  font-family: inherit;
  font-size: var(--text-sm, 13px);
  line-height: 1.5;
  text-align: left;
  text-decoration: none;
  color: var(--gray-1200, #1c1c1a);
  white-space: normal;
  transform: translateX(-50%) translateY(3px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 150ms ease-out, transform 150ms ease-out, visibility 150ms;
  pointer-events: none;
}
.tip:hover::before,
.tip:focus-visible::before { opacity: 1; visibility: visible; }
.tip:hover::after,
.tip:focus-visible::after {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
}
.tip:focus-visible { outline: 2px solid var(--gray-1200, #1c1c1a); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .tip::before, .tip::after { transition: none; }
}
