%% moeptikz.sty
%% Copyright 2015-2026 Stephan M. Guenther
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2008 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Stephan M. Guenther.
%
% This work consists of the files moeptikz.sty, moeptikz-doc.tex,
% README.md and Makefile and the derived file moeptikz-doc.pdf.
%
% The complete work and its issue tracker are available at
%   https://github.com/moepinet/moeptikz

% 2020/10/01: \DeclareDocumentCommand is part of the kernel (formerly xparse)
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\ProvidesPackage{moeptikz}[2026/11/15 v1.1 moepTikZ]

\RequirePackage{keyval}
\RequirePackage{tikz}

\usetikzlibrary{shapes.symbols}
\usetikzlibrary{decorations.markings}

\DeclareDocumentCommand{\tikzextractx}{m m}{%
	\tikz@scan@one@point\pgfutil@firstofone#1\relax%
	\edef#2{\the\pgf@x}%
}%
\DeclareDocumentCommand{\tikzextracty}{m m}{%
	\tikz@scan@one@point\pgfutil@firstofone#1\relax%
	\edef#2{\the\pgf@y}%
}%

% The arrows of hub, switch, mlswitch, router and fwrouter take the colour of
% draw=<colour> or color=<colour>, whichever comes last, as in version 1.0;
% colour shortcuts such as red and \color do not change them, and without
% either they are black.  The two keys record the colour in TikZ's deferred
% options, in the order of the options (also those of the picture, a scope or
% every node), as the colour name without colour mixins.
% \moeptikz@savestrokecolor saves it as moeptikz@stroke and
% \moeptikz@fillwithstrokecolor fills the arrows with it: \pgfsetfillcolor
% applies the colour mixins in effect (e.g. beamer's
% \setbeamercovered{transparent}) once, so that covered arrows fade.  Not
% PGF's stroke colour pgfstrokecolor: it holds the mixins of the moment it was
% set, e.g. none at the beginning of a picture whose nodes are covered later
% (\pause, \onslide in the picture).
\let\moeptikz@drawcolor\pgfutil@empty
\def\moeptikz@recorddrawcolor#1{%
	\edef\moeptikz@temp{#1}%
	\ifx\moeptikz@temp\pgfutil@empty\else
	\ifx\moeptikz@temp\tikz@nonetext\else
		\tikz@addoption{\def\moeptikz@drawcolor{#1}}%
	\fi\fi
}
\pgfkeys{
	/tikz/draw/.append code={\moeptikz@recorddrawcolor{#1}},
	/tikz/color/.append code={\moeptikz@recorddrawcolor{#1}}
}
\def\moeptikz@savestrokecolor{%
	\ifx\moeptikz@drawcolor\pgfutil@empty
		\pgfutil@colorlet{moeptikz@stroke}{black}%
	\else
		\pgfutil@colorlet{moeptikz@stroke}{\moeptikz@drawcolor}%
	\fi
}
\def\moeptikz@fillwithstrokecolor{\pgfsetfillcolor{moeptikz@stroke}}

\newif\ifmoeptikz@shading
\define@key{moeptikz}{shading}[true]{%
	\pgfutil@ifundefined{moeptikz@shading#1}{%
		\PackageError{moeptikz}{Invalid value `#1' for key `shading'}%
			{Use shading=true or shading=false.}%
	}{%
		\csname moeptikz@shading#1\endcsname
	}%
}

% The shapes paint their bodies with shadings, flat ones with shading=false:
% moeptikz@shading and the darker moeptikz@shadingnuc in the colour
% moeptikz@fill (see \moeptikz@setshading), moeptikz@servereject (eject
% buttons of the server) and moeptikz@paper (paper of messageopen).  Each is
% declared once when the package is loaded, with the colours it depends on as
% optional argument of \pgfdeclare...shading.  PGF creates the PDF object of
% such a shading when it is used, with the colour mixins in effect applied
% (e.g. those of beamer's \setbeamercovered{transparent}), and keeps it for
% the resulting colours of the dependencies: every distinct shading is written
% to the PDF only once, and a shading in a covered part of a frame fades like
% a TikZ fill without changing the visible ones.  All colours of a shading are
% mixed from one colour and white, so it depends on both: a mixin can change
% white also where the colour stays the same (black on a black background).

% \moeptikz@declareshading{<name>}{<inner>}{<outer>}{<flat>}
% Declares the shadings <name>@on, radial from white via <inner> to <outer>
% percent of moeptikz@fill, and <name>@off, flat <flat> percent of it.
\def\moeptikz@declareshading#1#2#3#4{%
	\pgfdeclareradialshading[moeptikz@fill,white]{#1@on}%
		{\pgfpoint{-25bp}{-25bp}}{%
			rgb(0bp)=(1,1,1);
			color(20bp)=(moeptikz@fill!#2);
			color(50bp)=(moeptikz@fill!#3)
		}%
	\pgfdeclareradialshading[moeptikz@fill,white]{#1@off}{\pgfpoint{0}{0}}{%
		color(0bp)=(moeptikz@fill!#4);
		color(100bp)=(moeptikz@fill!#4)
	}%
}
\moeptikz@declareshading{moeptikz@shading}{20}{60}{30}
\moeptikz@declareshading{moeptikz@shadingnuc}{70}{90}{70}

% Provides the shadings moeptikz@shading and moeptikz@shadingnuc in the fill
% colour (or the current colour if no fill colour is set), radial or flat
% depending on \ifmoeptikz@shading.
\def\moeptikz@setshading{%
	\ifx\tikz@fillcolor\pgfutil@empty
		\pgfutil@colorlet{moeptikz@fill}{.}%
	\else
		\pgfutil@colorlet{moeptikz@fill}{\tikz@fillcolor}%
	\fi
	\edef\moeptikz@tmp{\ifmoeptikz@shading on\else off\fi}%
	\pgfaliasshading{moeptikz@shading}{moeptikz@shading@\moeptikz@tmp}%
	\pgfaliasshading{moeptikz@shadingnuc}{moeptikz@shadingnuc@\moeptikz@tmp}%
}

\DeclareDocumentCommand{\moeptikzset}{m}{%
	\setkeys{moeptikz}{#1}%
}

\moeptikzset{shading=true}

\DeclareOption{shading}{\moeptikzset{shading=true}}
\DeclareOption{noshading}{\moeptikzset{shading=false}}
% key=value options, e.g. \usepackage[shading=false]{moeptikz}
\DeclareOption*{\expandafter\moeptikzset\expandafter{\CurrentOption}}
\ProcessOptions*\relax

% Saved macros of every shape, evaluated once when the node is created:
% \moeptikz@size  the size, so that expressions like `minimum size=1cm+2mm'
%                 work
% \moeptikz@ysep  outer ysep + inner ysep, the gap between shape and node text
\def\moeptikz@savedmacros{%
	\savedmacro\moeptikz@size{%
		\pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/minimum width}}%
		\edef\moeptikz@size{\the\pgf@xa}%
	}%
	\savedmacro\moeptikz@ysep{%
		\pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/inner ysep}}%
		\pgfmathaddtolength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
		\edef\moeptikz@ysep{\the\pgf@ya}%
	}%
	% size of the node text, for the text anchor: PGF does not keep the text
	% box of a node, a later reference such as (x.text) or (x.base) would read
	% the box of another node
	\savedmacro\moeptikz@textwd{\edef\moeptikz@textwd{\the\wd\pgfnodeparttextbox}}%
	\savedmacro\moeptikz@textht{\edef\moeptikz@textht{\the\ht\pgfnodeparttextbox}}%
}

% Helpers for the declarations of the shapes.  All but \moeptikz@declarestyle
% are used inside \pgfdeclareshape (only there \savedanchor, \anchor,
% \inheritanchor, ... are defined).
%
% \moeptikz@savednortheast, \moeptikz@savedsouthwest
% Declare the saved anchors \northeast = (size/2,size/2) and \southwest =
% -\northeast, the upper right and the lower left corner of the node; the
% drawing code gives its points relative to them.  Both use \moeptikz@size,
% hence they have to come after \moeptikz@savedmacros.
\def\moeptikz@savednortheast{%
	\savedanchor\northeast{%
		\pgf@x=.5\dimexpr\moeptikz@size\relax
		\pgf@y=\pgf@x
	}%
}
\def\moeptikz@savedsouthwest{%
	\savedanchor\southwest{%
		\pgf@x=-.5\dimexpr\moeptikz@size\relax
		\pgf@y=\pgf@x
	}%
}

% \moeptikz@outlineanchors{<border code>}
% Declares the border of a shape (\anchorborder, <border code> is e.g.
% \moeptikz@polyborder\moeptikz@db@outline) and its anchors center, text (see
% \moeptikz@textanchor), base and mid with their east and west variants (see
% \moeptikz@textlineanchors and \moeptikz@sideanchors) and north, south, east,
% west, north east, ..., which lie on the border in the respective direction:
% north east is the same point as the angle anchor 45, north as 90, and so on.
% All shapes but internet (PGF's cloud anchors) get their anchors from it,
% directly or inherited.  An \anchor declared after it replaces the one of the
% same name (the shape @key does so with text).
\def\moeptikz@outlineanchors#1{%
	\anchor{center}{\pgfpointorigin}%
	\anchorborder{#1}%
	\anchor{north}{\pgf@x=0pt\pgf@y=1pt#1}%
	\anchor{south}{\pgf@x=0pt\pgf@y=-1pt#1}%
	\anchor{east}{\pgf@x=1pt\pgf@y=0pt#1}%
	\anchor{west}{\pgf@x=-1pt\pgf@y=0pt#1}%
	\anchor{north east}{\pgf@x=1pt\pgf@y=1pt#1}%
	\anchor{north west}{\pgf@x=-1pt\pgf@y=1pt#1}%
	\anchor{south east}{\pgf@x=1pt\pgf@y=-1pt#1}%
	\anchor{south west}{\pgf@x=-1pt\pgf@y=-1pt#1}%
	\anchor{text}{\moeptikz@textanchor{#1}}%
	\moeptikz@textlineanchors
	\moeptikz@sideanchors
}

% \moeptikz@textlineanchors
% Declares base and mid as PGF's rectangle does: base lies on the baseline of
% the node text below the centre of the shape (below the shape, where the text
% is), mid .5ex above it.  They use the text anchor of the shape when they are
% computed, hence also a text anchor that the shape declares later (@key).  A
% matrix of nodes places its cells at base by default.  (PGF computes anchors
% with \nullfont, where .5ex is 0pt; pgfmath selects the current text font,
% as for PGF's rectangle.)
\def\moeptikz@textlineanchors{%
	\expandafter\moeptikz@textlineanchors@
		\csname pgf@anchor@\pgf@sm@shape@name @text\endcsname
}
\def\moeptikz@textlineanchors@#1{%
	\anchor{base}{#1\pgf@x=0pt}%
	\anchor{mid}{#1\pgf@x=0pt\pgfmathaddtolength\pgf@y{.5ex}}%
}

% \moeptikz@sideanchors
% Declares base east, base west, mid east and mid west for a shape with the
% anchors east, west, base and mid: the x of east or west and the y of base or
% mid, as for PGF's rectangle.
\def\moeptikz@sideanchors{%
	\moeptikz@sideanchor{base east}{east}{base}%
	\moeptikz@sideanchor{base west}{west}{base}%
	\moeptikz@sideanchor{mid east}{east}{mid}%
	\moeptikz@sideanchor{mid west}{west}{mid}%
}
% \moeptikz@sideanchor{<new anchor>}{<anchor for x>}{<anchor for y>}
\def\moeptikz@sideanchor#1#2#3{%
	\edef\moeptikz@tmp{%
		\noexpand\anchor{#1}{%
			\expandafter\noexpand\csname pgf@anchor@\pgf@sm@shape@name @#2\endcsname
			\noexpand\edef\noexpand\moeptikz@sidex{\noexpand\the\noexpand\pgf@x}%
			\expandafter\noexpand\csname pgf@anchor@\pgf@sm@shape@name @#3\endcsname
			\noexpand\pgf@x=\noexpand\moeptikz@sidex\relax}}%
	\moeptikz@tmp
}

% \moeptikz@inheritanchors{<shape>}
% Takes over size, border and anchors of the shape <shape>, which has to be
% declared before: its saved anchors and macros, its border and its anchors
% center, north, east, south, west, north east, ..., south west and text; base,
% mid and their east and west variants are declared anew from these, so that
% they follow a text anchor that the shape declares later.
\def\moeptikz@inheritanchors#1{%
	\inheritsavedanchors[from=#1]%
	\inheritanchorborder[from=#1]%
	\inheritanchor[from=#1]{center}%
	\inheritanchor[from=#1]{north}%
	\inheritanchor[from=#1]{east}%
	\inheritanchor[from=#1]{south}%
	\inheritanchor[from=#1]{west}%
	\inheritanchor[from=#1]{north east}%
	\inheritanchor[from=#1]{north west}%
	\inheritanchor[from=#1]{south east}%
	\inheritanchor[from=#1]{south west}%
	\inheritanchor[from=#1]{text}%
	\moeptikz@textlineanchors
	\moeptikz@sideanchors
}

% \moeptikz@novalue{<key>}
% Makes the shape key <key>, a style declared before, take no value:
% <key>=<value>, e.g. server=2cm, gives the pgfkeys error "You may not specify
% a value for the key '/tikz/<key>'" and the value is ignored.  Like the
% pgfkeys handler .value forbidden it puts a check in front of the code of
% the style, but the check tests the argument of the key (\pgfkeysnovalue
% without a value), not \pgfkeyscurrentvalue: code that is put in front of
% the style later, e.g. by <key>/.prefix style={thick}, runs before the check
% and changes \pgfkeyscurrentvalue with its own keys.
\def\moeptikz@novalue#1{%
	\tikzset{#1/.prefix code={\moeptikz@novalue@check{#1}{##1}}}%
}
% \moeptikz@novalue@check{<key>}{<argument of the key>}
\long\def\moeptikz@novalue@check#1#2{%
	\def\moeptikz@tmp{#2}%
	\ifx\moeptikz@tmp\pgfkeysnovalue@text\else
		\pgfkeysvalueof{/errors/value forbidden/.@cmd}{/tikz/#1}{#2}\pgfeov
	\fi
}

% \moeptikz@declarestyle{<name>}{<default fill colour>}
% Declares the style <name> of the shape @<name>, used after its
% \pgfdeclareshape: \node[server] sets shape=@server, minimum size=1cm and
% fill=<default fill colour>.  Size and colours are given as options of their
% own after the shape name, e.g. \node[server, minimum size=2cm, fill=red].
% The key takes no value (see \moeptikz@novalue).
\def\moeptikz@declarestyle#1#2{%
	\tikzset{
		#1/.style={
			shape=@#1,
			minimum size=1cm,
			fill=#2
		}
	}%
	\moeptikz@novalue{#1}%
}


%==============================================================================
% Border of the shapes
%==============================================================================
% Lines between nodes, e.g. \draw (a) -- (b), and anchors given as an angle,
% e.g. (a.30), end on the border of a shape.  PGF asks a shape for such a
% border point by running its \anchorborder code: on entry (\pgf@x,\pgf@y) is a
% vector pointing from the node center in the requested direction.  It is
% given in the node's own coordinate system, i.e. position, rotation and
% scaling of the node are already undone.  The code has to leave the border
% point in (\pgf@x,\pgf@y), again relative to the node center.
%
% The outline of a shape consists of one or more polygons, each given as a list
% of vertices {x1}{y1}{x2}{y2}... in units of half the node size, i.e. (1,1) is
% the upper right corner of the node's bounding box.  The border point is the
% intersection of the ray from the center with the polygons.  If the ray
% crosses them several times (non-convex outlines, antennas), the crossing
% farthest away from the center is used: that is where a line coming from
% outside first touches the shape.
%
% The computations use e-TeX's \dimexpr, numbers are stored as dimensions in pt
% (1pt means 1.0).  \dimexpr computes a*b/c with a 64-bit intermediate result,
% so there is neither an overflow nor a loss of precision.
\newdimen\moeptikz@dx
\newdimen\moeptikz@dy
\newdimen\moeptikz@t
\newif\ifmoeptikz@direction
\def\moeptikz@stop{\moeptikz@stop}

% Scales the direction (\pgf@x,\pgf@y) such that max(|dx|,|dy|) = 1 and stores
% it in (\moeptikz@dx,\moeptikz@dy).  \ifmoeptikz@direction is false for a
% zero direction, i.e. if the target point coincides with the node center.
\def\moeptikz@normalize{%
	\pgf@xa=\ifdim\pgf@x<0pt -\fi\pgf@x
	\pgf@ya=\ifdim\pgf@y<0pt -\fi\pgf@y
	\ifdim\pgf@ya>\pgf@xa \pgf@xa=\pgf@ya \fi
	\ifdim\pgf@xa<0.001pt
		\moeptikz@directionfalse
	\else
		\moeptikz@directiontrue
		\moeptikz@dx=\dimexpr 1pt*\number\pgf@x/\number\pgf@xa\relax
		\moeptikz@dy=\dimexpr 1pt*\number\pgf@y/\number\pgf@xa\relax
	\fi
}

% Stores the border point t*(dx,dy)*size/2 in (\pgf@x,\pgf@y), t=\moeptikz@t.
\def\moeptikz@borderpoint{%
	\pgf@xa=.5\dimexpr\moeptikz@size\relax
	\pgf@x=\dimexpr\moeptikz@t*\number\moeptikz@dx/65536\relax
	\pgf@y=\dimexpr\moeptikz@t*\number\moeptikz@dy/65536\relax
	\pgf@x=\dimexpr\pgf@xa*\number\pgf@x/65536\relax
	\pgf@y=\dimexpr\pgf@xa*\number\pgf@y/65536\relax
}

% \moeptikz@edge{x1}{y1}{x2}{y2}
% Intersects the ray t*d, t>0, d=(dx,dy) with the edge P + s*e, 0<=s<=1, where
% P=(x1,y1) and e=(x2,y2)-P.  With the cross product a x b = ax*by - ay*bx the
% solution of t*d = P + s*e is
%   t = (P x e)/(d x e)   and   s = (P x d)/(d x e).
% \moeptikz@t is set to t if t is larger than the value found so far.
\def\moeptikz@edge#1#2#3#4{%
	\pgf@xa=\dimexpr#3pt-#1pt\relax % e
	\pgf@ya=\dimexpr#4pt-#2pt\relax
	\pgf@xb=\dimexpr\moeptikz@dx*\number\pgf@ya/65536
		-\moeptikz@dy*\number\pgf@xa/65536\relax % d x e
	\pgf@yb=\dimexpr#1\pgf@ya-#2\pgf@xa\relax % P x e
	\pgf@xc=\dimexpr#1\moeptikz@dy-#2\moeptikz@dx\relax % P x d
	\ifdim\pgf@xb<0pt
		\pgf@xb=-\pgf@xb \pgf@yb=-\pgf@yb \pgf@xc=-\pgf@xc
	\fi
	% d x e = 0: the ray is parallel to the edge.  The tolerance of 0.1% for s
	% catches rays through a vertex despite rounding errors.  t < 16 excludes
	% garbage (the outlines lie within |x|,|y| < 2) and prevents an overflow.
	\ifdim\pgf@xb>0pt
	\ifdim\pgf@xc>-.001\pgf@xb
	\ifdim\pgf@xc<1.001\pgf@xb
	\ifdim\pgf@yb>0pt
	\ifdim\pgf@yb<16\pgf@xb
		\pgf@yb=\dimexpr 1pt*\number\pgf@yb/\number\pgf@xb\relax
		\ifdim\pgf@yb>\moeptikz@t \moeptikz@t=\pgf@yb \fi
	\fi\fi\fi\fi\fi
}

% \moeptikz@polyborder{<outline macros>}
% Border point for an outline made of one or more polygons (one macro each),
% used as \anchorborder code.
\def\moeptikz@polyborder#1{%
	\moeptikz@normalize
	\ifmoeptikz@direction
		\moeptikz@t=-1pt
		\moeptikz@polygons#1\moeptikz@stop
		% no intersection cannot happen for an outline around the center; to be
		% on the safe side use the bounding box then
		\ifdim\moeptikz@t<0pt \moeptikz@t=1pt \fi
		\moeptikz@borderpoint
	\else
		\pgf@x=0pt
		\pgf@y=0pt
	\fi
}
\def\moeptikz@polygons#1{%
	\ifx\moeptikz@stop#1%
	\else
		\expandafter\moeptikz@poly@first#1\moeptikz@stop\moeptikz@stop
		\expandafter\moeptikz@polygons
	\fi
}
\def\moeptikz@poly@first#1#2{%
	\def\moeptikz@x@first{#1}\def\moeptikz@y@first{#2}%
	\def\moeptikz@x@last{#1}\def\moeptikz@y@last{#2}%
	\moeptikz@poly@next
}
\def\moeptikz@poly@next#1#2{%
	\ifx\moeptikz@stop#1%
		% closing edge from the last to the first vertex
		\moeptikz@edge\moeptikz@x@last\moeptikz@y@last
			\moeptikz@x@first\moeptikz@y@first
	\else
		\moeptikz@edge\moeptikz@x@last\moeptikz@y@last{#1}{#2}%
		\def\moeptikz@x@last{#1}\def\moeptikz@y@last{#2}%
		\expandafter\moeptikz@poly@next
	\fi
}

% \moeptikz@capsule<macro>{x1}{y1}{x2}{y2}{r}
% Defines <macro> as the outline of a line from (x1,y1) to (x2,y2) drawn with
% round caps and line width 2r: a polygon with 10 vertices on the two cap
% circles.  Evaluated once when the package is loaded.
\def\moeptikz@capsule#1#2#3#4#5#6{%
	\pgfmathsetmacro\moeptikz@phi{atan2(#5-#3,#4-#2)}%
	\gdef#1{}%
	\moeptikz@capsule@arc#1{#4}{#5}{#6}{90,45,0,-45,-90}%
	\moeptikz@capsule@arc#1{#2}{#3}{#6}{-90,-135,-180,-225,-270}%
}
\def\moeptikz@capsule@arc#1#2#3#4#5{%
	\foreach \moeptikz@a in {#5} {%
		\pgfmathsetmacro\moeptikz@vx{#2+#4*cos(\moeptikz@phi+\moeptikz@a)}%
		\pgfmathsetmacro\moeptikz@vy{#3+#4*sin(\moeptikz@phi+\moeptikz@a)}%
		\xdef#1{#1{\moeptikz@vx}{\moeptikz@vy}}%
	}%
}

% \moeptikz@setthinlines
% Line width of the thin lines of hub, switch, router, client and messageopen:
% .4pt (the default of TikZ) at the default size of 1cm, scaled with the node
% size.  The shapes are symbols, their look depends on their size only and not
% on the line width of the picture (e.g. thick or line width=...).  Computed
% in scaled points (1cm = 1864679sp, .4pt = 26214sp), so that it is exactly
% .4pt at 1cm.
\def\moeptikz@setthinlines{%
	\pgfsetlinewidth{\dimexpr\moeptikz@size*26214/1864679\relax}%
}

% \moeptikz@unit: half the node size, the unit of the coordinates in the
% drawing code of fw and all shapes after it, which sets it before use
% (directly or with \moeptikz@setup).  \moeptikz@pt{x}{y} is the point (x,y)
% in this unit computed by TeX, so x and y must be numbers;
% \moeptikz@ptexpr{x}{y} computes it with pgfmath, so x and y may also be
% expressions such as -#4+.08.
\newdimen\moeptikz@unit
\def\moeptikz@pt#1#2{\pgfqpoint{#1\moeptikz@unit}{#2\moeptikz@unit}}
\def\moeptikz@ptexpr#1#2{%
	\pgfpoint{(#1)*\moeptikz@unit}{(#2)*\moeptikz@unit}}

% \moeptikz@setup{<factor>}
% Common start of the drawing code of fw, db, smartphone, user, modem,
% wlanmodem, key and keyhole: provides the shadings (\moeptikz@setshading),
% sets \moeptikz@unit to half the node size, the line width to <factor>
% times the node size and the stroke colour to black.
\def\moeptikz@setup#1{%
	\moeptikz@setshading
	\moeptikz@unit=.5\dimexpr\moeptikz@size\relax
	\pgfmathsetlength\pgf@xa{#1*\moeptikz@size}%
	\pgfsetlinewidth{\pgf@xa}%
	\pgfsetstrokecolor{black}%
}

% \moeptikz@fillstroke{<path>}
% Fills <path> and then strokes it, as two separate paths.  One
% \pgfusepath{fill,stroke} is the PDF operator B, which paints fill and stroke
% as one object: with transparency the stroke knocks out the fill under it, as
% the PDF specification prescribes (Ghostscript, MuPDF), while poppler-based
% viewers composite the two.  Two paths look the same in every viewer.
\def\moeptikz@fillstroke#1{%
	#1\pgfusepath{fill}%
	#1\pgfusepath{stroke}%
}

% \moeptikz@background<drawing code>
% Code of \backgroundpath.  PGF runs the background path without a scope and
% places the node text afterwards, so every transformation, colour or line width
% set while drawing the shape would also apply to the text (e.g. the hub's
% \pgftransformshift moved its text up).  The shapes draw everything
% themselves, hence the drawing code can safely run in its own scope.
%
% PGF inserts the node text without updating the bounding box of the picture,
% because normally the text lies inside the background path.  Here it lies
% below the shape, hence \moeptikz@textbbox adds it to the bounding box
% afterwards.
\def\moeptikz@background#1{%
	\pgfscope
	#1%
	\endpgfscope
	\moeptikz@textbbox
}

% \moeptikz@textbbox
% Adds the node text including inner sep (the area a label=below would cover)
% to the bounding box: every point of a path being constructed enlarges the
% bounding box, \pgfusepath{} then throws the path away without drawing it.
% Empty node texts are skipped, so that \node[router] {}; keeps its size.
\def\moeptikz@textbbox{%
	\ifdim\dimexpr\wd\pgfnodeparttextbox+\ht\pgfnodeparttextbox
			+\dp\pgfnodeparttextbox\relax>0pt
		\pgfscope
			% (macros, not registers: \pgfpathrectanglecorners uses the
			% scratch registers \pgf@xa, \pgf@xb, ... itself)
			\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/inner xsep}}%
			\edef\moeptikz@ixsep{\the\pgf@x}%
			\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/inner ysep}}%
			\edef\moeptikz@iysep{\the\pgf@x}%
			\pgf@sh@reanchor{\pgf@sm@shape@name}{text}%
			\edef\moeptikz@tx{\the\pgf@x}%
			\edef\moeptikz@ty{\the\pgf@y}%
			\pgfpathrectanglecorners
				{\pgfqpoint{\dimexpr\moeptikz@tx-\moeptikz@ixsep\relax}%
					{\dimexpr\moeptikz@ty-\dp\pgfnodeparttextbox
						-\moeptikz@iysep\relax}}%
				{\pgfqpoint{\dimexpr\moeptikz@tx+\wd\pgfnodeparttextbox
						+\moeptikz@ixsep\relax}%
					{\dimexpr\moeptikz@ty+\ht\pgfnodeparttextbox
						+\moeptikz@iysep\relax}}%
			\pgfusepath{}%
		\endpgfscope
	\fi
}

% \moeptikz@textanchor{<border code>}
% Code of the anchor `text': the node text is placed below the shape exactly
% where label=below would put a label, i.e. centered below the border point at
% 270 degrees and separated from it by outer ysep + inner ysep.  Hence
% \node[router] {A}; and \node[router,label=below:A] {}; look the same.
\def\moeptikz@textanchor#1{%
	\pgf@x=0pt
	\pgf@y=-1pt
	#1%
	\advance\pgf@x by -.5\dimexpr\moeptikz@textwd\relax
	\advance\pgf@y by -\moeptikz@ysep
	\advance\pgf@y by -\moeptikz@textht\relax
}



%==============================================================================
% server
%==============================================================================
% outline (see \moeptikz@polyborder)
\def\moeptikz@server@outline{%
	{.75}{.4}{-.75}{.4}{-.97}{-.18}{-.99}{-.18}%
	{-.99}{-.4}{.99}{-.4}{.99}{-.18}{.97}{-.18}%
}
% shading of the eject buttons (see the shadings at the beginning)
\pgfdeclareverticalshading[black,white]{moeptikz@servereject}{100bp}{%
	color(0bp)=(black); color(100bp)=(black!70)}
% The server is drawn in parts, so that the rack can reuse them.
\def\moeptikz@server@setup{
	\moeptikz@setshading
	\pgfmathparse{.004*\moeptikz@size}\let\moeptikz@lw\pgfmathresult
	\pgfmathparse{.005*\moeptikz@size}\let\moeptikz@arc\pgfmathresult
}
\def\moeptikz@server@front{
	% front
	\pgfpathrectanglecorners{\northeast \pgf@y=-.2\pgf@y}{\northeast \pgf@x=-\pgf@x \pgf@y=-.4\pgf@y}
	\pgfshadepath{moeptikz@shading}{-25}
	\pgfusepath{}

	\pgfpathmoveto{\northeast \pgf@y=-.2\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=-.2\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.99\pgf@x \pgf@y=-.18\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.99\pgf@x \pgf@y=-.18\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{-25}
	\pgfusepath{}
}
\def\moeptikz@server@lid{
	% lid
	\pgfpathmoveto{\northeast \pgf@x=.75\pgf@x \pgf@y=.4\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.97\pgf@x \pgf@y=-.18\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.97\pgf@x \pgf@y=-.18\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.75\pgf@x \pgf@y=.4\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{11.5}
	\pgfusepath{}
}
% \moeptikz@server@vlines{<x1>,<x2>,...}
% Vertical lines at the given x from height -.4 to -.28 (units of \northeast).
\def\moeptikz@server@vlines#1{%
	\pgfutil@for\moeptikz@x:=#1\do{%
		\pgfpathmoveto{\northeast \pgf@x=\moeptikz@x\pgf@x \pgf@y=-.4\pgf@y}%
		\pgfpathlineto{\northeast \pgf@x=\moeptikz@x\pgf@x \pgf@y=-.28\pgf@y}%
		\pgfusepath{stroke}%
	}%
}
% \moeptikz@server@slits{<xa1>/<xb1>,<xa2>/<xb2>,...}
% Filled slits from x=<xa> to x=<xb> and from height -.21 to -.26 (units of
% \northeast).
\def\moeptikz@server@slits#1{%
	\pgfutil@for\moeptikz@x:=#1\do{\expandafter\moeptikz@server@slit\moeptikz@x\relax}%
}
\def\moeptikz@server@slit#1/#2\relax{%
	\pgfpathrectanglecorners{\northeast \pgf@x=#1\pgf@x \pgf@y=-.21\pgf@y}%
		{\northeast \pgf@x=#2\pgf@x \pgf@y=-.26\pgf@y}%
	\pgfusepath{fill}%
}
% \moeptikz@server@leds{<y>}{<x1>,<x2>,...}
% LEDs (dots in the current fill colour) at height <y> and the given x (units
% of \northeast).
\def\moeptikz@server@leds#1#2{%
	\pgfutil@for\moeptikz@x:=#2\do{%
		\pgfpathcircle{\northeast \pgf@x=\moeptikz@x\pgf@x \pgf@y=#1\pgf@y}{.5\pgflinewidth}%
		\pgfusepath{fill}%
	}%
}
\def\moeptikz@server@details{
	% frame and dividers in the lower part of the front
	\pgfsetstrokecolor{black}
	\pgfsetlinewidth{1.5*\moeptikz@lw}
	\pgfsetcornersarced{\pgfpoint{\moeptikz@arc}{\moeptikz@arc}}
	\pgfpathmoveto{\northeast \pgf@x=-.9\pgf@x \pgf@y=-.4\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.9\pgf@x \pgf@y=-.28\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.9\pgf@x \pgf@y=-.28\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.9\pgf@x \pgf@y=-.4\pgf@y}
	\pgfusepath{stroke}
	\moeptikz@server@vlines{-.895,.895}
	\pgfsetlinewidth{2*\moeptikz@lw}
	\moeptikz@server@vlines{-.44,-.225,.225,.44}

	% optical drive
	\pgfsetfillcolor{black}
	\pgfpathrectanglecorners{\northeast \pgf@x=.9\pgf@x \pgf@y=-.22\pgf@y}{\northeast \pgf@x=.34\pgf@x \pgf@y=-.24\pgf@y}
	\pgfusepath{fill}

	% slits in the upper part of the front
	\moeptikz@server@slits{.3/.285,.26/.245,.22/.205,.18/.165,.14/.125,.10/.085,.06/.045}
	\moeptikz@server@slits{-.3/-.285,-.26/-.245,-.22/-.205,-.18/-.165,-.14/-.125,-.10/-.085,-.06/-.045}

	% LEDs
	\pgfsetfillcolor{cyan}
	\moeptikz@server@leds{-.22}{-.35,-.375,-.4,-.425,-.45}
	\pgfsetfillcolor{black}
	\moeptikz@server@leds{-.22}{-.475,-.5,-.525,-.55}
	\pgfsetfillcolor{cyan}
	\moeptikz@server@leds{-.24}{-.35,-.375,-.4,-.425}
	\pgfsetfillcolor{black}
	\moeptikz@server@leds{-.24}{-.45,-.475,-.5,-.525,-.55}
	% eject buttons (two dark panels between the dividers)
	\pgfsetcornersarced{\pgfpoint{0pt}{0pt}}
	\pgfpathrectanglecorners{\northeast \pgf@x=-.425\pgf@x \pgf@y=-.3925\pgf@y}{\northeast \pgf@x=-.24\pgf@x \pgf@y=-.2925\pgf@y}
	\pgfshadepath{moeptikz@servereject}{180}
	\pgfusepath{}

	\pgfpathrectanglecorners{\northeast \pgf@x=.425\pgf@x \pgf@y=-.3925\pgf@y}{\northeast \pgf@x=.24\pgf@x \pgf@y=-.2925\pgf@y}
	\pgfshadepath{moeptikz@servereject}{180}
	\pgfusepath{}
}
\def\moeptikz@server@draw{
	\moeptikz@server@setup
	\moeptikz@server@front
	\moeptikz@server@lid
	\moeptikz@server@details
}
\pgfdeclareshape{@server}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@server@outline}
	\backgroundpath{\moeptikz@background\moeptikz@server@draw}
	\moeptikz@savednortheast
}

\moeptikz@declarestyle{server}{black}


%==============================================================================
% client
%==============================================================================
% outline (see \moeptikz@polyborder)
\def\moeptikz@client@outline{%
	{1}{.79}{-1}{.79}{-1}{-.5}{-.25}{-.5}{-.25}{-.79}%
	{-.4}{-1}{.1}{-1}{.25}{-.79}{.25}{-.5}{1.02}{-.5}%
}
\def\moeptikz@client@draw{
	\moeptikz@setshading
	\moeptikz@setthinlines
	\pgfmathparse{.01*\moeptikz@size}\let\moeptikz@lwlarge\pgfmathresult
	\pgfmathparse{.01*\moeptikz@size}\let\moeptikz@arc\pgfmathresult
	\pgfsetcornersarced{\pgfpoint{\moeptikz@arc}{\moeptikz@arc}}

	\pgfsetstrokecolor{black!40}
	\pgfpathmoveto{\southwest \pgf@x=.98\pgf@x \pgf@y=.50\pgf@y}
	\pgfpathlineto{\southwest \pgf@y=.48\pgf@y}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@y=.73\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.98\pgf@x \pgf@y=.75\pgf@y}
	\pgfusepath{stroke}

	\pgfsetlinewidth{\moeptikz@lwlarge}
	% stand
	\pgfpathmoveto{\southwest \pgf@x=.25\pgf@x \pgf@y=0\pgf@y}
	\pgfpathlineto{\southwest \pgf@x=-.25\pgf@x \pgf@y=0\pgf@y}
	\pgfpathlineto{\southwest \pgf@x=-.25\pgf@x \pgf@y=.75\pgf@y}
	\pgfpathlineto{\southwest \pgf@x=-.10\pgf@x}
	\pgfpathlineto{\southwest \pgf@x=.40\pgf@x}
	\pgfpathlineto{\southwest \pgf@x=.25\pgf@x \pgf@y=.75\pgf@y}
	\pgfpathlineto{\southwest \pgf@x=.25\pgf@x \pgf@y=.55\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{-33}
	\pgfusepath{stroke}

	\pgfsetlinewidth{\dimexpr\moeptikz@size*65536/1864679\relax} % 1pt at 1cm, scaled with the size
	% 3D display frame (stroked in the fill colour: rim of half the line width)
	\pgfsetfillcolor{black!40}
	\moeptikz@fillstroke{\pgfpathrectanglecorners
		{\southwest \pgf@x=.99\pgf@x \pgf@y=.47\pgf@y}{\northeast \pgf@y=.77\pgf@y}}

	% black outer monitor frame (likewise stroked in the fill colour)
	\pgfsetstrokecolor{black}
	\pgfsetfillcolor{black}
	\moeptikz@fillstroke{\pgfpathrectanglecorners
		{\southwest \pgf@y=.48\pgf@y}{\northeast \pgf@x=.98\pgf@x \pgf@y=.75\pgf@y}}

	% display area
	\pgfsetfillcolor{black!90}
	\moeptikz@fillstroke{\pgfpathrectanglecorners{\southwest \pgf@x=.95\pgf@x \pgf@y=.43\pgf@y}{\northeast \pgf@x=.93\pgf@x \pgf@y=.70\pgf@y}}

	\pgfpathrectanglecorners{\southwest \pgf@x=.95\pgf@x \pgf@y=.43\pgf@y}{\northeast \pgf@x=.93\pgf@x \pgf@y=.70\pgf@y}
	\pgfshadepath{moeptikz@shadingnuc}{180}
	\pgfusepath{}
}
\pgfdeclareshape{@client}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@client@outline}
	\backgroundpath{\moeptikz@background\moeptikz@client@draw}
	\moeptikz@savednortheast
	\moeptikz@savedsouthwest
}

\moeptikz@declarestyle{client}{black}


%==============================================================================
% notebook
%==============================================================================
\def\moeptikz@nb@vx{10}
\def\moeptikz@nb@vy{15}
\def\moeptikz@nb@vz{-10}
% \moeptikz@nb@factors{x}{y}{z}
% Central projection of the point (x,y,z) from the eye point (vx,vy,vz) =
% (\moeptikz@nb@vx,\moeptikz@nb@vy,\moeptikz@nb@vz), which looks along the z
% axis (image plane z = vz+1, origin in front of the eye): sets
% \moeptikz@nb@fx to (x-vx)/(z-vz) and \moeptikz@nb@fy to (y-vy)/(z-vz).
\def\moeptikz@nb@factors#1#2#3{%
	\pgfmathparse{(#1-\moeptikz@nb@vx)/(#3-\moeptikz@nb@vz)}%
	\let\moeptikz@nb@fx\pgfmathresult
	\pgfmathparse{(#2-\moeptikz@nb@vy)/(#3-\moeptikz@nb@vz)}%
	\let\moeptikz@nb@fy\pgfmathresult
}
% \moeptikz@transform{x}{y}{z}
% Multiplies \pgf@x and \pgf@y, which hold the unit on entry, by the factors
% of the projection of the point (x,y,z).
\newcommand{\moeptikz@transform}[3]{%
	\moeptikz@nb@factors{#1}{#2}{#3}%
	\pgf@x=\moeptikz@nb@fx\pgf@x
	\pgf@y=\moeptikz@nb@fy\pgf@y
}

% \moeptikz@point{x}{y}{z}: the projected point in units of half the node size
% (\northeast), for the drawing code of the notebook
\newcommand\moeptikz@point[3]{%
	\northeast
	\moeptikz@transform{#1}{#2}{#3}
}

% The notebook is drawn in a perspective projection (see \moeptikz@transform),
% shifted by (\moeptikz@nb@shiftx,\moeptikz@nb@shifty) and then scaled by 10,
% as in \moeptikz@notebook@draw.  Its outline consists of the projected
% corners of screen and keyboard, computed once when the package is loaded.
\pgfmathparse{-\moeptikz@nb@vx/\moeptikz@nb@vz-1/(\moeptikz@nb@vx*\moeptikz@nb@vz)}
\let\moeptikz@nb@shiftx\pgfmathresult
\pgfmathparse{-\moeptikz@nb@vy/\moeptikz@nb@vz}
\let\moeptikz@nb@shifty\pgfmathresult
\def\moeptikz@notebook@outline{}
\def\moeptikz@nb@vertex#1#2#3{%
	\pgf@x=1pt
	\pgf@y=1pt
	\moeptikz@transform{#1}{#2}{#3}%
	\pgf@x=10\dimexpr\pgf@x+\moeptikz@nb@shiftx pt\relax
	\pgf@y=10\dimexpr\pgf@y+\moeptikz@nb@shifty pt\relax
	\edef\moeptikz@notebook@outline{\moeptikz@notebook@outline
		{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}}%
}
\moeptikz@nb@vertex{-1.0}{1.1}{-.1}
\moeptikz@nb@vertex{-1.0}{0}{-.1}
\moeptikz@nb@vertex{-1.0}{0}{-.5}
\moeptikz@nb@vertex{1.0}{0}{-.5}
\moeptikz@nb@vertex{1.0}{0}{-.1}
\moeptikz@nb@vertex{1.0}{1.1}{-.1}

% The keys of the keyboard, 14 in the top row and 14 x 5 below.  Their corners
% do not depend on the node, so \moeptikz@notebook@keys holds them, one
% \moeptikz@nb@key{fx1}{fy1}{fx2}{fy2}{fx3}{fy3}{fx4}{fy4} per key with the
% projection factors of its four corners.  The first notebook of the document
% computes the list (documents without notebooks do not pay for it), with the
% same pgfmath expressions as the drawing code did before for every notebook,
% hence with the same numbers.
\def\moeptikz@notebook@keys{%
	\moeptikz@nb@computekeys
	\moeptikz@notebook@keys
}
\def\moeptikz@nb@computekeys{%
	\gdef\moeptikz@notebook@keys{}%
	\foreach \x in {1,2,...,14} {%
		\pgfmathparse{-1.025+\x*0.13}\let\moeptikz@xa\pgfmathresult
		\pgfmathparse{-1.025+\x*0.13+.1}\let\moeptikz@xb\pgfmathresult
		\moeptikz@nb@addkey{\moeptikz@xa}{-.12}{\moeptikz@xb}{-.12}%
			{\moeptikz@xb}{-.14}{\moeptikz@xa}{-.14}%
	}%
	\foreach \x in {1,2,...,14} {%
		\foreach \z in {0,1,...,4} {%
			\pgfmathparse{-1.025+\x*0.13}\let\moeptikz@xa\pgfmathresult
			\pgfmathparse{-1.025+\x*0.13+0.1}\let\moeptikz@xb\pgfmathresult
			\pgfmathparse{-.15-\z*0.035}\let\moeptikz@za\pgfmathresult
			\pgfmathparse{-.15-\z*0.035-0.025}\let\moeptikz@zb\pgfmathresult
			\moeptikz@nb@addkey{\moeptikz@xa}{\moeptikz@za}%
				{\moeptikz@xb}{\moeptikz@za}{\moeptikz@xb}{\moeptikz@zb}%
				{\moeptikz@xa}{\moeptikz@zb}%
		}%
	}%
}
% \moeptikz@nb@addkey{x1}{z1}{x2}{z2}{x3}{z3}{x4}{z4}
% Appends the key with the corners (x1,0,z1), ..., (x4,0,z4) to
% \moeptikz@notebook@keys.
\def\moeptikz@nb@addkey#1#2#3#4#5#6#7#8{%
	\moeptikz@nb@factors{#1}{0}{#2}%
	\edef\moeptikz@tmp{{\moeptikz@nb@fx}{\moeptikz@nb@fy}}%
	\moeptikz@nb@factors{#3}{0}{#4}%
	\edef\moeptikz@tmp{\moeptikz@tmp{\moeptikz@nb@fx}{\moeptikz@nb@fy}}%
	\moeptikz@nb@factors{#5}{0}{#6}%
	\edef\moeptikz@tmp{\moeptikz@tmp{\moeptikz@nb@fx}{\moeptikz@nb@fy}}%
	\moeptikz@nb@factors{#7}{0}{#8}%
	\edef\moeptikz@tmp{\noexpand\moeptikz@nb@key
		\moeptikz@tmp{\moeptikz@nb@fx}{\moeptikz@nb@fy}}%
	\expandafter\pgfutil@g@addto@macro\expandafter\moeptikz@notebook@keys
		\expandafter{\moeptikz@tmp}%
}
% \moeptikz@nb@drawkeys
% Fills the keys.  PGF rounds their corners (\pgfsetcornersarced) when it uses
% a path, with trigonometry for each of the 336 corners; that is most of the
% time a notebook takes.  As long as the node size and the linear part of the
% transformation (rotation, scaling) stay the same, the rounded keys of two
% notebooks differ only by the translation of the transformation (\pgf@pt@x,
% \pgf@pt@y): PGF computes the rounding from differences of points, and TeX
% adds and subtracts dimensions exactly.  Hence \moeptikz@nb@cache keeps the
% rounded keys of the last notebook relative to its translation, and the next
% notebook with the same \moeptikz@nb@cachekey only moves them.  The cache
% holds one notebook only, so it takes a fixed amount of memory.
\def\moeptikz@nb@cachekey{}
\def\moeptikz@nb@cache{}
\def\moeptikz@nb@drawkeys{%
	\edef\moeptikz@tmp{%
		\moeptikz@size,\pgf@pt@aa,\pgf@pt@ab,\pgf@pt@ba,\pgf@pt@bb}%
	\ifx\moeptikz@tmp\moeptikz@nb@cachekey
		\moeptikz@nb@cache
	\else
		\global\let\moeptikz@nb@cachekey\moeptikz@tmp
		\gdef\moeptikz@nb@cache{}%
		\moeptikz@notebook@keys
	\fi
}
% \moeptikz@nb@key{fx1}{fy1}...{fx4}{fy4}
% Fills the key with these factors, rounded by PGF, and appends the rounded
% path, relative to the translation, to \moeptikz@nb@cache.
\def\moeptikz@nb@key#1#2#3#4#5#6#7#8{%
	\pgfpathmoveto{\northeast\pgf@x=#1\pgf@x\pgf@y=#2\pgf@y}%
	\pgfpathlineto{\northeast\pgf@x=#3\pgf@x\pgf@y=#4\pgf@y}%
	\pgfpathlineto{\northeast\pgf@x=#5\pgf@x\pgf@y=#6\pgf@y}%
	\pgfpathlineto{\northeast\pgf@x=#7\pgf@x\pgf@y=#8\pgf@y}%
	\pgfpathclose
	% round here (\pgfusepath would do it) to keep the rounded path
	\pgfsyssoftpath@getcurrentpath\moeptikz@path
	\pgfprocessround\moeptikz@path\moeptikz@path
	\pgfsyssoftpath@setcurrentpath\moeptikz@path
	\pgfusepath{fill}%
	\moeptikz@nb@move-%
	\xdef\moeptikz@nb@cache{\unexpanded\expandafter{\moeptikz@nb@cache}%
		\noexpand\moeptikz@nb@cachedkey
			{\unexpanded\expandafter{\moeptikz@moved}}}%
}
% \moeptikz@nb@cachedkey{<rounded path relative to the translation>}
\def\moeptikz@nb@cachedkey#1{%
	\def\moeptikz@path{#1}%
	\moeptikz@nb@move+%
	\pgfsyssoftpath@setcurrentpath\moeptikz@moved
	\pgfusepath{fill}%
}
% \moeptikz@nb@move<sign>
% \moeptikz@moved = the soft path \moeptikz@path, a list of <token>{<x>}{<y>}
% with points only (no rectangles), with every point moved by
% <sign>(\pgf@pt@x,\pgf@pt@y).
\def\moeptikz@nb@move#1{%
	\let\moeptikz@moved\pgfutil@empty
	\def\moeptikz@sign{#1}%
	\expandafter\moeptikz@nb@movepoint\moeptikz@path\moeptikz@stop{}{}%
}
\def\moeptikz@nb@movepoint#1#2#3{%
	\ifx#1\moeptikz@stop\else
		\edef\moeptikz@moved{\unexpanded\expandafter{\moeptikz@moved}%
			\noexpand#1{\the\dimexpr#2\moeptikz@sign\pgf@pt@x\relax}%
			{\the\dimexpr#3\moeptikz@sign\pgf@pt@y\relax}}%
		\expandafter\moeptikz@nb@movepoint
	\fi
}

\def\moeptikz@notebook@draw{
	\moeptikz@setshading
	\pgfmathparse{.0025*\moeptikz@size}\let\moeptikz@lw\pgfmathresult
	\pgfmathparse{.01*\moeptikz@size}\let\moeptikz@arc\pgfmathresult
	\pgfmathparse{.004*\moeptikz@size}\let\moeptikz@arcsmall\pgfmathresult

	\pgfsetcornersarced{\pgfpoint{\moeptikz@arc}{\moeptikz@arc}}
	\pgfsetlinewidth{\moeptikz@lw}

	\pgftransformscale{10}
	\pgftransformshift{\northeast \pgfpoint{\moeptikz@nb@shiftx\pgf@x}{\moeptikz@nb@shifty\pgf@y}}

	% front edge (simulated by a surface underneath the keyboard)
	\pgfsetfillcolor{black!40}
	\pgfpathmoveto{\moeptikz@point{-1.0}{-.05}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.01}{-.05}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.01}{-.01}{-.5}}
	\pgfpathlineto{\moeptikz@point{-1.0}{-.01}{-.5}}
	\pgfpathclose
	\pgfusepath{fill}

	% right edge
	\pgfpathmoveto{\moeptikz@point{1.01}{-0.01}{-.5}}
	\pgfpathlineto{\moeptikz@point{1.01}{-.05}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.0}{0}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.0}{0}{-.5}}
	\pgfpathclose
	\pgfusepath{fill}

	% keyboard surface
	\pgfsetstrokecolor{black!30}
	\pgfpathmoveto{\moeptikz@point{-1.0}{0}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.0}{0}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.0}{0}{-.5}}
	\pgfpathlineto{\moeptikz@point{-1.0}{0}{-.5}}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{180}
	\pgfusepath{stroke}

	% 3D effect of the screen (grey strip on the right)
	\pgfpathmoveto{\moeptikz@point{-1.0}{0}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.005}{0}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.005}{1.1}{-.1}}
	\pgfpathlineto{\moeptikz@point{-1.0}{1.1}{-.1}}
	\pgfpathclose
	\pgfusepath{fill}

	% black screen frame
	\pgfsetfillcolor{black}
	\pgfpathmoveto{\moeptikz@point{-1.0}{0}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.0}{0}{-.1}}
	\pgfpathlineto{\moeptikz@point{1.0}{1.1}{-.1}}
	\pgfpathlineto{\moeptikz@point{-1.0}{1.1}{-.1}}
	\pgfpathclose
	\pgfusepath{fill}

	% display area
	\pgfpathmoveto{\moeptikz@point{-.95}{0.055}{-.1}}
	\pgfpathlineto{\moeptikz@point{.95}{0.055}{-.1}}
	\pgfpathlineto{\moeptikz@point{.95}{1.045}{-.1}}
	\pgfpathlineto{\moeptikz@point{-.95}{1.045}{-.1}}
	\pgfpathclose
	\pgfshadepath{moeptikz@shadingnuc}{180}
	\pgfusepath{}

	% trackpad (stroked in the fill colour: rim of half the line width)
	\pgfsetfillcolor{black!30}
	\moeptikz@fillstroke{%
		\pgfpathmoveto{\moeptikz@point{-.4}{0}{-.33}}%
		\pgfpathlineto{\moeptikz@point{.4}{0}{-.33}}%
		\pgfpathlineto{\moeptikz@point{.4}{0}{-.49}}%
		\pgfpathlineto{\moeptikz@point{-.4}{0}{-.49}}%
		\pgfpathclose}

	% keys
	\pgfsetcornersarced{\pgfpoint{\moeptikz@arcsmall}{\moeptikz@arcsmall}}
	\pgfsetfillcolor{black}
	\moeptikz@nb@drawkeys
}
\pgfdeclareshape{@notebook}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@notebook@outline}
	\backgroundpath{\moeptikz@background\moeptikz@notebook@draw}
	\moeptikz@savednortheast
}

\moeptikz@declarestyle{notebook}{black}


%==============================================================================
% hub
%==============================================================================
% outline (see \moeptikz@polyborder)
\def\moeptikz@hub@outline{%
	{0}{.95}{-1}{.15}{-1}{-.15}{0}{-.95}{1}{-.15}{1}{.15}%
}
\def\moeptikz@hub@draw{
	\moeptikz@setshading
	\moeptikz@savestrokecolor
	\pgfsetstrokecolor{black}
	\moeptikz@setthinlines
	% sharp corners, also under rounded corners on the node or picture;
	% 0.01pt, not 0pt: tiny arcs instead of miter joins, hence no spikes
	\pgfsetcornersarced{\pgfpoint{0.01pt}{0.01pt}}

	\pgfpathmoveto{\northeast \pgf@y=.95\pgf@y \pgf@x=0pt}
	\pgfpathlineto{\northeast \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.6\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=.15\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@x=-\pgf@x \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=-.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.95\pgf@y}
	\pgfpathlineto{\northeast \pgf@y=-.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.6\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@x=0pt \pgf@y=-.6\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.95\pgf@y}
	\pgfusepath{stroke}

	\moeptikz@fillwithstrokecolor
	\pgftransformshift{\northeast \pgf@x=0pt \pgf@y=.15\pgf@y}
	\pgftransformxslant{1.33}
	\pgftransformyslant{-0.375}
	\pgftransformyscale{.9}
	\pgfpathmoveto{\northeast \pgf@x=-.75\pgf@x \pgf@y=.075\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.75\pgf@x \pgf@y=-.075\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.15\pgf@x \pgf@y=-.075\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.15\pgf@x \pgf@y=-.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.75\pgf@x \pgf@y=0pt}
	\pgfpathlineto{\northeast \pgf@x=.15\pgf@x \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.15\pgf@x \pgf@y=.075\pgf@y}
	\pgfpathclose
	\pgfusepath{fill}
}
\pgfdeclareshape{@hub}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@hub@outline}
	\backgroundpath{\moeptikz@background\moeptikz@hub@draw}
	\moeptikz@savednortheast
}

\moeptikz@declarestyle{hub}{black}


%==============================================================================
% switch
%==============================================================================
% The switch is drawn in two parts, so that mlswitch can reuse the body.
\def\moeptikz@switch@body{
	\moeptikz@setshading
	\moeptikz@savestrokecolor
	\pgfsetstrokecolor{black}
	\moeptikz@setthinlines
	% sharp corners, also under rounded corners on the node or picture;
	% 0.01pt, not 0pt: tiny arcs instead of miter joins, hence no spikes
	\pgfsetcornersarced{\pgfpoint{0.01pt}{0.01pt}}

	\pgfpathmoveto{\northeast \pgf@x=0pt \pgf@y=.95\pgf@y}
	\pgfpathlineto{\northeast \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.6\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=.15\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@y=-.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.6\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=-.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.95\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@x=0pt \pgf@y=-.6\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.95\pgf@y}
	\pgfusepath{stroke}
}
% \moeptikz@switch@arrowpair{<x>}{<y>}
% Two arrows in the plane of the lid, the lower one to the right and the
% upper one to the left, scaled by .45 and shifted by (<x>,<y>) (units of
% \northeast).  The braces keep the transformations local to the pair.
\def\moeptikz@switch@arrowpair#1#2{
	{
		\pgftransformshift{\northeast \pgf@x=#1\pgf@x \pgf@y=#2\pgf@y}
		\pgftransformscale{.45}
		\pgftransformyscale{.9}
		\pgfpathmoveto{\northeast \pgf@x=-.75\pgf@x \pgf@y=.075\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=-.75\pgf@x \pgf@y=-.075\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=.25\pgf@x \pgf@y=-.075\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=.25\pgf@x \pgf@y=-.15\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=.75\pgf@x \pgf@y=0pt}
		\pgfpathlineto{\northeast \pgf@x=.25\pgf@x \pgf@y=.15\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=.25\pgf@x \pgf@y=.075\pgf@y}
		\pgfpathclose
		\pgfusepath{fill}

		\pgfpathmoveto{\northeast \pgf@x=.75\pgf@x \pgf@y=0.20\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=-.25\pgf@x \pgf@y=0.20\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=-.25\pgf@x \pgf@y=0.125\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=-.75\pgf@x \pgf@y=0.275\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=-.25\pgf@x \pgf@y=0.425\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=-.25\pgf@x \pgf@y=0.35\pgf@y}
		\pgfpathlineto{\northeast \pgf@x=.75\pgf@x \pgf@y=0.35\pgf@y}
		\pgfpathclose
		\pgfusepath{fill}
	}
}
\def\moeptikz@switch@arrows{
	\moeptikz@fillwithstrokecolor
	\pgftransformshift{\northeast \pgf@x=0pt \pgf@y=.15\pgf@y}
	\pgftransformxslant{1.33}
	\pgftransformyslant{-0.375}
	\moeptikz@switch@arrowpair{.45}{.1}
	\moeptikz@switch@arrowpair{-.45}{.1}
	\moeptikz@switch@arrowpair{.45}{-.2}
	\moeptikz@switch@arrowpair{-.45}{-.2}
}
\def\moeptikz@switch@draw{
	\moeptikz@switch@body
	\moeptikz@switch@arrows
}
% Size, anchors and border are those of the hub, which has the same outline.
\pgfdeclareshape{@switch}{
	\moeptikz@inheritanchors{@hub}
	\backgroundpath{\moeptikz@background\moeptikz@switch@draw}
}

\moeptikz@declarestyle{switch}{black}

%==============================================================================
% router
%==============================================================================
% The router outline consists of two half ellipses with center (0,+-c), c=.15,
% and radii rx=1 and ry=.75 (in units of half the node size), joined by the
% vertical lines x=+-1, |y|<=c.  For the ray t*(dx,dy) with a=|dy|, b=|dx|
% and max(a,b)=1 the border point is
%   on a vertical line  if a <= c*b:  t = 1
%   on an ellipse       otherwise:    (t*b)^2 + (t*a-c)^2/ry^2 = 1, i.e.
%     t = (a*c + sqrt(a^2*c^2 + (ry^2-c^2)*A))/A   with   A = ry^2*b^2 + a^2
\def\moeptikz@router@anchorborder{%
	\moeptikz@normalize
	\ifmoeptikz@direction
		\pgf@xa=\ifdim\moeptikz@dx<0pt -\fi\moeptikz@dx % b
		\pgf@ya=\ifdim\moeptikz@dy<0pt -\fi\moeptikz@dy % a
		\ifdim\pgf@ya>.15\pgf@xa
			\pgf@xb=\dimexpr.5625\dimexpr\pgf@xa*\number\pgf@xa/65536\relax
				+\pgf@ya*\number\pgf@ya/65536\relax % A
			\pgf@yb=\dimexpr.0225\dimexpr\pgf@ya*\number\pgf@ya/65536\relax
				+.54\pgf@xb\relax
			\edef\moeptikz@tmp{\pgf@sys@tonumber\pgf@yb}%
			\pgfmathsqrt@{\moeptikz@tmp}%
			\pgf@yb=\dimexpr.15\pgf@ya+\pgfmathresult pt\relax
			\moeptikz@t=\dimexpr 1pt*\number\pgf@yb/\number\pgf@xb\relax
		\else
			\moeptikz@t=1pt
		\fi
		\moeptikz@borderpoint
	\else
		\pgf@x=0pt
		\pgf@y=0pt
	\fi
}
% The router is drawn in parts, so that fwrouter can reuse them.
\def\moeptikz@router@setup{
	\moeptikz@setshading
	\moeptikz@savestrokecolor
	\pgfsetstrokecolor{black}
	\moeptikz@setthinlines
	% sharp corners, also under rounded corners on the node or picture;
	% 0.01pt, not 0pt: tiny arcs instead of miter joins, hence no spikes
	\pgfsetcornersarced{\pgfpoint{0.01pt}{0.01pt}}

	\pgfmathparse{1/2*\moeptikz@size}\let\moeptikz@rx\pgfmathresult
	\pgfmathparse{3/8*\moeptikz@size}\let\moeptikz@ry\pgfmathresult
}
\def\moeptikz@router@body{
	% router body
	\pgfpathmoveto{\northeast \pgf@x=-\pgf@x \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=-.15\pgf@y}
	\pgfpatharcaxes{180}{360}{\pgfpoint{\moeptikz@rx}{0pt}}{\pgfpoint{0pt}{\moeptikz@ry}}
	\pgfpathlineto{\northeast \pgf@y=.15\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}
	\pgfusepath{stroke}
}
% path of the top ellipse, centre (0,.15), radii 1 and .75
\def\moeptikz@router@topellipse{
	\pgfpathellipse{\northeast \pgf@x=0pt \pgf@y=.15\pgf@y}
		{\northeast \pgf@y=0pt}
		{\northeast \pgf@x=0pt \pgf@y=-.75\pgf@y}
}
\def\moeptikz@router@top{
	\moeptikz@router@topellipse
	\pgfshadepath{moeptikz@shading}{0}
	\pgfusepath{stroke}
}
% \moeptikz@router@arrow{<along>}{<across>}
% Double-headed arrow from -1 to 1 through the centre (units of \northeast);
% <along> and <across> are the registers of the coordinates along and across
% it: {\pgf@x}{\pgf@y} is horizontal, {\pgf@y}{\pgf@x} turned by 90 degrees.
\def\moeptikz@router@arrow#1#2{
	\pgfpathmoveto{\northeast #1=-#1 #2=0pt}
	\pgfpathlineto{\northeast #1=-.5#1 #2=-.15#2}
	\pgfpathlineto{\northeast #1=-.5#1 #2=-.05#2}
	\pgfpathlineto{\northeast #1=.5#1 #2=-.05#2}
	\pgfpathlineto{\northeast #1=.5#1 #2=-.15#2}
	\pgfpathlineto{\northeast #1=#1 #2=0pt}
	\pgfpathlineto{\northeast #1=.5#1 #2=.15#2}
	\pgfpathlineto{\northeast #1=.5#1 #2=.05#2}
	\pgfpathlineto{\northeast #1=-.5#1 #2=.05#2}
	\pgfpathlineto{\northeast #1=-.5#1 #2=.15#2}
	\pgfpathclose
	\pgfusepath{fill}
}
\def\moeptikz@router@arrows{
	\moeptikz@fillwithstrokecolor
	\pgftransformshift{\northeast \pgf@x=0pt \pgf@y=.15\pgf@y}
	\pgftransformxslant{1.33}
	\pgftransformyslant{-0.375}
	{
		\pgftransformyscale{.8}
		\pgftransformxscale{1.3}
		\moeptikz@router@arrow{\pgf@x}{\pgf@y}
	}
	{
		\pgftransformyscale{0.5}
		\pgftransformxscale{2.2}
		\moeptikz@router@arrow{\pgf@y}{\pgf@x}
	}
}
\def\moeptikz@router@draw{
	\moeptikz@router@setup
	\moeptikz@router@body
	\moeptikz@router@top
	\moeptikz@router@arrows
}
\pgfdeclareshape{@router}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@router@anchorborder}
	\backgroundpath{\moeptikz@background\moeptikz@router@draw}
	\moeptikz@savednortheast
}

% the draw colour sets the colour of the arrows
\moeptikz@declarestyle{router}{black}
\tikzset{router/.append style={draw=black}}



%==============================================================================
% nuc
%==============================================================================
% outline (see \moeptikz@polyborder)
\def\moeptikz@nuc@outline{%
	{0}{1}{1}{.25}{1}{-.25}{0}{-1}{-1}{-.25}{-1}{.25}%
}
% antennas: the long parts of the three thick lines drawn in
% \moeptikz@nuc@draw (line width .075*size, i.e. radius .075 in units of
% half the size)
\moeptikz@capsule\moeptikz@nuc@rearantenna{-.2}{.7}{-.4}{1.5}{.075}
\moeptikz@capsule\moeptikz@nuc@leftantenna{-.6}{-.5}{-.8}{.7}{.075}
\moeptikz@capsule\moeptikz@nuc@rightantenna{.6}{-.5}{.8}{.7}{.075}
% The rays at 45 and 135 degrees just touch the caps of the front antennas, so
% north east and north west are the antenna tips; a change of the antennas can
% move these two anchors onto the lid.
\def\moeptikz@nuc@anchorborder{%
	\moeptikz@polyborder{\moeptikz@nuc@outline
		\moeptikz@nuc@rearantenna\moeptikz@nuc@leftantenna
		\moeptikz@nuc@rightantenna}}
\def\moeptikz@nuc@draw{
	\moeptikz@setshading
	\pgfsetstrokecolor{black}
	\pgfsetcornersarced{\pgfpoint{1pt}{1pt}}

	% rear antenna
	\pgfmathparse{.075*\moeptikz@size}
	\pgfsetlinewidth\pgfmathresult
	\pgfsetroundcap

	\pgfpathmoveto{\northeast \pgf@x=-.1\pgf@x \pgf@y=.6\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.2\pgf@x \pgf@y=.7\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.4\pgf@x \pgf@y=1.5\pgf@y}
	\pgfusepath{stroke}

	% body
	\pgfmathparse{.025*\moeptikz@size}
	\pgfsetlinewidth\pgfmathresult

	\pgfpathmoveto{\northeast \pgf@x=0pt}
	\pgfpathlineto{\northeast \pgf@y=.25\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.5\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=.25\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shadingnuc}{0}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@x=-\pgf@x \pgf@y=-.25\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=.25\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-.5\pgf@y}
	\pgfpathlineto{\northeast \pgf@y=.25\pgf@y}
	\pgfpathlineto{\northeast \pgf@y=-.25\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-\pgf@y}
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@x=0pt \pgf@y=-.5\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=0pt \pgf@y=-\pgf@y}
	\pgfusepath{stroke}

	% front antennas
	\pgfmathparse{.075*\moeptikz@size}
	\pgfsetlinewidth\pgfmathresult

	\pgfpathmoveto{\northeast \pgf@x=-.5\pgf@x \pgf@y=-.4\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.6\pgf@x \pgf@y=-.5\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-.8\pgf@x \pgf@y=.7\pgf@y}
	\pgfusepath{stroke}

	\pgfpathmoveto{\northeast \pgf@x=.5\pgf@x \pgf@y=-.4\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.6\pgf@x \pgf@y=-.5\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=.8\pgf@x \pgf@y=.7\pgf@y}
	\pgfusepath{stroke}

	% LED (its radius is .15 times the line width of the antennas)
	\pgfsetfillcolor{cyan}
	\pgfpathcircle{\northeast \pgf@x=.05\pgf@x \pgf@y=.7\pgf@y}{.15\pgflinewidth}
	\pgfusepath{fill}
}
\pgfdeclareshape{@nuc}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@nuc@anchorborder}
	\backgroundpath{\moeptikz@background\moeptikz@nuc@draw}
	\moeptikz@savednortheast
}

\moeptikz@declarestyle{nuc}{black}
% ap is an alias for nuc; like nuc it takes no value
\tikzset{ap/.style={nuc}}
\moeptikz@novalue{ap}


%==============================================================================
% messageopen
%==============================================================================
% Fallback colours of messageopen and messageclosed: the envelope is filled
% with moeptikz@envelope if the node has no fill colour and drawn with
% moeptikz@envelopeline if it has no draw colour, e.g. after color=red.
% Defined with xcolor, so that they follow its colour model (e.g. its option
% gray).
\definecolor{moeptikz@envelope}{rgb}{0.91,0.82,0.67}
\definecolor{moeptikz@envelopeline}{rgb}{0.84,0.58,0.47}
% \moeptikz@message@fill, \moeptikz@message@stroke: set the fill and the
% stroke colour of the envelope (the node's colours or these fallback colours)
\def\moeptikz@message@fill{%
	\ifx\tikz@fillcolor\pgfutil@empty
		\pgfsetfillcolor{moeptikz@envelope}%
	\else
		\pgfsetfillcolor{\tikz@fillcolor}%
	\fi
}
\def\moeptikz@message@stroke{%
	\ifx\tikz@strokecolor\pgfutil@empty
		\pgfsetstrokecolor{moeptikz@envelopeline}%
	\else
		\pgfsetstrokecolor{\tikz@strokecolor}%
	\fi
}

% outline (see \moeptikz@polyborder)
\def\moeptikz@messageopen@outline{%
	{0}{1}{.27}{.8}{.8}{.8}{.8}{.44}{1}{.25}{1}{-1}%
	{-1}{-1}{-1}{.25}{-.8}{.44}{-.8}{.8}{-.27}{.8}%
}
\tikzset{paper color/.initial={black}}
% shading of the paper in the colour moeptikz@paper (see the shadings at the
% beginning)
\pgfdeclarehorizontalshading[moeptikz@paper,white]{moeptikz@paper}{100bp}{%
	color(0bp)=(white); color(100bp)=(moeptikz@paper!30)}
% the outer edge of the envelope (pentagon), filled and stroked separately
\def\moeptikz@messageopen@envelope{%
	\pgfpathmoveto{\northeast \pgf@x=0\pgf@x}%
	\pgfpathlineto{\northeast \pgf@y=.25\pgf@y}%
	\pgfpathlineto{\northeast \pgf@y=-\pgf@y}%
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y}%
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=.25\pgf@y}%
	\pgfpathclose
}
\def\moeptikz@messageopen@draw{
	\pgfkeys{/tikz/paper color/.get=\moeptikz@papercolor}
	\moeptikz@setthinlines

	\pgfmathparse{.2*sqrt(\moeptikz@size)}\let\moeptikz@arc\pgfmathresult
	\pgfsetcornersarced{\pgfpoint{\moeptikz@arc}{\moeptikz@arc}}

	% envelope
	\moeptikz@fillstroke\moeptikz@messageopen@envelope

	% paper
	\pgfutil@colorlet{moeptikz@paper}{\moeptikz@papercolor}%
	\pgfsetstrokecolor{moeptikz@paper!80}
	% sharp corners for the paper (the rounding of the envelope is still set);
	% 0.01pt, not 0pt: tiny arcs instead of miter joins, hence no spikes
	\pgfsetcornersarced{\pgfpoint{0.01pt}{0.01pt}}
	\pgfpathrectanglecorners{\northeast \pgf@x=.8\pgf@x \pgf@y=.8\pgf@y}
		{\northeast \pgf@x=-.8\pgf@x \pgf@y=-.8\pgf@y}
	\pgfshadepath{moeptikz@paper}{180}
	\pgfusepath{stroke}

	% left flap
	\pgfsetcornersarced{\pgfpoint{\moeptikz@arc}{\moeptikz@arc}}
	\moeptikz@message@fill
	\moeptikz@message@stroke
	\moeptikz@fillstroke{
		\pgfpathmoveto{\southwest}
		\pgfpathlineto{\southwest \pgf@y=-.25\pgf@y}
		\pgfpathlineto{\southwest \pgf@y=.3875\pgf@y \pgf@x=0\pgf@x}
		\pgfpathclose
	}

	% right flap
	\moeptikz@fillstroke{
		\pgfpathmoveto{\southwest \pgf@x=-\pgf@x}
		\pgfpathlineto{\southwest \pgf@y=-.25\pgf@y \pgf@x=-\pgf@x}
		\pgfpathlineto{\southwest \pgf@y=.3875\pgf@y \pgf@x=0\pgf@x}
		\pgfpathclose
	}

	% bottom flap
	\moeptikz@fillstroke{
		\pgfpathmoveto{\southwest}
		\pgfpathlineto{\southwest \pgf@x=-\pgf@x}
		\pgfpathlineto{\southwest \pgf@y=.3\pgf@y \pgf@x=0\pgf@x}
		\pgfpathclose
	}
}
\pgfdeclareshape{@messageopen}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@messageopen@outline}
	\backgroundpath{\moeptikz@background\moeptikz@messageopen@draw}
	\moeptikz@savednortheast
	\moeptikz@savedsouthwest
}

% the draw colour sets the colour of the lines
\moeptikz@declarestyle{messageopen}{black!30}
\tikzset{messageopen/.append style={draw=black}}

%==============================================================================
% messageclosed
%==============================================================================
% outline (see \moeptikz@polyborder)
\def\moeptikz@messageclosed@outline{%
	{1}{.625}{1}{-.625}{-1}{-.625}{-1}{.625}%
}
\def\moeptikz@messageclosed@draw{
	\moeptikz@message@stroke
	\moeptikz@message@fill

	\pgfmathparse{.05*sqrt(\moeptikz@size)}\let\moeptikz@lw\pgfmathresult
	\pgfmathparse{.2*sqrt(\moeptikz@size)}\let\moeptikz@arc\pgfmathresult

	\pgfsetlinewidth{\moeptikz@lw}
	\pgfsetcornersarced{\pgfpoint{\moeptikz@arc}{\moeptikz@arc}}

	% left flap
	\moeptikz@fillstroke{
		\pgfpathmoveto{\southwest \pgf@y=.625\pgf@y}
		\pgfpathlineto{\southwest \pgf@y=-.625\pgf@y}
		\pgfpathlineto{\southwest \pgf@y=.0125\pgf@y \pgf@x=0\pgf@x}
		\pgfpathclose
	}

	% right flap
	\moeptikz@fillstroke{
		\pgfpathmoveto{\southwest \pgf@x=-\pgf@x \pgf@y=.625\pgf@y}
		\pgfpathlineto{\southwest \pgf@y=-.625\pgf@y \pgf@x=-\pgf@x}
		\pgfpathlineto{\southwest \pgf@y=.0125\pgf@y \pgf@x=0\pgf@x}
		\pgfpathclose
	}

	% bottom flap
	\moeptikz@fillstroke{
		\pgfpathmoveto{\southwest \pgf@y=.625\pgf@y}
		\pgfpathlineto{\southwest \pgf@x=-\pgf@x \pgf@y=.625\pgf@y}
		\pgfpathlineto{\southwest \pgf@y=-.075\pgf@y \pgf@x=0\pgf@x}
		\pgfpathclose
	}

	% top flap
	\moeptikz@fillstroke{
		\pgfpathmoveto{\southwest \pgf@y=-.625\pgf@y}
		\pgfpathlineto{\southwest \pgf@x=-\pgf@x \pgf@y=-.625\pgf@y}
		\pgfpathlineto{\southwest \pgf@y=.075\pgf@y \pgf@x=0\pgf@x}
		\pgfpathclose
	}
}
\pgfdeclareshape{@messageclosed}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@messageclosed@outline}
	\backgroundpath{\moeptikz@background\moeptikz@messageclosed@draw}
	\moeptikz@savedsouthwest
}

% the draw colour sets the colour of the lines
\moeptikz@declarestyle{messageclosed}{black!30}
\tikzset{messageclosed/.append style={draw=black}}


%==============================================================================
% internet
%==============================================================================
% A cloud with a configurable number of puffs, e.g.
%   \node[internet,puffs=7] at (0,0) {Internet};
% Geometry, anchors and border are taken from PGF's cloud shape (library
% shapes.symbols): the cloud grows with its text, which -- unlike the other
% shapes -- is placed in the middle of the cloud; minimum width or minimum
% height enlarge it, aspect sets the ratio of width to height (default 2).
% Only the drawing is done here in the style of the other shapes: the cloud is
% filled with the fill colour, shaded or flat depending on the package option
% shading; the key empty (or fill=none) leaves it unfilled.  The draw colour
% selects the outline (black by default).  TikZ's own fill and draw find an
% empty path, hence the colours affect only the cloud and not the text.
\newif\ifmoeptikz@empty
\def\moeptikz@internet@draw{%
	% the path of PGF's cloud
	\csname pgf@sh@bg@cloud\endcsname
	% fill=none switches TikZ's fill mode off.  TikZ collects the mode switches
	% of the node in \tikz@mode and evaluates them only later, hence they are
	% evaluated here (locally, the drawing code runs in its own scope).
	\tikz@mode@filltrue
	\tikz@mode
	\ifmoeptikz@empty
		\tikz@mode@fillfalse
	\fi
	\iftikz@mode@fill
		\moeptikz@setshading
		\pgfshadepath{moeptikz@shading}{0}%
	\fi
	\ifx\tikz@strokecolor\pgfutil@empty
		\pgfsetstrokecolor{black}%
	\else
		\pgfsetstrokecolor{\tikz@strokecolor}%
	\fi
	\pgfusepath{stroke}%
}
\pgfdeclareshape{@internet}{
	\inheritsavedanchors[from=cloud]
	\inheritanchorborder[from=cloud]
	\inheritanchor[from=cloud]{center}
	\inheritanchor[from=cloud]{mid}
	\inheritanchor[from=cloud]{base}
	\inheritanchor[from=cloud]{north}
	\inheritanchor[from=cloud]{south}
	\inheritanchor[from=cloud]{east}
	\inheritanchor[from=cloud]{west}
	\inheritanchor[from=cloud]{north east}
	\inheritanchor[from=cloud]{north west}
	\inheritanchor[from=cloud]{south east}
	\inheritanchor[from=cloud]{south west}
	\moeptikz@sideanchors
	\backgroundpath{\moeptikz@background\moeptikz@internet@draw}
}
% PGF's cloud degenerates if only one of minimum width and minimum height is
% large: the other one follows the text, the ellipse becomes very flat and the
% puffs too large.  Hence both are adjusted to the aspect (width/height) before
% the cloud computes its radii: height >= width/aspect, width >= height*aspect.
\def\moeptikz@internet@size{%
	\pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/minimum width}}%
	\pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/minimum height}}%
	\pgf@xb=\pgfshapeaspect\pgf@ya
	\ifdim\pgf@xb>\pgf@xa \pgf@xa=\pgf@xb \fi
	\pgf@yb=\pgfshapeaspectinverse\pgf@xa
	\ifdim\pgf@yb>\pgf@ya \pgf@ya=\pgf@yb \fi
	\edef\moeptikz@tmp{\the\pgf@xa}%
	\pgfkeyslet{/pgf/minimum width}\moeptikz@tmp
	\edef\moeptikz@tmp{\the\pgf@ya}%
	\pgfkeyslet{/pgf/minimum height}\moeptikz@tmp
}
% The saved anchors and macros of a shape are computed by the macro
% \pgf@sh@s@<shape name> when a node is created.  Run the adjustment first.
\expandafter\let\expandafter\moeptikz@internet@cloudsaved
	\csname pgf@sh@s@@internet\endcsname
