/* "Ink" look for every lecture page (piloted on L05). Loaded together with ink.js, which adds
   class "ink" to <html> and the #ink-* filters and patterns; without ink.js none of the .ink
   rules apply. Numbers, text and code are never
   filtered: only cell outlines, arcs, tree edges and fills get the line-art treatment. */

:root {
  --ink-line: #2b2823;          /* the pen */
  --ink-paper: #fbf7ec;         /* warm paper behind the drawings */
  --ink-cell: #fffdf6;          /* an empty cell */
  --ink-cur-bg: #f8e7c2;
  --ink-src-bg: #e3efe9;
  --ink-path-bg: #e2efe2;
  --ink-dim-bg: #f2eee3;
  --ink-glow: #f0a43a;
  --ink-stamp: #a3352b;         /* red-brown stamp-pad ink */
  --ink-grain: 0.05;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink-line: #e6dfcf;
    --ink-paper: #1c1b18;
    --ink-cell: #22211d;
    --ink-cur-bg: #3d3018;
    --ink-src-bg: #183332;
    --ink-path-bg: #1b3324;
    --ink-dim-bg: #1f1e1b;
    --ink-glow: #ffbf5e;
    --ink-stamp: #e27a6c;
    --ink-grain: 0.045;
  }
}
:root[data-theme="dark"] {
  --ink-line: #e6dfcf;
  --ink-paper: #1c1b18;
  --ink-cell: #22211d;
  --ink-cur-bg: #3d3018;
  --ink-src-bg: #183332;
  --ink-path-bg: #1b3324;
  --ink-dim-bg: #1f1e1b;
  --ink-glow: #ffbf5e;
  --ink-stamp: #e27a6c;
  --ink-grain: 0.045;
}

/* ---------- paper ---------- */

.ink .demo .svgbox,
.ink .hero-demo .svgbox,
.ink .l5grid {
  background-color: var(--ink-paper);
  position: relative;
}
.ink .demo .svgbox::before,
.ink .hero-demo .svgbox::before {
  /* paper grain: a turbulence texture, drawn once by the browser, no image file */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: var(--ink-grain);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.5 0 0 0 0 0.45 0 0 0 0 0.35 0 0 0 1.4 -0.35'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23g)'/%3E%3C/svg%3E");
}
.ink .demo .svgbox > svg:not(.ink-flow),
.ink .hero-demo .svgbox > svg:not(.ink-flow) { position: relative; }

/* ---------- SVG drawings: strip tables, arcs, recursion tree ---------- */

