diff --git a/core/modules/layout/config/display.bound.admin_master.yml b/core/modules/layout/config/display.bound.admin_master.yml
new file mode 100644
index 0000000..5b33c5f
--- /dev/null
+++ b/core/modules/layout/config/display.bound.admin_master.yml
@@ -0,0 +1,41 @@
+id: admin_master
+label: Default admin layout
+layout: static_layout:layout__two-col
+layoutSettings: {  }
+blockInfo:
+  block.ikwqqmzh:
+    region: first
+    weight: '100'
+    region-type: content
+  block.pasmpbio:
+    region: first
+    weight: '200'
+    region-type: content
+  block.hiuobsyq:
+    region: first
+    weight: '300'
+    region-type: content
+  block.aduoefgo:
+    region: second
+    weight: '100'
+    region-type: aside
+  block.cefddxxz:
+    region: second
+    weight: '200'
+    region-type: aside
+  block.fvurzags:
+    region: second
+    weight: '300'
+    region-type: aside
+  block.cwycrmwm:
+    region: second
+    weight: '400'
+    region-type: aside
+  block.nrinfrbu:
+    region: second
+    weight: '500'
+    region-type: aside
+  block.hhqpbxal:
+    region: second
+    weight: '600'
+    region-type: aside
diff --git a/core/modules/layout/config/display.bound.front_master.yml b/core/modules/layout/config/display.bound.front_master.yml
new file mode 100644
index 0000000..fe9c371
--- /dev/null
+++ b/core/modules/layout/config/display.bound.front_master.yml
@@ -0,0 +1,37 @@
+id: front_master
+label: Default layout
+layout: static_layout:layout__two-col
+layoutSettings: {  }
+blockInfo:
+  block.nnadgxph:
+    region: first
+    weight: '100'
+    region-type: content
+  block.xytwvpdi:
+    region: first
+    weight: '200'
+    region-type: content
+  block.xzcwrtdy:
+    region: first
+    weight: '300'
+    region-type: content
+  block.miqumptd:
+    region: first
+    weight: '400'
+    region-type: content
+  block.htgrsglh:
+    region: second
+    weight: '100'
+    region-type: aside
+  block.scxwxgon:
+    region: second
+    weight: '200'
+    region-type: aside
+  block.fqcxgrof:
+    region: second
+    weight: '300'
+    region-type: aside
+  block.ebrcmkge:
+    region: second
+    weight: '400'
+    region-type: aside
diff --git a/core/modules/layout/css/layout.base-rtl.css b/core/modules/layout/css/layout.base-rtl.css
new file mode 100644
index 0000000..e0e3a00
--- /dev/null
+++ b/core/modules/layout/css/layout.base-rtl.css
@@ -0,0 +1,3 @@
+/**
+ * @file layout.base-rtl.css
+ */
diff --git a/core/modules/layout/css/layout.base.css b/core/modules/layout/css/layout.base.css
new file mode 100755
index 0000000..323f22e
--- /dev/null
+++ b/core/modules/layout/css/layout.base.css
@@ -0,0 +1,59 @@
+/**
+ * @file layout.base.css
+ */
+
+.layout-app,
+.layout-app * {
+  -moz-box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.layout-app .form-textarea {
+  display: none;
+}
+
+/**
+ * Regions.
+ */
+.layout-app header .operations {
+  float: left; /* LTR */
+}
+.layout-app header .info {
+  float: right; /* LTR */
+}
+
+/**
+ * Blocks.
+ */
+.layout-app .blocks {
+  display: table;
+  table-layout: fixed;
+  width: 100%;
+}
+.layout-app .blocks .row {
+  display: table-row;
+}
+.layout-app .blocks .block {
+  display: table-cell;
+  overflow: hidden;
+}
+.layout-app .blocks .block:hover {
+  cursor: pointer;
+}
+.layout-app .block > .lining {
+  display: inline-block;
+  height:100%;
+  position: relative;
+  width: 100%;
+}
+
+/**
+ * Block information.
+ */
+.layout-app .block .type-indicator,
+.layout-app .block .label {
+  display: block;
+}
+.layout-app .block .type-indicator {
+  float: left; /* LTR */
+}
diff --git a/core/modules/layout/css/layout.icons-rtl.css b/core/modules/layout/css/layout.icons-rtl.css
new file mode 100644
index 0000000..aed81b5
--- /dev/null
+++ b/core/modules/layout/css/layout.icons-rtl.css
@@ -0,0 +1,3 @@
+/**
+ * @file layout.icons-rtl.css
+ */
diff --git a/core/modules/layout/css/layout.icons.css b/core/modules/layout/css/layout.icons.css
new file mode 100644
index 0000000..595ac42
--- /dev/null
+++ b/core/modules/layout/css/layout.icons.css
@@ -0,0 +1,44 @@
+/**
+ * @file layout.icons.css
+ */
+.layout-app .icon {
+  border: 0;
+  line-height: 1;
+  padding-left: 2.5em; /* LTR */
+  position: relative;
+  text-indent: -9999px;
+}
+.layout-app .icon-text {
+  text-indent: 0;
+}
+.layout-app .icon:before {
+  background-attachment: scroll;
+  background-color: transparent;
+  background-position: center center;
+  background-repeat: no-repeat;
+  content: '';
+  display: block;
+  height: 100%;
+  left: 0.6667em; /* LTR */
+  position: absolute;
+  top: 0;
+  width: 20px;
+}
+.layout-app button.icon {
+  background-color: transparent;
+  font-size: 1em;
+}
+
+/**
+ * Icons.
+ */
+.layout-app .icon-plus:before,
+.layout-app .icon-plus:active:before,
+.layout-app .icon-plus.active:before {
+  background-image:url("../images/plus.png");
+}
+.layout-app .icon-gear:before,
+.layout-app .icon-gear:active:before,
+.layout-app .icon-gear.active:before {
+  background-image:url("../images/gear_fff.png");
+}
diff --git a/core/modules/layout/css/layout.theme-rtl.css b/core/modules/layout/css/layout.theme-rtl.css
new file mode 100644
index 0000000..71312a9
--- /dev/null
+++ b/core/modules/layout/css/layout.theme-rtl.css
@@ -0,0 +1,3 @@
+/**
+ * @file layout.theme-rtl.css
+ */
diff --git a/core/modules/layout/css/layout.theme.css b/core/modules/layout/css/layout.theme.css
new file mode 100644
index 0000000..1b0c267
--- /dev/null
+++ b/core/modules/layout/css/layout.theme.css
@@ -0,0 +1,153 @@
+/**
+ * @file layout.theme.css
+ */
+.layout-region-demonstration {
+  background-image: -webkit-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
+  background-image: linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
+  color: white;
+  font-size: 0.8em;
+  margin: 3px;
+  padding: 10px;
+  text-transform: uppercase;
+}
+.layout-app {
+  background-color: #ffffff;
+  box-shadow: 0px 0px 1px 1px rgba(0,0,0,0.1);
+}
+.layout-app .layout-display {
+  background-color: #e0e0e0;
+  border: 1px solid #ddd;
+  padding: 2em;
+}
+
+/**
+ * Regions.
+ */
+.layout-region > .lining {
+  background-color: #ffffff;
+  border-color: #cccccc;
+  border-style: solid;
+  border-width: 1px;
+  box-shadow: 0px 0px 1px 1px rgba(0, 0, 0, 0.1);
+  padding: 0.75em;
+}
+.layout-region header {
+  padding-left: 0.5em;
+  padding-right: 0.5em;
+}
+.layout-region header .label {
+  color: #666666;
+  font-size: x-small;
+  letter-spacing: 0.1em;
+  text-transform: uppercase;
+}
+
+/**
+ * Blocks.
+ */
+ .layout-app .blocks .block {
+  padding: 0.5em;
+ }
+.layout-app .block > .lining {
+  background-image: -webkit-linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%);
+  background-image: linear-gradient(rgb(102,149,168) 0%,rgb(92,133,150) 99%,rgb(92,133,150) 100%);
+  min-height: 4.5em;
+}
+z.layout-region.layout-block {
+  background-image:-webkit-linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%);
+  background-image:linear-gradient(rgb(123,194,170) 0%,rgb(114,179,156) 99%,rgb(114,179,156) 100%);
+}
+z.layout-region .page-block {
+  background-image: -webkit-linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%);
+  background-image: linear-gradient(rgb(137,211,124) 0%,rgb(128,198,117) 99%,rgb(128,198,117) 100%);
+}
+.layout-region .operations button {
+  background-image: -webkit-linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%);
+  background-image: linear-gradient(rgb(254,254,254) 0%,rgb(225,225,225) 100%);
+  border: 1px solid #ddd;
+  padding-bottom: 0.5em;
+  padding-top: 0.5em;
+}
+.layout-region .operations button:hover {
+  border: 1px solid #cccccc;
+  box-shadow:0px 0px 1px 1px rgba(0,0,0,0.1);
+}
+.layout-region .add-block-press {
+  background-image: -webkit-linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%);
+  background-image: linear-gradient(rgb(245,245,245) 0%,rgb(221,221,221) 100%);
+  border: 1px solid #c5c5c5;
+}
+/**
+ * Block operations.
+ */
+.layout-region .mb-block-operations,
+.layout-region .lb-block-operations,
+.layout-region .pb-block-operations {
+  background-color: transparent;
+  height: 100%;
+  left: 0; /* LTR */
+  opacity:0;
+  position: absolute;
+  text-align: center;
+  -webkit-transition: all 0.3s;
+  -webkit-transition-property: all;
+  -webkit-transition-duration: 0.3s;
+  -webkit-transition-delay: initial;
+  top: 23px;
+  width: 100%;
+}
+.layout-region .mb-block-operations:hover,
+.layout-region .lb-block-operations:hover,
+.layout-region .pb-block-operations:hover {
+  opacity: 1;
+}
+.layout-region .drag,
+.layout-region .gear {
+  background-position: center;
+  background-repeat: no-repeat;
+  display: inline-block;
+  height: 20px;
+  width: 25px;
+}
+.layout-region .mb-gear {
+  background-image:url("../images/gear_fff.png");
+}
+z.layout-region .mb-drag {
+  background-image:url("../images/drag_fff.png");
+}
+z.layout-region .pb-gear {
+  background-image:url("../images/gear_555.png");
+}
+z.layout-region .pb-drag {
+  background-image:url("../images/drag_555.png");
+}
+z.layout-region .lb-gear {
+  background-image:url("../images/gear_555.png");
+}
+z.layout-region .lb-drag {
+  background-image:url("../images/drag_555.png");
+}
+
+/**
+ * Block information.
+ */
+.layout-app .block .type-indicator,
+.layout-app .block .label {
+  color: #ffffff;
+  padding-bottom: 0.1667em;
+  padding-top: 0.1667em;
+}
+.layout-app .block .type-indicator {
+  border-bottom: 1px solid #ffffff;
+  border-right: 1px solid #ffffff; /* LTR */
+  font-weight: bold;
+  max-width: 2em;
+  padding-left: 0.25em;
+  padding-right: 0.25em;
+}
+.layout-app .block .label {
+  font-weight: bold;
+}
+.layout-app .block .type-indicator + .label {
+  margin-left: 2em; /* LTR */
+}
diff --git a/core/modules/layout/grunt.js b/core/modules/layout/grunt.js
new file mode 100644
index 0000000..79bb9e6
--- /dev/null
+++ b/core/modules/layout/grunt.js
@@ -0,0 +1,66 @@
+/**
+ * @file
+ * Grunt file for the layout JS app. Allows for linting and build processes.
+ *
+ * @see http://gruntjs.com/
+ */
+module.exports = function(grunt) {
+  // Project configuration.
+  grunt.initConfig({
+    lint: {
+      all: [
+        'js/collections/*.js',
+        'js/models/*.js',
+        'js/views/*.js',
+        'js/routers/*.js'
+      ]
+    },
+    concat: {
+      dist: {
+        src: [
+          'js/models/*.js',
+          'js/collections/*.js',
+          'js/views/*.js',
+          'js/routers/*.js',
+          'js/*.js'
+        ],
+        // For simplicity now
+        dest: 'js/app.js'
+      },
+    },
+    watch: {
+      files: '<config:lint.all>',
+      tasks: 'default'
+    },
+    min: {
+      dist: {
+        src: ['js/app.js'],
+        dest: 'js/app.min.js'
+      }
+    },
+    jshint: {
+      options: {
+        curly: true,
+        immed: false,
+        undef: true,
+        browser: true,
+        laxbreak: true
+      },
+      globals: {
+        jQuery: true,
+        Backbone: true,
+        Drupal: true,
+        drupalSettings: true,
+        VIE: true,
+        _: true
+      }
+    }
+  });
+
+  // Load local tasks; we should add local tasks later.
+  // grunt.loadTasks("tasks");
+
+  // Set default
+  grunt.registerTask('default', 'lint concat min');
+
+};
diff --git a/core/modules/layout/images/gear_fff.png b/core/modules/layout/images/gear_fff.png
new file mode 100755
index 0000000..dfd4aae
--- /dev/null
+++ b/core/modules/layout/images/gear_fff.png
@@ -0,0 +1,238 @@
+PNG
+
+   IHDR            sBIT|d   	pHYs    ~   tEXtCreation Time 11/14/121   tEXtSoftware Adobe Fireworks CS6輲  VprVWxMKQτ	"h 2&bpZq,E\s74غB?@]AĥxRP:~˜{0dsO|e
+i'l%84M9=ZdYQm omMo?h#
+!^4{?8.O9OLq'U}[Vk=N9_˴kk91oI_8ۉK8U:o%/uyos%><tVI$&\IG%ȿμƊ=o.ycy2=sfřfg鹒'ggy(пdӈw9n/tW?|CZQ;jQ! k:_[?ڪ?ڪBmk(_[5+cMIPT,%6^Mr]Y3ꮰT0/d*[+4?WTKZMM{]M   HmkBF                                                                   )3  NmkTSx}YwG&dYUS0/:{<H2@ʔ_tb[RϽ7"̈IRYrFDlbrpvaFaC8wu^XazXtLӋYM'gpyRo5t1?[/z潤7z{gd ?o?-zzpmoHthoAe]x}	`C7MG8tG:lr;#>9{G6ᐝd58f)kc[C앵؝ᑃdG.Fpҁ.V<`3}s޲,BP&=S%}ةؗDǾ^)й!h9$G@5[Ua:<Z|"Oq%ua9!!1t3t
+98bØNDpA	uTs(y$bPkӉ|{g_ Yg轒P5is]co[Zm-$D2kcFҵkVp
+]:k;3gx 3$[)b%Mb-2%К"N$T TUrE]WA'puN
+Qjj7|PJ"&Mq>*8>Ybx>$i&&xNDL2a^A6㘹wРj#9&|
+3i9102mHIGoE#hXX}@dY\}\|6 qnG&0WpuK41['@VEo0fKcӘ
+ˡC|:QfDG):*V
+*3橤c&{-pG+ޯIPP.Pd"џ1}b^9\.yW&;SvBy"IYKRft+`H3 'eO|^<̯cWVnA^\UwJT؛Cެַ'gC8Az^9NrADa&;'ޚIw	bXAcBX)B|6K1B>Cȿޣ&{3%`L3ӌ4S#L7imB!z;sPM`KKV9uوA5Fۣk^hzMJF*[bDܴ@M@V$ٵbgU9D&Fbպl9Ťkr\_T0RJRl]!{sYk܀`!e`~cl6]t5[wqf3:\)RF]I,mrD,Lg6 `G*'j1|Z+FcJqGe>b,@d@u8#F&eF׈D؄Dr&A٥CV`OxN:d%i\bEV~D8ZS+x1!@"ґf(*&' O{?Tp1{'[س&/YѲBzppvH@Go)Wאr3i/3i ӛSNN<y"GqBM	7;mJe8c-|ڹ$q|sS"5ZpPE1܂	uWMWYɿg[SPRbZ.(SU߂'^þÉyj}r7c@Q%Pgy hG(YIAiBìz#jN1<桐RӒJ$9bjهQm[̛HBj٤l}}s93"ͮv0IS=b@4I7/[ RBe,(lWHfr#w${.m/EYUھ0Dg- rj:QM&tѥ#ހ9hItU)LR],m4si,>%8p~Fٺ0*D瞐\g&nׄj1:㘺*LHļEq*Eds"M̥x=E6 f׍}Zxjo-VaA~O<?G|%y;Ih)	K)K³ٻh`XK\9*eJRW[!#Hs^-9ga-4GcҸb#(E͜HQc>N ܥ0fĔlQD`aEXvXV˰9泀yf.Bj謃isЮˋ'/3̔t&|&X+/h&dA51U#8
+^WyV0;lyN_f2kϨVx2XYI*0ɮT5DmU\)xSc3q>sA;i}g(y-2{ut"uN:eʹ|\BTyFRafGOJ=?"D*":}Ȧ_<!	Rt)7΅44k
+ޜT&`KڪUKp$[SocI*MELŨ2YiiJ89߈Q'W8;F#hx4-	xXYflRWNj%u	yB|>bCi}n]_H6{1}n32bXU钝]_k/uy:$K[	{YMoH@(7 V%|e=}nǾ5o %0h"1q*='cc%N`SNvAvzLƈgIK\8gkFKl)ΟԜ_k>1LS8:HvzLi`ڈYd)ΟԜ_icZ1m=L^9~y٤D{z,K㎥k.gb3iB\+aJ:v{yRöY|qE+nXXw	-\V<^qzL[2-;]"WsgyRp?#N10:0eoG^^6I|Ds}Nڼzǡ]v4to3RQV#i]'	mإUmx-rUd(wEWy]0*Uvѭز採ѹaqOd
+|Ub7bDU?Kܟs[dO."ʖ/7,mvaZLksLƄ-+o50	<qeaZ'xwVwR$lƟgAj	Taw>My@)_HnogV+G%⣬;jw[~òTҹ~ї94SE
+ŋd]qCЊtZF˫E&YΥΞǡ=s!KZ2p!U¶##Uݿ%y^s9TC/%ps/D+ʯA2]̓E7ӅW椯-*uTe?
+q:q@#h=GÆGmGFzKO-;*E_!qbku1Ҡ^֕wFO;t{NkѧO̮-y[`3~n??=
+5ʒs?oz{mFe|G8ù^J1=^pźE*DrQZ'Q³gl{C]BlzNb΅pŢ?_෕b$gճ;6r!?aVs<&3;@޲@Hj^q9ɹ	Wx!=Grk-]W3Z$g↌UT4{Л7䩗.ؒwКgb{*nK8"?xEupQy<o^*aGZL!-7\U/=-=9R+:~	lʌtN7DLI N{Ŵ?{zE>LI>l+/Vb'OzMwnas3i/=ѝmFA6.ZKg;[gΝusV@ߑ(,kBwY<X:Y:˶Νu9KBw+ng;Y*8~ٝzmf:[տ;},t_ٕwltѝn7ΝuVuֹ&5XyYBw+:Yhy+:Yn]g;l?ʻBw[yYB7Y۵ٝVu6ٯ9Ia	fJKVeo,dޓ$|oaT55|M3XEWkuP֠Z۸mFYZH[*m-K[\0"뽱
+âEY_q4JY1ӗX~-hFhNg;^'ψ2՗7B`Jѵ}ېm@)i+h뜴u!Z[C+PӛI'ȉD0/f}NQ搧Yp5&ϰ$<
+fo3Kd<l_%%]MiQG)iN-cDLJrQJZw_@/n{s\s#p
+,qu{}{XL_ey$*,$J=dMysC2'yO/8	e0mDe\ƠuY1+G`yln4Ni'Q'_w\yD"Q7yd#dwAlbP(\L$CmedqyQP,-S甋|7k.7S&$aKJr#2}pJA苧G_R[G_/~w.?C@~Rտ
+t->Q"aj;ruCȼ~P;Ǣs=Rc%Hmط:c<l3l諯Εy=X"ɶЯmZDkVi<U>G7to^mD]"k'ՖE"IؿQ~;펏?]o/fdUq}v?*4q*i>,}Y+z;{K{ r$ֻo{lw\e6jت˨ݩUUfB_~U\sJ.ʯ Q<YRLXAڴ2rYw,K\QVoƥtKԮf%'416׸**l?K`<<ӆ8mCpH3f%phl}KjX$p/,nƓ]23yݱLLߏ2zF~|w)ޙ:_>Ix_p+.z?+~f[w0F[Ҝ8
+{>^ol}ۇsM?X>\?/R4WT8X]CK޿>[J)8
+~@G=b@S
+b3EW	Xc)IhK_so틒 W\9}Ya	CJ/fj1"IYi$5?%YXP\䑕H*$ZIx{!)o%;ݖOO^c>+y6'V"pNRPF|9~_8q\m6GM^Vę◳5l&~Y	f['`kYT?LvYZpkț{q\,^уWT	}O"kld5}<mp;w=,[dW6uzdwq{Q_pOV!ϩ֗]	9>5]ƈjؾCqx=Bƪ_]QPyFЖ+jvyY_H>]j+,(F,UX;WwVv_-6&FrhMk|nSmކ$YNה^K+}~i,r~i$e5C2wWz=rрOIIsQ MzrdaAߐ|qLP?daN@ ]޸,|ҟ{kpwh8HΆWW[2Qd$fшfрV4x\9"ц'8gj$oz5(tm=֏	Yfkͽxdʼɝ<=0x̭oO/#!!߀<O̑bT v)@uOo>o**iק2x&)r.mVU t<y%E)UptIOd<QYqcol]EFo5fo^d⼾S:sR93/;#:L.v|vaF!2k{p1~ާ[x%?>ߡ]{5g)6M߶t%9vqvqʾ=ߧx;1t@Ss}<?=Ð4>=)};>@"{LՆd$P#-"^x8n)OEC6;X# Fpj1ZS~tsoSw?b't=آ-6<t?:N/:>XmīChƻ{32D>? d\0+hF44 فY8l՘"&#Pe
+MNOǫ/[/A~'}q]Qq't6>'GA?}lkzݴZUڳx{wvr[knnk|`2&cpL;::{',8 :M/~pBʣwx{pɆqN|_wkNq/iߏ"7įy< |Jd0Ǎ1(6ߣ잎CԷ /uu7az(x5ZLz5Df`ky#Q^ؖڞβTPM64|hB3I	HL#GQ1 kԪoUҷ?ݰkEF8q3|녁LQj Ќہ9N jۏ-'=BZ:ܾe{5}/ S"ߵ\>(\~خ%zVlPEKcvѳm7e. 6?b7AiPl>{{~+*uMAOVWE۱9|TRSiXVB 1eXS oӷhŮc؅nӘ~;jݘ]6̆-9aؙb>8 X\ *8t(vř㌦ą`k^?ܜGn̨zUOq(02ľNr*7C~Adg$A,UD0U18HCVnTJlc<
+++Pj9V^V8H[.F<Ê,!h(g$m,5y0YKUhyA=>-	VγqQ,V[.m TjN,\X%XzmʨFg2?LZ)7647V몈q9	 E'c4NmQ!:h	8sM@+}U/#TZNaDgQrubqyS~8ogD;Ige*d[Z~I;,TW
+ÖFj{;̩Mypp΁:8NSEzgQ68LBя<A3tr5EVF
+ܰ%ne.0DNJh¸
+"r[ƶ(`en,u8Vẘ[)JULv	]:URn1uHߪµ2XbNZj+ZFHVFXlW0g"
+&V7}9^4k(ZHD,{dǏb`[)py~=i9"a.ly~Xl <v=@(E*
+q#X Jջ<
+bkc jxBעutHt n@zr%&RB7HTb?x!X.
+TBcgT|GeR$*nE}s S*@nN% 9FHT<p=ANjy˔
+;G/1s"2\h.$=VhEfs"ADPyqɄf-)LM hzsUd
+fHDV3	$""m9&b[m%\Dd3[ێZ*R"rc-:(Rg4AU^ľhS˻\搩Xl.?Z\5.D&*d"Em6LeTZ-J4*B3u=1 *5k޺yӏB$X?igA	CA<Ze/zAޣn(M^e'5pjREw(@C^Rϩ`gRFR]	E"UMU{i31UTݬh3)UR{6P-.&(]G4'$XD $	l[e)M6SZ"^:NY/H$*z%q1`,$9f*8۬F=SD'|Xݬp31VCgQ
+Do~KDV^2KhKTTp
+[NDu31VyDdgLܰ]0/m0yu<5ʹp\7;0L*SO7SuEћᄺG91`-1_:rNa A KK-e H(TBiM؂DJl"
+eΝZwT˧4TpR4pVKþg{EɑƧ^Ϡ!k>5p޳!JPiv@e O>K,^Bk(,1vz'hc(9we}HeޕT"\>g>}!+;q^3õJbbXCIL!iLKy&X W+GH?&qj@\Q!KTw95NIBnlIB!I$a4Dpe^b
+EW1Q\RUES%,*Z5RB8$*D"*yObrٍՓ!-ѕ㈃Ɇ0j"zh(Z	hHbݜa	)i R/H1YÂQ rfy r&b*5L
+DefIky8	.Jq5LAzf29B-RiԥW"szyϭy-7kź|C/וٵXp/N!#TD$$Ļ{wY5wGG9[mdb[]pfp|ɎَjCN!X;÷_Z)>ҮxNgՋ)]:Lq)g]?!8k8A7 v{5]>9;zIysz>elћ[ew_zppaHiJ/ރ>;HCNLh`DF`Cvr:{Հ/3SϷ+#3<rȥ}Ñ.V<`3o^^!G(썟;֖+?:6t=m>szO&t%xC׵@jRq%ua9!!1t3t
+98bØNDpKy;X
+Z3v̡tI(AIL'61sb7+g=?/^,]#6Z566$JַdtfbBLX5v
+.tr+
+(&wi [|=d+YIQQ,EZSĉV*ن
+Qjj7#|%:$bR>΍3*FAݤFm=v%b"]xƾs}`oƀDW1e|Gm+$Ssxܶq )&ziqcaIeqIabr^tĹ5Kp\5Y.fhl Ymqiyx@fKcӘ
+ˡ;w]n&f"Y0Qd bh
+ZC+` ~*n̰ۈbPP.Pd"џ1}b^9\.yW&;SvB?iIYKRft+`H3 'eO|^<̯cWVnA^\UwJTcqr61/'q~hs&;'ޚIw	bXAcBX)B|6K1B>Cȿo^oG	<63|ӌ4c0͔~0CͯroPM`KKV9uوA5F+?'cQ#-1"nZB J TFEӊZ3*7
+M%*Īu*r5I&g帾$aJ$\pe]!{sYk܀`!e`~$EWu'`6ɕR,Jm$Е6(gY8XNrt(a#xxrç%OjM"cH055qڂ׈d ֈ1`p`H$ (8
+L	IXsZ-שX60_*7λJ<y{{:t$Jɉ#$&e?~ &liIKChoPkn5[5dk_#7K{LZ#T7S>|Q\tPtM3@۩$gΘhU\p$q|sS"5ZpPE1ܢ?DzC^?q]mten>i;U-!}aEib"=EW-y);A|,NVͤ蓛rƀ*:=˫@ > ~gOM'4̪7Һ<6+cKic
+.5-D23/&ڨV}ܶż$M9JNY
+l7XS9#:oc<c*F Dt :*YV^΂6ydf/'<~Msc0}aZ@(P԰uL
+Ep1KGW_s2c$銫RZiڻX5*VsO?i*Ҥ9X}p_GK_q4K&dE3Lu#LaT=!ΤMv	Cbu1uU&:ayu-:U(-E͙Kzl(,+ZP)x~ϏJ!w!R=Sgw=Ѻ6$̹r2Tʤޥ0QBF\E2暽 ' [r) ;D7\cy[h$qGgZ0+9|t8AKa͈)֣2[/sK17
+<y~~]^z/;`湊_o/}C>N3g//z40SFәTbeO, T*x鶟^X	X4R8}E ?Z`e%8'RPJ|	TŃrQL-Q9T5 ϷH4-kӑrAJ;mf`ꤖ7jCq	RU*ZcH]s=}* NIXN|D!~`&dKѥ<s8^ЌWB_Z`?+L{s¶R
+Қ-ESTjڒVkD./Ñl	gOٿ9sb&q4U3eFORb˔
+rgE)4~#F^1@F6dHL&;a5*gqCI]*_9^%8=z
+I)-Nt}.ً pw{ŊEJ
+^{׬ӱ$]J`κmz@
+F	*Q+es;ǜ} zU_$&>Y;cu]s	pNZ<Ȯ4\[c1b6I3s)kgl~hM1 qg\;]ic
+7R^ΟԜ_i!cZ1L091-bL:Gi;]4+/8TwhX1ciܱt,\|6_q|v=v%]IǮ5u/O
+Qs6k9/|qe=-.~şˊ+ΟԜ_iKƴeǴKb,O
+qdIõ2BҴ{Ck3鑯hIW8Ky·cƀ]*wj$k4в2VZ}"* Fr[e.[1C3:7=Д^OOTV,eW=ī^.5smj]?b?X¿*[߰4d;مk3͝3:Į^	4z$NPq/dTJiెka3ԛ[JQxo^\9mp$_Rjq~{\*7U|"EYVC @mSIJڦE_ ҬN%)\/򓍚w+C+i-γ:Td9:{΅K/ojifĒT	rTVwxw<Su*TUb	($Vt1OULn+K\~Q)F(K<Ti->wC}ĉJz	:WXW?]JөKB9F6?pyehOߢQdI9ϝ7=&*#N/ÞlE=+KO!e+;Y³>!.z!]z6Y=|N~sz)NBbџOwWJh^1@~C+'柰GݏJwg+Yf?|
+NoX=p5}zD[z}+<^K~╖C-Yܐ*{XߕF~zRÅ';hf37}	T ޿)?x5oQy<o^*aGZL!-7\U/=-=9}R+:~lʌtN7DLI N{Ŵ\ 4Q3%P+OmZ?)5݉&uǭϤ?Cۿt_v;Y/B߯ZF6ltg 8&;5[gΝusV@ߑ(,kBwz
+eczfw6Ng;,.Bw+в,tgoB+W=װvgouVuK7НVuMfWu6ʻFw6ڤƱwusΝu6qʻBw[yYB7Y۵ٝVu6&QM,tgw,+|NRXB5; ox}3տ{ٛ($-[D %UuAwEͽ._Lnsf9y zѕf5hiKfDmFYZH[*mVi{̥lh[.oX3 뽱ug~Ѩ+ig}4*g_n,*cnڒn-h=vhTЏ{t6ѝ~"(_}ySk7gm hrD1zJZUkkH6Eo6NƯG$ ]j|TLJF8!ypzԶb%{OHސ$!;E@)ـW9,!'oq+PӛI'(յ;p9Z^J_O{e2+,8
+m:J_IR4w>#YIβ-"K=խ=\F+n__zT|5ŧO G[_m8em&4)׷T7Vї鋣f?T]OH@@ڎ=/{'XP|NտG
+4[{B}	{^Boѓ{p=ʆM}*U[E+,ƭ`ycF}z>9W<3%unJV\:r{N c[:E^e%*΂<ZV~U廪ȩRB_~*sC^hZ]g y&gϨKLR(y~ΠuDI+jYݐ띑_ahO/aUs|
+M|_%͇R2?vToE[ͽVG'dXuHC_Ii7(9^
+c*M'̺7}O{lVu-vH">Zəm~AGuǽi{{Z*U%DWU	'JJ=ggv~t_<fĕ\ia+	ݷ|-[
+ۀ~J+,AJH4[RY>:|a_|E{cde{w!vo5]oH͉>d,G#];hc䯀JD_p+.zy+r1n}~^<IQ)䧺 }~uA۵>p2! gY*6(ie>;fj*	-X)IhK_s틒 \9}Y0'6=K'pň$|daAGV"%h%a톤뗀v[?U>yU6 |:n9 GISrVy|u9~}nr'Y1,`;YEhը?n<o6p¦up)UlXE:&}+P&s}N<tvYy({q\,^уWT{O"nd5}<m/;w=,-ϊ+uqFwv̸ɏ(mK'	G_PuϢH2+=\M:y^wI#2Y
+mӨ?dܦf mS{=nĥwl}6ZMQV%W&evʕ#ᩔꍱҎ6shY MzrdaAqnHqWLPN07dҽR3G=c\e
+s pޠC&"w,IYdQ}4Re=#OQiã{u^Pmkɂ]'OJ1!l܋Wb4'{)`{?>C(~9	!UByF"$#%x:[4S~;~8tFME%T/$D!fKsR*Œx85$9Ǹ1\^JN"_zHb滩u~X*7y-={	̯֙}B'BygoܣqdgnpdlM<EZjľVqnWśHS:sR93/;#:L.v|vaF!2k{pOcOspɆwh^maMlmmӷ!@f	w}j]xG0wG)3z>0CtOO0d)w{zlOq0/mJ1K8d6QAGZ:ѽ	'p:"S [x.`ElvGx?0_b6?:qp;ڧ)^mN1p{Eg[mxbt^X}u|4f&>%Wн!\w7#7b>;iLiY|\n 4ӈ/@)!@mxX4]ld¸}{pvp9`qMr9|N\G-Ar?}h`|u0V!m'4Nq>No.0)\;~W)nQ51`OI}<$zp9	l>D}+YNݏ]ׁPwY 0~ߋȉW$2yGDzY4b[j{;ښSC6X`	$Sj&"M3vqD^NZAS:V0H
+wG6 u~ 3F@3bo:냨n?8
+t#
+~h9hZr^֔8LiPN?|r~ƶ/sa~YqA-E϶0
+,G۔w؊=TЏ#Ay߲B}e-45=Z_ijLmQIM_bUZ5A?0r8_lccMGN"bMc
+xucv|L632׶A`g
+C׋ ~`q%r<ӡo۱dg3nB5x(B7,rs
+1V=Cuø
+:gvu,AITvTTLt26 M[R)9U(XRrn@ZyZ me+vH|\V+,UXָba;?d!+.-7W,$tZ9BeG]Xϲ^nYP";9Hs=c\K`)Zqfl"p3aja, ܌[aЮ"dC_NUl;l$$~w@";)F@DmJRrSN&76fAT<Pi9Q/]FYlFqMἝ$E|q0yliq8$Lh
+SE\m*[zѫQlN@36Úe;*:<8-LqqD٨0mAG? ehY)Lsrd#,,sv9z*9*mۖ肕U2Zb^Pgn(-W3% b#jwTWJM"}
+`9iaɯh!яZaWs_;m܊P8(WfX sxѬk!K.e~?sJEn]aRZ@(@Ea,T e(Q`6+N^Tr*T'S܋	^! ^ȹHcf@C\#Qc܃+Pq^!QUKœ*YD-ϵXO@X9  6Q Q28C8JTy,S*F%^p%#3& z222ÿZKuΉ4hAA'66c\9014yUa[+#Y͔'ZfP"2mD33pARvdlm;jHe2LHE<Uybj"EXL-BsCN`!,,h!rY[S׸,^<4`X3Qi*Z7Vd#<'qHl z2N?rbsbbQv *&!hi@y^%\7yéI1y]@3Kq|"<?	KBH[w%gT5Tp6Ues`TURuͤpFTEK=Lg@U\付<@gwF70rPbISGd&	c/h 8V '_m~oi4ILkT:'xa8A;d ~ŀ^h瘛lNuҧ4n&
+bupBXIWΞEA*!-MkZ[y	ȴ/-QQc7S)l:upZA2 sv!,tbB	È
+̞7s%073O=L]Fo&Jb`Ā	`_|
+-R_4:XDS.K,Th"PU5a)-\g@+l:wD.ShP/^PJRS5
+Z-Ŗ%Gz=e<L
+Z{H;</7{Jb`z*IC_XB-E<\
+.P{B
+m؁b轞آ!ճ?!yWRr퇆
+ІyHCn()Whhb%1!f@J!d3},mT䙸rbG\"1Whǵ&qE..Qp8I$?	!I$M? #'/P.1z*]TGq}KV*Mh
+^H	Xz3@$=E"e7"FWO6􆴬FWN6ώ#N&
+@dVè1h%Z!}ts'ВƦ\!.KG[#U@dZFC ˙~-@CAN
+hOT0)iUҚ%&@+09l;ˠVLJQ2\[»F{)=f7>+~ @}%zv==V=[W3<wzH3"		.{~xUsWyNy#9Kޟ曥OFKvTos?O>XNg)H
+hѧljUm-z?A/n5[mmVJ{p_(0|wMiє6Я?C%`.QA   mkBSx]N0 QʫajohlU&fnÃsfd,>Op3]E1T	яjV2ڃ-puyGpodl`d/e>v
+9]Aݩ6ٞGÃT{1H	QlH':iуŏpa'D:__CE  ymkBT 8                                                                    x횉m0]HI!)$FR?6c<lHٱdtC"+RJ)RJkJ߃L_SUn7ss~uU-Uyy9c/Juz?i>>>~ sm+vuՑνYu8uN?WP>1JsWiV_uKEϸ/r_gKW]ױEYcl,[TYHT}xL#}A GV7^}>iҞ-i;}LJX&TP3T#ߨgJl e'=?͘ona|7>?ǐU%;/mN/IfQփz{<d6dn;Qm{{5$iѦxg<$"^%=RJ)Ste/֔ a};k_y?9Ԛlz}m#GKk!k(9G1z,Q&liV濊#_<3Ξm$^9g{9&w&:˙uf֚R:ֽL+mWW^z%I2loZf?k4W-#	?V/c^!!{u̵ʴUٷAGe>G}?v✽3X~j{zTAO^ʰ>?sy|G)P</11~2ў׆R/7 Ӿsmsr"(2cϹ;~u-)}<U1g:apb5{3(k!m'mʞ2.~[)}GκbXELpaԃ77Fy0@ߋL?󞕹Khi@=RJ)RJ)RJ]M;;j7]&  SmkBT U                                                                    xi`Qqqqq!	COMlS$I$I$I$I$I$IqO9˵wOo]ss,Խu˲<^0tc}av=7_{V9z}ٿ^s_y~?}ez۶@wE՟k$I$I$I                                         @?
+=T  mkBT x                                                                    x흍)q ĉ8D^>׻gI@XjjgiЃ`0`0?ϟ|:s eQ3|ӧO|:2|.};7eGFO6_Qv]T]^ˮg{>pjzkuo{yye?{-x/D:3D&򈼹e^Hyi#/OGzϪ߯_~
+:sMe#M3Y#=2QЙ[\s=E8}E>GȩTڲTg-}VfoSVwzV}./>~<Vrv@>!?U1<#}=F[ ~QڋBN..+푹^edLo+[\-kdW(}6q$#?z6Bөi?L7!3O_Q}Пuo[=tkȋM!'}/Ƈdr2_Cﲨ:`0:8o=+8-4}۞cĥXdq{bUq©ήm!ƶg*ΪU\z[GA=^+ru{LV	U?)V>ғ)x|Yҁgi\yi^cUo*=!TY?rfgWsʽVn*VX#=Fϫ+[F~yH\L~[O҇h5ݵTow|Sfӟ+);F;:x)/OSyUo2e)Ve3'wgGg=J^`0
+ľu kU,Ksؑ5nY,bXw{w&3QהNQev	]ƷgcH˞i{A3I8hwduwUIWq8I>+@pQşGcZ\ƪUߝ]/:3d;ɫ:gB9R|GW~w2;fz<AǏߊg_ly=Uy3= [6_3]U_k]]ײ2;j->t|+i5nΟgZY|<1NyŬ|E7k?z/k><=Α}N΅>uWydʬdz`0*\?W8GY:Dgcg<2+'W6qn؟{ru"w<Tk.\rnO>U쏘~c#T?+y{Q,,^qF/Xv8.֩g3}ȸOP~n%hUG4(_sn|W}Tg&x^c,Fѭ+<#+}/Uw8BRh_|33!mr\7U9m({ѝpvew[xG]߱?g;,nҽow8]וb?OV=Z_#ve?vN_WrYLo;1g9pV^G~>[_vNOS3`0Q[	veO\k^8 ֔v<Zbz\Opbn$~}oz3јmKvU]^iNWA#x딫jtq:E=z%օq)CcYEqyRG-+u(K\hP'*^ء^q=m=y|Kvūe\rȊ4={W1;=ݷxp;o@>ȘT\Ԏ+C=*ɫ|GJOCW]x1.ﵠ9_EбVq)v(ʑ}[GwǺ{-oSdו_˞׃2;iT&w*w:g׭SOsj%Z[~_˯d֮+w]7`0]kIu+eL]ւoA^;=GR? v쯱;<y o$N1紈=:ߥPVu< <&3KyC/4r)i=*/|Ύ^]QNН1qGw>ù{<FVr2nlo؍ا|mo'qbӋr`eef6
+0lzsA_x7췣*U}R%+C_	ڟ~I\Q~ky#_jo~DyU^`5pko?:ˮCw>?Kv:A}E:_n+{u=rq͓̳]>>d}+|L01`0leg:׺񶊝`W,3O?]\9P~[kOWiGc~)-<w.3q}'vuw$Vnv(r52S;Wk_Kϔ8B/hEՠ'9w?K;x:x<|@cϽVyc@ۖSw8Bq]=2lBe6V}eR(	VeZT4ade2ޒ+nYBTqSߔ<[&=f[|szP)G}{Zׅ3n7jpWwftEw[ǽ;`l?`0`0`{~i`oLy>uoi\qK|} 7Svu9G쯿c¾#>,jow{ՆݲL=mW2u_8دjo?kD߱mw>#}E:OۡO;<sy}ڛk}~|M'8CTo+[WUQr'\'tTYwz.D=W|~q=_ yMǏktbS=2|ұyN_}Oe摽ۏtLS6q`Cjf3#ܰ?z1H]\"W]O;2'@@~tG:{u7m1Q]PWV2Sz]ϥzs3]vxwҞ:ڗ>y`$j?tU  _mkBT s                                                                    xځ	@FhGpGpFpFqH=;OxkvmX*}\_q\>߇ǹ+!f4cӶ>saTڧ?Oլ}MΏ&w|-%_Xm9-׽^i٪nXg?WO@p~_<)el-Л                                                      z2IY  
+mkBT ~                                                                    x흍8FSHI!)$FRHnwHYx3ꇤ saaaaxIǏ'U{o_ھgW9o'GW{>~Jlo߾)*/N\ϱov[iZ_ձaJΝ/:6O-92b?Tlk%?_21BsY5>:> c=1Owy^- ڶ,Xz usM#גU]>H_yYv!ۉ_miRus]Xm_g)YY)m]y,m z1aaaxEߓGקo/Y\k6xjgH|yu.\aæM&wk#ϐ$?]Mo\Ⱦ,/ڥQ@~6s?)}, lgX #vQgBٙ^uのuhm?}{].~}v_J;xogJY]޳@.)oqC?}>@Xߘ'- (W?	źvƔOʙRv[K?[A}?-wmՑ}<GcK1}uxLzަU00Pc[<>g\=c}Mggg	Ǆ-B^k_g?F? v0||؎=ǧHPgs/hؑIt~{n^}ZyD5XWvO)"c0vYZ|~_%/,p\ɹyΰZ/;/xs_9?Pܯ5ݻ\[y|č8g ʱL{?00_k3>z_\S|<)b|7aaaxn.ta?l^Cvkؽ#~e)3<3^kdlc&jK+o"e<.ʞ`^(3zu
+l+6v<ïk7]/lc[`On}򚄫G뎱zt^v2)?;Wmr5ocIz?Ozx{&!ez."ѯ1Gg{+ҏlw<=}GݽFƨ^)zIpGK ֜{{eG12ۭqiumf>.}~a?00[u+7Svq֭y΅
+?ނ}XwŶv?ߩDZۓ-q/?߳=<~#>Fk"qzrQo	9r,nY[;o:)@-`ק-7({߯S@µK9֠ɸ>:n3
+_[_*mtcmC>qSL<?<nѯn!>=<6;ǫsaaa{xˌ\ފpx?0׋#5zяc]x^l򼠕(f:~٣^lin59W~\;?vn6erUbS~v^UO7O(|;+SG4|?f*?rW~2oNٟS9~daևmH6mX[J~s.ym4ٶO|Bd/b5ɿyU?0000000.P~*1@G\⟿KrKXs2(ߥ纎J8'>X@▼QQbqwxb)_K|v 1M6kee-2Ǜ59?K^E~9ϱQﱮYF8N?~;:=J<-t ĒyNAgC	\NXKs)'^Kg\~2}6}Գ)n]Or^j~"{p29w6/.z-v:+M{WJYZ굢`%Ҥl9ힶկ#OUz+U?;sd~vND7*.Y+v:ye;8}~|+ÑޅN9}{Bƞ#txխsXɿkSV/uJ=oG<ջL'L:D]6jfgLz/+ؽ[{rCMYq~[{yy	czA;w9zszWHVax3  ף  2iTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        ">
+   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+      <rdf:Description rdf:about=""
+            xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+         <xmp:CreatorTool>Adobe Fireworks CS6 (Macintosh)</xmp:CreatorTool>
+         <xmp:CreateDate>2012-11-14T20:41:31Z</xmp:CreateDate>
+         <xmp:ModifyDate>2012-11-14T20:43:14Z</xmp:ModifyDate>
+      </rdf:Description>
+      <rdf:Description rdf:about=""
+            xmlns:dc="http://purl.org/dc/elements/1.1/">
+         <dc:format>image/png</dc:format>
+      </rdf:Description>
+   </rdf:RDF>
+</x:xmpmeta>
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                            
+<?xpacket end="w"?>̷qO   IDAT80/Ul@FLp}q	I	s8T{@bH2l-(K2|R VΉ@]ٷ
+	x3
+`f]jBv!9|oKg|f?<s	=@WQr,d64-զ\l<Y¦gu] HNj .7-rDُ=8uWI<=Yl&:    IENDB`
\ No newline at end of file
diff --git a/core/modules/layout/images/plus.png b/core/modules/layout/images/plus.png
new file mode 100644
index 0000000..b5544c1
--- /dev/null
+++ b/core/modules/layout/images/plus.png
@@ -0,0 +1,204 @@
+PNG
+
+   IHDR         a   sBIT|d   	pHYs    ~   tEXtCreation Time 11/14/121   tEXtSoftware Adobe Fireworks CS6輲  prVWxMhAHQO"J4T-֞I-ؐ]=	< <'O⡞EWnf?fwgM$Iyd;yۼvPm6F^W*ٓ?cdlz^l c#~#r_-_6Vv_3 >t_8[vh=I5FcZuljC>XZmw:sLaeN_+xg׬Nm54>dhIuۨ8{qff9V-8+˞?_(㹴ާ;Dg^L]4+<#yDZ^;wR+eҚk>0'?#8G÷;)7ֳͩ%sOFw$wO&!-cG=^K}GqClx6' 9r=`:ZX "nT{c>kr--".O>㦞:ӵJz9RYltu=so 9ֹ~<ԋ.NH*(8&'ǯD%XiGxfPdUu.ɴs͟i=cǟ=gwĿ_?!/;~=7W|W|W|W|ŗ',~\ůq___o$G |oH?~&]/aψ>C3 ~C5	7Nj}&o:_d<?]u[?h5])rLicJ>%(CH|:ԯ=Դ8l   HmkBF                                                                   )3  <mkTSx][sƒq仓Sه}Qڪ8`DRPAٲ_\6IVUow6\śmH@`f{o_]?:gZa#8Xji]]k]ǻnsr=G?AuZ^+V\B9S&C~p\*JR){<ƛѽw̞g}uZvv)&}:kw:tv{t>Q^zC: NKCv?v8ZayXtuMؠC.pü 6G6Ufi?B8\D{4Ϭ?і?!:72fqv s@?Z9VsBzGiJ6c1|=}Lg!!d2̹3x8a2ǬsL`xc8#陡-HšǓPNl%]_z8P7{\Z݊([^y	{f}M5V趖ʐ$>@$=pXΰ4ii;tsʠ'ق
+5k+]1ȪOg+i1[HeM:*En!FpB6EH TRZ!uL]ibwg0\Ji
+*&Yvᣯgf75@NЦH
+=K'RoNʫ`3cj;wJxnHj#9 4ߔB3?r=QȀ8d,G$7fYf!w.KcF;A\L0j,!f3qƬ,'E4'z>ǖΠcN@t/V  h,]3r*>tdV
+9%2tZV`] ~{BW1f_ہ*HlbH&ZE(EbR-gh<qG+^k^L]	Fg9AOT(Ӌie1Yԙq/h>94lW.upU$pF6 \UWHR{c0⤯3pO>W,x51+:i|HP4*FeШ 4*gcʫOϾdB֍({׫uSg8J0bLb0&Jm42B(9_!4S΋beL͚lPN~.'79k3lfH6v`zMءHaKHj̐e~SvFŢqw tEoYĨu*m>z`,jׇ$T)dJy;f[{,ah\A7B`}:)ѝ=G
+my֕[uqz3y0kB~:Xjx,,n3߇<rHxpb.#b{8d*#\i ʘT:хڔǈa2Xm̀	vb:~b% `}q:pL~n%B! yהX>aaOG4CQ40))~Qx^RL\Im
+[ƈ3+CmӼ FB L<̗cfE-4LО
+k88F~}8EgqGE,
+5d:CN<)% |)?C@;'}J qEPz	?'43̝X,f?w`)sgmI51f!POcZc1Hz/XxprOV	'?2 턡MjQ s E3SF荰n/pp66L7"̙m?#öFAIc\lHez@D؟32y_8rҐQN`,{z֣ y \Eu+zAdB!+o!,ej0l1tK@ؐԨaSU_ㄩs5AG{W86IN+,.jq6̟4|a	bacH(..ѱs}+]gׄl12L'aiZ/h5X)O10dPfU)10/{+
+Czc(in4ԇt:s3{tЅ%f'-]i+d+0*ǜzGG2}P5)q' $Q,lےX>t'	=2sFL:zCD:h3j+^`Ev%ދ59hg_h_y^߾o:'M<cQvA>CxsգyWjMW$+R-a0Y4`vc~IV a+
+􂺯6bKJJC-;>IGw"@=(qi.nDL]Mˍrz?ߓ+[$uvqi[E 230iZ'! _٦HEi)0XbkJW@_ DAIS ?2$6MFKq0O
+?q)<	~d`oSNV-ebڒ\R5xu8pDǷN,IҊL2~}ӀGbq( wYD8hN-	$5 1n1zŽa,mN0E8V!؄*ESNRSUIgU^PPI01xx|7Q g/z{O|Xz+*#I߿i1M}DwCo@~#ߐԨhJ5L|F-
+{7&h ,I<2`+N/q E&j4 Z7Ld	=S@QՒ riM դf1Yn <񯟤\&&Z#`,p')׫	fBkU}.].DzQ>,Inj"m1jVm.6^3^BWk5UA\[S=m0EÔj2Mk`{F?g/~rfLhZh7Y	hIFZ5zL^bm)cKyMS{=bINzJj<zǮcgF̌ ((^kk!mCӐGѪ6ۦeQYY=TXaje@.!kFN$j%VcϚ9+R-nT3К56Z<'6'Ng+V7)ϯky<0jͮ\^S>+oBZNaxvGQ(lzi26_~_><X=09[3tHg"ZzȚq~,A8rzeꮛԃxbK,f>{_6뒦MLpEXoMѩ>H`}CXnVZ5Z^x/yZ$l6n5qL6DpIXkTH16G`⊨a*jMG#ԞxAjc4Q04)TaRyʘ%EE)ꮪ-Yu-`h420YQTkTnt7$kޢK嘿U~DoJɥz,0^]"ө3B`ֆWfy'ngNh*3G <Bfy
+l>+{HoF;P?kIE_Uѕ'6p	)*Z	5Hy[a;	?5N$3N`bGrkΙi*Pf
+ZG:ݽp5)uO/yEz;*w0b%"/?RO_.oriH"Va-/g	)h#9i%i؎^lKV[^'KcO&oAy5k(>ŒE~;ܥ;)Y#R+d%#5GZ(|F8$^ނ|`6ICw?jyTKn%~-o@091<.{[[ZN ʟr7º%.w8CJk9zm]st%G]3ڨf蚡0m=￬ٹf祳5;\s;i\m;|vjvٹfэ!>W3tfF5C]P8x~9es^sv5g-vV30tf/C	C+jW]st+YyW3&0tf蚡0׵fM`z]5;ac]Λʻkv.zV	]f"]9{38^yWsv!gw!Dg2kl~p?{!lŢw܉[g޼)pC4o53ZHV{>mt6>|u|]Z?cm{-:\"q㋟3IEEDvg>GKTvmO#h߀3Bfh֬f蚡Xb~ȧ4ƤMb&3pH:g-ϻcTHmΈwM+>¯\{ۆsn
++2^³Ή!Oˠ~8_[m-h{W[*hɽŔ,>R{4FHބ_e1i4` GŔ,	W1)Ӗ*w'v7?mzN٠kHǐ]!+"wXe匔
+P7qd
+Gjv{Eg<+SZ"yk
+r};5d)G0%|	zx\ϕ_ľRN1 eDwL= -^iL]TeT.GE2[l!cIɗtkD{Rҕ-!}v&{̺ AK[VY{I_+e*x\oF&JSҬ˂O_)[FGZ*'>)bQJ_)}i%e{ A!Hy9"c}v"ad/A#iX?N	Fce!1*X#bi0~7~i\){mEJ>GyxCyh'lsEm\m36Ndk{l  O0Ůy\=Yrw]v߅ގڄ7~57MksmpmYw+͊cSBLPO(rZFƍeZY9[	ъ>V|,}梱f]JE؊̷<kkLஸ+fr	6/VgT=Z$wu=gTQ-^EKCIB؁;y
+I:<	MD[CI~R6d2	ϫ<{}MGV-rR+ʢo0ڲG#Mh.t;bf 36N
+dEs9.qc -zB#`oc-R@rl7ih "=>ClRRhMEkpU+Z6pWde|Iygo#ϏOrUKZ6}mh%5aamH{SNLbzdEkc FcjUļogs4B=o-Ĕuqۘ Aܘ#N'mUhAz {vY?,*|9)?vFvFb=sC-҇fWHo*e$ī]6c7!k_lP{GOXvJ*ƽs/$k"uek	SFˬKBpVgÔ6#Qil)F	E;տ8hFl5R?W1i(-뿭}.}Ӌ+Q#Q&&iUٕRא͚{}Amʮ	9</^>'\\swbOe(!~
+=_ombw;'-BilrV6v&Į}׏#DK]LE//O7!wcSF)lw7Gs&5NxYv/h'l'lrq5.{Ծ<csS63*4c6hAY^E:gd3kYl0='keCn*d#X;S،<~G.*UKOҤ&BO]~Fgd_ӾVػ=ѳmQ(Hd3F3h<q6uF%|ٺd4-:uZ_h}%kw+C8A;vvy*{A ien$.[+'+9jaGZٵ6e8dipиupg>e`?b IFw}vp;;: gyvma0{<`tiS3Vn㵾s.;jo9bsait?:ěXGRgEw~sŃ.d:{B
+[.Н~M &ENҚq}%x/?YT6zJ_nzOIFC	8z
+GҦ#ΠW1;=]Q
+5~ѠQvT3<hNt=:ݡu7'|t<`JwNIGPã.s>;"'j 0"@;Y`6T)*MPM0k\BaDH#ϺsG@Rᅓ!>AĈ.Yr~ :t(an=pG:[v~}|| eSn! RٳgFtmO}8PO<5of|?댟1ԏE3ឝ%}hgz{OQy5>w~$Ogi1M}[pn'9A?x	ã.柵)tSgsdjCU8d9>vL4Ԗf@\Սm|mBNH07mT>rxn~AyA%QSX95^Μ꬜YWԚ*lLr6VjPҞ6=R[ٚ6N킵$9U/8
+UNYUTfD̤S8$x0t?>Emּ{B#YW<YZ-XU=[uTԪGO/[yTd.Q>$7CzcH~nqs+$Uvtc_veW{82sLCFF7`auA=GCǱCF|cиCfvt"?,j5<&g]>ڴȶ DSyTeS;&MS.ұsZVM(`jށ*3{!qO>]䐍fmg97`W{HAG{$	aLmfG#=ݏvGX+~5NXt:4l=<`0Paqi?B%n=gVh՟ꏈQZ3F8F;sZT:dc;OdPz.>Gcq7c:CHg!!dΝ&Uǁ1\8fpcPûCW陡-HšǓPNl%]_z87?
+OJVSV3
+Ӿnft[KeH [va,[gXൗ.C7:{-ȠPK"*@~& HqT$Zb'dSĉj	@%u+U;&̰T3X=[젺=cK):MA#.â1|ڌvxX2}#hS'T9^>"&~sR^SYSue@PS[ЍJ!FN9ў(dmHI#3K,Kߎ;e1#ם u.[&Xn5pg38hdcV@ne|cKg1a
+Scxn+O$]3r*>tdV
+9%2tZV`] ~{BW1f_ہ*HlbH&ZE(EbR-gh<qG+^k^L]	Fg9ьDL/.ŬgZRgƁzp0:Ұ'_=ԙ_U^E؀pV1\#)J]
+5{#NpJ-Nq
+pzOVĬ!AeШA2hԂ<)>qWW?EFCbY7}v2{`L.e0RۿG{_.i>pDp6ߋ+`14kVdA:p͠#ءHaKHj̐e~SvFŢqwtEoYĨu*m>z`,jׇ$T)dJy;f[{,ah\A7B`}:){~wrYWn	d
+6RcgU8X|tva#k4c>`VFw\%y.щ]RdeLL\AB|mcDl0Au6fNl;E?Β~i0>).f!N'ҭ~cZ~!D9+1g2@"hБf(JA&E2/
+ ^w[Oj-4wV "%0FYoZ(n,1Pg1d6+oa<WX#415e)8;rp/`Q!rjI)p
+{YER]q[ ?'}J qEwgإe9lv1pќ2wܖT-X(a`b
+E/9);lROV	'?2 턡MjQ s 3Wd}8E7º.)ƒ<d2hZRd0gNQ0<*M%-qI#ݖ) -a} }JC6gD=;Sqы[[ "M@re2<m
+I/~hΙC28n	R=5l귊Uka0ut4zow
+&ICieE-n]&息"L#^>0ڞq?|ɂ0<$͘sk_:s&eԐa:KGZ|QG"EsM̅x:7;AIVUۧĈ|H*,{z]Ѻ&PRR}	%>BZ7XƖ9N
+ttILHs^w4P$7oq[ay[>".7q HBf-1NwB_1t)ȇL׹tf22V
+ٽyDoދ59hg_h_y^߾o:'M<cQvA>CxsգyWjMW$+R-a0Y4`v`7.[A_*꾾Նhu:XIiHe'<!?N(0N8ŭh+4iaQN[3/"7b-nA\8mKa$^f&Mk}$<D8(!Klvp4]+(1iJ"_ܘ&	وu)I'.	~߶4 t¶RUl)[(ԖRcDÑ':pbLVd̎ϔ?W^M/Mz$5妯,6єԔlD_)vbYzuWZqF!ޏ(
+⋦Tg \|CN\q!>D%sR O5Ln-
+K @'x?$# M&@zVv	=S@QՒ riM դf1Yn <񯟤\&&Z#`os^?I^Mh6]sw| ҋ/d9NrsTiUHosi."B}PZM\&I-
+
+B9lχ)?TݔnZ#3}8ORWڌ	mV ;;M;H&@	ЋU^M!]k}OrҫURc<vtؙ;3cg#&=
+ZH[+4{iB+CVAVhkw*ˀ\C֌IlJ6;VKUzA=,v5#rB|J?:S@kkԆؠxb3(:kvTMgC5Z+WφJ囐o)@Qk4DT"^MWlt׬"V0|yNz j3Ⱥֲf8Gγuzڢ0L=H'Ēh/AkFn`|o.i:WTH{aT@Y7viE:UՁjLhVS!LmÝMT.5Fc!~DKGJfC~<'^vژ3Mn̼x2MJt=UXTD2zIoQGJal;p]m;&Lmf]>bmؗ1WѫR]fK	Y`\y׽ESg18<,N*݁su	]ţ=h7k7w;O/XCz+ځe\+MJm(E;OxmJZRT(gjgS6*#w"9V*gQ,Hn=92M]= N;Hg/}{G.F=z9Gj~	%mS.-SqIC*,0ZyCc,G
+#9i%~)M(vkt:d^򟀿5'*?yL{4Q~ʫ_C,)}/+.F)-thZ!+..2.'5!]$1Vr^G#IjҼTxo9S5V,?=b\7MmoA'S?kQf;Gl+nG8(;oqv~A}<U5C/k CI2]s9ڬ9蚣K8kv^>;[5;\sPafe3tf蚡k.?pv;X~ZOo9es^sv5g#]3tKghkkkfh&+ﴚ7w5;jM[yW3&0tf蚡0׸Mz]5Gq|+jvvW\s׳fM`z]5Caz]ٛʻk.cU=+jW]3t]ȅgv@wxZ-[o-ń)^[gk`݉[g޼)pC4o53ZHV{>mt3"|Tt!Dkvi]CkD׶#Zs}Ø_:cCИt[Ti?_KTlǺ-zhjB߮-t~)0t0pF~-ښ5C]3t+X,CTfrØ][_D;]~jZ︰o=FVWal36qG>46f;qlQH衹=MU<Jh¯	kax%:^PeREROC=(v7	&40_J$9h=4RSC1;FCݛB
+k{mm3<csb=ˠ~'/x-j6
+z=E+ӂ1[m!ƴh,HEo=&{qh.Lx#6Xg
+BlD/gH!%^+ej˼VߠVb\8|YI#?eWVT+aORZ볟">zx`͝XRVPDݍ|1+qk/'}	O{ "IwbHЖ5JbA/_yL7}d1{Xi1c}E;4pw9$s,)Z.𛒽l"ܽHuʝȷms߬ӘNdoMu)<17(qVOrVWZdIކ|S;ɨV$43[)o+Ű,`cX@8uCrF}b7 @~9;kea'Fy{ȻǱu]X٧><?s@"kk.Q
+m=|DuxCyoVy{]]tF%XP3EߦJCђn[QrOG& 2am\dB:*QG%DX}T0[|mE݁;zvQрhQ84eg桊bY;~=RC|gٚ*|V
+$Ph&TI蛯wx<2*xkyo]ro\iWm}іw?R^ɳ;f76N
+4^Gs9u.~V -zB\XH%nlHF&@*hujEϦXpv˗$6$W;eWQ&b<f}ؠ4uMMiptaJIlQHZ|M!`|~\7P\~L-/8ʛ7ȳ9pOyЂÆb:ømL|Ѡ1qGsJ:Ee_zgciɢIӚwRheۗ-kŶb~/~F֯F<4(tza3awk?ׅz'Pwl먫`17kGb/)*vAaYg_Ƹ?eڻ$uhCvRYf9G	ET~1_a@4kg4bMR?W1i(-N?B/*\'x}Vde.[׻b;3]qspREO[v(0\iQaRM$ERo/ՊI}Lv+&uQE%o|&N:X)2άq3QkAs.`/;7IVY^YFld3kS'ۻi2y(F6|clSvW!iv{r].͢>[| &!Ŀ+-V!dkW!V(eywS$OHBg۱%bwccF%|ٺd6|E`q5ϷdM"L2R[ao'_zDDtWFſT?_$P"$-K?3~/ڪ~/^U6r.Oy<,fᚅ<*c`gtuϮ=Oyϼ7X{k{ȕĕax|ۣsxvZ]2}v8:}2SN5HҠ?jA|Nvtp63{}zo][xt1;^ 9ǅ.;~sԌsx}qn=wX&#nvQґOO{xp؅L˝)*о<	w~NҚq%x.¿㞃.BO㽤svT3nnzOIFC	8z<nצ~ ΚW1;=]#G{*pQGG7SEpj;iSwjwκWȻVX}+ca9%At`']K6v}v4P")uxᢕ;pKSs@NcN/qObex>raz}Cɻ}x`\H'&Dip`T2`\ ]%('9Έ{AC9OϨ/O<-68| 0.#IdӞczhYOs#G]?kiS#φç w4p Ɇs|`f=i-̀<=)084>]@E'o;ʩJ-}
+tzܢx<YSX95^Μ꬜YWԚ*lLr6VjPҞ6=R[ٚ6N킵$9U/8
+UNYUTfD̤S8$x0t?>Emּ{B#YW<YZ-XU=[uTԪGO/[yTd.Q>$7CzcH~nqs+$Uvtc_v =8l)%;_:lpN|G΋k5Gך5) ̻4--f``oVҘf[Y^wS܃&W׈+
+*F\_W ~t_.=ruie3s̛   mkBSx]N0 QʫajohlU&fnÃsfd,>Op3]E1T	яjV2ڃ-puyGpodl`d/e>v
+9]Aݩ6ٞGÃT{1H	QlH':iуŏpa'D:__CE  ymkBT 8                                                                    x횉m0]HI!)$FR?6c<lHٱdtC"+RJ)RJkJ߃L_SUn7ss~uU-Uyy9c/Juz?i>>>~ sm+vuՑνYu8uN?WP>1JsWiV_uKEϸ/r_gKW]ױEYcl,[TYHT}xL#}A GV7^}>iҞ-i;}LJX&TP3T#ߨgJl e'=?͘ona|7>?ǐU%;/mN/IfQփz{<d6dn;Qm{{5$iѦxg<$"^%=RJ)Ste/֔ a};k_y?9Ԛlz}m#GKk!k(9G1z,Q&liV濊#_<3Ξm$^9g{9&w&:˙uf֚R:ֽL+mWW^z%I2loZf?k4W-#	?V/c^!!{u̵ʴUٷAGe>G}?v✽3X~j{zTAO^ʰ>?sy|G)P</11~2ў׆R/7 Ӿsmsr"(2cϹ;~u-)}<U1g:apb5{3(k!m'mʞ2.~[)}GκbXELpaԃ77Fy0@ߋL?󞕹Khi@=RJ)RJ)RJ]M;;j7]&  SmkBT U                                                                    xi`Qqqqq!	COMlS$I$I$I$I$I$IqO9˵wOo]ss,Խu˲<^0tc}av=7_{V9z}ٿ^s_y~?}ez۶@wE՟k$I$I$I                                         @?
+=T  1mkBT                                                                     xֱ@E}ADDADIw
+dp
+ܤ?;Je+ҿRY<#+e=#ҿRY}#+eݶ-ҿNϺ%OaeYJ<x{?i*~
+eߺq#JeYaTHJeYTmHJeY                                                       29ps  mkBT x                                                                    x흍)q ĉ8D^>׻gI@XjjgiЃ`0`0?ϟ|:s eQ3|ӧO|:2|.};7eGFO6_Qv]T]^ˮg{>pjzkuo{yye?{-x/D:3D&򈼹e^Hyi#/OGzϪ߯_~
+:sMe#M3Y#=2QЙ[\s=E8}E>GȩTڲTg-}VfoSVwzV}./>~<Vrv@>!?U1<#}=F[ ~QڋBN..+푹^edLo+[\-kdW(}6q$#?z6Bөi?L7!3O_Q}Пuo[=tkȋM!'}/Ƈdr2_Cﲨ:`0:8o=+8-4}۞cĥXdq{bUq©ήm!ƶg*ΪU\z[GA=^+ru{LV	U?)V>ғ)x|Yҁgi\yi^cUo*=!TY?rfgWsʽVn*VX#=Fϫ+[F~yH\L~[O҇h5ݵTow|Sfӟ+);F;:x)/OSyUo2e)Ve3'wgGg=J^`0
+ľu kU,Ksؑ5nY,bXw{w&3QהNQev	]ƷgcH˞i{A3I8hwduwUIWq8I>+@pQşGcZ\ƪUߝ]/:3d;ɫ:gB9R|GW~w2;fz<AǏߊg_ly=Uy3= [6_3]U_k]]ײ2;j->t|+i5nΟgZY|<1NyŬ|E7k?z/k><=Α}N΅>uWydʬdz`0*\?W8GY:Dgcg<2+'W6qn؟{ru"w<Tk.\rnO>U쏘~c#T?+y{Q,,^qF/Xv8.֩g3}ȸOP~n%hUG4(_sn|W}Tg&x^c,Fѭ+<#+}/Uw8BRh_|33!mr\7U9m({ѝpvew[xG]߱?g;,nҽow8]וb?OV=Z_#ve?vN_WrYLo;1g9pV^G~>[_vNOS3`0Q[	veO\k^8 ֔v<Zbz\Opbn$~}oz3јmKvU]^iNWA#x딫jtq:E=z%օq)CcYEqyRG-+u(K\hP'*^ء^q=m=y|Kvūe\rȊ4={W1;=ݷxp;o@>ȘT\Ԏ+C=*ɫ|GJOCW]x1.ﵠ9_EбVq)v(ʑ}[GwǺ{-oSdו_˞׃2;iT&w*w:g׭SOsj%Z[~_˯d֮+w]7`0]kIu+eL]ւoA^;=GR? v쯱;<y o$N1紈=:ߥPVu< <&3KyC/4r)i=*/|Ύ^]QNН1qGw>ù{<FVr2nlo؍ا|mo'qbӋr`eef6
+0lzsA_x7췣*U}R%+C_	ڟ~I\Q~ky#_jo~DyU^`5pko?:ˮCw>?Kv:A}E:_n+{u=rq͓̳]>>d}+|L01`0leg:׺񶊝`W,3O?]\9P~[kOWiGc~)-<w.3q}'vuw$Vnv(r52S;Wk_Kϔ8B/hEՠ'9w?K;x:x<|@cϽVyc@ۖSw8Bq]=2lBe6V}eR(	VeZT4ade2ޒ+nYBTqSߔ<[&=f[|szP)G}{Zׅ3n7jpWwftEw[ǽ;`l?`0`0`{~i`oLy>uoi\qK|} 7Svu9G쯿c¾#>,jow{ՆݲL=mW2u_8دjo?kD߱mw>#}E:OۡO;<sy}ڛk}~|M'8CTo+[WUQr'\'tTYwz.D=W|~q=_ yMǏktbS=2|ұyN_}Oe摽ۏtLS6q`Cjf3#ܰ?z1H]\"W]O;2'@@~tG:{u7m1Q]PWV2Sz]ϥzs3]vxwҞ:ڗ>y`$j?tU  
+mkBT ~                                                                    x흍8FSHI!)$FRHnwHYx3ꇤ saaaaxIǏ'U{o_ھgW9o'GW{>~Jlo߾)*/N\ϱov[iZ_ձaJΝ/:6O-92b?Tlk%?_21BsY5>:> c=1Owy^- ڶ,Xz usM#גU]>H_yYv!ۉ_miRus]Xm_g)YY)m]y,m z1aaaxEߓGקo/Y\k6xjgH|yu.\aæM&wk#ϐ$?]Mo\Ⱦ,/ڥQ@~6s?)}, lgX #vQgBٙ^uのuhm?}{].~}v_J;xogJY]޳@.)oqC?}>@Xߘ'- (W?	źvƔOʙRv[K?[A}?-wmՑ}<GcK1}uxLzަU00Pc[<>g\=c}Mggg	Ǆ-B^k_g?F? v0||؎=ǧHPgs/hؑIt~{n^}ZyD5XWvO)"c0vYZ|~_%/,p\ɹyΰZ/;/xs_9?Pܯ5ݻ\[y|č8g ʱL{?00_k3>z_\S|<)b|7aaaxn.ta?l^Cvkؽ#~e)3<3^kdlc&jK+o"e<.ʞ`^(3zu
+l+6v<ïk7]/lc[`On}򚄫G뎱zt^v2)?;Wmr5ocIz?Ozx{&!ez."ѯ1Gg{+ҏlw<=}GݽFƨ^)zIpGK ֜{{eG12ۭqiumf>.}~a?00[u+7Svq֭y΅
+?ނ}XwŶv?ߩDZۓ-q/?߳=<~#>Fk"qzrQo	9r,nY[;o:)@-`ק-7({߯S@µK9֠ɸ>:n3
+_[_*mtcmC>qSL<?<nѯn!>=<6;ǫsaaa{xˌ\ފpx?0׋#5zяc]x^l򼠕(f:~٣^lin59W~\;?vn6erUbS~v^UO7O(|;+SG4|?f*?rW~2oNٟS9~daևmH6mX[J~s.ym4ٶO|Bd/b5ɿyU?0000000.P~*1@G\⟿KrKXs2(ߥ纎J8'>X@▼QQbqwxb)_K|v 1M6kee-2Ǜ59?K^E~9ϱQﱮYF8N?~;:=J<-t ĒyNAgC	\NXKs)'^Kg\~2}6}Գ)n]Or^j~"{p29w6/.z-v:+M{WJYZ굢`%Ҥl9ힶկ#OUz+U?;sd~vND7*.Y+v:ye;8}~|+ÑޅN9}{Bƞ#txխsXɿkSV/uJ=oG<ջL'L:D]6jfgLz/+ؽ[{rCMYq~[{yy	czA;w9zszWHVax3  ף  2iTXtXML:com.adobe.xmp     <?xpacket begin="﻿" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27        ">
+   <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+      <rdf:Description rdf:about=""
+            xmlns:xmp="http://ns.adobe.com/xap/1.0/">
+         <xmp:CreatorTool>Adobe Fireworks CS6 (Macintosh)</xmp:CreatorTool>
+         <xmp:CreateDate>2012-11-14T19:20:21Z</xmp:CreateDate>
+         <xmp:ModifyDate>2012-11-14T19:22:55Z</xmp:ModifyDate>
+      </rdf:Description>
+      <rdf:Description rdf:about=""
+            xmlns:dc="http://purl.org/dc/elements/1.1/">
+         <dc:format>image/png</dc:format>
+      </rdf:Description>
+   </rdf:RDF>
+</x:xmpmeta>
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                                                                                                    
+                            
+<?xpacket end="w"?>   TIDAT8cdVZƈM.Kj_qܹ	+bm.5u1000L2%lrrrF\J[R zL1^(    IENDB`
\ No newline at end of file
diff --git a/core/modules/layout/includes/layout.admin.inc b/core/modules/layout/includes/layout.admin.inc
new file mode 100644
index 0000000..8bc2270
--- /dev/null
+++ b/core/modules/layout/includes/layout.admin.inc
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * @file
+ * Administration functions for layouts.
+ */
+
+use Drupal\layout\Plugin\Core\Entity\Display;
+
+/**
+ * Page callback: Presents a list of layouts.
+ *
+ * @return array
+ *   An array as expected by drupal_render().
+ *
+ * @see layout_menu()
+ */
+function layout_page_list() {
+  // Get list of layouts defined by enabled modules and themes.
+  $layouts = layout_manager()->getDefinitions();
+
+  $rows = array();
+  $header = array(t('Name'), t('Source'));
+  foreach ($layouts as $name => $layout) {
+    $provider_info = system_get_info($layout['provider']['type'], $layout['provider']['provider']);
+
+    // Build table columns for this row.
+    $row = array();
+    $row['name'] = l($layout['title'], 'admin/structure/templates/manage/' . $name);
+    // Type can either be 'module' or 'theme'.
+    $row['provider'] = t('@name @type', array('@name' => $provider_info['name'], '@type' => t($layout['provider']['type'])));
+
+    $rows[] = $row;
+  }
+
+  $build = array();
+  $build['table'] = array(
+    '#theme' => 'table',
+    '#header' => $header,
+    '#rows' => $rows,
+  );
+  return $build;
+
+  // Ensure the provider types are translatable. These do not need to run,
+  // just inform the static code parser of these source strings.
+  t('module');
+  t('theme');
+}
+
+/**
+ * Page callback: Demonstrates a layout template.
+ *
+ * @param string $key
+ *   The key of the page layout being requested.
+ *
+ * @return array
+ *   An array as expected by drupal_render().
+ *
+ * @see layout_menu()
+ */
+function layout_page_view($key) {
+  $layout = layout_manager()->getDefinition($key);
+  drupal_set_title(t('View template %name', array('%name' => $layout['title'])), PASS_THROUGH);
+
+  // Render the layout in an admin context with region demonstrations.
+  $instance = layout_manager()->createInstance($key, array());
+  $regions = $instance->getRegions();
+  foreach ($regions as $region => $info) {
+    $regions[$region] = '<div class="layout-region-demonstration">' . check_plain($info['label']) . '</div>';
+  }
+  $build['demonstration'] = array(
+    '#type' => 'markup',
+    '#markup' => $instance->renderLayout(TRUE, $regions),
+  );
+  $build['#attached']['css'][] = drupal_get_path('module', 'layout') . '/layout.admin.css';
+  return $build;
+}
+
+/**
+ * Page callback: Presents list of displays.
+ *
+ * @see display_menu()
+ */
+function layout_master_list() {
+  $controller = entity_list_controller('display');
+  return $controller->render();
+}
+
+/**
+ * Page callback: Presents the display editing form.
+ *
+ * @see display_menu()
+ */
+function layout_master_edit(Display $display) {
+  drupal_set_title(t('<em>Edit layout</em> @label', array('@label' => $display->label())), PASS_THROUGH);
+  return entity_get_form($display);
+}
+
+/**
+ * Page callback: webservice handling RESTful(-ish) requests from the JS app.
+ * Currently it only updates the *whole*
+ *
+ * @todo: convert this to use the routing system (currently we use
+ * Backbone.emulateHTTP).
+ * @todo: allow this to consume application/json-payloads (currently we need
+ * Backbone.emulateJSON)
+ * @todo: protect against CSRF. We should use a session-based token. This issue
+ * will reoccur with all RESTful services, because  a per-request token (à la
+ * form-token just is not RESTful).
+ *
+ * @param Drupal\layout\Plugin\Core\Entity\Display $display
+ * @param null $a
+ * @param null $b
+ * @param null $c
+ * @return int
+ */
+function layout_master_webservice(Display $display, $a=NULL, $b=NULL, $c=NULL) {
+  if (isset($display->locked) && is_object($display->locked) && $display->locked->owner != $GLOBALS['user']->uid) {
+    // @todo: currently menu_access_denied returns a status 200?
+    // @todo: make sure JS client handles this properly.
+    return MENU_ACCESS_DENIED;
+  }
+  // This is all evil, evil, evil - hacking this blindly bottom-up.
+  $payload = isset($_POST['model']) ? drupal_json_decode($_POST['model']) : FALSE;
+  $method = isset($_POST['_method']) ? $_POST['_method'] : FALSE;
+  switch ($a) {
+    // stores complete layout
+    case 'layout':
+      $blockInfo = array();
+      // Shove the
+      foreach ($payload['regions'] as $region) {
+        foreach ($region['blockInstances'] as $blockInstance) {
+          $block = $blockInstance['id'];
+          $blockInfo['block.' . $block] = array(
+            'region' => $region['id'],
+            'weight' => $blockInstance['weight'] * 100
+          );
+        }
+      }
+      $display->set('blockInfo', $blockInfo);
+      // Store changes in TempStore.
+      layout_master_cache_set($display);
+      drupal_exit();
+      break;
+    // Update single region
+    case 'region':
+      $region_id = $b;
+      die();
+      break;
+    // Update single block
+    case 'block':
+      $block_id = $b;
+      break;
+  }
+  return ;
+}
+
+
+/**
+ * Page to break lock on a display being edited.
+ */
+function layout_master_break_lock_confirm($form, &$form_state, Display $display) {
+  $form_state['display'] = &$display;
+  $form = array();
+  if (empty($display->locked)) {
+    $form['message']['#markup'] = t('There is no lock on display %name to break.', array('%name' => $display->get('id')));
+    return $form;
+  }
+
+  $cancel = drupal_container()->get('request')->query->get('cancel');
+  if (empty($cancel)) {
+    $cancel = 'admin/structure/layouts/manage/' . $display->get('id') . '/edit';
+  }
+
+  $account = user_load($display->locked->owner);
+  $form = confirm_form($form,
+    t('Do you want to break the lock on display %name?',
+      array('%name' => $display->get('label'))),
+    $cancel,
+    t('By breaking this lock, any unsaved changes made by !user will be lost.', array('!user' => theme('username', array('account' => $account)))),
+    t('Break lock'),
+    t('Cancel'));
+  $form['actions']['submit']['#submit'][] = 'layout_master_break_lock_confirm_submit';
+  return $form;
+}
+
+/**
+ * Form submit handler to break_lock on a display.
+ */
+function layout_master_break_lock_confirm_submit(&$form, &$form_state) {
+  $display = $form_state['display'];
+  drupal_container()->get('user.tempstore')->get('layout')->delete($display->get('id'));
+  $form_state['redirect'] = 'admin/structure/layouts/manage/' . $display->get('id') . '/edit';
+  drupal_set_message(t('The lock has been broken and you may now edit this display.'));
+}
diff --git a/core/modules/layout/js/collections/collections.js b/core/modules/layout/js/collections/collections.js
new file mode 100644
index 0000000..b71c783
--- /dev/null
+++ b/core/modules/layout/js/collections/collections.js
@@ -0,0 +1,27 @@
+/**
+ * @file
+ * This file contains the collections of models for the layout js-app.
+ *
+ * @todo: split into separate files.
+ */
+(function ($, _, Backbone, Drupal, drupalSettings) {
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.RegionsCollection = Backbone.Collection.extend({
+    model: Drupal.layout.RegionModel
+  });
+
+  Drupal.layout.BlocksCollection = Backbone.Collection.extend({
+    model: Drupal.layout.BlockModel
+  });
+
+  Drupal.layout.BlockInstancesCollection = Backbone.Collection.extend({
+    model: Drupal.layout.BlockInstanceModel,
+    comparator: function(model) {
+      return model.get('weight');
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal, drupalSettings);
diff --git a/core/modules/layout/js/layout.admin.js b/core/modules/layout/js/layout.admin.js
new file mode 100755
index 0000000..79fe84e
--- /dev/null
+++ b/core/modules/layout/js/layout.admin.js
@@ -0,0 +1,75 @@
+(function ($, window, Drupal, drupalSettings) {
+
+"use strict";
+
+/**
+ * Attach display editor functionality.
+ */
+Drupal.behaviors.displayEditor = {
+
+  attach: function (context, settings) {
+    var appModel, appView;
+
+    function randomId() {
+      var chars = "abcdefghiklmnopqrstuvwxyz";
+      var randomString = '';
+      for (var i=0; i < 8; i++) {
+        var rnum = Math.floor(Math.random() * chars.length);
+        randomString += chars.substring(rnum,rnum+1);
+      }
+      return randomString;
+    }
+
+    /**
+     * Helper function generating a BlocksCollection populated with randomly
+     * named items.
+     *
+     * @return {Drupal.layout.BlocksCollection}
+     */
+    Drupal.layout.getBlocksCollection = function() {
+      var blocks = [];
+      // Generate a bunch of randomly named blocks.
+      for (var i = 0; i<10; i++) {
+        var id = randomId();
+        var b = new Drupal.layout.BlockModel({
+          'id': id,
+          'label': 'Label ' + id
+        });
+        blocks.push(b);
+      }
+      return new Drupal.layout.BlocksCollection(blocks);
+    }
+
+    /**
+     * Generates the required Backbone Collections and Models.
+     * @param layoutData
+     * @return {Drupal.layout.RegionsCollection}
+     */
+    function generateRegionCollections(layoutData) {
+      var regions = new Drupal.layout.RegionsCollection();
+      _(layoutData.regions).each(function(region) {
+        regions.add(new Drupal.layout.RegionModel({
+          id: region.id,
+          label: region.label,
+          blockInstances:
+            new Drupal.layout.BlockInstancesCollection().reset(region.blockInstances, {silent: true})
+        }));
+      });
+      return regions;
+    }
+
+    // Populate the appModel
+    Drupal.layout.appModel = new Drupal.layout.AppModel({
+      id: drupalSettings.layout.id,
+      regions: generateRegionCollections(drupalSettings.layout.layoutData)
+    });
+    var appView = new Drupal.layout.AppView({
+      model: Drupal.layout.appModel,
+      el: $('#block-system-main'),
+      locked: drupalSettings.layout.locked
+    });
+    appView.render();
+  }
+};
+
+})(jQuery, window, Drupal, drupalSettings);
diff --git a/core/modules/layout/js/models/app-model.js b/core/modules/layout/js/models/app-model.js
new file mode 100644
index 0000000..b7535b4
--- /dev/null
+++ b/core/modules/layout/js/models/app-model.js
@@ -0,0 +1,24 @@
+/**
+ * @file
+ * This model hold application state and corresponds to the layout containing
+ * regions (and block instances).
+ *
+ * @todo: probably split this AppModel into AppModel and LayoutModel.
+ */
+(function ($, _, Backbone, Drupal) {
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+  Drupal.layout.AppModel = Backbone.Model.extend({
+    url: function() {
+      return drupalSettings.layout.webserviceURL + '/layout';
+    },
+    defaults: {
+      'id': null,
+      'template': null,
+      'regions': null,
+      'config': null
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/js/models/block-model.js b/core/modules/layout/js/models/block-model.js
new file mode 100644
index 0000000..e746ef5
--- /dev/null
+++ b/core/modules/layout/js/models/block-model.js
@@ -0,0 +1,30 @@
+/**
+ * @file
+ * This model corresponds to a block that can be placed
+ */
+(function ($, _, Backbone, Drupal, drupalSettings) {
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.BlockModel = Backbone.Model.extend({
+    defaults: {
+      /* CMI name */
+      'id': null,
+      'label': '',
+      'description': '',
+      'config': {}
+    },
+    // @todo: create a new BlockInstanceModel instance via a webservice (or
+    // another way of ensuring that the id of the BlockInstanceMdoel is unique).
+    createBlockInstance: function() {
+      return new Drupal.layout.BlockInstanceModel({
+        'id': this.get('id'),
+        'label': this.get('id'),
+        'blockId': this.get('id'),
+        'config': this.get('config')
+      });
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal, drupalSettings);
diff --git a/core/modules/layout/js/models/blockinstance-model.js b/core/modules/layout/js/models/blockinstance-model.js
new file mode 100644
index 0000000..d39caf1
--- /dev/null
+++ b/core/modules/layout/js/models/blockinstance-model.js
@@ -0,0 +1,26 @@
+/**
+ * @file
+ * This model corresponds to the instance of a block placed in a region of a
+ * layout.
+ */
+(function ($, _, Backbone, Drupal, drupalSettings) {
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.BlockInstanceModel = Backbone.Model.extend({
+    url: function() {
+      return drupalSettings.layout.webserviceURL + '/block';
+    },
+    defaults: {
+      // Unique id of the block instance.
+      'id': null,
+      'weight': null,
+      // Unique id of the block (e.g CMI key).
+      'blockId': null,
+      'region': '',
+      'config': {}
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal, drupalSettings);
diff --git a/core/modules/layout/js/models/region-model.js b/core/modules/layout/js/models/region-model.js
new file mode 100644
index 0000000..0cb35e3
--- /dev/null
+++ b/core/modules/layout/js/models/region-model.js
@@ -0,0 +1,21 @@
+/**
+ * @file
+ * This model corresponds to a region in a layout.
+ */
+(function ($, _, Backbone, Drupal) {
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.RegionModel = Backbone.Model.extend({
+    url: function() {
+      return drupalSettings.layout.webserviceURL + '/region/' + this.get('id');
+    },
+    defaults: {
+      'id': null,
+      'blockInstances': null,
+      'config': null
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/js/theme.js b/core/modules/layout/js/theme.js
new file mode 100644
index 0000000..b0e24b1
--- /dev/null
+++ b/core/modules/layout/js/theme.js
@@ -0,0 +1,49 @@
+/**
+ * @file
+ * Theme functions for the layout js-app.
+ */
+(function ($) {
+  /**
+   * Theme function for a region.
+   * @param id
+   * @param label
+   * @return {String}
+   */
+  Drupal.theme.layoutRegion = function (id, label) {
+    var html =
+      '<div id="layout-region-' + id + '" class="layout-region">' +
+        '<div class="lining">' +
+          '<header class="clearfix">' +
+            '<div role="form" class="operations">' +
+              '<button name="block" value="add" role="button" aria-label="' + Drupal.t('Add block to region') + '" class="icon icon-plus">' + Drupal.t('Add') + '</button>' +
+              '<button name="block" value="configure" role="button" aria-label="' + Drupal.t('Configure block in region') + '" class="icon icon-gear">' + Drupal.t('Configure') + '</button>' +
+            '</div>' +
+            '<div class="info"><span class="label">' + label + '</span></div>' +
+          '</header>' +
+          '<div class="blocks">' +
+            '<div class="row"></div>'
+          '</div>' +
+        '</div>' +
+      '</div>';
+    return html;
+  }
+
+  /**
+   * Theme function to get the html for a block instance.
+   * @param id
+   * @param label
+   * @return {String}
+   */
+  Drupal.theme.layoutBlock = function (id, label, attributes) {
+    return '<div class="block" id="block-' + id + '">' +
+      '<div class="lining">' +
+        '<div class="info">' +
+          '<span class="type-indicator mb-text">M</span>' +
+          '<span class="label mb-text">' + id + '&nbsp;block</span>' +
+        '</div>' +
+        '<div class="operations mb-block-operations"><span class="gear mb-gear"></span></div>' +
+      '</div>' +
+     '</div>';
+  };
+
+})(jQuery);
diff --git a/core/modules/layout/js/views/app-view.js b/core/modules/layout/js/views/app-view.js
new file mode 100644
index 0000000..4b8985a
--- /dev/null
+++ b/core/modules/layout/js/views/app-view.js
@@ -0,0 +1,52 @@
+/**
+ * @file
+ * This file holds the master view for the layout js app.
+ */
+(function ($, _, Backbone, Drupal) {
+
+  "use strict";
+
+  // @todo: be RESTful. Not sure whether the router/rest.module are in place.
+  // Instead of using REST verbs, POST will be used and $_POST['_method'] will
+  // contain the verb.
+  Backbone.emulateHTTP = true;
+  // Payloads will be sent as application/x-www-form-urlencoded, in
+  // $_POST['model'].
+  Backbone.emulateJSON = true;
+
+  Drupal.layout = Drupal.layout || {};
+  Drupal.layout.AppView = Backbone.View.extend({
+    initialize: function(options) {
+      this.regionsView = new Drupal.layout.UpdatingCollectionView({
+        el: this.$el.find('.layout-display'),
+        collection: this.model.get('regions'),
+        nestedViewConstructor:Drupal.layout.RegionView,
+        nestedViewTagName:'div'
+      });
+    },
+    render: function() {
+      // @todo: this should move to layout.admin.js and provide better handling.
+      // Do not setup the js app if another user is currently operating on this
+      // layout (locked on the server via TempStore).
+      if (this.options.locked) {
+        return false;
+      }
+      this.regionsView.render();
+      this.$el.sortable({
+        items: '.block',
+        connectWith: '.connected-sortable',
+        cursor: 'move',
+        stop: function(event, ui) {
+          ui.item.trigger('drop', ui.item.index());
+        }
+      });
+      return this;
+    },
+    remove: function() {
+      this.$el.sortable('destroy');
+      this.regionsView.remove();
+      this.$el.remove();
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/js/views/blockinstance-view.js b/core/modules/layout/js/views/blockinstance-view.js
new file mode 100644
index 0000000..aded8a8
--- /dev/null
+++ b/core/modules/layout/js/views/blockinstance-view.js
@@ -0,0 +1,38 @@
+/**
+ * @file
+ * This view controls a single BlockInstance.
+ */
+(function ($, _, Backbone, Drupal) {
+
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.BlockInstanceView = Backbone.View.extend({
+    events:{
+      'click':'onClick',
+      'drop':'onDrop'
+    },
+    onDrop:function (event, index) {
+      // Trigger reorder, will be handled in Drupal.layout.RegionView.
+      this.$el.trigger('reorder', [this.model, index]);
+      // @todo: handle dropping onto enpty region.
+      event.preventDefault();
+      event.stopPropagation();
+      return ;
+    },
+    onClick:function () {
+      this.dialogView = new Drupal.layout.BlockInstanceModalView({
+        model: this.model,
+        title: this.model.get('label')
+      });
+      this.dialogView.render();
+    },
+    render:function () {
+      this.setElement($(Drupal.theme('layoutBlock', this.model.get('id'), this.model.get('label'), this.model.attributes)));
+      return this;
+    }
+  });
+
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/js/views/blockinstancemodal-view.js b/core/modules/layout/js/views/blockinstancemodal-view.js
new file mode 100644
index 0000000..7746d03
--- /dev/null
+++ b/core/modules/layout/js/views/blockinstancemodal-view.js
@@ -0,0 +1,34 @@
+/**
+ * @file
+ * This view controls and instantiates the dialog configuring a BlockInstance.
+ */
+(function ($, _, Backbone, Drupal) {
+
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+  Drupal.layout.BlockInstanceModalView = Drupal.layout.ModalView.extend({
+    events: {
+      'click button.delete': 'removeBlockInstance'
+    },
+    removeBlockInstance: function() {
+      // Remove model.
+      this.model.collection.remove(this.model);
+      // Destroy model on server.
+      this.model.destroy();
+      // Close and remove dialog.
+      this.remove();
+    },
+    render: function() {
+      this.$el.html(
+        '<button class="delete">' + Drupal.t('Ok, delete!') + '</button> ' +
+        '<button class="dialog-cancel">Cancel</button>'
+      );
+      this.show();
+      return this;
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
+
+
diff --git a/core/modules/layout/js/views/blockselectormodal-view.js b/core/modules/layout/js/views/blockselectormodal-view.js
new file mode 100644
index 0000000..5e6a3c4
--- /dev/null
+++ b/core/modules/layout/js/views/blockselectormodal-view.js
@@ -0,0 +1,66 @@
+/**
+ * @file
+ * BlockSelectorModalView displays Blocks available for placement in a given
+ * region, creates BlockInstance from a selected Block adds it to the region.
+ *
+ * @todo: use a form/server-side generated listing or a proper webservice to
+ * retrieve the "placeable" Blocks.
+ * @todo: split of Drupal.layout.BlockListItemView into separate file.
+ */
+(function ($, _, Backbone, Drupal) {
+
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+  Drupal.layout.BlockSelectorModalView = Drupal.layout.ModalView.extend({
+    events: {
+      'select': 'selectBlock'
+    },
+    selectBlock: function(e, block) {
+      // Model is RegionModel
+      var instance = block.createBlockInstance();
+      this.model.get('blockInstances').add(instance);
+      // Remove & close dialog.
+      this.remove();
+    },
+    tagName: 'ul',
+    render: function() {
+      this.$el.empty();
+      this._collectionView = new Drupal.layout.UpdatingCollectionView({
+        collection:this.collection,
+        nestedViewConstructor:Drupal.layout.BlockListItemView,
+        nestedViewTagName:'li'
+      });
+      this._collectionView.setElement(this.$el);
+      this._collectionView.render();
+      this.show();
+      return this;
+    },
+    remove: function() {
+      if (this._collectionView) {
+        this._collectionView.remove();
+      }
+      // Apparently no need to call this.dialog.close(); remove this.$el
+      // closes the jQueryUI Dialog, oh jqueryui magic ...
+      this.$el.remove();
+    }
+  });
+
+  Drupal.layout.BlockListItemView = Backbone.View.extend({
+    events: {
+      'click a': 'selectBlock'
+    },
+    selectBlock: function(e) {
+      // Pass this click & model to the parent view.
+      this.$el.trigger('select', [this.model]);
+      e.preventDefault();
+      e.stopPropagation();
+      return ;
+    },
+    render: function() {
+      this.$el.html('Add <a href="#">Block ' + this.model.get('label') + '</a>');
+      return this;
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/js/views/modal-view.js b/core/modules/layout/js/views/modal-view.js
new file mode 100644
index 0000000..26eba39
--- /dev/null
+++ b/core/modules/layout/js/views/modal-view.js
@@ -0,0 +1,33 @@
+/**
+ * @file
+ * Base view wrapping a dialog.js based dialog.
+ *
+ * @todo: maybe provide meaningful form-loading?
+ */
+(function ($, _, Backbone, Drupal) {
+
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.ModalView = Backbone.View.extend({
+    dialog: null,
+    callback: null,
+    initialize: function(options) {
+      this.callback = options.callback || null;
+      this.dialog = Drupal.dialog(this.$el, {title: this.options.title});
+    },
+    show: function() {
+      this.dialog.showModal();
+    },
+    close: function() {
+      this.dialog.close();
+    },
+    remove: function() {
+      // Apparently no need to call this.dialog.close(); remove this.$el
+      // closes the jQueryUI Dialog, oh jqueryui magic ...
+      this.$el.remove();
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/js/views/region-view.js b/core/modules/layout/js/views/region-view.js
new file mode 100644
index 0000000..8a8834a
--- /dev/null
+++ b/core/modules/layout/js/views/region-view.js
@@ -0,0 +1,106 @@
+/**
+ * @file
+ * This view controls a region and the blockInstances contained in it. Opens
+ * the BlockSelectorModalView on request.
+ */
+(function ($, _, Backbone, Drupal) {
+
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.RegionView = Backbone.View.extend({
+    events:{
+      'click [name="block"][value="add"]':'onClickAdd',
+      'click [name="block"][value="configure"]':'onClickConfigure',
+      'reorder':'reorderInstances'
+    },
+
+    onClickConfigure:function (e) {
+      this.dialogView = new Drupal.layout.RegionModalView({
+        model: this.model,
+        title: this.model.get('label')
+      });
+      this.dialogView.render();
+      e.preventDefault();
+      e.stopPropagation();
+    },
+
+    onClickAdd:function (e) {
+      var collection = Drupal.layout.getBlocksCollection();
+      this.modalView = new Drupal.layout.BlockSelectorModalView({
+        model: this.model,
+        collection: collection,
+        title: Drupal.t('Please select a block to place in the regions %region', {'%region': this.model.get('label')})
+      });
+      this.modalView.render();
+      e.preventDefault();
+      e.stopPropagation();
+      return ;
+    },
+
+    // @todo: listen to collection events in app-view.js instead/propagate event.
+    saveFullLayout: function() {
+      // Show the "changed" notice.
+      $('.display-changed').removeClass('js-hide');
+      Drupal.layout.appModel.save();
+    },
+
+    initialize:function () {
+      var blockInstances = this.model.get('blockInstances');
+      this._collectionView = new Drupal.layout.UpdatingCollectionView({
+        collection:blockInstances,
+        nestedViewConstructor:Drupal.layout.BlockInstanceView,
+        nestedViewTagName:'div',
+        el: this.$el,
+        nestedViewContainerSelector: '.blocks .row'
+      });
+
+      // @todo: be selective about what change-events trigger requests to the
+      // server.
+      // "Debounce" rapid sequences of change events to avoid unnecessary requests.
+      blockInstances.on('change', _.debounce(function() {
+        this.saveFullLayout();
+      }, 100), this);
+      blockInstances.on('add', this.saveFullLayout, this);
+      blockInstances.on('remove', this.saveFullLayout, this);
+    },
+
+    render:function () {
+      this.$el.html(Drupal.theme.layoutRegion(this.model.get('id'), this.model.get('label')));
+      this._collectionView.render();
+      return this;
+    },
+
+    remove:function () {
+      this.$el.empty();
+      this._collectionView.remove();
+    },
+
+    reorderInstances:function (event, model, position) {
+      var collection = this.model.get('blockInstances');
+      // handle cross collection.
+      if (!collection.contains(model)) {
+        // let's remove it from the other first before adding it here.
+        model.collection.remove(model);
+      } else {
+        if (model.get('weight')==position) {
+          return ;
+        }
+        collection.remove(model);
+      }
+      collection.each(function (model, index) {
+        var weight = index;
+        if (index >= position) {
+          weight += 1;
+        }
+        model.set('weight', weight);
+      });
+      model.set('weight', position);
+      collection.add(model, {at:position});
+      collection.trigger('reorder');
+      this.render();
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/js/views/regionmodal-view.js b/core/modules/layout/js/views/regionmodal-view.js
new file mode 100644
index 0000000..4eca478
--- /dev/null
+++ b/core/modules/layout/js/views/regionmodal-view.js
@@ -0,0 +1,23 @@
+/**
+ * @file
+ */
+(function ($, _, Backbone, Drupal) {
+
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+  Drupal.layout.RegionModalView = Drupal.layout.ModalView.extend({
+    events: {
+    },
+    render: function() {
+      this.$el.html(
+        '<div>Configure region type? Load some FAPI form here.</div>' +
+        '<button class="dialog-cancel">' + Drupal.t('Close') + '</button>'
+      );
+      this.show();
+      return this;
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
+
diff --git a/core/modules/layout/js/views/updatingcollection-view.js b/core/modules/layout/js/views/updatingcollection-view.js
new file mode 100644
index 0000000..3568a27
--- /dev/null
+++ b/core/modules/layout/js/views/updatingcollection-view.js
@@ -0,0 +1,105 @@
+/**
+ * @file
+ */
+(function ($, _, Backbone, Drupal) {
+  "use strict";
+
+  Drupal.layout = Drupal.layout || {};
+
+  Drupal.layout.UpdatingCollectionView = Backbone.View.extend({
+    initialize:function (options) {
+      if (!options.nestedViewConstructor) {
+        throw "no child view constructor provided";
+      }
+      if (!options.nestedViewTagName) {
+        throw "no child view tag name provided";
+      }
+
+      this._nestedViews = [];
+      this.collection.each(this._addModel, this);
+      this.collection.bind('add', this._addModel, this);
+      this.collection.bind('remove', this._removeModel, this);
+    },
+
+    /**
+     * Retrieves a nested Backbone.View by its Backbone.Model
+     * @param model
+     * @return {Backbone.Model}
+     * @private
+     */
+    _getViewByModel: function(model) {
+      // @todo this probably should be cached/tracked.
+      var vs = _(this._nestedViews).select(function (nv) {
+        return nv.model === model;
+      });
+      return vs.length ? vs[0] : false;
+    },
+
+    /**
+     * Return either this.$el or if a nestedViewContainerSelector-option was
+     * given the element that matches this.$(nestedViewContainerSelector).
+     *
+     * @return {jQuery}
+     * @private
+     */
+    _getContainerElement: function() {
+      if (this.options.nestedViewContainerSelector) {
+        return this.$(this.options.nestedViewContainerSelector);
+      }
+      else {
+        return this.$el;
+      }
+    },
+
+    /**
+     * Called when a new model is added to the collection.
+     *
+     * @param {Backbone.Model} model
+     * @private
+     */
+    _addModel:function (model) {
+      var nv = new this.options.nestedViewConstructor({
+        tagName:this.options.nestedViewTagName,
+        model:model
+      });
+
+      this._nestedViews.push(nv);
+      if (this._rendered) {
+        this._getContainerElement().append(nv.render().$el);
+      }
+    },
+
+    /**
+     * Called when a new model is removed from the collection.
+     *
+     * @param {Backbone.Model} model
+     * @private
+     */
+    _removeModel:function (model) {
+      var viewToRemove = this._getViewByModel(model);
+      this._nestedViews = _(this._nestedViews).without(viewToRemove);
+      if (this._rendered && viewToRemove) {
+        viewToRemove.$el.remove();
+      }
+    },
+
+    /**
+     * Renders all nested views (one per model in the view's collection).
+     *
+     * @return {Drupal.layout.UpdatingCollectionView}
+     */
+    render:function () {
+      this._rendered = true;
+      var $el  = this._getContainerElement();
+      $el.empty();
+      // Use the collection to make sure the order of the rendered views is
+      // up-to-date.
+      this.collection.each(function(m) {
+        var nv = this._getViewByModel(m);
+        $el.append(nv.render().$el);
+      }, this);
+      return this;
+    }
+  });
+
+})(jQuery, _, Backbone, Drupal);
diff --git a/core/modules/layout/layout.admin.css b/core/modules/layout/layout.admin.css
deleted file mode 100644
index 6e38bf4..0000000
--- a/core/modules/layout/layout.admin.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.layout-display {
-  background: rgb(224, 224, 224);
-}
-
-.layout-region-demonstration {
-  background-image: -moz-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
-  background-image: -o-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
-  background-image: -ms-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
-  background-image: -webkit-linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
-  background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.4, rgb(70,70,71)), color-stop(0.7, rgb(91,91,94)), color-stop(0.88, rgb(125,124,125)));
-  background-image: linear-gradient(bottom, rgb(70,70,71) 40%, rgb(91,91,94) 70%, rgb(125,124,125) 88%);
-  color: white;
-  font-size: 0.8em;
-  margin: 3px;
-  padding: 10px;
-  text-transform: uppercase;
-}
diff --git a/core/modules/layout/layout.admin.inc b/core/modules/layout/layout.admin.inc
deleted file mode 100644
index 9a1a921..0000000
--- a/core/modules/layout/layout.admin.inc
+++ /dev/null
@@ -1,75 +0,0 @@
-<?php
-
-/**
- * @file
- * Administration functions for layouts.
- */
-
-/**
- * Page callback: Presents a list of layouts.
- *
- * @return array
- *   An array as expected by drupal_render().
- *
- * @see layout_menu()
- */
-function layout_page_list() {
-  // Get list of layouts defined by enabled modules and themes.
-  $layouts = layout_manager()->getDefinitions();
-
-  $rows = array();
-  $header = array(t('Name'), t('Source'));
-  foreach ($layouts as $name => $layout) {
-    $provider_info = system_get_info($layout['provider']['type'], $layout['provider']['provider']);
-
-    // Build table columns for this row.
-    $row = array();
-    $row['name'] = l($layout['title'], 'admin/structure/templates/manage/' . $name);
-    // Type can either be 'module' or 'theme'.
-    $row['provider'] = t('@name @type', array('@name' => $provider_info['name'], '@type' => t($layout['provider']['type'])));
-
-    $rows[] = $row;
-  }
-
-  $build = array();
-  $build['table'] = array(
-    '#theme' => 'table',
-    '#header' => $header,
-    '#rows' => $rows,
-  );
-  return $build;
-
-  // Ensure the provider types are translatable. These do not need to run,
-  // just inform the static code parser of these source strings.
-  t('module');
-  t('theme');
-}
-
-/**
- * Page callback: Demonstrates a layout template.
- *
- * @param string $key
- *   The key of the page layout being requested.
- *
- * @return array
- *   An array as expected by drupal_render().
- *
- * @see layout_menu()
- */
-function layout_page_view($key) {
-  $layout = layout_manager()->getDefinition($key);
-  drupal_set_title(t('View template %name', array('%name' => $layout['title'])), PASS_THROUGH);
-
-  // Render the layout in an admin context with region demonstrations.
-  $instance = layout_manager()->createInstance($key, array());
-  $regions = $instance->getRegions();
-  foreach ($regions as $region => $info) {
-    $regions[$region] = '<div class="layout-region-demonstration">' . check_plain($info['label']) . '</div>';
-  }
-  $build['demonstration'] = array(
-    '#type' => 'markup',
-    '#markup' => $instance->renderLayout(TRUE, $regions),
-  );
-  $build['#attached']['css'][] = drupal_get_path('module', 'layout') . '/layout.admin.css';
-  return $build;
-}
diff --git a/core/modules/layout/layout.module b/core/modules/layout/layout.module
old mode 100644
new mode 100755
index c6ed7ae..73861d4
--- a/core/modules/layout/layout.module
+++ b/core/modules/layout/layout.module
@@ -5,17 +5,20 @@
  * Manages page layouts for content presentation.
  */
 
+use Drupal\layout\Plugin\Core\Entity\Display;
+
 /**
  * Implements hook_menu().
  */
 function layout_menu() {
+  // Layout template demonstration.
   $items['admin/structure/templates'] = array(
     'title' => 'Templates',
     'description' => 'Overview of the list of layout templates available.',
     'page callback' => 'layout_page_list',
     'access callback' => 'user_access',
     'access arguments' => array('administer layouts'),
-    'file' => 'layout.admin.inc',
+    'file' => 'includes/layout.admin.inc',
   );
   $items['admin/structure/templates/manage/%'] = array(
     'title' => 'View template',
@@ -23,8 +26,44 @@ function layout_menu() {
     'page arguments' => array(4),
     'access callback' => 'layout_user_access',
     'access arguments' => array(4),
-    'file' => 'layout.admin.inc',
+    'file' => 'includes/layout.admin.inc',
+  );
+  // Master layout editing.
+  $items['admin/structure/layouts'] = array(
+    'title' => 'Layouts',
+    'description' => 'Overview of the list of layouts available.',
+    'page callback' => 'layout_master_list',
+    'access callback' => 'user_access',
+    'access arguments' => array('administer layouts'),
+    'file' => 'includes/layout.admin.inc',
+  );
+  $items['admin/structure/layouts/manage/%layout_master_cache'] = array(
+    'title' => 'Edit layout',
+    'page callback' => 'layout_master_edit',
+    'page arguments' => array(4),
+    'access callback' => 'user_access',
+    'access arguments' => array('administer layouts'),
+    'file' => 'includes/layout.admin.inc',
+  );
+
+  $items['admin/structure/layouts/manage/%layout_master_cache/webservice'] = array(
+    'title' => 'Webservice',
+    'page callback' => 'layout_master_webservice',
+    'page arguments' => array(4),
+    'access callback' => 'user_access',
+    'access arguments' => array('administer layouts'),
+    'file' => 'includes/layout.admin.inc',
   );
+
+  $items['admin/structure/layouts/manage/%layout_master_cache/break-lock'] = array(
+    'title' => 'Break lock',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('layout_master_break_lock_confirm', 4),
+    'access callback' => 'user_access',
+    'access arguments' => array('administer layouts'),
+    'file' => 'includes/layout.admin.inc',
+  );
+
   return $items;
 }
 
@@ -80,3 +119,137 @@ function layout_theme($existing, $type, $theme, $path) {
   }
   return $items;
 }
+
+/**
+ * Entity URI callback.
+ *
+ * @param \Drupal\layout\Plugin\Core\Entity\Display $display
+ *   Dispaly configuration entity instance.
+ *
+ * @return array
+ *   Entity URI information.
+ */
+function layout_master_uri(Display $display) {
+  return array(
+    'path' => 'admin/structure/layouts/manage/' . $display->id(),
+  );
+}
+
+/**
+ * Load one display object by its identifier.
+ *
+ * @todo Remove once not needed for layout_menu().
+ *
+ * @return \Drupal\layout\Plugin\Core\Entity\Display
+ *   Display configuration entity instance.
+ */
+function layout_master_load($id) {
+  return entity_load('display', $id);
+}
+
+/**
+ * Specialized menu callback to load a display.
+ *
+ * @param $name
+ *   The machine name of the display.
+ *
+ * @return
+ *   The display object.
+ */
+function layout_master_cache_load($name) {
+  $display_temp_store = drupal_container()->get('user.tempstore')->get('layout');
+  $display = $display_temp_store->get($name);
+
+  if (empty($display)) {
+    $display = layout_master_load($name);
+  }
+
+  if (empty($display)) {
+    return FALSE;
+  }
+  // This mimics views_ui's behaviour.
+  $display->editing = TRUE;
+  $display->locked = $display_temp_store->getMetadata($display->get('id'));
+
+  return $display;
+}
+
+/**
+ * Specialized cache function.
+ */
+function layout_master_cache_set(Display $display) {
+  // This mimics views_ui's behaviour.
+  $display->changed = TRUE;
+  drupal_container()->get('user.tempstore')->get('layout')->set($display->id, $display);
+}
+
+/**
+ * Implements hook_entity_info_alter().
+ *
+ * Add URI callback to Display config entities to support listing API.
+ */
+function layout_entity_info_alter(&$entity_info) {
+  $entity_info['display']['uri_callback'] = 'layout_master_uri';
+  $entity_info['display']['list_controller_class'] = 'Drupal\layout\DisplayListController';
+  $entity_info['display']['form_controller_class']['default'] = 'Drupal\layout\DisplayFormController';
+  $entity_info['display']['list_path'] = 'admin/structure/layouts';
+  $entity_info['display']['entity_keys']['label'] = 'label';
+}
+
+/**
+ * Ajax callback for block placement display switching.
+ */
+function layout_ajax_block_placement_callback($form, &$form_state) {
+  return $form['blocks'];
+}
+
+/**
+ * Implements hook_library_info().
+ */
+function layout_library_info() {
+  $libraries = array();
+  $path = drupal_get_path('module', 'layout');
+  $libraries['layout.admin'] = array(
+    'title' => 'Layout admin',
+    'version' => NULL,
+    'css' => array(
+      $path . '/css/layout.base.css' => array(),
+      $path . '/css/layout.theme.css' => array(),
+      $path . '/css/layout.icons.css' => array(),
+    ),
+    'js' => array(
+      // Drupal's pseudo-templates
+      $path . '/js/theme.js' => array('defer' => TRUE),
+
+      // Models
+      $path . '/js/layout.admin.js' => array('defer' => TRUE),
+      $path . '/js/models/app-model.js' => array('defer' => TRUE),
+      $path . '/js/models/block-model.js' => array('defer' => TRUE),
+      $path . '/js/models/blockinstance-model.js' => array('defer' => TRUE),
+      $path . '/js/models/region-model.js' => array('defer' => TRUE),
+
+      // Collections bundled for the time being.
+      $path . '/js/collections/collections.js' => array('defer' => TRUE),
+
+      // Views other Views extend first
+      $path . '/js/views/updatingcollection-view.js' => array('defer' => TRUE),
+      $path . '/js/views/modal-view.js' => array('defer' => TRUE),
+
+      $path . '/js/views/region-view.js' => array('defer' => TRUE),
+      $path . '/js/views/blockinstance-view.js' => array('defer' => TRUE),
+      $path . '/js/views/blockinstancemodal-view.js' => array('defer' => TRUE),
+
+      $path . '/js/views/regionmodal-view.js' => array('defer' => TRUE),
+      $path . '/js/views/blockinstancemodal-view.js' => array('defer' => TRUE),
+      $path . '/js/views/blockselectormodal-view.js' => array('defer' => TRUE),
+
+      $path . '/js/views/app-view.js' => array('defer' => TRUE),
+    ),
+    'dependencies' => array(
+      array('system', 'backbone'),
+      array('system', 'drupal.dialog'),
+      array('system', 'jquery.ui.sortable'),
+    ),
+  );
+  return $libraries;
+}
diff --git a/core/modules/layout/layouts/static/one-col/one-col.tpl.php b/core/modules/layout/layouts/static/one-col/one-col.tpl.php
index 61af832..529eb06 100644
--- a/core/modules/layout/layouts/static/one-col/one-col.tpl.php
+++ b/core/modules/layout/layouts/static/one-col/one-col.tpl.php
@@ -12,7 +12,7 @@
  */
 ?>
 <div class="layout-display layout-one-col <?php print $attributes['class']; ?>"<?php print $attributes; ?>>
-  <div class="layout-region">
+  <div class="layout-region layout-region-content">
     <?php print $content['content']; ?>
   </div>
 </div>
diff --git a/core/modules/layout/layouts/static/twocol/two-col.tpl.php b/core/modules/layout/layouts/static/twocol/two-col.tpl.php
index 810a052..ab59cac 100644
--- a/core/modules/layout/layouts/static/twocol/two-col.tpl.php
+++ b/core/modules/layout/layouts/static/twocol/two-col.tpl.php
@@ -14,11 +14,11 @@
  */
 ?>
 <div class="layout-display layout-two-col clearfix <?php print $attributes['class']; ?>"<?php print $attributes; ?>>
-  <div class="layout-region layout-col-first">
+  <div class="layout-region layout-region-first">
     <?php print $content['first']; ?>
   </div>
 
-  <div class="layout-region layout-col-second">
+  <div class="layout-region layout-region-second">
     <?php print $content['second']; ?>
   </div>
 </div>
diff --git a/core/modules/layout/lib/Drupal/layout/Config/DisplayBase.php b/core/modules/layout/lib/Drupal/layout/Config/DisplayBase.php
index afe3229..cac0407 100644
--- a/core/modules/layout/lib/Drupal/layout/Config/DisplayBase.php
+++ b/core/modules/layout/lib/Drupal/layout/Config/DisplayBase.php
@@ -135,4 +135,22 @@ public function getAllRegionTypes() {
     }
     return array_unique($types);
   }
+
+  /**
+   * Implements DisplayInterface::export().
+   */
+  public function export() {
+    // Start by exporting the public properties.
+    $class_info = new \ReflectionClass($this);
+    $properties = array();
+    foreach ($class_info->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
+      $name = $property->getName();
+      $properties[$name] = $this->$name;
+    }
+
+    // Now, add protected data - the blockInfo array.
+    $properties['blockInfo'] = $this->blockInfo;
+
+    return $properties;
+  }
 }
diff --git a/core/modules/layout/lib/Drupal/layout/Config/DisplayInterface.php b/core/modules/layout/lib/Drupal/layout/Config/DisplayInterface.php
index 871aadc..c40e699 100644
--- a/core/modules/layout/lib/Drupal/layout/Config/DisplayInterface.php
+++ b/core/modules/layout/lib/Drupal/layout/Config/DisplayInterface.php
@@ -50,7 +50,7 @@
    * @return array
    *   An array keyed on each block's configuration object name. Each value is
    *   an array of information that determines the placement of the block within
-   *   a layout, including:
+   *   a layout, including but not limited to:
    *   - region: The region in which to display the block (for bound displays
    *     only).
    *   - region-type: The type of region that is most appropriate for the block.
@@ -82,4 +82,11 @@ public function mapBlocksToLayout(LayoutInterface $layout);
    *   region types were assigned.
    */
   public function getAllRegionTypes();
+
+  /**
+   * Returns this display as an array suitable for permanent storage.
+   *
+   * @return array
+   */
+  public function export();
 }
diff --git a/core/modules/layout/lib/Drupal/layout/Config/DisplayStorageController.php b/core/modules/layout/lib/Drupal/layout/Config/DisplayStorageController.php
new file mode 100644
index 0000000..cc86f93
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/Config/DisplayStorageController.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @file ConfigStorageController.php
+ *
+ * Definition of Drupal\layout\Config\DisplayStorageController.
+ */
+
+namespace Drupal\layout\Config;
+
+use Drupal\Core\Config\Entity\ConfigStorageController;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\layout\Config\DisplayInterface;
+
+/**
+ * Storage controller for all Display entity types.
+ */
+class DisplayStorageController extends ConfigStorageController {
+  public function getProperties(EntityInterface $entity) {
+    if (!$entity instanceof DisplayInterface) {
+      throw new \RuntimeException(sprintf('DisplayStorageController::getProperties can only work with objects implementing Drupal\\layout\\Config\\DisplayInterface, object of type "%s" was given.', get_class($entity)));
+    }
+
+    return $entity->export();
+  }
+}
diff --git a/core/modules/layout/lib/Drupal/layout/DisplayFormController.php b/core/modules/layout/lib/Drupal/layout/DisplayFormController.php
new file mode 100755
index 0000000..3d0cc3f
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/DisplayFormController.php
@@ -0,0 +1,207 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\layout\DisplayFormController.
+ */
+
+namespace Drupal\layout;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityFormController;
+use Drupal\layout\Plugin\Core\Entity\Display;
+
+/**
+ * Form controller for the display edit forms.
+ */
+class DisplayFormController extends EntityFormController {
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::form().
+   */
+  public function form(array $form, array &$form_state, EntityInterface $display) {
+    // Get list of layouts to be exposed for display layout selection.
+    $layouts = drupal_container()->get('plugin.manager.layout')->getDefinitions();
+    $layout_options = array();
+    foreach ($layouts as $key => $layout) {
+      $layout_options[$key] = $layout['title'];
+    }
+    $layout_keys = array_keys($layout_options);
+
+    // Add default values to form_state['values'].
+    if (!isset($form_state['values'])) {
+      $form_state['values'] = array();
+    }
+
+
+    $form_state['values'] += array(
+      'layout' => isset($display->layout) ? $display->layout : reset($layout_keys)
+    );
+
+    // @todo: we need proper lock & dirty handling.
+    // @todo: this needs to happen in the client to.
+    if (isset($display->dirty) && $display->dirty) {
+      $form['dirty'] = array(
+        '#type' => 'container',
+        '#attributes' => array('class' => array('view-locked', 'messages', 'warning')),
+        '#children' => t('This display has been edited by you and the changes have not been saved yet.'),
+        '#weight' => -10,
+      );
+    }
+
+    $locked = isset($display->locked) && is_object($display->locked) && $display->locked->owner != $GLOBALS['user']->uid;
+    // Copied from ViewsEditFormController
+    if ($locked) {
+      $form['locked'] = array(
+        '#type' => 'container',
+        '#attributes' => array('class' => array('view-locked', 'messages', 'warning')),
+        '#children' => t('This display is being edited by user !user, and is therefore locked from editing by others. This lock is @age old. Click here to <a href="@break">break this lock</a>.',
+          // @todo: add callback to break lock.
+          array(
+            '!user' => theme('username', array('account' => user_load($display->locked->owner))),
+            '@age' => format_interval(REQUEST_TIME - $display->locked->updated),
+            '@break' => url('admin/structure/layouts/manage/' . $display->get('id') . '/break-lock')
+          )
+        ),
+        '#weight' => -10,
+      );
+    }
+    else {
+      $message = t('* All changes are stored temporarily. Click Save to make your changes permanent. Click Cancel to discard your changes.');
+
+      $form['changed'] = array(
+        '#type' => 'container',
+        '#attributes' => array('class' => array('display-changed', 'messages', 'warning')),
+        '#children' => $message,
+        '#weight' => -10,
+      );
+      if (empty($display->changed)) {
+        $form['changed']['#attributes']['class'][] = 'js-hide';
+      }
+    }
+
+
+
+    $form['layout'] = array(
+      '#type' => 'select',
+      '#title' => t('Template'),
+      '#default_value' => $form_state['values']['layout'],
+      '#options' => $layout_options,
+      '#ajax' => array(
+        'callback' => 'layout_ajax_block_placement_callback',
+        'wrapper' => 'display-blocks',
+        'method' => 'replace',
+        'effect' => 'fade',
+      ),
+    );
+
+    // To support the Ajax interaction, remap the display to the newly selected
+    // layout. This will reorganize the blocks as appropriate.
+    if (!isset($display->layout) || ($form_state['values']['layout'] != $display->layout)) {
+      $layout = layout_manager()->createInstance($form_state['values']['layout'], array());
+      $display->remapToLayout($layout);
+      // Store changes in TempStore.
+      layout_master_cache_set($display);
+    }
+
+    // Add block editing interface wrapper for Ajax operation.
+    $form['blocks'] = array(
+      '#prefix' => '<div id="display-blocks" class="layout-app">',
+      '#suffix' => '</div>',
+    );
+    $form['blocks']['demonstration'] = $this->layoutDemonstration($display);
+    return parent::form($form, $form_state, $display);
+  }
+
+  /**
+   * Produces a render array demonstration form of the display.
+   */
+  private function layoutDemonstration(EntityInterface $display) {
+    // Render the layout in an admin context with region demonstrations.
+    $layout = layout_manager()->createInstance($display->layout, array());
+    $build['demonstration'] = array(
+      '#type' => 'markup',
+      '#markup' => $layout->renderLayout(TRUE, array()),
+    );
+    // Add the backbone app.
+    $build['#attached']['library'][] = array('layout', 'layout.admin');
+    $locked = isset($display->locked) && is_object($display->locked) && $display->locked->owner != $GLOBALS['user']->uid;
+    // Add the webservice URL and display id.
+    $build['#attached']['js'][] =array(
+      'data' => array(
+        'layout' => array(
+          'webserviceURL' => url('admin/structure/layouts/manage/' . $display->id . '/webservice'),
+          'locked' => $locked,
+          'layoutData' => $display->exportGroupedByRegion()
+        )
+      ),
+      'type' => 'setting',
+    );
+    return $build;
+  }
+
+  /**
+   * Temporary implementation of block markup generation.
+   */
+  private function layoutBlock($block_id) {
+    $block_id = str_replace('block.', '', $block_id);
+    return '<div id="block-' . $block_id . '" class="block"><div class="block-master"><div class="information"><span class="type-indicator mb-text">M</span><span class="label mb-text">' . $block_id . '&nbsp;block</span></div><div class="operations"><span class="gear mb-gear"></span></div></div></div>';
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::actions().
+   */
+  protected function actions(array $form, array &$form_state) {
+    // Only includes a Save action for the entity, no direct Delete button.
+    return array(
+      'submit' => array(
+        '#value' => t('Save'),
+        '#validate' => array(
+          array($this, 'validate'),
+        ),
+        '#submit' => array(
+          array($this, 'submit'),
+          array($this, 'save'),
+        ),
+      ),
+      'cancel' => array(
+        '#value' => t('Cancel'),
+        '#submit' => array(
+          array($this, 'cancel'),
+        ),
+      )
+    );
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityFormController::save().
+   */
+  public function save(array $form, array &$form_state) {
+    $display = $this->getEntity($form_state);
+    $cached_display = layout_master_cache_load($display->id);
+    // All changes are already in TempStore. So a save commit all changes.
+    $cached_display->save();
+    // Bust the TempStore. Remove the display form TempStore so it will be reloaded.
+    drupal_container()->get('user.tempstore')->get('layout')->delete($cached_display->id);
+
+    watchdog('display', 'Layout @label saved.', array('@label' => $display->label()), WATCHDOG_NOTICE);
+    drupal_set_message(t('Layout %label saved.', array('%label' => $display->label())));
+  }
+
+  /**
+   * Form submission handler for the 'cancel' action.
+   *
+   * @param array $form
+   *   An associative array containing the structure of the form.
+   * @param array $form_state
+   *   A reference to a keyed array containing the current state of the form.
+   */
+  public function cancel(array $form, array &$form_state) {
+    // Remove this view from cache so edits will be lost.
+    $display = $this->getEntity($form_state);
+    $cached_display = layout_master_cache_load($display->id);
+    drupal_container()->get('user.tempstore')->get('layout')->delete($cached_display->id);
+    $form_state['redirect'] = 'admin/structure/layouts';
+  }
+
+}
diff --git a/core/modules/layout/lib/Drupal/layout/DisplayListController.php b/core/modules/layout/lib/Drupal/layout/DisplayListController.php
new file mode 100644
index 0000000..b07e7ee
--- /dev/null
+++ b/core/modules/layout/lib/Drupal/layout/DisplayListController.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\layout\DisplayListController.
+ */
+
+namespace Drupal\layout;
+
+use Drupal\Core\Config\Entity\ConfigEntityListController;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\layout\Plugin\Core\Entity\Display;
+
+/**
+ * Provides a listing of displays.
+ */
+class DisplayListController extends ConfigEntityListController {
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityListController::getOperations().
+   *
+   * Only allow edit operation, not possible to delete.
+   */
+  public function getOperations(EntityInterface $entity) {
+    $uri = $entity->uri();
+    $operations['edit'] = array(
+      'title' => t('Edit'),
+      'href' => $uri['path'] . '/edit',
+      'options' => $uri['options'],
+      'weight' => 10,
+    );
+    return $operations;
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityListController::buildHeader();
+   */
+  public function buildHeader() {
+    $row['label'] = t('Layout name');
+    $row['applied'] = t('Applied to');
+    $row['template'] = t('Template');
+    $row['operations'] = t('Operations');
+    return $row;
+  }
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityListController::buildRow();
+   */
+  public function buildRow(EntityInterface $entity) {
+    $row['label'] = check_plain($entity->label());
+    // @todo: refer back to pages using this display.
+    $row['applied'] = $entity->id() == 'front_master' ? t('All front end pages (master)') : t('All admin pages (admin master)');
+    $layout = drupal_container()->get('plugin.manager.layout')->getDefinition($entity->layout);
+    $provider_info = system_get_info($layout['provider']['type'], $layout['provider']['provider']);
+    // Type can either be 'module' or 'theme'.
+    $provider_text = t('@name @type', array('@name' => $provider_info['name'], '@type' => t($layout['provider']['type'])));
+    $row['template'] = check_plain($layout['title'] . ' (' . $provider_text . ')');
+    $operations = $this->buildOperations($entity);
+    $row['operations']['data'] = $operations;
+    return $row;
+  }
+
+}
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/Display.php b/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/Display.php
index d954832..7a2daca 100644
--- a/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/Display.php
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/Display.php
@@ -21,7 +21,7 @@
  *   id = "display",
  *   label = @Translation("Display"),
  *   module = "layout",
- *   controller_class = "Drupal\Core\Config\Entity\ConfigStorageController",
+ *   controller_class = "Drupal\layout\Config\DisplayStorageController",
  *   config_prefix = "display.bound",
  *   entity_keys = {
  *     "id" = "id",
@@ -117,7 +117,7 @@ protected function sortBlocks() {
 
     foreach ($regions as $region_name => &$blocks) {
       uasort($blocks, 'drupal_sort_weight');
-      $this->blocksInRegions[$region_name] = array_keys($blocks);
+      $this->blocksInRegions[$region_name] = $blocks;
     }
   }
 
@@ -183,4 +183,42 @@ public function getLayoutInstance() {
 
     return $this->layoutInstance;
   }
+
+  /**
+   * Returns an array representation grouped for json-serialisation.
+   * @todo: this is a bad name (and should probably)
+   *
+   * @return array
+   */
+  public function exportGroupedByRegion() {
+    // Render the layout in an admin context with region demonstrations.
+    $layout = layout_manager()->createInstance($this->layout, array());
+    $regions = $layout->getRegions();
+    $data = array(
+      'id' => $this->id,
+      'layout' => $this->layout
+    );
+    foreach ($regions as $region => $info) {
+      $region_data = array(
+        'id' => $region,
+        'label' => $info['label'],
+        'blockInstances' => array()
+      );
+      $existing_blocks = $this->getSortedBlocksByRegion($region);
+      foreach ($existing_blocks as $block => $placement) {
+        // @todo: this should be proper data. Block instances should maybe
+        // be classed objects as well.
+        $block_id = str_replace('block.', '', $block);
+        $region_data['blockInstances'][] = array(
+          'id' => $block_id,
+          'label' => $block_id,
+          'blockId' => 'default',
+          'weight' => $placement['weight'],
+          'region' => $placement['region'],
+        );
+      }
+      $data['regions'][] = $region_data;
+    }
+    return $data;
+  }
 }
diff --git a/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/UnboundDisplay.php b/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/UnboundDisplay.php
index 5450e2c..ed7591b 100644
--- a/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/UnboundDisplay.php
+++ b/core/modules/layout/lib/Drupal/layout/Plugin/Core/Entity/UnboundDisplay.php
@@ -24,7 +24,7 @@
  *   id = "unbound_display",
  *   label = @Translation("Unbound Display"),
  *   module = "layout",
- *   controller_class = "Drupal\Core\Config\Entity\ConfigStorageController",
+ *   controller_class = "Drupal\layout\Config\DisplayStorageController",
  *   config_prefix = "display.unbound",
  *   entity_keys = {
  *     "id" = "id",
diff --git a/core/modules/layout/lib/Drupal/layout/Tests/DisplayInternalLogicTest.php b/core/modules/layout/lib/Drupal/layout/Tests/DisplayInternalLogicTest.php
index 07a77bf..89c2817 100644
--- a/core/modules/layout/lib/Drupal/layout/Tests/DisplayInternalLogicTest.php
+++ b/core/modules/layout/lib/Drupal/layout/Tests/DisplayInternalLogicTest.php
@@ -67,9 +67,8 @@ public function testBlockSorting() {
       'left' => array('block.test_block_3', 'block.test_block_1'),
       'right' => array('block.test_block_2'),
     );
-    $this->assertIdentical($this->twocol->getSortedBlocksByRegion('left'), $expected['left']);
-    $this->assertIdentical($this->twocol->getSortedBlocksByRegion('right'), $expected['right']);
-    $this->assertIdentical($this->twocol->getAllSortedBlocks(), $expected);
+    $this->assertIdentical(array_keys($this->twocol->getSortedBlocksByRegion('left')), $expected['left']);
+    $this->assertIdentical(array_keys($this->twocol->getSortedBlocksByRegion('right')), $expected['right']);
   }
 
   /**
@@ -88,7 +87,7 @@ public function testBlockMapping() {
     );
     $two_to_one = clone($this->twocol);
     $two_to_one->remapToLayout($this->onecol->getLayoutInstance());
-    $this->assertIdentical($two_to_one->getAllSortedBlocks(), $expected);
+    $this->assertIdentical(array_keys($two_to_one->getSortedBlocksByRegion('middle')), $expected['middle']);
 
     // Remap from onecol to twocol. Since the blocks are assigned the 'content'
     // region type, and twocol's 'left' region has that type, the blocks are
@@ -99,7 +98,8 @@ public function testBlockMapping() {
     );
     $one_to_two = clone($this->onecol);
     $one_to_two->remapToLayout($this->twocol->getLayoutInstance());
-    $this->assertIdentical($one_to_two->getAllSortedBlocks(), $expected);
+    $this->assertIdentical(array_keys($one_to_two->getSortedBlocksByRegion('left')), $expected['left']);
+    $this->assertIdentical(array_keys($one_to_two->getSortedBlocksByRegion('right')), $expected['right']);
 
     // Bind the unbound display to the twocol layout:
     // - Block 1 is assigned the 'content' region type, so is expected to be
@@ -115,7 +115,8 @@ public function testBlockMapping() {
     );
     $unbound_to_twocol = $this->unbound->generateDisplay($this->twocol->getLayoutInstance(), 'unbound_to_twocol');
     $this->assertTrue($unbound_to_twocol instanceof Display, 'Binding the unbound display successfully created a Display object');
-    $this->assertIdentical($unbound_to_twocol->getAllSortedBlocks(), $expected);
+    $this->assertIdentical(array_keys($unbound_to_twocol->getSortedBlocksByRegion('left')), $expected['left']);
+    $this->assertIdentical(array_keys($unbound_to_twocol->getSortedBlocksByRegion('right')), $expected['right']);
 
     // Generate an unbound display from the twocol display.
     $expected = array(