\expandafter\def\csname pgf@sh@s@@internet\endcsname{%
	\moeptikz@internet@size
	\moeptikz@internet@cloudsaved
}

\tikzset{
internet/.style={
	shape=@internet,
	fill=black,
	puffs=10,
	aspect=2,
	cloud ignores aspect=false
},
% number of puffs of an internet cloud
puffs/.style={/pgf/cloud puffs=#1},
% an internet cloud without filling
empty/.is if=moeptikz@empty
}
\moeptikz@novalue{internet}


%==============================================================================
% fw (firewall)
%==============================================================================
% A brick wall in an oblique view: a front face, a side face receding to the
% back right and a top face.  By default the wall stands upright and shows its
% narrow end (vertical), with the key `horizontal' it lies and shows its long
% side.  Coordinates are in units of half the node size.

% \moeptikz@fw@geometry{<v|h>}{front width}{front height}{angle}{depth}
% Defines the corners of the wall, scaled to fit into the node: front face
% (xa,ya)-(xb,yb), side face up to x=xc, back edges at yc (bottom) and yd
% (top), top face starting at xe.  Evaluated once at load time.
\def\moeptikz@fw@geometry#1#2#3#4#5{%
	\def\moeptikz@fw@set##1##2{%
		\pgfmathsetmacro\moeptikz@tmp{##2}%
		\expandafter\let\csname moeptikz@fw@#1@##1\endcsname\moeptikz@tmp}%
	\pgfmathsetmacro\moeptikz@fw@sc{2/max(#2+#5*cos(#4),#3+#5*sin(#4))}%
	\moeptikz@fw@set{w}{\moeptikz@fw@sc*#2}%
	\moeptikz@fw@set{h}{\moeptikz@fw@sc*#3}%
	\moeptikz@fw@set{dx}{\moeptikz@fw@sc*#5*cos(#4)}%
	\moeptikz@fw@set{dy}{\moeptikz@fw@sc*#5*sin(#4)}%
	\def\moeptikz@fw@g##1{\csname moeptikz@fw@#1@##1\endcsname}%
	\moeptikz@fw@set{xa}{-(\moeptikz@fw@g{w}+\moeptikz@fw@g{dx})/2}%
	\moeptikz@fw@set{ya}{-(\moeptikz@fw@g{h}+\moeptikz@fw@g{dy})/2}%
	\moeptikz@fw@set{xb}{\moeptikz@fw@g{xa}+\moeptikz@fw@g{w}}%
	\moeptikz@fw@set{xc}{\moeptikz@fw@g{xb}+\moeptikz@fw@g{dx}}%
	\moeptikz@fw@set{xe}{\moeptikz@fw@g{xa}+\moeptikz@fw@g{dx}}%
	\moeptikz@fw@set{yb}{\moeptikz@fw@g{ya}+\moeptikz@fw@g{h}}%
	\moeptikz@fw@set{yc}{\moeptikz@fw@g{ya}+\moeptikz@fw@g{dy}}%
	\moeptikz@fw@set{yd}{\moeptikz@fw@g{yb}+\moeptikz@fw@g{dy}}%
	% outline (see \moeptikz@polyborder)
	\expandafter\edef\csname moeptikz@fw@outline@#1\endcsname{%
		{\moeptikz@fw@g{xa}}{\moeptikz@fw@g{ya}}{\moeptikz@fw@g{xb}}{\moeptikz@fw@g{ya}}%
		{\moeptikz@fw@g{xc}}{\moeptikz@fw@g{yc}}{\moeptikz@fw@g{xc}}{\moeptikz@fw@g{yd}}%
		{\moeptikz@fw@g{xe}}{\moeptikz@fw@g{yd}}{\moeptikz@fw@g{xa}}{\moeptikz@fw@g{yb}}}%
}
\moeptikz@fw@geometry{v}{.6}{1.6}{40}{.9}
\moeptikz@fw@geometry{h}{1.9}{.55}{40}{.8}

% \moeptikz@fw@bond<macro>{rows}{bricks per row}
% Defines <macro> as the mortar joints of a running bond in the unit square,
% a list of segments {s1}{t1}{s2}{t2}.  Evaluated once at load time.
\def\moeptikz@fw@bond#1#2#3{%
	\gdef#1{}%
	\pgfmathtruncatemacro\moeptikz@fw@rm{#2-1}%
	\foreach \moeptikz@fw@r in {1,...,\moeptikz@fw@rm} {%
		\pgfmathsetmacro\moeptikz@fw@t{\moeptikz@fw@r/#2}%
		\xdef#1{#1{0}{\moeptikz@fw@t}{1}{\moeptikz@fw@t}}%
	}%
	\foreach \moeptikz@fw@r in {0,...,\moeptikz@fw@rm} {%
		\foreach \moeptikz@fw@b in {1,...,#3} {%
			\pgfmathsetmacro\moeptikz@fw@s
				{(\moeptikz@fw@b-.5*mod(\moeptikz@fw@r,2))/#3}%
			\ifdim\moeptikz@fw@s pt<.999pt % s >= .5/#3 > 0; no joint at the edge s = 1
				\pgfmathsetmacro\moeptikz@fw@ta{\moeptikz@fw@r/#2}%
				\pgfmathsetmacro\moeptikz@fw@tb{(\moeptikz@fw@r+1)/#2}%
				\xdef#1{#1{\moeptikz@fw@s}{\moeptikz@fw@ta}%
					{\moeptikz@fw@s}{\moeptikz@fw@tb}}%
			\fi
		}%
	}%
}
% joints of the front, side and top faces (s along the first, t along the
% second edge of the face)
\moeptikz@fw@bond\moeptikz@fw@v@front{6}{2}
\moeptikz@fw@bond\moeptikz@fw@v@side{6}{3}
\def\moeptikz@fw@v@top{%
	{0}{.33333}{1}{.33333}{0}{.66667}{1}{.66667}%
	{.5}{0}{.5}{.33333}{.5}{.66667}{.5}{1}}
\moeptikz@fw@bond\moeptikz@fw@h@front{2}{5}
\moeptikz@fw@bond\moeptikz@fw@h@side{2}{2}
\moeptikz@fw@bond\moeptikz@fw@h@top{3}{5}

% A face is the parallelogram o + s*u + t*v, 0 <= s,t <= 1.
% \moeptikz@fw@face{ox}{oy}{ux}{uy}{vx}{vy} selects it (units of half the node
% size), \moeptikz@fw@pt{s}{t} is a point on it, \moeptikz@fw@joints<list>
% adds the segments of a joint list to the path.
\def\moeptikz@fw@face#1#2#3#4#5#6{%
	\edef\moeptikz@fw@ox{\the\dimexpr#1\moeptikz@unit\relax}%
	\edef\moeptikz@fw@oy{\the\dimexpr#2\moeptikz@unit\relax}%
	\edef\moeptikz@fw@ux{\the\dimexpr#3\moeptikz@unit\relax}%
	\edef\moeptikz@fw@uy{\the\dimexpr#4\moeptikz@unit\relax}%
	\edef\moeptikz@fw@vx{\the\dimexpr#5\moeptikz@unit\relax}%
	\edef\moeptikz@fw@vy{\the\dimexpr#6\moeptikz@unit\relax}%
}
\def\moeptikz@fw@pt#1#2{%
	\pgfqpoint
		{\dimexpr\moeptikz@fw@ox+#1\dimexpr\moeptikz@fw@ux\relax
			+#2\dimexpr\moeptikz@fw@vx\relax\relax}%
		{\dimexpr\moeptikz@fw@oy+#1\dimexpr\moeptikz@fw@uy\relax
			+#2\dimexpr\moeptikz@fw@vy\relax\relax}%
}
\def\moeptikz@fw@joints#1{%
	\expandafter\moeptikz@fw@seg#1\moeptikz@stop\moeptikz@stop
		\moeptikz@stop\moeptikz@stop
}
\def\moeptikz@fw@seg#1#2#3#4{%
	\ifx\moeptikz@stop#1%
	\else
		\pgfpathmoveto{\moeptikz@fw@pt{#1}{#2}}%
		\pgfpathlineto{\moeptikz@fw@pt{#3}{#4}}%
		\expandafter\moeptikz@fw@seg
	\fi
}
% \moeptikz@fw@paint{fill code}{joint colour}{joint list}: fills the current
% face and draws its joints
\def\moeptikz@fw@paint#1#2#3{%
	\pgfpathmoveto{\moeptikz@fw@pt{0}{0}}%
	\pgfpathlineto{\moeptikz@fw@pt{1}{0}}%
	\pgfpathlineto{\moeptikz@fw@pt{1}{1}}%
	\pgfpathlineto{\moeptikz@fw@pt{0}{1}}%
	\pgfpathclose
	#1%
	\pgfsetstrokecolor{#2}%
	\expandafter\moeptikz@fw@joints\csname moeptikz@fw@\moeptikz@fw@orient @#3\endcsname
	\pgfusepath{stroke}%
}
% coordinates of the current orientation (saved macro \moeptikz@fw@orient)
\def\moeptikz@fw@c#1{\csname moeptikz@fw@\moeptikz@fw@orient @#1\endcsname}
\def\moeptikz@fw@p#1#2{%
	\pgfqpoint{\moeptikz@fw@c{#1}\moeptikz@unit}{\moeptikz@fw@c{#2}\moeptikz@unit}}

\def\moeptikz@fw@draw{%
	\moeptikz@setup{.03}%
	\pgfsetroundjoin
	% front face: shaded like the other shapes
	\moeptikz@fw@face{\moeptikz@fw@c{xa}}{\moeptikz@fw@c{ya}}%
		{\moeptikz@fw@c{w}}{0}{0}{\moeptikz@fw@c{h}}%
	\moeptikz@fw@paint{\pgfshadepath{moeptikz@shadingnuc}{0}\pgfusepath{}}%
		{white!90!black}{front}%
	% side face receding to the back right: darker
	\moeptikz@fw@face{\moeptikz@fw@c{xb}}{\moeptikz@fw@c{ya}}%
		{\moeptikz@fw@c{dx}}{\moeptikz@fw@c{dy}}{0}{\moeptikz@fw@c{h}}%
	\moeptikz@fw@paint{\pgfsetfillcolor{moeptikz@fill!85!black}\pgfusepath{fill}}%
		{white!75!black}{side}%
	% top face: darkest
	\moeptikz@fw@face{\moeptikz@fw@c{xa}}{\moeptikz@fw@c{yb}}%
		{\moeptikz@fw@c{w}}{0}{\moeptikz@fw@c{dx}}{\moeptikz@fw@c{dy}}%
	\moeptikz@fw@paint{\pgfsetfillcolor{moeptikz@fill!70!black}\pgfusepath{fill}}%
		{white!65!black}{top}%
	% inner edges
	\pgfsetstrokecolor{black}%
	\pgfmathsetlength\pgf@xa{.015*\moeptikz@size}%
	\pgfsetlinewidth{\pgf@xa}%
	\pgfpathmoveto{\moeptikz@fw@p{xa}{yb}}%
	\pgfpathlineto{\moeptikz@fw@p{xb}{yb}}%
	\pgfpathlineto{\moeptikz@fw@p{xb}{ya}}%
	\pgfpathmoveto{\moeptikz@fw@p{xb}{yb}}%
	\pgfpathlineto{\moeptikz@fw@p{xc}{yd}}%
	\pgfusepath{stroke}%
	% outline
	\pgfmathsetlength\pgf@xa{.025*\moeptikz@size}%
	\pgfsetlinewidth{\pgf@xa}%
	\pgfpathmoveto{\moeptikz@fw@p{xa}{ya}}%
	\pgfpathlineto{\moeptikz@fw@p{xb}{ya}}%
	\pgfpathlineto{\moeptikz@fw@p{xc}{yc}}%
	\pgfpathlineto{\moeptikz@fw@p{xc}{yd}}%
	\pgfpathlineto{\moeptikz@fw@p{xe}{yd}}%
	\pgfpathlineto{\moeptikz@fw@p{xa}{yb}}%
	\pgfpathclose
	\pgfusepath{stroke}%
}
% border of the current orientation
\def\moeptikz@fw@anchorborder{%
	\expandafter\moeptikz@polyborder\expandafter
		{\csname moeptikz@fw@outline@\moeptikz@fw@orient\endcsname}%
}
\newif\ifmoeptikz@horizontal
\pgfdeclareshape{@fw}{
	\moeptikz@savedmacros
	% orientation: v (upright) or h (horizontal), see key `horizontal'
	\savedmacro\moeptikz@fw@orient{%
		\ifmoeptikz@horizontal
			\def\moeptikz@fw@orient{h}%
		\else
			\def\moeptikz@fw@orient{v}%
		\fi
	}
	\moeptikz@outlineanchors{\moeptikz@fw@anchorborder}
	\backgroundpath{\moeptikz@background\moeptikz@fw@draw}
}