.ink .svgbox rect { filter: url(#ink-rough); }
.ink .svgbox line,
.ink .svgbox path:not([fill^="var"]) { filter: url(#ink-rough-u); }
.ink .svgbox marker path { filter: none; }

/* outlines become a fine dark pen */
.ink .svgbox rect[stroke="var(--line)"] { stroke: var(--ink-line); stroke-opacity: 0.55; stroke-width: 0.9; }
.ink .svgbox rect[stroke="var(--ink-2)"] { stroke: var(--ink-line); stroke-opacity: 0.85; }
.ink .svgbox line[stroke="var(--ink-2)"] { stroke: var(--ink-line); stroke-opacity: 0.7; stroke-width: 1.1; }
/* not-yet-visited recursion-tree edges are pencilled in; graph demos (L11–L14) give dashes their
   own meaning (back/cross edges, removed edges), so their plain edges stay solid */
.ink .svgbox line[stroke="var(--line)"] { stroke: var(--ink-line); stroke-opacity: 0.3; }
.ink .tx-svg line[stroke="var(--line)"] { stroke-opacity: 0.22; stroke-dasharray: 3 3; }

/* fills: plain paper, or light hatching for highlighted cells */
.ink .svgbox rect[fill="var(--card)"] { fill: var(--ink-cell); }
/* not reached yet: pencil outline, no ink */
.ink .svgbox rect[fill="var(--paper-2)"] { fill: var(--ink-dim-bg); stroke: var(--ink-line); stroke-opacity: 0.3; stroke-dasharray: 3 2.5; }
.ink .svgbox rect[fill="var(--mark)"] { fill: url(#ink-h-cur); }
.ink .svgbox rect[fill="var(--teal-soft)"] { fill: url(#ink-h-src); }
.ink .svgbox rect[fill="var(--green-soft)"] { fill: url(#ink-h-path); }

/* numbers stay crisp: a paper halo keeps them clear of the hatching (not for light text drawn
   on a dark fill, e.g. L14's newly added vertex) */
.ink .svgbox text:not([fill="var(--paper)"]):not([fill="var(--card)"]):not([fill="#fff"]):not([fill="white"]) {
  paint-order: stroke;
  stroke: var(--ink-cell);
  stroke-width: 3px;
  stroke-linejoin: round;
}

/* ---------- the LCS grid (an HTML table) ---------- */

.ink .l5grid td,
.ink .l5grid th { border-color: transparent; background-color: var(--ink-cell); }
.ink .l5grid th { background-color: var(--ink-paper); }
.ink .l5grid td::before,
.ink .l5grid th::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1px solid var(--ink-line);
  opacity: 0.45;
  filter: url(#ink-rough);
  pointer-events: none;
}
.ink .l5grid td.empty { background-color: var(--ink-dim-bg); }
.ink .l5grid td.empty::before { opacity: 0.2; }
.ink .l5grid td.cur,
.ink .l5grid td.src,
.ink .l5grid td.path,
.ink .l5grid th.hit { box-shadow: none; text-shadow: 0 0 3px var(--ink-cell), 0 0 1px var(--ink-cell); }
.ink .l5grid td.cur { background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--amber) 40%, transparent) 0 1px, transparent 1px 4px), repeating-linear-gradient(-45deg, color-mix(in srgb, var(--amber) 22%, transparent) 0 1px, transparent 1px 6px), var(--ink-cur-bg); }
.ink .l5grid td.src { background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--teal) 35%, transparent) 0 1px, transparent 1px 5px), var(--ink-src-bg); }
.ink .l5grid td.path { background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--green) 35%, transparent) 0 1px, transparent 1px 5px), repeating-linear-gradient(-45deg, color-mix(in srgb, var(--green) 20%, transparent) 0 1px, transparent 1px 7px), var(--ink-path-bg); }
.ink .l5grid th.hit { background: repeating-linear-gradient(45deg, color-mix(in srgb, var(--amber) 30%, transparent) 0 1px, transparent 1px 5px), var(--ink-cur-bg); }
.ink .l5grid td.cur::before { border: 2px solid var(--amber); opacity: 1; }
.ink .l5grid td.src::before { border: 1.5px solid var(--teal); opacity: 0.95; }
.ink .l5grid td.path::before { border: 2px solid var(--green); opacity: 1; }

/* ---------- glowing flow ---------- */

.ink .sd-view,
.ink .tx-svg { position: relative; }
.ink-flow {
  position: absolute;
  left: 0;
  top: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 2;
}
.ink .ink-flow .ink-streak,
.ink .svgbox .ink-flow .ink-streak {
  fill: none;
  stroke: var(--ink-glow);
  stroke-width: 3.5;
  stroke-linecap: round;
  filter: url(#ink-blur);
  opacity: 0.9;
  animation: ink-streak var(--ink-ms) cubic-bezier(0.45, 0, 0.3, 1) forwards;
}
.ink-flow .ink-dot,
.ink-flow .ink-dot-glow {
  offset-rotate: 0deg;
  offset-distance: 0%;
  animation: ink-travel var(--ink-ms) cubic-bezier(0.45, 0, 0.3, 1) forwards;
}
.ink-flow .ink-dot { fill: #fff6df; stroke: var(--ink-glow); stroke-width: 1.4; }
.ink-flow .ink-dot-glow { fill: var(--ink-glow); opacity: 0.55; filter: url(#ink-blur); }
@keyframes ink-travel {
  0% { offset-distance: 0%; opacity: 0; }
  12% { opacity: 1; }
  88% { opacity: 1; }
  100% { offset-distance: 100%; opacity: 0; }
}
@keyframes ink-streak {
  from { stroke-dashoffset: var(--ink-from); }
  to { stroke-dashoffset: var(--ink-to); }
}
/* arrival: the entry glows once, and its value is inked in. Any shape can be a target: SVG
   rect, circle, ellipse, path, g, text, or an HTML box. The glow is a drop-shadow pulse in
   --ink-glow (light and dark); the 0% and 100% keyframes are left out and the animation does not
   fill forwards, so the element starts and ends on its own filter and nothing stays on it. */
.ink .ink-hit { animation: ink-hit 0.55s ease-out var(--ink-delay) backwards; }
.ink .ink-hit.ink-val:not(td) { animation: ink-hit 0.55s ease-out var(--ink-delay) backwards, ink-val 0.25s ease-out var(--ink-delay) both; }
@keyframes ink-hit { 35% { filter: drop-shadow(0 0 7px var(--ink-glow)); } }
/* shapes the rough pen draws (see above) keep their pen while they glow */
.ink .svgbox rect.ink-hit { animation-name: ink-hit-svg; }
.ink .svgbox line.ink-hit,
.ink .svgbox path.ink-hit:not([fill^="var"]) { animation-name: ink-hit-svg-u; }
.ink td.ink-hit { animation: ink-hit-td 0.55s ease-out var(--ink-delay) both; }
.ink .ink-val { animation: ink-val 0.25s ease-out var(--ink-delay) both; }
.ink td.ink-hit.ink-val { animation: ink-hit-td 0.55s ease-out var(--ink-delay) both, ink-val-td 0.25s ease-out var(--ink-delay) both; }
@keyframes ink-hit-svg {
  0% { filter: url(#ink-rough) drop-shadow(0 0 0 transparent); }
  35% { filter: url(#ink-rough) drop-shadow(0 0 7px var(--ink-glow)); }
  100% { filter: url(#ink-rough) drop-shadow(0 0 0 transparent); }
}
@keyframes ink-hit-svg-u {
  0% { filter: url(#ink-rough-u) drop-shadow(0 0 0 transparent); }
  35% { filter: url(#ink-rough-u) drop-shadow(0 0 7px var(--ink-glow)); }
  100% { filter: url(#ink-rough-u) drop-shadow(0 0 0 transparent); }
}
@keyframes ink-hit-td {
  0% { box-shadow: 0 0 0 0 transparent; }
  35% { box-shadow: 0 0 12px 2px var(--ink-glow); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
@keyframes ink-val { from { opacity: 0; } to { opacity: 1; } }
@keyframes ink-val-td { from { color: transparent; } }

/* ---------- chapter stamps: a red-brown rubber seal ---------- */

.ink-seal {
  display: inline-block;
  color: var(--ink-stamp);
  line-height: 0;
  transform: rotate(var(--ink-rot, -10deg));
  mix-blend-mode: multiply;   /* ink soaks into the paper */
  opacity: 0.92;
}
.ink-seal svg { width: 100%; height: 100%; display: block; overflow: visible; }
.ink-seal text { font-family: Georgia, "Times New Roman", serif; }
:root[data-theme="dark"] .ink-seal { mix-blend-mode: normal; opacity: 0.88; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .ink-seal { mix-blend-mode: normal; opacity: 0.88; } }

.ink-seal.on-card { position: absolute; top: 10px; right: 10px; width: 64px; height: 64px; }
.ink .chapcard { position: relative; }
.ink-tally { text-align: center; margin: -4px 0 18px; font-size: 14px; color: var(--ink-2); }
.ink-tally b { color: var(--ink-stamp); font-family: var(--mono); }

/* the chapter bar: a tiny seal (ring + check) printed with the same uneven ink */
.ink .chapnav a.ink-stamped::after {
  content: "";
  display: inline-block;
  width: 13px;
  height: 13px;
  margin-left: 5px;
  vertical-align: -2px;
  background: var(--ink-stamp);
  transform: rotate(-12deg);
  opacity: 0.95;
  -webkit-mask: var(--ink-mini-seal) center / contain no-repeat;
  mask: var(--ink-mini-seal) center / contain no-repeat;
}
:root {
  --ink-mini-seal: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 26 26'%3E%3Cfilter id='s' x='-5%25' y='-5%25' width='110%25' height='110%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='1' seed='4'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -3 0 0 0 2.5'/%3E%3CfeComposite in='SourceGraphic' operator='in'/%3E%3C/filter%3E%3Cg filter='url(%23s)' fill='none' stroke='%23000'%3E%3Ccircle cx='13' cy='13' r='11.2' stroke-width='2.6'/%3E%3Ccircle cx='13' cy='13' r='7.6' stroke-width='0.9'/%3E%3Cpath d='M9.2 13.4l2.6 2.6l5-5.6' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/g%3E%3C/svg%3E");
}

.ink-stampbox {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 26px 0 0;
  padding: 12px 16px;
  border: 1px dashed var(--line);
  border-radius: 12px;
  font-size: 14px;
  color: var(--ink-2);
}
.ink-stampbox .ink-seal { flex: none; width: 76px; height: 76px; }
.ink-stampbox .ink-seal.empty {
  border: 1.5px dashed var(--stone);
  border-radius: 50%;
  opacity: 0.5;
  transform: none;
  width: 60px;
  height: 60px;
  margin: 8px;
  mix-blend-mode: normal;
}
.ink-stampbox.on { border-style: solid; border-color: color-mix(in srgb, var(--ink-stamp) 40%, transparent); }
.ink-stampbox b { color: var(--ink); }

/* stamping: comes down from above, presses (a little squashed, extra dark), lifts off */
.ink-seal.thud { animation: ink-thud 0.55s cubic-bezier(0.3, 0, 0.3, 1) both; }
@keyframes ink-thud {
  0% { transform: rotate(var(--ink-rot)) scale(1.8); opacity: 0; filter: blur(1.5px); }
  45% { transform: rotate(var(--ink-rot)) scale(0.9); opacity: 1; filter: none; }
  70% { transform: rotate(var(--ink-rot)) scale(1.04); }
  100% { transform: rotate(var(--ink-rot)) scale(1); opacity: 0.92; }
}

@media (prefers-reduced-motion: reduce) {
  .ink-flow { display: none; }
  .ink .ink-hit, .ink .ink-hit.ink-val:not(td), .ink .svgbox .ink-hit, .ink td.ink-hit, .ink td.ink-hit.ink-val, .ink .ink-val, .ink-seal.thud { animation: none; }
}
