fix #522, spec_line glitches and improvements

- xlim/ylim expansion was incorrect
- remove border= from plot parameters (carryover from spec_hist)
- fix how min/max dots are sometimes truncated (using xpd)
- allow most parameters to be per-plot instead of all-plots global
diff --git a/R/mini_plots.R b/R/mini_plots.R
index 1c15262..764d7bf 100644
--- a/R/mini_plots.R
+++ b/R/mini_plots.R
@@ -264,28 +264,62 @@
                       file = NULL,
                       file_type = if (is_latex()) "png" else "svg", ...) {
   if (is.list(x)) {
+    lenx <- length(x)
+
     if (same_lim) {
       if (is.null(xlim)) {
-        xlim <- base::range(unlist(x))
+        xlim <- lapply(x, base::range)
       }
       if (is.null(ylim) && !is.null(y)) {
-        ylim <- base::range(unlist(y))
+        ylim <- lapply(y, base::range)
       }
     }
     if (is.null(y)) {
-      y <- replicate(length(x), NULL, simplify = FALSE)
-    } else if (!is.list(y) || length(x) != length(y)) {
+      y <- replicate(lenx, NULL, simplify = FALSE)
+    } else if (!is.list(y) || lenx != length(y)) {
       stop("'x' and 'y' are not the same length")
     }
-    return(Map(function(x_, y_) {
-      spec_line(x = x_, y = y_,
-                width = width, height = height,
-                same_lim = same_lim, xlim = xlim, ylim = ylim,
-                xaxt = xaxt, yaxt = yaxt, ann = ann, col = col, border = border,
-                frame.plot = frame.plot, lwd = lwd,
-                minmax = minmax, min = min, max = max,
-                dir = dir, file = file, file_type = file_type, ...)
-    }, x, y))
+
+    # any of the arguments can be per-plot controlling, but an arg
+    # that is normally not length-1 may be recycled (incorrectly) by
+    # Map, so we have to listify them if not already lists;
+    # enforce a restriction of recycling only length 1 or lenx
+
+    # first, start with the literals (x,y)
+    # same_lim, not a factor anymore
+    dots <- list(x = x, y = y)
+
+    # second, we know these args are likely to be vectors (length > 1)
+    # or lists, so we have to handle them carefully and double-list if
+    # present
+    notlen1 <- list(xlim = xlim, ylim = ylim,
+                    minmax = minmax, min = min, max = max)
+    dots <- c(dots, Map(
+      function(L, nm) {
+        if (is.null(L)) return(list(NULL))
+        if (!is.list(L) || !is.list(L[[1]])) return(list(L))
+        if (!length(L) %in% c(1L, lenx)) {
+          stop("length of '", nm, "' must be 1 or the same length as 'x'")
+        }
+        L
+      }, notlen1, names(notlen1)))
+
+    # last, all remaining arguments that we don't already know about
+    # are length-1, so can be easily listified; using 'formals()'
+    # allows us to not hard-code all params, for future expansion?
+    len1args <- mget(setdiff(names(formals()),
+                             c(names(dots), "same_lim", "x", "y", "...")))
+    dots <- c(dots, Map(
+      function(V, nm) {
+        if (is.null(V)) return(list(NULL))
+        if (!length(V) %in% c(1L, lenx)) {
+          stop("length of '", nm, "' must be 1 or the same length as 'x'")
+        }
+        V
+      }, len1args, names(len1args)))
+
+    return(do.call(Map, c(list(f = spec_line), dots)))
+
   }
 
   if (is.null(x)) return(NULL)
@@ -310,10 +344,10 @@
   if (is.null(max)) max <- minmax
 
   expand <- c(
-    if (!is.null(min) && length(min)) 0.96 else 1,
-    if (!is.null(max) && length(max)) 1.04 else 1)
-  xlim <- xlim * expand
-  ylim <- ylim * expand
+    if (!is.null(min) && length(min)) -0.04 else 0,
+    if (!is.null(max) && length(max)) +0.04 else 0)
+  xlim <- xlim + diff(xlim) * expand
+  ylim <- ylim + diff(ylim) * expand
 
   file_type <- match.arg(file_type, c("svg", "png"))
 
@@ -337,18 +371,18 @@
   on.exit(grDevices::dev.off(curdev), add = TRUE)
 
   graphics::par(mar = c(0, 0, 0.2, 0), lwd = lwd)
-  graphics::plot(x, y, type = "l", xlim = xlim, ylim = ylim, border = border,
+  graphics::plot(x, y, type = "l", xlim = xlim, ylim = ylim,
                  xaxt = xaxt, yaxt = yaxt, ann = ann, col = col,
                  frame.plot = frame.plot, ...)
 
   if (!is.null(min) && length(min)) {
     ind <- which.min(y)
-    do.call(graphics::points, c(list(x[ind], y[ind]), min))
+    do.call(graphics::points, c(list(x[ind], y[ind], xpd = NA), min))
   }
 
   if (!is.null(max) && length(max)) {
     ind <- which.max(y)
-    do.call(graphics::points, c(list(x[ind], y[ind]), max))
+    do.call(graphics::points, c(list(x[ind], y[ind], xpd = NA), max))
   }
 
   grDevices::dev.off(curdev)