diff --git a/src/components/ColorPicker.css b/src/components/ColorPicker.css
index 853450ac..06251805 100644
--- a/src/components/ColorPicker.css
+++ b/src/components/ColorPicker.css
@@ -1,28 +1,18 @@
 .color-picker {
-  width: 205px;
   background: rgb(255, 255, 255);
   border: 0px solid rgba(0, 0, 0, 0.25);
   box-shadow: rgba(0, 0, 0, 0.25) 0px 1px 4px;
   border-radius: 4px;
-  position: relative;
+  position: absolute;
+  left: -5.5px;
 }
 
 .color-picker-control-container {
-  display: flex;
+  display: grid;
+  grid-template-columns: auto 1fr;
   align-items: center;
 }
 
-.color-picker-triangle-shadow {
-  width: 0px;
-  height: 0px;
-  border-style: solid;
-  border-width: 0px 9px 10px;
-  border-color: transparent transparent rgba(0, 0, 0, 0.1);
-  position: absolute;
-  top: -11px;
-  left: 12px;
-}
-
 .color-picker-triangle {
   width: 0px;
   height: 0px;
@@ -34,13 +24,20 @@
   left: 12px;
 }
 
-.color-picker-content {
-  padding: 1rem 0.5rem 0.5rem 1rem;
+.color-picker-triangle-shadow {
+  border-color: transparent transparent rgba(0, 0, 0, 0.1);
+  top: -11px;
 }
 
-.colors-gallery {
-  display: flex;
-  flex-wrap: wrap;
+.color-picker-content {
+  padding: 0.5rem 0.5rem;
+  display: grid;
+  grid-template-columns: repeat(5, auto);
+  grid-gap: 0.5rem;
+}
+
+.color-picker-content .color-input-container {
+  grid-column: 1 / span 5;
 }
 
 .color-picker-swatch {
@@ -49,7 +46,7 @@
   width: 1.875rem;
   cursor: pointer;
   border-radius: 4px;
-  margin: 0px 0.375rem 0.375rem 0px;
+  margin: 0;
   box-sizing: border-box;
   border: 1px solid #ddd;
 }
@@ -68,6 +65,9 @@
   right: 0px;
   bottom: 0px;
   left: 0px;
+}
+.color-picker-transparent,
+.color-picker-label-swatch {
   background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==")
     left center;
 }
@@ -81,6 +81,27 @@
   display: flex;
   align-items: center;
   justify-content: center;
+  z-index: 1;
+  position: relative;
+}
+.color-input-container:focus-within .color-picker-hash {
+  box-shadow: 0 0 0 2px #a5d8ff;
+}
+.color-input-container:focus-within .color-picker-hash::before,
+.color-input-container:focus-within .color-picker-hash::after {
+  content: "";
+  width: 1px;
+  height: 100%;
+  position: absolute;
+  top: 0;
+}
+.color-input-container:focus-within .color-picker-hash::before {
+  background: #dee2e6;
+  right: -1px;
+}
+.color-input-container:focus-within .color-picker-hash::after {
+  background: #fff;
+  right: -2px;
 }
 
 .color-input-container {
@@ -88,14 +109,14 @@
 }
 
 .color-picker-input {
-  width: 6.25em;
+  width: 12ch; /* length of `transparent` + 1 */
+  margin: 0;
   font-size: 1rem;
   color: #343a40;
   border: 0px;
   outline: none;
   height: 1.75em;
   box-shadow: #dee2e6 0px 0px 0px 1px inset;
-  box-sizing: content-box;
   border-radius: 0px 4px 4px 0px;
   float: left;
   padding: 1px;
@@ -108,6 +129,19 @@
   width: 1.875rem;
   margin-right: 0.25rem;
   border: 1px solid #dee2e6;
+  position: relative;
+  overflow: hidden;
+  background-color: transparent !important;
+}
+
+.color-picker-label-swatch::after {
+  content: "";
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: var(--swatch-color);
 }
 
 .color-picker-keybinding {
diff --git a/src/components/ColorPicker.tsx b/src/components/ColorPicker.tsx
index 8a1b0e1e..b8351b3c 100644
--- a/src/components/ColorPicker.tsx
+++ b/src/components/ColorPicker.tsx
@@ -24,12 +24,14 @@ const Picker = function({
   onChange,
   onClose,
   label,
+  showInput = true,
 }: {
   colors: string[];
   color: string | null;
   onChange: (color: string) => void;
   onClose: () => void;
   label: string;
+  showInput: boolean;
 }) {
   const firstItem = React.useRef<HTMLButtonElement>();
   const activeItem = React.useRef<HTMLButtonElement>();
@@ -72,7 +74,7 @@ const Picker = function({
         activeElement,
       );
       if (index !== -1) {
-        const length = gallery!.current!.children.length;
+        const length = gallery!.current!.children.length - (showInput ? 1 : 0);
         const nextIndex =
           event.key === KEYS.ARROW_RIGHT
             ? (index + 1) % length
@@ -108,57 +110,57 @@ const Picker = function({
       aria-label={t("labels.colorPicker")}
       onKeyDown={handleKeyDown}
     >
-      <div className="color-picker-triangle-shadow"></div>
+      <div className="color-picker-triangle color-picker-triangle-shadow"></div>
       <div className="color-picker-triangle"></div>
-      <div className="color-picker-content">
-        <div
-          className="colors-gallery"
-          ref={el => {
-            if (el) {
-              gallery.current = el;
-            }
-          }}
-        >
-          {colors.map((_color, i) => (
-            <button
-              className="color-picker-swatch"
-              onClick={() => {
-                onChange(_color);
-              }}
-              title={`${_color} — ${keyBindings[i].toUpperCase()}`}
-              aria-label={_color}
-              aria-keyshortcuts={keyBindings[i]}
-              style={{ backgroundColor: _color }}
-              key={_color}
-              ref={el => {
-                if (el && i === 0) {
-                  firstItem.current = el;
-                }
-                if (el && _color === color) {
-                  activeItem.current = el;
-                }
-              }}
-              onFocus={() => {
-                onChange(_color);
-              }}
-            >
-              {_color === "transparent" ? (
-                <div className="color-picker-transparent"></div>
-              ) : (
-                undefined
-              )}
-              <span className="color-picker-keybinding">{keyBindings[i]}</span>
-            </button>
-          ))}
-        </div>
-        <ColorInput
-          color={color}
-          label={label}
-          onChange={color => {
-            onChange(color);
-          }}
-          ref={colorInput}
-        />
+      <div
+        className="color-picker-content"
+        ref={el => {
+          if (el) {
+            gallery.current = el;
+          }
+        }}
+      >
+        {colors.map((_color, i) => (
+          <button
+            className="color-picker-swatch"
+            onClick={() => {
+              onChange(_color);
+            }}
+            title={`${_color} — ${keyBindings[i].toUpperCase()}`}
+            aria-label={_color}
+            aria-keyshortcuts={keyBindings[i]}
+            style={{ backgroundColor: _color }}
+            key={_color}
+            ref={el => {
+              if (el && i === 0) {
+                firstItem.current = el;
+              }
+              if (el && _color === color) {
+                activeItem.current = el;
+              }
+            }}
+            onFocus={() => {
+              onChange(_color);
+            }}
+          >
+            {_color === "transparent" ? (
+              <div className="color-picker-transparent"></div>
+            ) : (
+              undefined
+            )}
+            <span className="color-picker-keybinding">{keyBindings[i]}</span>
+          </button>
+        ))}
+        {showInput && (
+          <ColorInput
+            color={color}
+            label={label}
+            onChange={color => {
+              onChange(color);
+            }}
+            ref={colorInput}
+          />
+        )}
       </div>
     </div>
   );
@@ -188,7 +190,7 @@ const ColorInput = React.forwardRef(
     React.useImperativeHandle(ref, () => inputRef.current);
 
     return (
-      <div className="color-input-container">
+      <label className="color-input-container">
         <div className="color-picker-hash">#</div>
         <input
           spellCheck={false}
@@ -206,7 +208,7 @@ const ColorInput = React.forwardRef(
           onBlur={() => setInnerValue(color)}
           ref={inputRef}
         />
-      </div>
+      </label>
     );
   },
 );
@@ -231,7 +233,11 @@ export function ColorPicker({
         <button
           className="color-picker-label-swatch"
           aria-label={label}
-          style={color ? { backgroundColor: color } : undefined}
+          style={
+            color
+              ? ({ "--swatch-color": color } as React.CSSProperties)
+              : undefined
+          }
           onClick={() => setActive(!isActive)}
           ref={pickerButton}
         />
@@ -257,6 +263,7 @@ export function ColorPicker({
                 pickerButton.current?.focus();
               }}
               label={label}
+              showInput={false}
             />
           </Popover>
         ) : null}
diff --git a/src/components/Dialog.scss b/src/components/Dialog.scss
index f696e042..2668f694 100644
--- a/src/components/Dialog.scss
+++ b/src/components/Dialog.scss
@@ -1,7 +1,6 @@
 @import "../_variables";
 
 .Dialog__title {
-  --metric: calc(var(--space-factor) * 4);
   display: grid;
   align-items: center;
   margin-top: 0;
@@ -18,15 +17,23 @@
 }
 
 @media #{$media-query} {
+  .Dialog {
+    --metric: calc(var(--space-factor) * 4);
+    --inset-left: #{"max(var(--metric), env(safe-area-inset-left))"};
+    --inset-right: #{"max(var(--metric), env(safe-area-inset-right))"};
+  }
   .Dialog__title {
     grid-template-columns: calc(var(--space-factor) * 7) 1fr calc(
         var(--space-factor) * 7
       );
     position: sticky;
     top: calc(-1 * var(--metric));
-    margin: calc(-1 * var(--metric));
+    margin: calc(-1 * var(--inset-right));
+    margin-top: calc(-1 * var(--metric));
     margin-bottom: var(--metric);
-    padding: calc(var(--space-factor) * 2) var(--metric);
+    padding: calc(var(--space-factor) * 2);
+    padding-left: var(--inset-left);
+    padding-right: var(--inset-right);
     background: white;
     font-size: 1.25em;
 
@@ -38,9 +45,13 @@
     text-align: center;
   }
   .Dialog .Island {
+    width: 100vw;
     height: 100%;
     box-sizing: border-box;
     overflow-y: auto;
+    padding-left: #{"max(calc(var(--padding) * var(--space-factor)), env(safe-area-inset-left))"};
+    padding-right: #{"max(calc(var(--padding) * var(--space-factor)), env(safe-area-inset-right))"};
+    padding-bottom: #{"max(calc(var(--padding) * var(--space-factor)), env(safe-area-inset-bottom))"};
   }
 
   .Dialog .Modal__close {
diff --git a/src/components/ExportDialog.scss b/src/components/ExportDialog.scss
index 71c335db..6a88e3c1 100644
--- a/src/components/ExportDialog.scss
+++ b/src/components/ExportDialog.scss
@@ -16,16 +16,30 @@
 }
 
 .ExportDialog__actions {
+  width: 100%;
   display: flex;
+  grid-gap: calc(var(--space-factor) * 2);
   align-items: top;
   justify-content: space-between;
-  flex-wrap: wrap;
 }
 
-.ExportDialog__scales {
-  display: flex;
-  align-items: baseline;
-  justify-content: flex-end;
+.ExportDialog__name {
+  grid-column: project-name;
+  margin: auto;
+}
+
+@media (max-width: 550px) {
+  .ExportDialog {
+    display: flex;
+    flex-direction: column;
+  }
+  .ExportDialog__actions {
+    flex-direction: column;
+    align-items: center;
+  }
+  .ExportDialog__actions > * {
+    margin-bottom: calc(var(--space-factor) * 3);
+  }
 }
 
 @media #{$media-query} {
@@ -40,13 +54,4 @@
   .ExportDialog__dialog .Island {
     overflow-y: auto;
   }
-  .ExportDialog__actions {
-    flex-direction: column;
-  }
-  .ExportDialog__actions > * {
-    margin-bottom: calc(var(--space-factor) * 3);
-  }
-  .ExportDialog__scales {
-    justify-content: flex-start;
-  }
 }
diff --git a/src/components/ExportDialog.tsx b/src/components/ExportDialog.tsx
index 8cd6845a..ff8cc7f2 100644
--- a/src/components/ExportDialog.tsx
+++ b/src/components/ExportDialog.tsx
@@ -111,10 +111,10 @@ function ExportModal({
   }
 
   return (
-    <div onKeyDown={handleKeyDown}>
+    <div onKeyDown={handleKeyDown} className="ExportDialog">
       <div className="ExportDialog__preview" ref={previewRef}></div>
-      <div className="ExportDialog__actions">
-        <Stack.Col gap={1}>
+      <Stack.Col gap={2} align="center">
+        <div className="ExportDialog__actions">
           <Stack.Row gap={2}>
             <ToolButton
               type="button"
@@ -148,44 +148,42 @@ function ExportModal({
               onClick={() => onExportToBackend(exportedElements)}
             />
           </Stack.Row>
-        </Stack.Col>
-        {actionManager.renderAction("changeProjectName")}
-        <Stack.Col gap={1}>
-          <div className="ExportDialog__scales">
-            <Stack.Row gap={2} align="baseline">
-              {scales.map(s => (
-                <ToolButton
-                  key={s}
-                  size="s"
-                  type="radio"
-                  icon={`x${s}`}
-                  name="export-canvas-scale"
-                  aria-label={`Scale ${s} x`}
-                  id="export-canvas-scale"
-                  checked={s === scale}
-                  onChange={() => setScale(s)}
-                />
-              ))}
-            </Stack.Row>
+          <div className="ExportDialog__name">
+            {actionManager.renderAction("changeProjectName")}
           </div>
-          {actionManager.renderAction("changeExportBackground")}
-          {someElementIsSelected && (
-            <div>
-              <label>
-                <input
-                  type="checkbox"
-                  checked={exportSelected}
-                  onChange={event =>
-                    setExportSelected(event.currentTarget.checked)
-                  }
-                  ref={onlySelectedInput}
-                />{" "}
-                {t("labels.onlySelected")}
-              </label>
-            </div>
-          )}
-        </Stack.Col>
-      </div>
+          <Stack.Row gap={2}>
+            {scales.map(s => (
+              <ToolButton
+                key={s}
+                size="s"
+                type="radio"
+                icon={`x${s}`}
+                name="export-canvas-scale"
+                aria-label={`Scale ${s} x`}
+                id="export-canvas-scale"
+                checked={s === scale}
+                onChange={() => setScale(s)}
+              />
+            ))}
+          </Stack.Row>
+        </div>
+        {actionManager.renderAction("changeExportBackground")}
+        {someElementIsSelected && (
+          <div>
+            <label>
+              <input
+                type="checkbox"
+                checked={exportSelected}
+                onChange={event =>
+                  setExportSelected(event.currentTarget.checked)
+                }
+                ref={onlySelectedInput}
+              />{" "}
+              {t("labels.onlySelected")}
+            </label>
+          </div>
+        )}
+      </Stack.Col>
     </div>
   );
 }
diff --git a/src/components/Popover.tsx b/src/components/Popover.tsx
index 7e981073..c033040d 100644
--- a/src/components/Popover.tsx
+++ b/src/components/Popover.tsx
@@ -1,4 +1,4 @@
-import React, { useLayoutEffect, useRef } from "react";
+import React, { useLayoutEffect, useRef, useEffect } from "react";
 import "./Popover.css";
 
 type Props = {
@@ -35,18 +35,20 @@ export function Popover({
     }
   }, [fitInViewport]);
 
+  useEffect(() => {
+    if (onCloseRequest) {
+      const handler = (e: Event) => {
+        if (!popoverRef.current?.contains(e.target as Node)) {
+          onCloseRequest();
+        }
+      };
+      document.addEventListener("pointerdown", handler, false);
+      return () => document.removeEventListener("pointerdown", handler, false);
+    }
+  }, [onCloseRequest]);
+
   return (
     <div className="popover" style={{ top: top, left: left }} ref={popoverRef}>
-      <div
-        className="cover"
-        onClick={onCloseRequest}
-        onContextMenu={event => {
-          event.preventDefault();
-          if (onCloseRequest) {
-            onCloseRequest();
-          }
-        }}
-      />
       {children}
     </div>
   );
diff --git a/src/components/ProjectName.css b/src/components/ProjectName.css
index 5e66194a..07079b2c 100644
--- a/src/components/ProjectName.css
+++ b/src/components/ProjectName.css
@@ -2,9 +2,8 @@
   display: inline-block;
   cursor: pointer;
   border: 1.5px solid #eee;
-  height: 2.5rem;
-  line-height: 2.5rem;
-  padding: 0 0.5rem;
+  line-height: 1;
+  padding: 0.75rem;
   white-space: nowrap;
   border-radius: var(--space-factor);
 }
diff --git a/src/components/ToolIcon.scss b/src/components/ToolIcon.scss
index 68a7bac3..30308aba 100644
--- a/src/components/ToolIcon.scss
+++ b/src/components/ToolIcon.scss
@@ -13,7 +13,6 @@
   cursor: pointer;
   background-color: var(--button-gray-1);
   -webkit-tap-highlight-color: transparent;
-
   border-radius: var(--space-factor);
 }