\moeptikz@declarestyle{fw}{red!50!black}
% a lying firewall (fw) showing its long side
\tikzset{horizontal/.is if=moeptikz@horizontal}

%==============================================================================
% fwrouter
%==============================================================================
% A router with a firewall on top: the upper half of the cylinder wall and the
% top are bricks in the colour `fw color' (default red!50!black), the lower
% half and the arrows are drawn as for the router (fill and draw colour).
% Size, anchors and border are those of the router.
\tikzset{fw color/.initial={red!50!black}}
\def\moeptikz@fwrouter@draw{%
	\moeptikz@router@setup
	\moeptikz@router@body
	% from now on shade with the wall colour
	\pgfkeysgetvalue{/tikz/fw color}\tikz@fillcolor
	\moeptikz@setshading
	\moeptikz@unit=.5\dimexpr\moeptikz@size\relax
	\pgfmathsetlength\pgf@xa{.02*\moeptikz@size}%
	\edef\moeptikz@mortar{\the\pgf@xa}%
	% upper half of the cylinder wall, between the front arcs of the ellipses
	% at height 0 and .15
	\pgfpathmoveto{\northeast \pgf@x=-\pgf@x \pgf@y=0pt}
	\pgfpatharcaxes{180}{360}{\pgfpoint{\moeptikz@rx}{0pt}}{\pgfpoint{0pt}{\moeptikz@ry}}
	\pgfpathlineto{\northeast \pgf@y=.15\pgf@y}
	\pgfpatharcaxes{0}{-180}{\pgfpoint{\moeptikz@rx}{0pt}}{\pgfpoint{0pt}{\moeptikz@ry}}
	\pgfpathclose
	\pgfshadepath{moeptikz@shadingnuc}{0}
	\pgfusepath{}
	% vertical joints of the single course (own scope: the PDF keeps the
	% stroke colour after a TeX group)
	\pgfscope
		\pgfsetlinewidth{\moeptikz@mortar}%
		\pgfsetstrokecolor{white!75!black}%
		\foreach \moeptikz@a in {202.5,225,...,337.5} {%
			\pgfpathmoveto{\pgfpointpolar{\moeptikz@a}
				{\moeptikz@unit and .75\moeptikz@unit}}%
			\pgfpathlineto{\pgfpointadd{\pgfpointpolar{\moeptikz@a}
				{\moeptikz@unit and .75\moeptikz@unit}}
				{\pgfqpoint{0pt}{.15\moeptikz@unit}}}%
		}%
		\pgfusepath{stroke}%
	\endpgfscope
	% outline of the upper wall: front arc at height 0 and both sides (the
	% shading covered the inner half of the body's outline at the sides)
	\pgfpathmoveto{\northeast \pgf@x=-\pgf@x \pgf@y=.15\pgf@y}
	\pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=0pt}
	\pgfpatharcaxes{180}{360}{\pgfpoint{\moeptikz@rx}{0pt}}{\pgfpoint{0pt}{\moeptikz@ry}}
	\pgfpathlineto{\northeast \pgf@y=.15\pgf@y}
	\pgfusepath{stroke}
	% top: shaded, then a running bond in the plane of the top circle,
	% rotated by 30 degrees and clipped to the top ellipse
	\pgfscope
		\moeptikz@router@topellipse
		\pgfshadepath{moeptikz@shadingnuc}{0}
		\pgfusepath{clip}
		\pgftransformshift{\pgfqpoint{0pt}{.15\moeptikz@unit}}
		\pgftransformyscale{.75}
		\pgftransformrotate{30}
		\pgfsetlinewidth{\moeptikz@mortar}
		\pgfsetstrokecolor{white!75!black}
		% courses of height .3, bricks of length .6 (units of half the size)
		\foreach \moeptikz@r in {-4,...,4} {%
			\pgfmathsetmacro\moeptikz@ya{.3*\moeptikz@r}%
			\pgfmathsetmacro\moeptikz@yb{.3*\moeptikz@r+.3}%
			\pgfpathmoveto{\pgfqpoint{-1.2\moeptikz@unit}{\moeptikz@ya\moeptikz@unit}}%
			\pgfpathlineto{\pgfqpoint{1.2\moeptikz@unit}{\moeptikz@ya\moeptikz@unit}}%
			\foreach \moeptikz@b in {-2,...,2} {%
				\pgfmathsetmacro\moeptikz@xa{.6*\moeptikz@b+.3*mod(\moeptikz@r+4,2)}%
				\pgfpathmoveto{\pgfqpoint{\moeptikz@xa\moeptikz@unit}{\moeptikz@ya\moeptikz@unit}}%
				\pgfpathlineto{\pgfqpoint{\moeptikz@xa\moeptikz@unit}{\moeptikz@yb\moeptikz@unit}}%
			}%
		}%
		\pgfusepath{stroke}
	\endpgfscope
	\moeptikz@router@topellipse
	\pgfusepath{stroke}
	\moeptikz@router@arrows
}
\pgfdeclareshape{@fwrouter}{
	\moeptikz@inheritanchors{@router}
	\backgroundpath{\moeptikz@background\moeptikz@fwrouter@draw}
}

\moeptikz@declarestyle{fwrouter}{black}


%==============================================================================
% mlswitch
%==============================================================================
% A multilayer switch: the body of the switch with the arrows of the router on
% its lid, scaled by .7 around the centre of the lid so that they stay on the
% lid, and two arrows pointing apart on each of the two front faces.  Size,
% anchors and border are those of the switch.

% \moeptikz@mlswitch@arrow{s0}{s1}{s2}{t}{shaft}{head}
% Arrow in the unit square of a face from s0 via the base of the head at s1
% to the tip at s2, at height t, half widths of shaft and head (units of half
% the node size, \moeptikz@unit).
\def\moeptikz@mlswitch@arrow#1#2#3#4#5#6{%
	\pgfpathmoveto{\pgfqpoint{#1\moeptikz@unit}
		{\dimexpr#4\moeptikz@unit-#5\moeptikz@unit\relax}}%
	\pgfpathlineto{\pgfqpoint{#2\moeptikz@unit}
		{\dimexpr#4\moeptikz@unit-#5\moeptikz@unit\relax}}%
	\pgfpathlineto{\pgfqpoint{#2\moeptikz@unit}
		{\dimexpr#4\moeptikz@unit-#6\moeptikz@unit\relax}}%
	\pgfpathlineto{\pgfqpoint{#3\moeptikz@unit}{#4\moeptikz@unit}}%
	\pgfpathlineto{\pgfqpoint{#2\moeptikz@unit}
		{\dimexpr#4\moeptikz@unit+#6\moeptikz@unit\relax}}%
	\pgfpathlineto{\pgfqpoint{#2\moeptikz@unit}
		{\dimexpr#4\moeptikz@unit+#5\moeptikz@unit\relax}}%
	\pgfpathlineto{\pgfqpoint{#1\moeptikz@unit}
		{\dimexpr#4\moeptikz@unit+#5\moeptikz@unit\relax}}%
	\pgfpathclose
}
% the two arrows of a front face
\def\moeptikz@mlswitch@sidearrows{%
	\moeptikz@mlswitch@arrow{.42}{.25}{.1}{.5}{.12}{.3}%
	\moeptikz@mlswitch@arrow{.58}{.75}{.9}{.5}{.12}{.3}%
	\pgfusepath{fill}%
}
\def\moeptikz@mlswitch@draw{%
	\moeptikz@switch@body
	% arrows of the router on the lid (own scope: the transformations must
	% not affect the arrows on the front faces drawn below)
	\pgfscope
		\pgftransformshift{\northeast \pgf@x=0pt \pgf@y=.15\pgf@y}%
		\pgftransformscale{.7}%
		\pgftransformshift{\northeast \pgf@x=0pt \pgf@y=-.15\pgf@y}%
		\moeptikz@router@arrows
	\endpgfscope
	% arrows on the front faces in the draw colour; each face is mapped onto
	% the unit square: left face from (-1,-.15) along (1,-.8) and (0,.3),
	% right face from (0,-.95) along (1,.8) and (0,.3)
	\moeptikz@fillwithstrokecolor%
	\moeptikz@unit=.5\dimexpr\moeptikz@size\relax
	\pgfscope
		\pgftransformcm{1}{-.8}{0}{.3}%
			{\pgfqpoint{-\moeptikz@unit}{-.15\moeptikz@unit}}%
		\moeptikz@mlswitch@sidearrows
	\endpgfscope
	\pgfscope
		\pgftransformcm{1}{.8}{0}{.3}{\pgfqpoint{0pt}{-.95\moeptikz@unit}}%
		\moeptikz@mlswitch@sidearrows
	\endpgfscope
}
\pgfdeclareshape{@mlswitch}{
	\moeptikz@inheritanchors{@switch}
	\backgroundpath{\moeptikz@background\moeptikz@mlswitch@draw}
}

\moeptikz@declarestyle{mlswitch}{black}

%==============================================================================
% db (database)
%==============================================================================
% A database: a cylinder seen from the side with two rings (stacked disks).
% Radii rx, ry of the ellipses and the heights yt, yb of the centres of the
% top and bottom ellipse, in units of half the node size.
\def\moeptikz@db@rx{.8}
\def\moeptikz@db@ry{.26}
\def\moeptikz@db@yt{.62}
\def\moeptikz@db@yb{-.62}
% outline (see \moeptikz@polyborder): back half of the top ellipse and front
% half of the bottom ellipse, every 15 degrees; computed once at load time
\def\moeptikz@db@outline{}
\foreach \moeptikz@a in {0,15,...,180} {%
	\pgfmathsetmacro\moeptikz@xa{\moeptikz@db@rx*cos(\moeptikz@a)}%
	\pgfmathsetmacro\moeptikz@ya{\moeptikz@db@yt+\moeptikz@db@ry*sin(\moeptikz@a)}%
	\xdef\moeptikz@db@outline{\moeptikz@db@outline{\moeptikz@xa}{\moeptikz@ya}}%
}
\foreach \moeptikz@a in {180,195,...,360} {%
	\pgfmathsetmacro\moeptikz@xa{\moeptikz@db@rx*cos(\moeptikz@a)}%
	\pgfmathsetmacro\moeptikz@ya{\moeptikz@db@yb+\moeptikz@db@ry*sin(\moeptikz@a)}%
	\xdef\moeptikz@db@outline{\moeptikz@db@outline{\moeptikz@xa}{\moeptikz@ya}}%
}
% heights of the two rings
\pgfmathsetmacro\moeptikz@db@ya{\moeptikz@db@yt-(\moeptikz@db@yt-\moeptikz@db@yb)/3}
\pgfmathsetmacro\moeptikz@db@yc{\moeptikz@db@yt-2*(\moeptikz@db@yt-\moeptikz@db@yb)/3}

% front half of the ellipse at height #1 (from left to right)
\def\moeptikz@db@arc#1{%
	\pgfpathmoveto{\moeptikz@pt{-\moeptikz@db@rx}{#1}}%
	\pgfpatharcaxes{180}{360}{\moeptikz@pt{\moeptikz@db@rx}{0}}%
		{\moeptikz@pt{0}{\moeptikz@db@ry}}%
}
\def\moeptikz@db@draw{%
	\moeptikz@setup{.025}%
	% body: sides and front half of the bottom ellipse
	\pgfpathmoveto{\moeptikz@pt{-\moeptikz@db@rx}{\moeptikz@db@yt}}%
	\pgfpathlineto{\moeptikz@pt{-\moeptikz@db@rx}{\moeptikz@db@yb}}%
	\pgfpatharcaxes{180}{360}{\moeptikz@pt{\moeptikz@db@rx}{0}}%
		{\moeptikz@pt{0}{\moeptikz@db@ry}}%
	\pgfpathlineto{\moeptikz@pt{\moeptikz@db@rx}{\moeptikz@db@yt}}%
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}%
	\pgfusepath{stroke}%
	% rings
	\moeptikz@db@arc{\moeptikz@db@ya}%
	\moeptikz@db@arc{\moeptikz@db@yc}%
	\pgfusepath{stroke}%
	% top
	\pgfpathellipse{\moeptikz@pt{0}{\moeptikz@db@yt}}%
		{\moeptikz@pt{\moeptikz@db@rx}{0}}{\moeptikz@pt{0}{\moeptikz@db@ry}}%
	\pgfshadepath{moeptikz@shading}{90}%
	\pgfusepath{stroke}%
}
\pgfdeclareshape{@db}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@db@outline}
	\backgroundpath{\moeptikz@background\moeptikz@db@draw}
}

\moeptikz@declarestyle{db}{black}

%==============================================================================
% rack
%==============================================================================
% Servers on top of each other: the fronts of the server, scaled in height
% such that the rack is as high as a router or a switch, and the lid of the
% server on top.  Units of half the node size; the front of a server spans
% .22, its lid .58.
\def\moeptikz@rack@h{1.85}
% \moeptikz@rack@geometry{number of servers}: computed once at load time
\def\moeptikz@rack@geometry#1{%
	\pgfmathsetmacro\moeptikz@rack@f{(\moeptikz@rack@h-.58)/(#1*.22)}%
	\pgfmathsetmacro\moeptikz@rack@step{.22*\moeptikz@rack@f}%
	% bottom of the fronts, top of the fronts, top of the lid
	\pgfmathsetmacro\moeptikz@rack@ya{-\moeptikz@rack@h/2}%
	\pgfmathsetmacro\moeptikz@rack@yd{\moeptikz@rack@ya+#1*\moeptikz@rack@step}%
	\pgfmathsetmacro\moeptikz@rack@ye{\moeptikz@rack@yd+.58}%
	% bottoms of the single fronts
	\gdef\moeptikz@rack@fronts{}%
	\pgfmathtruncatemacro\moeptikz@rack@last{#1-1}%
	\foreach \moeptikz@k in {0,...,\moeptikz@rack@last} {%
		\pgfmathsetmacro\moeptikz@tmp{\moeptikz@rack@ya+\moeptikz@k*\moeptikz@rack@step}%
		\xdef\moeptikz@rack@fronts{\unexpanded\expandafter{\moeptikz@rack@fronts}%
			\noexpand\moeptikz@rack@server{\moeptikz@tmp}}%
	}%
	% outline (see \moeptikz@polyborder)
	\xdef\moeptikz@rack@outline{%
		{-1}{\moeptikz@rack@ya}{1}{\moeptikz@rack@ya}%
		{1}{\moeptikz@rack@yd}{.97}{\moeptikz@rack@yd}%
		{.75}{\moeptikz@rack@ye}{-.75}{\moeptikz@rack@ye}%
		{-.97}{\moeptikz@rack@yd}{-1}{\moeptikz@rack@yd}}%
}
\moeptikz@rack@geometry{4}

% front of a server whose bottom is at height #1
\def\moeptikz@rack@server#1{%
	\pgfscope
		\pgftransformshift{\pgfqpoint{0pt}{#1\moeptikz@unit}}%
		\pgftransformyscale{\moeptikz@rack@f}%
		\pgftransformshift{\pgfqpoint{0pt}{.4\moeptikz@unit}}%
		\moeptikz@server@front
		\moeptikz@server@details
	\endpgfscope
}
\def\moeptikz@rack@draw{%
	\moeptikz@server@setup
	\moeptikz@unit=.5\dimexpr\moeptikz@size\relax
	\moeptikz@rack@fronts
	% lid of the server on top (it starts at -.18 in the server)
	\pgfscope
		\pgftransformshift{\pgfqpoint{0pt}
			{\dimexpr\moeptikz@rack@yd\moeptikz@unit+.18\moeptikz@unit\relax}}%
		\moeptikz@server@lid
	\endpgfscope
}
\pgfdeclareshape{@rack}{
	% saved anchors and macros of the server (\northeast is used by its
	% drawing code)
	\inheritsavedanchors[from=@server]
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@rack@outline}
	\backgroundpath{\moeptikz@background\moeptikz@rack@draw}
}

\moeptikz@declarestyle{rack}{black}


%==============================================================================
% smartphone
%==============================================================================
% A smartphone: a black body with rounded corners, a screen shaded in the fill
% colour (like the display of the client), a speaker and a home indicator.
% The body is extruded by (dx,dy) towards the back right to show its
% thickness; the whole phone is shifted by -(dx,dy)/2 to stay centred.  Units
% of half the node size.
\def\moeptikz@sp@dx{.05}
\def\moeptikz@sp@dy{.035}
% shifts of the copies of the body that form its thickness (from the back to
% the front) and of the front; computed once at load time
\gdef\moeptikz@sp@copies{}
\foreach \moeptikz@k in {10,9,...,1} {%
	\pgfmathsetmacro\moeptikz@xa{(\moeptikz@k/10-.5)*\moeptikz@sp@dx}%
	\pgfmathsetmacro\moeptikz@ya{(\moeptikz@k/10-.5)*\moeptikz@sp@dy}%
	\xdef\moeptikz@sp@copies{\unexpanded\expandafter{\moeptikz@sp@copies}%
		\noexpand\moeptikz@sp@body{\moeptikz@xa}{\moeptikz@ya}}%
}
\pgfmathsetmacro\moeptikz@sp@fx{-\moeptikz@sp@dx/2}
\pgfmathsetmacro\moeptikz@sp@fy{-\moeptikz@sp@dy/2}
% outline (see \moeptikz@polyborder): front and back body, corners not rounded
\pgfmathsetmacro\moeptikz@xa{-.45+\moeptikz@sp@fx}
\pgfmathsetmacro\moeptikz@xb{.45+\moeptikz@sp@fx}
\pgfmathsetmacro\moeptikz@xc{.45-\moeptikz@sp@fx}
\pgfmathsetmacro\moeptikz@xd{-.45-\moeptikz@sp@fx}
\pgfmathsetmacro\moeptikz@ya{-.9+\moeptikz@sp@fy}
\pgfmathsetmacro\moeptikz@yb{-.9-\moeptikz@sp@fy}
\pgfmathsetmacro\moeptikz@yc{.9-\moeptikz@sp@fy}
\pgfmathsetmacro\moeptikz@yd{.9+\moeptikz@sp@fy}
\edef\moeptikz@smartphone@outline{%
	{\moeptikz@xa}{\moeptikz@ya}{\moeptikz@xb}{\moeptikz@ya}%
	{\moeptikz@xc}{\moeptikz@yb}{\moeptikz@xc}{\moeptikz@yc}%
	{\moeptikz@xd}{\moeptikz@yc}{\moeptikz@xa}{\moeptikz@yd}}

% rectangle (x1,y1)-(x2,y2) with corner radius r (the radius stays set)
\def\moeptikz@sp@rect#1#2#3#4#5{%
	\pgfsetcornersarced{\moeptikz@pt{#5}{#5}}%
	\pgfpathrectanglecorners{\moeptikz@pt{#1}{#2}}{\moeptikz@pt{#3}{#4}}%
}
% a copy of the body shifted by (x,y); a TeX group suffices, since only the
% transformation and the corner radius change (\pgfscope would add q/Q)
\def\moeptikz@sp@body#1#2{%
	\begingroup
		\pgftransformshift{\moeptikz@pt{#1}{#2}}%
		\moeptikz@sp@rect{-.45}{-.9}{.45}{.9}{.13}%
		\pgfusepath{fill}%
	\endgroup
}
\def\moeptikz@smartphone@draw{%
	\moeptikz@setup{.02}%
	% thickness
	\pgfsetfillcolor{black!55}%
	\moeptikz@sp@copies
	% front (stroked in the fill colour: rim of half the line width)
	\pgftransformshift{\moeptikz@pt{\moeptikz@sp@fx}{\moeptikz@sp@fy}}%
	\pgfsetfillcolor{black}%
	\moeptikz@fillstroke{\moeptikz@sp@rect{-.45}{-.9}{.45}{.9}{.13}}%
	% screen
	\moeptikz@sp@rect{-.38}{-.7}{.38}{.74}{.03}%
	\pgfshadepath{moeptikz@shadingnuc}{180}%
	\pgfusepath{}%
	% speaker and home indicator
	\pgfsetfillcolor{black!55}%
	\moeptikz@sp@rect{-.12}{.8}{.12}{.83}{.015}%
	\pgfusepath{fill}%
	\moeptikz@sp@rect{-.14}{-.8}{.14}{-.775}{.012}%
	\pgfusepath{fill}%
}
\pgfdeclareshape{@smartphone}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@smartphone@outline}
	\backgroundpath{\moeptikz@background\moeptikz@smartphone@draw}
}

\moeptikz@declarestyle{smartphone}{black}

%==============================================================================
% user
%==============================================================================
% A person: a head above shoulders (upper half of an ellipse) with a small gap
% in between, both shaded in the fill colour.  Units of half the node size.
% The centre of the node lies in the gap, hence the outline for the border is
% the convex hull of head and shoulders (computed beforehand); lines from the
% side end next to the neck, from above at the head, from below at the
% shoulders.
\def\moeptikz@user@outline{%
	{-0.75}{-0.9}{0.75}{-0.9}{0.7386}{-0.7524}{0.7048}{-0.6093}{0.3571}{0.63}%
	{0.3291}{0.69}{0.2911}{0.7443}{0.2443}{0.7911}{0.19}{0.8291}{0.13}{0.8571}%
	{0.066}{0.8742}{0}{0.88}{-0.066}{0.8742}{-0.13}{0.8571}{-0.19}{0.8291}%
	{-0.2443}{0.7911}{-0.2911}{0.7443}{-0.3291}{0.69}{-0.3571}{0.63}%
	{-0.7048}{-0.6093}{-0.7386}{-0.7524}%
}
\def\moeptikz@user@draw{%
	\moeptikz@setup{.02}%
	% shoulders: upper half of the ellipse with centre (0,-.9), radii .75, .85
	\pgfpathmoveto{\moeptikz@pt{-.75}{-.9}}%
	\pgfpatharcaxes{180}{0}{\moeptikz@pt{.75}{0}}{\moeptikz@pt{0}{.85}}%
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{0}%
	\pgfusepath{stroke}%
	% head: circle with centre (0,.5), radius .38
	\pgfpathcircle{\moeptikz@pt{0}{.5}}{.38\moeptikz@unit}%
	\pgfshadepath{moeptikz@shading}{0}%
	\pgfusepath{stroke}%
}
\pgfdeclareshape{@user}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@user@outline}
	\backgroundpath{\moeptikz@background\moeptikz@user@draw}
}

\moeptikz@declarestyle{user}{black}

%==============================================================================
% usergroup
%==============================================================================
% A group of three persons: two in front (scaled by .6, at x=+-.5, standing on
% y=-.9) and one behind them (scaled by .58, centred, top at y=.62), drawn
% from back to front with the code of the user.  The outline is the convex
% hull of the three outlines of the user (computed beforehand for this
% layout).  Units of half the node size.
\def\moeptikz@usergroup@outline{%
	{-0.95}{-0.9}{0.95}{-0.9}{0.9432}{-0.8114}{0.9229}{-0.7256}%
	{0.7143}{0.018}{0.6975}{0.054}{0.6747}{0.0866}{0.6466}{0.1147}%
	{0.1417}{0.5684}{0.1102}{0.5905}{0.0754}{0.6067}{0.0383}{0.6166}%
	{0}{0.62}{-0.0383}{0.6166}{-0.0754}{0.6067}{-0.1102}{0.5905}%
	{-0.1417}{0.5684}{-0.6466}{0.1147}{-0.6747}{0.0866}{-0.6975}{0.054}%
	{-0.7143}{0.018}{-0.9229}{-0.7256}{-0.9432}{-0.8114}%
}
% a user at (x,y) scaled by s
\def\moeptikz@usergroup@one#1#2#3{%
	\pgfscope
		\pgftransformshift{\moeptikz@pt{#1}{#2}}%
		\pgftransformscale{#3}%
		\moeptikz@user@draw
	\endpgfscope
}
\def\moeptikz@usergroup@draw{%
	\moeptikz@unit=.5\dimexpr\moeptikz@size\relax
	\moeptikz@usergroup@one{0}{.1096}{.58}%
	\moeptikz@usergroup@one{-.5}{-.36}{.6}%
	\moeptikz@usergroup@one{.5}{-.36}{.6}%
}
\pgfdeclareshape{@usergroup}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@usergroup@outline}
	\backgroundpath{\moeptikz@background\moeptikz@usergroup@draw}
}

\moeptikz@declarestyle{usergroup}{black}

%==============================================================================
% modem, wlanmodem
%==============================================================================
% A modem: a flat box (front and lid in the perspective of the server) with
% five green LEDs on its front.  The wlanmodem is lower and has two antennas
% behind the box.  Units of half the node size.

% \moeptikz@modem@draw{front half width}{front bottom}{front top}%
%   {lid back half width}{lid back}{antennas: 0 or 1}
\def\moeptikz@modem@draw#1#2#3#4#5#6{%
	\moeptikz@setup{.02}%
	\ifnum#6>0
		% antennas behind the box
		\pgfscope
			\pgfmathsetlength\pgf@xa{.06*\moeptikz@size}%
			\pgfsetlinewidth{\pgf@xa}%
			\pgfsetroundcap
			\pgfpathmoveto{\moeptikz@ptexpr{-#4+.08}{#5-.05}}%
			\pgfpathlineto{\moeptikz@ptexpr{-#4-.05}{#5+.5}}%
			\pgfpathmoveto{\moeptikz@ptexpr{#4-.08}{#5-.05}}%
			\pgfpathlineto{\moeptikz@ptexpr{#4+.05}{#5+.5}}%
			\pgfusepath{stroke}%
		\endpgfscope
	\fi
	\pgfsetcornersarced{\moeptikz@ptexpr{.04}{.04}}%
	% lid
	\pgfpathmoveto{\moeptikz@ptexpr{-#1}{#3}}%
	\pgfpathlineto{\moeptikz@ptexpr{#1}{#3}}%
	\pgfpathlineto{\moeptikz@ptexpr{#4}{#5}}%
	\pgfpathlineto{\moeptikz@ptexpr{-#4}{#5}}%
	\pgfpathclose
	\pgfshadepath{moeptikz@shading}{11.5}%
	\pgfusepath{stroke}%
	% front
	\pgfpathrectanglecorners{\moeptikz@ptexpr{-#1}{#2}}{\moeptikz@ptexpr{#1}{#3}}%
	\pgfshadepath{moeptikz@shading}{-25}%
	\pgfusepath{stroke}%
	% LEDs
	\pgfsetfillcolor{green!70!black}%
	\pgfsetstrokecolor{black!60}%
	\pgfmathsetlength\pgf@xa{.01*\moeptikz@size}%
	\pgfsetlinewidth{\pgf@xa}%
	\foreach \moeptikz@i in {0,...,4} {%
		\moeptikz@fillstroke{\pgfpathcircle
			{\moeptikz@ptexpr{-#1+.2+\moeptikz@i*.17}{(#2+#3)/2}}{.045\moeptikz@unit}}%
	}%
}
% outlines (see \moeptikz@polyborder); the antennas of the wlanmodem are
% lines of width .12 with round caps
\def\moeptikz@modem@outline{%
	{-.85}{-.4}{.85}{-.4}{.85}{-.05}{.65}{.35}{-.65}{.35}{-.85}{-.05}}
\def\moeptikz@wlanmodem@outline{%
	{-.85}{-.55}{.85}{-.55}{.85}{-.2}{.65}{.2}{-.65}{.2}{-.85}{-.2}}
\moeptikz@capsule\moeptikz@wlanmodem@leftantenna{-.57}{.15}{-.7}{.7}{.06}
\moeptikz@capsule\moeptikz@wlanmodem@rightantenna{.57}{.15}{.7}{.7}{.06}
\def\moeptikz@wlanmodem@anchorborder{%
	\moeptikz@polyborder{\moeptikz@wlanmodem@outline
		\moeptikz@wlanmodem@leftantenna\moeptikz@wlanmodem@rightantenna}}
\pgfdeclareshape{@modem}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@polyborder\moeptikz@modem@outline}
	\backgroundpath{\moeptikz@background{%
		\moeptikz@modem@draw{.85}{-.4}{-.05}{.65}{.35}{0}}}
}
\pgfdeclareshape{@wlanmodem}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@wlanmodem@anchorborder}
	\backgroundpath{\moeptikz@background{%
		\moeptikz@modem@draw{.85}{-.55}{-.2}{.65}{.2}{1}}}
}

\moeptikz@declarestyle{modem}{black}
\moeptikz@declarestyle{wlanmodem}{black}

%==============================================================================
% key
%==============================================================================
% A key turned by 40 degrees (bow top left, bit bottom right) with some depth
% to the back.  It is drawn in its own coordinate system in units of half the
% node size: bow centred at (-.55,0) with a hole, blade along the x axis.
% \moeptikz@key@transform maps it into the node such that the key including
% its depth is centred.
\def\moeptikz@key@transform{%
	\pgftransformshift{\moeptikz@pt{-0.017}{0.034}}%
	\pgftransformrotate{-40}%
	\pgftransformscale{1.05}%
}
% blade with the bit (two teeth)
\def\moeptikz@key@blade{%
	\pgfpathmoveto{\moeptikz@pt{-0.3}{0.075}}%
	\pgfpathlineto{\moeptikz@pt{0.95}{0.075}}%
	\pgfpathlineto{\moeptikz@pt{0.95}{-0.27}}%
	\pgfpathlineto{\moeptikz@pt{0.83}{-0.27}}%
	\pgfpathlineto{\moeptikz@pt{0.83}{-0.16}}%
	\pgfpathlineto{\moeptikz@pt{0.72}{-0.16}}%
	\pgfpathlineto{\moeptikz@pt{0.72}{-0.23}}%
	\pgfpathlineto{\moeptikz@pt{0.6}{-0.23}}%
	\pgfpathlineto{\moeptikz@pt{0.6}{-0.075}}%
	\pgfpathlineto{\moeptikz@pt{-0.3}{-0.075}}%
	\pgfpathclose
}
% bow: ring with a hole (even odd rule)
\def\moeptikz@key@bow{%
	\pgfpathcircle{\moeptikz@pt{-.55}{0}}{.4\moeptikz@unit}%
	\pgfpathcircle{\moeptikz@pt{-.67}{0}}{.13\moeptikz@unit}%
}
\def\moeptikz@key@draw{%
	\moeptikz@setup{.02}%
	\pgfseteorule
	\pgfsetroundjoin
	\moeptikz@key@transform
	% depth: the key shifted to the back, dark
	\pgfscope
		\pgftransformshift{\moeptikz@pt{.06}{.05}}%
		\pgfsetfillcolor{black!80}%
		\moeptikz@fillstroke{\moeptikz@key@blade}%
		\moeptikz@fillstroke{\moeptikz@key@bow}%
	\endpgfscope
	\moeptikz@key@blade
	\pgfshadepath{moeptikz@shading}{-25}%
	\pgfusepath{stroke}%
	\moeptikz@key@bow
	\pgfshadepath{moeptikz@shading}{-25}%
	\pgfusepath{stroke}%
}
% outline (see \moeptikz@polyborder): blade and bow (as a 20-gon), each in
% front and shifted to the back, in node coordinates (precomputed with
% \moeptikz@key@transform)
\def\moeptikz@key@blade@outline{%
	{-0.208}{0.297}{0.798}{-0.547}{0.565}{-0.825}{0.468}{-0.744}{0.542}{-0.655}%
	{0.454}{-0.581}{0.407}{-0.637}{0.310}{-0.556}{0.415}{-0.432}{-0.309}{0.176}%
}
\def\moeptikz@key@blade@back@outline{%
	{-0.126}{0.296}{0.880}{-0.547}{0.647}{-0.825}{0.550}{-0.744}{0.624}{-0.655}%
	{0.536}{-0.581}{0.489}{-0.638}{0.392}{-0.557}{0.497}{-0.432}{-0.227}{0.176}%
}
\def\moeptikz@key@bow@outline{%
	{-0.138}{0.135}{-0.070}{0.248}{-0.041}{0.376}{-0.052}{0.507}{-0.103}{0.627}%
	{-0.190}{0.727}{-0.302}{0.794}{-0.430}{0.824}{-0.561}{0.812}{-0.682}{0.761}%
	{-0.781}{0.675}{-0.849}{0.562}{-0.879}{0.434}{-0.867}{0.303}{-0.816}{0.182}%
	{-0.730}{0.083}{-0.617}{0.016}{-0.489}{-0.014}{-0.358}{-0.003}%
	{-0.237}{0.049}%
}
\def\moeptikz@key@bow@back@outline{%
	{-0.056}{0.135}{0.012}{0.247}{0.041}{0.375}{0.030}{0.506}{-0.021}{0.627}%
	{-0.108}{0.726}{-0.220}{0.794}{-0.348}{0.824}{-0.479}{0.812}{-0.600}{0.761}%
	{-0.699}{0.675}{-0.767}{0.562}{-0.797}{0.434}{-0.785}{0.303}{-0.734}{0.182}%
	{-0.648}{0.083}{-0.535}{0.015}{-0.407}{-0.014}{-0.276}{-0.003}%
	{-0.155}{0.048}%
}
\def\moeptikz@key@anchorborder{%
	\moeptikz@polyborder{\moeptikz@key@blade@outline
		\moeptikz@key@blade@back@outline
		\moeptikz@key@bow@outline\moeptikz@key@bow@back@outline}}
\pgfdeclareshape{@key}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@key@anchorborder}
	\backgroundpath{\moeptikz@background\moeptikz@key@draw}
	% The border point at 270 degrees lies on the blade in the middle of the
	% key, hence the text goes below the lowest point of the key (the bit).
	% This replaces the text anchor of \moeptikz@outlineanchors.
	\anchor{text}{\moeptikz@textanchor{%
		\pgf@x=0pt
		\pgf@y=-0.4125\dimexpr\moeptikz@size\relax}}
}

\moeptikz@declarestyle{key}{black}

%==============================================================================
% keyhole
%==============================================================================
% A round plate with a keyhole, with some depth to the back like the key.  The
% plate (radius .88 of half the node size) and its copy at the back are
% shifted such that both together are centred.
\def\moeptikz@keyhole@plate{%
	\pgfpathcircle{\pgfpointorigin}{.88\moeptikz@unit}%
}
% the keyhole: circle around (0,.22) with radius .26 and a trapezoid below,
% one closed path
\def\moeptikz@keyhole@hole{%
	\pgfpathmoveto{\moeptikz@pt{.12}{-.011}}%
	\pgfpatharc{-62.5}{242.5}{.26\moeptikz@unit}%
	\pgfpathlineto{\moeptikz@pt{-.24}{-.55}}%
	\pgfpathlineto{\moeptikz@pt{.24}{-.55}}%
	\pgfpathclose
}
\def\moeptikz@keyhole@draw{%
	\moeptikz@setup{.02}%
	\pgfsetroundjoin
	\pgftransformshift{\moeptikz@pt{-.03}{-.025}}%
	% depth: the plate shifted to the back, dark
	\pgfscope
		\pgftransformshift{\moeptikz@pt{.06}{.05}}%
		\pgfsetfillcolor{black!80}%
		\moeptikz@fillstroke{\moeptikz@keyhole@plate}%
	\endpgfscope
	\moeptikz@keyhole@plate
	\pgfshadepath{moeptikz@shading}{-25}%
	\pgfusepath{stroke}%
	\pgfsetfillcolor{black!85}%
	\moeptikz@fillstroke{\moeptikz@keyhole@hole}%
}
% outline (see \moeptikz@polyborder): the plate in front and at the back,
% each as a 24-gon
\def\moeptikz@keyhole@front@outline{%
	{0.850}{-0.025}{0.820}{0.203}{0.732}{0.415}{0.592}{0.597}{0.410}{0.737}%
	{0.198}{0.825}{-0.030}{0.855}{-0.258}{0.825}{-0.470}{0.737}{-0.652}{0.597}%
	{-0.792}{0.415}{-0.880}{0.203}{-0.910}{-0.025}{-0.880}{-0.253}%
	{-0.792}{-0.465}{-0.652}{-0.647}{-0.470}{-0.787}{-0.258}{-0.875}%
	{-0.030}{-0.905}{0.198}{-0.875}{0.410}{-0.787}{0.592}{-0.647}%
	{0.732}{-0.465}{0.820}{-0.253}%
}
\def\moeptikz@keyhole@back@outline{%
	{0.910}{0.025}{0.880}{0.253}{0.792}{0.465}{0.652}{0.647}{0.470}{0.787}%
	{0.258}{0.875}{0.030}{0.905}{-0.198}{0.875}{-0.410}{0.787}{-0.592}{0.647}%
	{-0.732}{0.465}{-0.820}{0.253}{-0.850}{0.025}{-0.820}{-0.203}%
	{-0.732}{-0.415}{-0.592}{-0.597}{-0.410}{-0.737}{-0.198}{-0.825}%
	{0.030}{-0.855}{0.258}{-0.825}{0.470}{-0.737}{0.652}{-0.597}{0.792}{-0.415}%
	{0.880}{-0.203}%
}
\def\moeptikz@keyhole@anchorborder{%
	\moeptikz@polyborder{\moeptikz@keyhole@front@outline
		\moeptikz@keyhole@back@outline}}
\pgfdeclareshape{@keyhole}{
	\moeptikz@savedmacros
	\moeptikz@outlineanchors{\moeptikz@keyhole@anchorborder}
	\backgroundpath{\moeptikz@background\moeptikz@keyhole@draw}
}

\moeptikz@declarestyle{keyhole}{black}

%==============================================================================
% waves (wireless links)
%==============================================================================
% \draw[waves] (a) to (b);
% draws concentric arcs instead of the line, e.g. for a wireless link: their
% centre is the start of the path, their radii grow up to the end of the
% path.  waves=<n> sets the number of arcs (default 6), `wave angle' the
% opening angle of the arcs (default 70).  Colour and line width are those of
% the path, by default thin and grey (put own ones after `waves').  The arcs
% are placed by the markings decoration: at a mark the coordinate system has
% its origin on the path and its x axis along the path, hence the start of a
% straight path lies at (-r,0), r the distance from the start.
\tikzset{
	wave angle/.initial=70,
	% the arcs are drawn as a postaction, which uses the options of the path
	% (colour, line width); the path itself is not drawn
	waves/.style={
		line cap=round,
		line width=.3pt,
		black!60,
		draw=none,
		postaction={decorate,
			decoration={markings,
				mark=between positions {1/#1} and 1 step {1/#1} with {\moeptikz@wave}}}
	},
	waves/.default=6
}
\newdimen\moeptikz@wave@r
\def\moeptikz@wave{%
	\pgfmathsetlength\moeptikz@wave@r
		{\pgfkeysvalueof{/pgf/decoration/mark info/distance from start}}%
	\pgfmathsetmacro\moeptikz@wave@a{\pgfkeysvalueof{/tikz/wave angle}/2}%
	\pgfpathmoveto{\pgfpointadd{\pgfqpoint{-\moeptikz@wave@r}{0pt}}
		{\pgfpointpolar{-\moeptikz@wave@a}{\moeptikz@wave@r}}}%
	\pgfpatharc{-\moeptikz@wave@a}{\moeptikz@wave@a}{\moeptikz@wave@r}%
	\pgfusepath{stroke}%
}

%==============================================================================
% Key clashes with other packages
%==============================================================================
% A few packages use names of moeptikz keys, too.  The keys keep their names
% (documents use them), but each clash gets a warning at \begin{document},
% when all packages are loaded, so that the order of the \usepackage commands
% does not matter.
% - circuitikz: the path style switch (an alias of `closing switch', spst uses
%   it).  The package loaded last wins.  With circuitikz's option
%   compatibility its path styles begin with * (to[*switch]): no clash.
% - circuitikz: the shape waves.  TikZ tries an option as a key before it
%   tries it as a shape name, so \node[waves] always gets moeptikz's key.
% - The TikZ library graphdrawing (LuaTeX only; tikz-feynman loads it there)
%   forwards /tikz/horizontal and /tikz/graphs/horizontal to its own key
%   horizontal=<tail> to <head>.  \graph looks up its options and those of
%   its nodes in /tikz/graphs first, so there graph drawing's key wins.  For
%   /tikz/horizontal, .forward to appends the forwarding to moeptikz's key if
%   graphdrawing is loaded after moeptikz, otherwise moeptikz's key replaces
%   graph drawing's; either way moeptikz's key gives an error for <tail> to
%   <head>.  TikZ marks a loaded library with \tikz@library@<name>@loaded.
% - tikz-feynman without LuaTeX sets /tikz/horizontal to a warning that the
%   key needs LuaTeX.  The package loaded last wins.
\AtBeginDocument{%
	\@ifpackageloaded{circuitikz}{%
		% circuitikz's option compatibility (also as a class option) names the
		% path style *switch: then /tikz/spst is not defined either
		\pgfkeysifdefined{/tikz/spst/.@cmd}{%
			\PackageWarningNoLine{moeptikz}{%
				circuitikz also defines the TikZ key `switch';\MessageBreak
				the package loaded last wins. If it is moeptikz,\MessageBreak
				to[switch] and to[spst] draw no switch (use\MessageBreak
				to[closing switch] or to[cspst]), otherwise\MessageBreak
				\string\node[switch] draws only its text}%
		}{}%
		% old versions of circuitikz have no shape waves
		\@ifundefined{pgf@sh@s@waves}{}{%
			\PackageWarningNoLine{moeptikz}{%
				circuitikz has a shape `waves', but\MessageBreak
				\string\node[waves] uses moeptikz's key `waves' in any\MessageBreak
				load order; use \string\node[shape=waves] for the shape}%
		}%
	}{}%
	\@ifundefined{tikz@library@graphdrawing@loaded}{%
		\@ifpackageloaded{tikz-feynman}{%
			\PackageWarningNoLine{moeptikz}{%
				tikz-feynman also defines the TikZ key `horizontal'\MessageBreak
				(without LuaTeX); the package loaded last wins.\MessageBreak
				If it is moeptikz, horizontal=<a> to <b> gives an\MessageBreak
				error, otherwise \string\node[fw,horizontal] stays\MessageBreak
				upright; load tikz-feynman before moeptikz}%
		}{}%
	}{%
		\@ifpackageloaded{tikz-feynman}%
			{\def\moeptikz@temp{ (via tikz-feynman)}}%
			{\let\moeptikz@temp\@empty}%
		\PackageWarningNoLine{moeptikz}{%
			The TikZ library graphdrawing\moeptikz@temp\MessageBreak
			also defines the key `horizontal'. In \string\graph\space its\MessageBreak
			key wins (fw needs /tikz/horizontal there);\MessageBreak
			elsewhere write\MessageBreak
			/graph drawing/horizontal=<a> to <b>}%
	}%
}

\endinput
