anchor.diff:        FName = filename:join([Dir, Type ++ ".zss"]),
         case filelib:is_file(FName) of
           true ->
  -          zml:append_attr(Acc, {Type, FName});
  +          zml:append_attr(Acc, {Type, [FName]});
           false ->
             Acc
         end
  
positive.code: process(_ID, Attr, _Children, AST, Options) ->
    DeclaredZSS = get_declared_zss(Attr, Options),
    % DEBUG
    io:format("~n~p~n~n", [DeclaredZSS]),
    Processed = lists:map(fun(Styles) ->
          process_styles(Styles, AST, Options)
      end, DeclaredZSS),
    AST.
  
  get_declared_zss(Attr, Options) ->
  
negative.code:         _ -> {error, "Could not find "++FName++" in any of the search paths."}
        end
    end.
  
  remove_unused_css([], _AST, Acc) ->
    lists:reverse(Acc);
  remove_unused_css([{Selectors, Atts} | T], AST, Acc) ->
    ActiveSelectors = lists:reverse(lists:foldl(
      fun(A,InAcc) ->
          case ast_has_selector(AST,A) of
            true -> [A | InAcc];
            false -> InAcc
          end
      end, [], Selectors)),
    case ActiveSelectors of
      [] ->
        remove_unused_css(T, AST, Acc);
      _ ->
        remove_unused_css(T, AST, [{ActiveSelectors, Atts} | Acc])
    end.
  
  %% OK if it has some false positives, so we can keep it simple.
  %% Get rid of/ignore ":...", "[...]", and turn ">" into " ", and finally, "+"
  %% is pretty much ignored- returns true for now.
  %% Of course all with optional # and .  Also handle *.
  ast_has_selector(AST, Sel) ->
    % All that work not using regex earlier and now resorting to it here.  *sigh*
    % TODO: replace regex w/ some simple transforms
    S2 = re:replace(Sel, ":[^\\s]*", "", [{return, list}, global]),
    S3 = re:replace(S2,  "\\[.*?\\]","", [{return, list}, global]),
    S4 = re:replace(S3,  "\\+.*","", [{return, list}, global]),
    SFin = re:replace(S4,  ">"," ", [{return, list}, global]),
  
    case string:chr(SFin, $+) of
      0 ->
        Elements = string:tokens(string:strip(SFin), " "),
        scan_ast(Elements, AST);
      _ ->
        true
    end.
  
  scan_ast([], _) ->
    true;
  scan_ast(_, []) ->
    false;
  scan_ast(Elems, [Txt | T]) when is_list(Txt) ->
    scan_ast(Elems, T);
  scan_ast([E | T] = Elems, [{NEl, _, NAtt, NChildren}  | TAST]) ->
    case elements_match(E, NEl, NAtt) of
      true ->
        case T of
          [] ->
            true;
          _ ->
            scan_ast(T, NChildren)
        end;
      false ->
        case scan_ast(Elems, NChildren) of
          true ->
            true;
          false ->
            scan_ast(Elems, TAST)
        end
    end.
  
  elements_match(ElStr, {Name, _ID}, Attrs) ->
    elements_match(ElStr, Name, Attrs);
  elements_match(ElStr, Name, Attrs) ->
    {Element, Classes, ID} = pull_selector_atts(ElStr),
    ElementMatch =
      case Element of
        "*" ->
          true;
        _ ->
          Element == Name
      end,
    case ElementMatch of
      false -> false;
      true ->
        att_includes(Attrs, "class", Classes) and
          att_includes(Attrs, "id", ID)
    end.
  
  att_includes(_Attr, _Key, []) ->
    true;
  att_includes(Attr, Key, ReqVals) ->
    case zml:get_attr_vals(Key, Attr) of
      [] ->
        false;
      HasVals ->
        lists:all(fun(Req) -> lists:member(Req, HasVals) end, ReqVals)
    end.
  
  % Given a string with optional element and strung classes, id markers, it
  % returns the element name (* if none specified), the list of classes, and the
  % list of IDs (even though everyone knows you can't have that...)
  % That is, a simple, naive css rule parser
  pull_selector_atts(E) ->
    pull_selector_atts(E, elem, [], [], [], []).
  
  pull_selector_atts([], elem, [], [], [], []) ->
    {"*", [], []};
  pull_selector_atts([], elem, TAcc, [], [], []) ->
    {lists:reverse(TAcc), [], []};
  pull_selector_atts([], class, TAcc, El, ClAcc, IDAcc) ->
    {El, [lists:reverse(TAcc) | ClAcc], IDAcc};
  pull_selector_atts([], id, TAcc, El, ClAcc, IDAcc) ->
    {El, ClAcc, [lists:reverse(TAcc) | IDAcc]};
  
  pull_selector_atts([$.|T], elem, [], [], [], []) ->
    pull_selector_atts(T, class, [], "*", [], []);
  pull_selector_atts([$.|T], elem, TmpAcc, [], [], []) ->
    pull_selector_atts(T, class, [], lists:reverse(TmpAcc), [], []);
  pull_selector_atts([$.|T], class, TmpAcc, El, ClAcc, IDAcc) ->
    pull_selector_atts(T, class, [], El, [lists:reverse(TmpAcc) | ClAcc], IDAcc);
  pull_selector_atts([$.|T], id, TmpAcc, El, ClAcc, IDAcc) ->
    pull_selector_atts(T, class, [], El, ClAcc, [lists:reverse(TmpAcc) | IDAcc]);
  
  pull_selector_atts([$#|T], elem, [], [], [], []) ->
    pull_selector_atts(T, id, [], "*", [], []);
  pull_selector_atts([$#|T], elem, TmpAcc, [], [], []) ->
    pull_selector_atts(T, id, [], lists:reverse(TmpAcc), [], []);
  pull_selector_atts([$#|T], class, TmpAcc, El, ClAcc, IDAcc) ->
    pull_selector_atts(T, id, [], El, [lists:reverse(TmpAcc) | ClAcc], IDAcc);
  pull_selector_atts([$#|T], id, TmpAcc, El, ClAcc, IDAcc) ->
    pull_selector_atts(T, id, [], El, ClAcc, [lists:reverse(TmpAcc) | IDAcc]);
  
  pull_selector_atts([H|T], Type, TmpAcc, El, ClAcc, IDAcc) ->
    pull_selector_atts(T, Type, [H | TmpAcc], El, ClAcc, IDAcc).
  
  