Files
HiveGrid-Wireframes/02 Wireframes/D0 Foundation/D-D0b Layout Standards/Preview/index.html
T

3751 lines
120 KiB
HTML

<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>D-D0b Layout Preview</title>
<style>
:root {
--bg: #f6f8fa;
--surface: #ffffff;
--surface-subtle: #f1f4f7;
--border: #dce3ea;
--border-strong: #b8c4cf;
--text: #172635;
--muted: #5c6f82;
--muted-2: #74879a;
--primary: #2458d3;
--primary-dark: #1742a6;
--danger: #b42318;
--success: #147a46;
--warning: #9a5b00;
--padding-viz: rgba(139, 92, 246, 0.2);
--padding-viz-strong: #7c3aed;
--gap-viz: rgba(20, 184, 166, 0.18);
--gap-viz-strong: #0f766e;
--shadow: 0 16px 40px rgba(20, 35, 55, 0.12);
--radius: 8px;
--page-pad: 24px;
--section-gap: 24px;
--card-pad: 16px;
--control-h: 36px;
--font-body-default-regular-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-body-default-regular-0: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-body-small-regular-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-body-extra-small-semibold-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-body-default-semibold-150: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-heading: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--text-heading: 24px;
--text-heading--font-weight: 500;
--text-heading--line-height: 32px;
--text-body-default-regular-150: 16px;
--text-body-default-regular-150--font-weight: 400;
--text-body-default-regular-150--line-height: 24px;
--text-body-default-regular-0: 16px;
--text-body-default-regular-0--font-weight: 400;
--text-body-default-regular-0--line-height: 17px;
--text-body-small-regular-150: 14px;
--text-body-small-regular-150--font-weight: 400;
--text-body-small-regular-150--line-height: 21px;
--text-body-small-regular-0: 14px;
--text-body-small-regular-0--font-weight: 400;
--text-body-small-regular-0--line-height: 15px;
--text-body-default-semibold-150: 16px;
--text-body-default-semibold-150--font-weight: 600;
--text-body-default-semibold-150--line-height: 24px;
--text-body-extra-small-semibold-150: 12px;
--text-body-extra-small-semibold-150--font-weight: 600;
--text-body-extra-small-semibold-150--line-height: 18px;
font-family:
Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", sans-serif;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-size: 14px;
line-height: 1.5;
}
button,
input,
select,
textarea {
font: inherit;
}
.topbar {
position: sticky;
top: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
min-height: 56px;
padding: 0 var(--page-pad);
border-bottom: 1px solid var(--border);
background: rgba(255, 255, 255, 0.92);
backdrop-filter: blur(10px);
}
.brand {
display: flex;
align-items: center;
gap: 12px;
font-weight: 700;
}
.mark {
display: grid;
width: 28px;
height: 28px;
place-items: center;
border-radius: 6px;
background: var(--text);
color: #fff;
font-size: 12px;
}
.topbar-actions {
display: flex;
align-items: center;
gap: 8px;
}
.marker-toggle {
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 32px;
padding: 0 10px;
border: 1px solid var(--border-strong);
border-radius: 999px;
background: #fff;
color: var(--text);
font-size: 12px;
font-weight: 650;
cursor: pointer;
}
.marker-toggle-switch {
position: relative;
width: 32px;
height: 18px;
border-radius: 999px;
background: var(--gap-viz-strong);
}
.marker-toggle-switch::after {
content: "";
position: absolute;
top: 3px;
left: 17px;
width: 12px;
height: 12px;
border-radius: 999px;
background: #fff;
transition: left 160ms ease;
}
body.hide-gap-markers .marker-toggle-switch {
background: var(--border-strong);
}
body.hide-gap-markers .marker-toggle-switch::after {
left: 3px;
}
.legend {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 12px;
margin-top: 16px;
}
.legend-item {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--muted);
font-size: 13px;
}
.legend-dot {
width: 16px;
height: 16px;
border-radius: 4px;
}
.legend-dot.padding {
border: 1px solid var(--padding-viz-strong);
background: var(--padding-viz);
}
.legend-dot.gap {
border: 1px solid var(--gap-viz-strong);
background: var(--gap-viz);
}
.legend-dot.content {
border: 1px solid var(--border-strong);
background: #fff;
}
.page {
max-width: 1440px;
margin: 0 auto;
padding: var(--page-pad);
}
.hero {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 32px;
}
.eyebrow {
margin: 0 0 8px;
color: var(--muted-2);
font-size: 12px;
font-weight: 700;
letter-spacing: 0;
text-transform: uppercase;
}
h1,
h2,
h3,
p {
margin: 0;
}
h1 {
font-size: 36px;
line-height: 1.15;
letter-spacing: 0;
}
.subtitle {
max-width: 720px;
margin-top: 8px;
color: var(--muted);
font-size: 16px;
line-height: 1.5;
}
.section {
margin-top: var(--section-gap);
}
.section-head {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 24px;
margin-bottom: 16px;
}
.section-copy {
max-width: 760px;
}
h2 {
font-size: 22px;
line-height: 1.3;
}
.section-desc {
margin-top: 6px;
color: var(--muted);
}
.decision-map {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
}
.decision-link {
display: grid;
gap: 4px;
min-height: 92px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
text-decoration: none;
color: var(--text);
}
.decision-link strong {
font-size: 13px;
}
.decision-link span {
color: var(--muted);
font-size: 12px;
line-height: 1.4;
}
.decision-panel {
display: grid;
gap: 16px;
margin-bottom: 24px;
padding: 24px;
border: 1px solid #c7d2fe;
border-radius: 8px;
background: #eef3ff;
}
.decision-kicker {
color: #2443a8;
font-size: 12px;
font-weight: 800;
letter-spacing: 0;
text-transform: uppercase;
}
.decision-panel h3 {
font-size: 18px;
line-height: 1.35;
}
.decision-panel p {
color: #294268;
}
.decision-options {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.decision-option {
padding: 16px;
border: 1px solid #c7d2fe;
border-radius: 8px;
background: #fff;
}
.decision-option.recommended {
border-color: var(--primary);
box-shadow: inset 0 0 0 1px var(--primary);
}
.decision-option strong {
display: block;
margin-bottom: 4px;
}
.decision-option span {
display: block;
color: var(--muted);
font-size: 12px;
line-height: 1.45;
}
.decision-question {
padding: 12px 16px;
border-left: 4px solid var(--primary);
border-radius: 6px;
background: #fff;
color: var(--text);
font-weight: 650;
}
.decision-tag {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 8px;
border-radius: 999px;
background: #dbe4ff;
color: #2443a8;
font-size: 12px;
font-weight: 800;
}
.definition-grid {
display: grid;
grid-template-columns: minmax(260px, 0.9fr) minmax(0, 1.4fr);
gap: 24px;
}
.reference-strip {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.reference-card {
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.reference-card strong {
display: block;
margin-bottom: 6px;
}
.reference-card ul {
display: grid;
gap: 6px;
margin: 0;
padding-left: 18px;
color: var(--muted);
}
.d02-preview-grid {
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
gap: 24px;
margin-bottom: 24px;
}
.compare-block {
display: grid;
gap: 16px;
margin-bottom: 24px;
}
.compare-head {
display: grid;
gap: 4px;
}
.compare-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.compare-card {
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.compare-card.recommended {
border-color: var(--primary);
box-shadow: inset 0 0 0 1px var(--primary);
}
.compare-title {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
}
.mini-page {
--sample-page-pad: 24px;
--sample-card-pad: 16px;
--sample-gap: 16px;
position: relative;
padding: var(--sample-page-pad);
border: 1px solid var(--padding-viz-strong);
border-radius: 8px;
background:
repeating-linear-gradient(
45deg,
rgba(139, 92, 246, 0.22) 0,
rgba(139, 92, 246, 0.22) 8px,
rgba(139, 92, 246, 0.1) 8px,
rgba(139, 92, 246, 0.1) 16px
);
}
.mini-page-content {
display: grid;
gap: 10px;
min-height: 96px;
padding: 12px;
border: 1px dashed var(--border-strong);
border-radius: 6px;
background: #fff;
}
.mini-card {
position: relative;
padding: var(--sample-card-pad);
border: 1px solid var(--padding-viz-strong);
border-radius: 8px;
background:
repeating-linear-gradient(
45deg,
rgba(139, 92, 246, 0.2) 0,
rgba(139, 92, 246, 0.2) 8px,
rgba(139, 92, 246, 0.1) 8px,
rgba(139, 92, 246, 0.1) 16px
);
}
.mini-card-content {
display: grid;
gap: 8px;
min-height: 64px;
padding: 10px;
border: 1px dashed var(--border-strong);
border-radius: 6px;
background: #fff;
}
.mini-gap-frame {
display: grid;
gap: var(--sample-gap);
padding: 0;
border-radius: 8px;
background:
repeating-linear-gradient(
-45deg,
rgba(20, 184, 166, 0.2) 0,
rgba(20, 184, 166, 0.2) 8px,
rgba(20, 184, 166, 0.09) 8px,
rgba(20, 184, 166, 0.09) 16px
);
}
.mini-gap-item {
min-height: 42px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 6px;
background: #fff;
}
.layout-case {
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.layout-case.backlog {
border-style: dashed;
background: #fafbfc;
}
.layout-case.open {
border-color: #f5c76b;
background: #fffaf0;
}
.layout-case-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 16px;
margin-bottom: 12px;
}
.layout-case-head h3 {
font-size: 15px;
line-height: 1.35;
}
.value-row {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
}
.value-chip {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 8px;
border-radius: 999px;
background: var(--surface-subtle);
color: var(--muted);
font-size: 12px;
font-weight: 650;
}
.layout-frame {
--viz-page-pad: 24px;
--viz-card-pad: 16px;
--viz-gap: 16px;
position: relative;
display: grid;
gap: var(--viz-gap);
padding: var(--viz-page-pad);
border: 1px solid var(--padding-viz-strong);
border-radius: 10px;
background:
repeating-linear-gradient(
45deg,
rgba(139, 92, 246, 0.24) 0,
rgba(139, 92, 246, 0.24) 8px,
rgba(139, 92, 246, 0.13) 8px,
rgba(139, 92, 246, 0.13) 16px
);
}
.layout-frame.compact {
--viz-page-pad: 24px;
--viz-card-pad: 16px;
--viz-gap: 16px;
}
.layout-frame.editor {
--viz-card-pad: 32px;
}
.layout-content-shell {
display: grid;
gap: var(--viz-gap);
border: 1px dashed var(--border-strong);
border-radius: 8px;
background: #fff;
}
.mock-header {
display: grid;
gap: 6px;
padding: 16px;
border-bottom: 1px solid var(--border);
}
.mock-title {
width: 44%;
height: 16px;
border-radius: 999px;
background: var(--text);
}
.mock-copy {
width: 64%;
height: 10px;
border-radius: 999px;
background: var(--border-strong);
}
.mock-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--viz-gap);
padding: var(--viz-gap);
}
.mock-grid.single {
grid-template-columns: 1fr;
}
.mock-card {
position: relative;
min-height: 120px;
padding: var(--viz-card-pad);
border: 1px solid var(--padding-viz-strong);
border-radius: 8px;
background:
repeating-linear-gradient(
45deg,
rgba(139, 92, 246, 0.18) 0,
rgba(139, 92, 246, 0.18) 8px,
rgba(139, 92, 246, 0.09) 8px,
rgba(139, 92, 246, 0.09) 16px
);
}
.mock-card-inner {
display: grid;
gap: 8px;
min-height: 72px;
padding: 12px;
border: 1px dashed var(--border-strong);
border-radius: 6px;
background: #fff;
}
.mock-line {
height: 10px;
border-radius: 999px;
background: var(--border-strong);
}
.mock-line.short {
width: 48%;
}
.mock-line.medium {
width: 72%;
}
.ownership-note {
display: grid;
gap: 8px;
padding: 16px;
border: 1px solid #c7d2fe;
border-radius: 8px;
background: #eef3ff;
color: #294268;
}
.ownership-note strong {
color: #183b7d;
}
.concept-list {
display: grid;
gap: 10px;
margin-bottom: 24px;
}
.concept-row {
display: grid;
grid-template-columns: 180px 1fr;
gap: 16px;
padding: 12px 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.concept-row strong {
font-size: 13px;
}
.term-list {
display: grid;
gap: 12px;
}
.term {
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.term strong {
display: block;
margin-bottom: 4px;
}
.padding-showcase {
display: grid;
gap: 16px;
}
.padding-sample {
--pad: 24px;
position: relative;
padding: var(--pad);
border: 1px solid var(--padding-viz-strong);
border-radius: 10px;
background:
repeating-linear-gradient(
45deg,
rgba(139, 92, 246, 0.24) 0,
rgba(139, 92, 246, 0.24) 8px,
rgba(139, 92, 246, 0.14) 8px,
rgba(139, 92, 246, 0.14) 16px
);
}
.padding-content {
min-height: 72px;
padding: 16px;
border: 1px dashed var(--border-strong);
border-radius: 8px;
background: #fff;
}
.padding-content.compact {
min-height: auto;
padding: 10px 12px;
}
.measure-tag {
position: absolute;
top: 8px;
right: 8px;
padding: 2px 8px;
border: 1px solid var(--padding-viz-strong);
border-radius: 999px;
background: #fff;
color: var(--padding-viz-strong);
font-size: 12px;
font-weight: 700;
}
.gap-sample {
--gap: 24px;
display: grid;
gap: var(--gap);
padding: 0;
border-radius: 8px;
background:
repeating-linear-gradient(
-45deg,
rgba(20, 184, 166, 0.2) 0,
rgba(20, 184, 166, 0.2) 8px,
rgba(20, 184, 166, 0.1) 8px,
rgba(20, 184, 166, 0.1) 16px
);
}
.gap-item {
padding: 12px 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.sample-title {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 16px;
margin-bottom: 8px;
}
.edge-padding-sample {
position: relative;
overflow: hidden;
padding: 16px;
border: 1px solid var(--padding-viz-strong);
border-radius: 10px;
background: #fff;
}
.edge-padding-sample::before,
.edge-padding-sample::after {
position: absolute;
top: 0;
bottom: 0;
width: 16px;
content: "";
background:
repeating-linear-gradient(
45deg,
rgba(139, 92, 246, 0.28) 0,
rgba(139, 92, 246, 0.28) 8px,
rgba(139, 92, 246, 0.16) 8px,
rgba(139, 92, 246, 0.16) 16px
);
}
.edge-padding-sample::before {
left: 0;
}
.edge-padding-sample::after {
right: 0;
}
.edge-padding-sample .padding-content {
position: relative;
z-index: 1;
}
.plain-sample {
position: relative;
padding: 16px;
border: 1px solid var(--border);
border-radius: 10px;
background: #fff;
}
.button-padding-viz {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 40px;
padding: 0 16px;
border: 1px solid var(--padding-viz-strong);
border-radius: 6px;
background:
repeating-linear-gradient(
45deg,
rgba(139, 92, 246, 0.3) 0,
rgba(139, 92, 246, 0.3) 8px,
rgba(139, 92, 246, 0.16) 8px,
rgba(139, 92, 246, 0.16) 16px
);
}
.button-label-viz {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 38px;
padding: 0 2px;
border-radius: 4px;
background: var(--primary);
color: #fff;
font-weight: 650;
}
.grid {
display: grid;
gap: 16px;
}
.grid.two {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid.three {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.card {
padding: var(--card-pad);
border: 1px solid var(--border);
border-radius: var(--radius);
background: var(--surface);
}
.card.tight {
padding: 16px;
}
.card.large {
padding: 32px;
}
.card h3 {
margin-bottom: 8px;
font-size: 16px;
line-height: 1.35;
}
.muted {
color: var(--muted);
}
.small {
color: var(--muted);
font-size: 12px;
}
.button-row,
.field-row,
.toolbar {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.button {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: var(--control-h);
padding: 0 16px;
border: 1px solid transparent;
border-radius: 6px;
background: var(--primary);
color: #fff;
font-weight: 650;
text-decoration: none;
cursor: default;
}
.button.secondary {
border-color: var(--border-strong);
background: #fff;
color: var(--text);
}
.button.ghost {
background: transparent;
color: var(--text);
}
.button.danger {
background: var(--danger);
}
.button.sm {
min-height: 32px;
padding: 0 12px;
font-size: 13px;
}
.button.lg {
min-height: 48px;
padding: 0 20px;
}
.scale {
display: grid;
grid-template-columns: repeat(8, minmax(0, 1fr));
gap: 12px;
}
.scale-item {
min-height: 112px;
padding: 12px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.bar {
margin-top: 12px;
border-radius: 4px;
background: var(--primary);
}
.demo-frame {
display: grid;
gap: 16px;
padding: 24px;
border: 1px dashed var(--border-strong);
border-radius: 8px;
background:
linear-gradient(rgba(36, 88, 211, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(36, 88, 211, 0.05) 1px, transparent 1px),
#fff;
background-size: 8px 8px;
}
.demo-page-header {
display: grid;
gap: 8px;
padding-bottom: 8px;
}
.rhythm-legend {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 12px;
}
.rhythm-comparison {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.rhythm-sample {
display: grid;
gap: 0;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.rhythm-sample.recommended {
border-color: var(--primary);
box-shadow: inset 0 0 0 1px var(--primary);
}
.rhythm-sample-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
margin-bottom: 16px;
}
.rhythm-sample-title {
display: grid;
gap: 3px;
}
.rhythm-sample-title strong {
font-size: 15px;
}
.rhythm-page-header-preview,
.rhythm-section-preview,
.rhythm-content-preview {
display: grid;
gap: 0;
}
.rhythm-eyebrow {
color: var(--muted);
font-family: var(--font-body-extra-small-semibold-150);
font-size: var(--text-body-extra-small-semibold-150);
font-weight: var(--text-body-extra-small-semibold-150--font-weight);
line-height: var(--text-body-extra-small-semibold-150--line-height);
letter-spacing: 0;
text-transform: uppercase;
}
.rhythm-title {
margin: 4px 0 0;
font-family: var(--font-heading);
font-size: var(--text-heading);
font-weight: var(--text-heading--font-weight);
line-height: var(--text-heading--line-height);
}
.rhythm-desc {
margin: 0;
color: var(--muted);
font-family: var(--font-body-small-regular-150);
font-size: var(--text-body-small-regular-150);
font-weight: var(--text-body-small-regular-150--font-weight);
line-height: var(--text-body-small-regular-150--line-height);
}
.rhythm-section-title {
margin: 0;
font-family: var(--font-body-default-semibold-150);
font-size: var(--text-body-default-semibold-150);
font-weight: var(--text-body-default-semibold-150--font-weight);
line-height: var(--text-body-default-semibold-150--line-height);
}
.rhythm-card-row {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.rhythm-mini-card {
min-height: 82px;
padding: 12px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface-subtle);
}
.rhythm-mini-card strong {
display: block;
margin-bottom: 6px;
font-size: 13px;
}
.rhythm-line {
height: 8px;
margin-top: 6px;
border-radius: 999px;
background: var(--muted-2);
}
.rhythm-line.short {
width: 60%;
}
.rhythm-list {
display: grid;
gap: 8px;
}
.rhythm-list-row {
display: grid;
grid-template-columns: 32px minmax(0, 1fr) 64px;
align-items: center;
gap: 8px;
min-height: 36px;
padding: 0 10px;
border: 1px solid var(--border);
border-radius: 6px;
background: #fff;
}
.rhythm-dot {
width: 24px;
height: 24px;
border-radius: 999px;
background: var(--border-strong);
}
.rhythm-pill {
height: 20px;
border-radius: 999px;
background: var(--border);
}
.rhythm-detail-grid {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: 16px;
margin-top: 16px;
}
.rhythm-detail-card {
display: grid;
gap: 0;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.rhythm-metric-list {
display: grid;
gap: 8px;
margin-top: 12px;
}
.rhythm-metric {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 8px 10px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface-subtle);
color: var(--muted);
font-size: 12px;
}
.rhythm-metric strong {
color: var(--text);
}
.token-impact {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
margin-top: 16px;
}
.token-impact-card {
display: grid;
gap: 12px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.token-impact-card.warning {
border-color: #f2c078;
background: #fffaf1;
}
.token-impact-card.recommended {
border-color: var(--primary);
box-shadow: inset 0 0 0 1px var(--primary);
}
.token-impact-card h3,
.token-impact-card p,
.token-rule-panel h3,
.token-rule-panel p,
.rhythm-detail-card h3,
.rhythm-detail-card p {
margin: 0;
}
.token-text-box {
max-width: 280px;
padding: 12px;
border: 1px dashed var(--border-strong);
border-radius: 6px;
background:
linear-gradient(rgba(36, 88, 211, 0.06) 1px, transparent 1px),
#fff;
background-size: 100% 8px;
}
.token-text-box.tight {
font-family: var(--font-body-default-regular-0);
font-size: var(--text-body-default-regular-0);
font-weight: var(--text-body-default-regular-0--font-weight);
line-height: var(--text-body-default-regular-0--line-height);
}
.token-text-box.readable {
font-family: var(--font-body-default-regular-150);
font-size: var(--text-body-default-regular-150);
font-weight: var(--text-body-default-regular-150--font-weight);
line-height: var(--text-body-default-regular-150--line-height);
}
.token-rule-panel {
margin-top: 16px;
padding: 16px;
border: 1px solid #c7d2fe;
border-radius: 8px;
background: #eef3ff;
}
.form {
display: grid;
gap: 16px;
}
.field {
display: grid;
gap: 8px;
}
label {
color: var(--text);
font-size: 13px;
font-weight: 650;
}
input,
select,
textarea {
width: 100%;
min-height: var(--control-h);
padding: 0 12px;
border: 1px solid var(--border-strong);
border-radius: 6px;
background: #fff;
color: var(--text);
}
textarea {
min-height: 88px;
padding-top: 10px;
resize: vertical;
}
.help {
color: var(--muted);
font-size: 12px;
line-height: 1.45;
}
.error {
color: var(--danger);
font-size: 12px;
line-height: 1.45;
}
.table-shell {
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
height: 52px;
padding: 0 16px;
border-bottom: 1px solid var(--border);
text-align: left;
vertical-align: middle;
}
th {
color: var(--muted);
font-size: 12px;
font-weight: 700;
}
tr:last-child td {
border-bottom: 0;
}
.pill {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0 8px;
border-radius: 999px;
background: #e8f6ee;
color: var(--success);
font-size: 12px;
font-weight: 700;
}
.pill.warning {
background: #fff2d6;
color: var(--warning);
}
.modal-grid {
display: grid;
gap: 24px;
}
.modal-version-grid {
display: grid;
gap: 16px;
}
.modal-version {
display: grid;
gap: 16px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.modal-version.recommended {
border-color: rgba(36, 88, 211, 0.42);
background: #f7f9ff;
}
.modal-version-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 16px;
}
.modal-size-row {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px;
}
.modal-size-row.four {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
.modal-size-card {
display: grid;
gap: 10px;
min-width: 0;
}
.modal-size-label {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px;
color: var(--muted);
font-size: 12px;
}
.modal-width-track {
display: flex;
align-items: center;
min-height: 64px;
padding: 12px;
border: 1px solid var(--border);
border-radius: 8px;
background:
repeating-linear-gradient(
90deg,
rgba(20, 184, 166, 0.08) 0,
rgba(20, 184, 166, 0.08) 8px,
transparent 8px,
transparent 16px
),
var(--surface-subtle);
}
.modal-width-block {
display: grid;
width: var(--preview-pct);
min-height: 40px;
place-items: center;
border: 1px solid var(--border-strong);
border-radius: 8px;
background: #fff;
color: var(--text);
font-size: 12px;
font-weight: 700;
box-shadow: var(--shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.08));
}
.viewport-behavior {
display: grid;
gap: 12px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface-subtle);
}
.viewport-row {
display: grid;
grid-template-columns: 120px 1fr 168px;
gap: 12px;
align-items: center;
}
.viewport-track {
position: relative;
min-height: 28px;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 999px;
background: #fff;
}
.viewport-dialog {
position: absolute;
inset-block: 5px;
left: 50%;
width: var(--dialog-ratio);
transform: translateX(-50%);
border-radius: 999px;
background: var(--primary);
}
.pattern-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 12px;
}
.pattern-card {
display: grid;
gap: 10px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.pattern-card strong {
font-size: 14px;
}
.pattern-mini {
position: relative;
min-height: 112px;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background: var(--surface-subtle);
}
.pattern-shell {
position: absolute;
inset: 0;
display: grid;
grid-template-columns: 28% 1fr;
}
.pattern-shell::before {
content: "";
border-right: 1px solid var(--border);
background: #fff;
}
.pattern-page-content {
margin: 12px;
border-radius: 6px;
background: #fff;
}
.pattern-overlay {
position: absolute;
inset: 0;
background: rgba(23, 38, 53, 0.24);
}
.pattern-dialog-box {
position: absolute;
top: 50%;
left: 50%;
width: 58%;
height: 48%;
transform: translate(-50%, -50%);
border-radius: 8px;
background: #fff;
box-shadow: var(--shadow);
}
.pattern-fullscreen-box {
position: absolute;
inset: 8px;
border-radius: 8px;
background: #fff;
box-shadow: var(--shadow);
}
.pattern-fullscreen-box::before {
content: "24px margin";
position: absolute;
top: 8px;
left: 10px;
color: var(--muted);
font-size: 10px;
font-weight: 700;
}
.pattern-drawer-box {
position: absolute;
inset-block: 0;
right: 0;
width: 46%;
border-left: 1px solid var(--border);
background: #fff;
box-shadow: var(--shadow);
}
.modal-demo {
--modal-pad: 16px;
width: min(var(--modal-w), 100%);
margin: 0 auto;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 10px;
background: #fff;
box-shadow: var(--shadow);
}
.modal-header,
.modal-body,
.modal-footer {
padding: var(--modal-pad);
}
.modal-header {
border-bottom: 1px solid var(--border);
}
.modal-body {
display: grid;
gap: 16px;
}
.modal-footer {
display: flex;
justify-content: flex-end;
gap: 8px;
border-top: 1px solid var(--border);
background: var(--surface-subtle);
}
.modal-xs {
--modal-w: 420px;
}
.modal-small {
--modal-w: 560px;
}
.modal-medium {
--modal-w: 720px;
}
.modal-large {
--modal-w: 1200px;
}
.modal-spacious {
--modal-pad: 32px;
}
.dialog-gap-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.dialog-gap-card {
display: grid;
gap: 16px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.dialog-gap-card.recommended {
border-color: rgba(36, 88, 211, 0.42);
background: #f7f9ff;
}
.gap-spec-list {
display: grid;
gap: 8px;
margin: 0;
padding: 0;
list-style: none;
color: var(--muted);
font-size: 12px;
}
.gap-spec-list li {
display: flex;
justify-content: space-between;
gap: 12px;
}
.gap-spec-list strong {
color: var(--text);
}
.dialog-gap-demo {
display: grid;
width: min(100%, 360px);
margin: 0 auto;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
box-shadow: 0 8px 24px rgba(20, 35, 55, 0.1);
}
.dialog-gap-header,
.dialog-gap-body,
.dialog-gap-footer {
padding: 16px;
}
.dialog-gap-header {
display: grid;
gap: 0;
border-bottom: 1px solid var(--border);
}
.dialog-gap-title {
height: 16px;
width: 48%;
border-radius: 4px;
background: var(--text);
}
.dialog-gap-description {
height: 12px;
width: 74%;
border-radius: 4px;
background: var(--border-strong);
}
.dialog-gap-body {
display: grid;
gap: 0;
}
.dialog-gap-field {
display: grid;
gap: 8px;
}
.dialog-gap-label {
height: 10px;
width: 34%;
border-radius: 4px;
background: var(--muted-2);
}
.dialog-gap-input {
height: 36px;
border: 1px solid var(--border-strong);
border-radius: 6px;
background: #fff;
}
.dialog-gap-section {
display: grid;
gap: 8px;
margin-top: 0;
}
.dialog-gap-row {
height: 40px;
border: 1px solid var(--border);
border-radius: 6px;
background: var(--surface-subtle);
}
.dialog-gap-footer {
display: flex;
justify-content: flex-end;
gap: 0;
border-top: 1px solid var(--border);
background: var(--surface-subtle);
}
.gap-marker {
position: relative;
display: block;
background:
repeating-linear-gradient(
45deg,
rgba(20, 184, 166, 0.22) 0,
rgba(20, 184, 166, 0.22) 4px,
rgba(20, 184, 166, 0.08) 4px,
rgba(20, 184, 166, 0.08) 8px
);
border: 1px dashed var(--gap-viz-strong);
}
.gap-marker.vertical {
height: var(--gap-size);
min-height: var(--gap-size);
}
.gap-marker.zero {
height: 0;
min-height: 0;
overflow: visible;
border: 0;
border-top: 1px dashed var(--gap-viz-strong);
background: transparent;
}
.gap-marker.horizontal {
width: var(--gap-size);
min-width: var(--gap-size);
align-self: stretch;
}
.gap-marker::after {
content: attr(data-label) " " attr(data-size);
position: absolute;
z-index: 1;
right: 4px;
top: 50%;
transform: translateY(-50%);
padding: 1px 4px;
border: 1px solid rgba(15, 118, 110, 0.28);
border-radius: 999px;
background: rgba(255, 255, 255, 0.92);
color: var(--gap-viz-strong);
font-size: 10px;
font-weight: 800;
line-height: 1.2;
white-space: nowrap;
pointer-events: none;
}
body.hide-gap-markers .gap-marker {
border-color: transparent;
background: transparent;
}
body.hide-gap-markers .gap-marker::after {
opacity: 0;
}
.gap-marker.horizontal::after {
top: -18px;
right: auto;
left: 50%;
transform: translateX(-50%);
}
.gap-marker.zero::after {
top: 0;
transform: translateY(-50%);
}
.dialog-gap-button {
width: 76px;
height: 32px;
border-radius: 6px;
background: var(--border-strong);
}
.dialog-gap-button.primary {
background: var(--primary);
}
.footer-layout-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
margin-top: 16px;
}
.footer-layout-card {
display: grid;
gap: 16px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.footer-layout-card.recommended {
border-color: rgba(36, 88, 211, 0.42);
background: #f7f9ff;
}
.footer-preview {
display: grid;
overflow: hidden;
border: 1px solid var(--border);
border-radius: 8px;
background: #fff;
}
.footer-preview-body {
min-height: 96px;
padding: 16px;
}
.footer-preview-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding: 16px;
border-top: 1px solid var(--border);
background: var(--surface-subtle);
}
.footer-preview.fill-actions .footer-preview-actions {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.footer-preview.fill-actions .dialog-gap-button {
width: auto;
}
.state {
display: grid;
min-height: 220px;
place-items: center;
padding: 32px;
border: 1px dashed var(--border-strong);
border-radius: 8px;
background: #fff;
text-align: center;
}
.state-inner {
max-width: 420px;
}
.state h3 {
margin-bottom: 8px;
}
.note {
padding: 16px;
border-left: 4px solid var(--primary);
border-radius: 6px;
background: #eef3ff;
color: #183b7d;
}
@media (max-width: 980px) {
:root {
--page-pad: 24px;
}
.grid.two,
.grid.three,
.decision-map,
.decision-options,
.scale,
.reference-strip,
.d02-preview-grid,
.compare-grid,
.concept-row,
.modal-size-row,
.modal-size-row.four,
.viewport-row,
.pattern-grid,
.definition-grid,
.rhythm-comparison,
.rhythm-detail-grid,
.token-impact,
.dialog-gap-grid,
.footer-layout-grid {
grid-template-columns: 1fr;
}
.hero,
.section-head {
display: grid;
}
}
@media (max-width: 640px) {
:root {
--page-pad: 16px;
--card-pad: 16px;
}
h1 {
font-size: 28px;
}
.topbar {
padding: 0 16px;
}
.topbar-actions {
display: none;
}
.rhythm-card-row {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<header class="topbar">
<div class="brand">
<div class="mark">D0b</div>
<span>D-D0b Layout Preview</span>
</div>
<div class="topbar-actions">
<button class="marker-toggle" id="gapToggle" type="button" aria-pressed="true">
<span>Spacing Tiles</span>
<span class="marker-toggle-switch" aria-hidden="true"></span>
</button>
<a class="button sm secondary" href="#overview">Uebersicht</a>
<a class="button sm secondary" href="preview.html">Full Page</a>
<a class="button sm secondary" href="#d01">D01</a>
<a class="button sm secondary" href="#d02">D02</a>
<a class="button sm secondary" href="#d03">D03</a>
<a class="button sm secondary" href="#d04">D04</a>
<a class="button sm secondary" href="#d05">D05</a>
<a class="button sm secondary" href="#d06">D06</a>
<a class="button sm secondary" href="#d07">D07</a>
<a class="button sm secondary" href="#d08">D08</a>
<a class="button sm secondary" href="#d09">D09</a>
</div>
</header>
<main class="page">
<section id="overview" class="hero">
<div>
<p class="eyebrow">Versioned reference preview</p>
<h1>Layout, spacing and sizing decisions</h1>
<p class="subtitle">
This page preserves the visual examples used for D-D0b. It helps
review spacing, widths, vertical rhythm and density, but the
Markdown standards are the source of truth.
</p>
</div>
<div class="note">
Kept intentionally: this HTML preview is stored with the D-D0b
planning files for visual review. Final rules live in the Obsidian
Markdown files and in the Subframe UI Standards.
</div>
</section>
<section class="section">
<div class="section-head">
<div class="section-copy">
<h2>Was du hier validierst</h2>
<p class="section-desc">
Diese Seite ist jetzt als Entscheidungsstrecke aufgebaut. Jede
Entscheidung hat eine Nummer, eine konkrete Frage und sichtbare
Beispiele darunter.
</p>
</div>
</div>
<div class="decision-map">
<a class="decision-link" href="preview.html">
<strong>Full Page Preview</strong>
<span>Oeffnet eine eigene Full-Page-Dummyseite mit App Shell und Layout-Umschaltern.</span>
</a>
<a class="decision-link" href="#d01">
<strong>D01 Grundraster</strong>
<span>Welche Abstandsskala ist unser Standard?</span>
</a>
<a class="decision-link" href="#d02">
<strong>D02 Page & Card Padding</strong>
<span>Wie viel Luft bekommen Seiten und Panels?</span>
</a>
<a class="decision-link" href="#d03">
<strong>D03 Text-Rhythmus</strong>
<span>Wie nah stehen Titel, Beschreibung und Inhalt?</span>
</a>
<a class="decision-link" href="#d04">
<strong>D04 Button Ownership</strong>
<span>Button-Groessen kommen aus der Button-Komponente.</span>
</a>
<a class="decision-link" href="#d05">
<strong>D05 Forms</strong>
<span>Form-Feldgruppen stehen standardmaessig 16px auseinander.</span>
</a>
<a class="decision-link" href="#d06">
<strong>D06 Table Ownership</strong>
<span>Tabellen-Dichte kommt aus der Table-Komponente.</span>
</a>
<a class="decision-link" href="#d07">
<strong>D07 Dialoge</strong>
<span>Welche Breiten gelten fuer kleine, normale und grosse Modale?</span>
</a>
<a class="decision-link" href="#d08">
<strong>D08 Dialog Internal Gaps</strong>
<span>Welche Abstaende gelten innerhalb normaler Dialoge?</span>
</a>
<a class="decision-link" href="#d09">
<strong>D09 States</strong>
<span>States sind inline Komponenten-Zustaende, keine eigenen Layout-Screens.</span>
</a>
</div>
</section>
<section id="d01" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D01 Grundraster / Spacing Scale</h2>
<p class="section-desc">
Validierter 8px-Rhythmus mit erlaubten Zwischenwerten. Nutze
diese Ansicht als visuelle Referenz fuer die freigegebenen
Layout-Abstaende.
</p>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Entscheidung D01</span>
</div>
<div>
<p class="decision-kicker">Was du festlegst</p>
<h3>Welche Abstandsskala darf in HiveGrid verwendet werden?</h3>
<p>
Das ist die Grundlage fuer alle weiteren Padding- und Gap-Entscheidungen.
Eine kleine Skala macht Screens konsistenter.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Sehr streng</strong>
<span>Nur 8, 16, 24, 32, 48, 64. Sehr sauber, aber manchmal zu grob.</span>
</div>
<div class="decision-option recommended">
<strong>8px Rhythmus + Ausnahmen</strong>
<span>4, 8, 12, 16, 24, 32, 48, 64. Praktisch fuer echte UI-Arbeit.</span>
</div>
<div class="decision-option">
<strong>Sehr frei</strong>
<span>Viele Zwischenwerte erlaubt. Flexibel, aber weniger konsistent.</span>
</div>
</div>
<div class="decision-question">
Entscheidung: Darf HiveGrid den 8px-Rhythmus mit 4px/12px-Ausnahmen nutzen?
</div>
</div>
<div class="scale">
<div class="scale-item">
<strong>4px</strong>
<p class="small">Tiny relation</p>
<div class="bar" style="height: 4px"></div>
</div>
<div class="scale-item">
<strong>8px</strong>
<p class="small">Label to field</p>
<div class="bar" style="height: 8px"></div>
</div>
<div class="scale-item">
<strong>12px</strong>
<p class="small">Compact groups</p>
<div class="bar" style="height: 12px"></div>
</div>
<div class="scale-item">
<strong>16px</strong>
<p class="small">Related items</p>
<div class="bar" style="height: 16px"></div>
</div>
<div class="scale-item">
<strong>24px</strong>
<p class="small">Card padding</p>
<div class="bar" style="height: 24px"></div>
</div>
<div class="scale-item">
<strong>32px</strong>
<p class="small">Section gap</p>
<div class="bar" style="height: 32px"></div>
</div>
<div class="scale-item">
<strong>48px</strong>
<p class="small">Large break</p>
<div class="bar" style="height: 48px"></div>
</div>
<div class="scale-item">
<strong>64px</strong>
<p class="small">Major break</p>
<div class="bar" style="height: 64px"></div>
</div>
</div>
</section>
<section id="d02" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D02 Page, Card und Grid Padding</h2>
<p class="section-desc">
Lila Flaechen zeigen Innenabstand. Das ist der Abstand zwischen
dem Rand eines Containers und seinem Inhalt. Tuerkise Flaechen
zeigen Gap: Abstand zwischen getrennten Elementen.
</p>
<div class="legend">
<span class="legend-item">
<span class="legend-dot padding"></span>
Padding / Innenabstand
</span>
<span class="legend-item">
<span class="legend-dot gap"></span>
Gap / Abstand zwischen Elementen
</span>
<span class="legend-item">
<span class="legend-dot content"></span>
Inhalt / Content
</span>
</div>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Entscheidung D02</span>
</div>
<div>
<p class="decision-kicker">Was du festlegst</p>
<h3>Wie viel Abstand bekommen Page-Container, Cards/Surfaces und Card-/Grid-Abstaende?</h3>
<p>
Diese Entscheidung bestimmt, ob HiveGrid eher kompakt, neutral
oder luftig wirkt. Es geht um sichtbare Layout-Standards, aber
Komponenten-Defaults bleiben fuehrend, wenn sie das Padding
bereits korrekt mitbringen.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Kompakt</strong>
<span>Page bleibt 24px min, Card 16px, Grid Gap 12px. Nur fuer enge Teilbereiche.</span>
</div>
<div class="decision-option recommended">
<strong>Entschieden: Admin Standard</strong>
<span>Page 24px, Card 16px, Grid Gap 16px. Gilt fuer Standard Desktop und kompakte Settings.</span>
</div>
<div class="decision-option">
<strong>Dialog-Variante</strong>
<span>32px ist kein freier Surface-Standard, aber als eigene Dialog-Variante erlaubt.</span>
</div>
</div>
<div class="decision-question">
Entschieden: Page Padding ist immer mindestens 24px.
Card/Surface Padding bleibt 16px. Grid/Card Gap ist standardmaessig
16px und kann in kompakten Teilbereichen auf 12px reduziert werden.
Grosse Detail-/Editorflaechen starten ebenfalls mit 16px; 32px ist
nur ueber die eigene Dialog-Variante erlaubt.
</div>
</div>
<div class="reference-strip">
<div class="reference-card">
<strong>Carbon-Orientierung</strong>
<ul>
<li>Carbon arbeitet mit einer kontrollierten Spacing Scale.</li>
<li>8px ist die zentrale Rhythmik, 16px kommt sehr haeufig vor.</li>
<li>Layout-Abstaende und Komponenten-Innenabstaende werden getrennt betrachtet.</li>
</ul>
</div>
<div class="ownership-note">
<strong>HiveGrid-Regel fuer Subframe</strong>
<p>
Die Werte unten sind Zielwerte fuer das sichtbare Layout. Wenn
Dialog, Card, Table, Button oder Input das passende Padding schon
intern haben, wird dieses Komponenten-Padding genutzt und nicht
manuell nachgebaut.
</p>
</div>
</div>
<div class="concept-list">
<div class="concept-row">
<strong>App Shell</strong>
<p class="muted">
Navigation, Sidebar, Topbar und der aeussere Content-Viewport.
Die App Shell hat nicht einfach einen Page Gap; sie stellt den
Bereich bereit, in dem die Seite liegt.
</p>
</div>
<div class="concept-row">
<strong>Page Padding</strong>
<p class="muted">
Innenabstand innerhalb des Page-Contents nach der App Shell.
Dieser Abstand verhindert, dass Inhalt direkt am Shell-Rand oder
Browserrand klebt.
</p>
</div>
<div class="concept-row">
<strong>Section / Grid Gap</strong>
<p class="muted">
Abstand zwischen getrennten Bereichen, Sections, Karten oder
Spalten. Das ist kein aeusserer Seitenrand.
</p>
</div>
<div class="concept-row">
<strong>Schmaler Screen</strong>
<p class="muted">
Wenn der verfuegbare Content-Bereich kleiner wird, bleibt der
Desktop-/Settings-Mindestabstand erstmal bei 24px. Danach muessen
Layouts umbrechen, stacken oder horizontal scrollen.
</p>
</div>
</div>
<div class="compare-block">
<div class="compare-head">
<h3>Vergleich 1: Page Padding</h3>
<p class="muted">
Das ist der Abstand vom Page-Content-Rand nach innen. Die App
Shell selbst ist hier nicht gemeint.
</p>
</div>
<div class="compare-grid">
<div class="compare-card">
<div class="compare-title">
<strong>16px</strong>
<span class="small">Sonderfall kompakt</span>
</div>
<div class="mini-page" style="--sample-page-pad: 16px">
<span class="measure-tag">16px</span>
<div class="mini-page-content">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
</div>
<div class="compare-card recommended">
<div class="compare-title">
<strong>24px</strong>
<span class="small">Empfohlen fuer Admin</span>
</div>
<div class="mini-page" style="--sample-page-pad: 24px">
<span class="measure-tag">24px</span>
<div class="mini-page-content">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
</div>
<div class="compare-card">
<div class="compare-title">
<strong>32px</strong>
<span class="small">Ruhigere Flaechen</span>
</div>
<div class="mini-page" style="--sample-page-pad: 32px">
<span class="measure-tag">32px</span>
<div class="mini-page-content">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
</div>
</div>
</div>
<div class="compare-block">
<div class="compare-head">
<h3>Vergleich 2: Card / Surface Padding</h3>
<p class="muted">
Das ist Innenabstand innerhalb von Cards, Panels oder
groesseren Surface-Bereichen.
</p>
</div>
<div class="compare-grid">
<div class="compare-card recommended">
<div class="compare-title">
<strong>16px</strong>
<span class="small">Kompakte Cards</span>
</div>
<div class="mini-card" style="--sample-card-pad: 16px">
<span class="measure-tag">16px</span>
<div class="mini-card-content">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
</div>
<div class="compare-card">
<div class="compare-title">
<strong>24px</strong>
<span class="small">Standard Cards</span>
</div>
<div class="mini-card" style="--sample-card-pad: 24px">
<span class="measure-tag">24px</span>
<div class="mini-card-content">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
</div>
<div class="compare-card">
<div class="compare-title">
<strong>32px</strong>
<span class="small">Editor / Detail</span>
</div>
<div class="mini-card" style="--sample-card-pad: 32px">
<span class="measure-tag">32px</span>
<div class="mini-card-content">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
</div>
</div>
</div>
<div class="compare-block">
<div class="compare-head">
<h3>Vergleich 3: Grid / Card Gap</h3>
<p class="muted">
Das ist der Abstand zwischen Karten, Spalten oder
zusammengehoerigen Layout-Bloecken.
</p>
</div>
<div class="compare-grid">
<div class="compare-card">
<div class="compare-title">
<strong>12px</strong>
<span class="small">Sehr dicht</span>
</div>
<div class="mini-gap-frame" style="--sample-gap: 12px">
<div class="mini-gap-item">Card A</div>
<div class="mini-gap-item">Card B</div>
<div class="mini-gap-item">Card C</div>
</div>
</div>
<div class="compare-card recommended">
<div class="compare-title">
<strong>16px</strong>
<span class="small">Empfohlen</span>
</div>
<div class="mini-gap-frame" style="--sample-gap: 16px">
<div class="mini-gap-item">Card A</div>
<div class="mini-gap-item">Card B</div>
<div class="mini-gap-item">Card C</div>
</div>
</div>
<div class="compare-card">
<div class="compare-title">
<strong>24px</strong>
<span class="small">Getrennte Bereiche</span>
</div>
<div class="mini-gap-frame" style="--sample-gap: 24px">
<div class="mini-gap-item">Card A</div>
<div class="mini-gap-item">Card B</div>
<div class="mini-gap-item">Card C</div>
</div>
</div>
</div>
</div>
<div class="d02-preview-grid">
<div class="layout-case">
<div class="layout-case-head">
<h3>Standard Desktop Page</h3>
<span class="small">Normale App-/Admin-Seite</span>
</div>
<div class="layout-frame">
<span class="measure-tag">Page 24px</span>
<div class="layout-content-shell">
<div class="mock-header">
<div class="mock-title"></div>
<div class="mock-copy"></div>
</div>
<div class="mock-grid">
<div class="mock-card">
<span class="measure-tag">Card 16px</span>
<div class="mock-card-inner">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
<div class="mock-card">
<span class="measure-tag">Card 16px</span>
<div class="mock-card-inner">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
</div>
</div>
</div>
<div class="value-row">
<span class="value-chip">Page padding 24px</span>
<span class="value-chip">Card padding 16px</span>
<span class="value-chip">Card gap 16px</span>
</div>
</div>
<div class="layout-case">
<div class="layout-case-head">
<h3>Kompakte Settings Page</h3>
<span class="small">Settings, Admin-Listen, dichter Kontext</span>
</div>
<div class="layout-frame compact">
<span class="measure-tag">Page 24px</span>
<div class="layout-content-shell">
<div class="mock-header">
<div class="mock-title"></div>
<div class="mock-copy"></div>
</div>
<div class="mock-grid single">
<div class="mock-card">
<span class="measure-tag">Card 16px</span>
<div class="mock-card-inner">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
</div>
</div>
<div class="mock-card">
<span class="measure-tag">Card 16px</span>
<div class="mock-card-inner">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
</div>
</div>
</div>
</div>
</div>
<div class="value-row">
<span class="value-chip">Page padding 24px</span>
<span class="value-chip">Compact card 16px</span>
<span class="value-chip">Gap 16px</span>
</div>
</div>
<div class="layout-case open">
<div class="layout-case-head">
<h3>Dialog-Variante: grosse Detail-/Editor-Flaeche</h3>
<span class="small">Nur ueber Dialog-Komponente</span>
</div>
<div class="layout-frame editor">
<span class="measure-tag">Dialog 32px</span>
<div class="layout-content-shell">
<div class="mock-header">
<div class="mock-title"></div>
<div class="mock-copy"></div>
</div>
<div class="mock-grid single">
<div class="mock-card">
<span class="measure-tag">Surface 32px</span>
<div class="mock-card-inner">
<div class="mock-line short"></div>
<div class="mock-line medium"></div>
<div class="mock-line"></div>
<div class="mock-line medium"></div>
</div>
</div>
</div>
</div>
</div>
<div class="value-row">
<span class="value-chip">Dialog spacious</span>
<span class="value-chip">32px nur als Dialog-Variante</span>
<span class="value-chip">D02 final bleibt 16px</span>
</div>
</div>
</div>
<div class="definition-grid">
<div class="term-list">
<div class="term">
<strong>Padding</strong>
<p class="muted">
Fachlich: Innenabstand. Er liegt innerhalb einer Flaeche,
Karte, Surface oder eines Containers. Padding sorgt dafuer,
dass Inhalt nicht direkt am Rand klebt.
</p>
</div>
<div class="term">
<strong>Gap</strong>
<p class="muted">
Fachlich: Zwischenraum in einem Layout. Gap liegt zwischen
mehreren Elementen, zum Beispiel zwischen zwei Karten oder
zwischen Formularfeldern.
</p>
</div>
<div class="term">
<strong>Margin</strong>
<p class="muted">
Fachlich: Aussenabstand. Margin schiebt ein Element von anderen
Bereichen weg. In unserem Layout-Lab nutzen wir meistens Gap,
weil es in Auto Layout besser kontrollierbar ist.
</p>
</div>
</div>
<div class="padding-showcase">
<div>
<div class="sample-title">
<strong>Page Padding</strong>
<span class="small">Benutzt am aeusseren Seitenrand.</span>
</div>
<div class="padding-sample" style="--pad: 24px">
<span class="measure-tag">24px</span>
<div class="padding-content">
<strong>Page content</strong>
<p class="muted">
Der Inhalt beginnt nicht direkt am Browser-/Shell-Rand,
sondern nach dem Page Padding.
</p>
</div>
</div>
</div>
<div>
<div class="sample-title">
<strong>Card / Surface Padding</strong>
<span class="small">Benutzt in Karten, Panels und Surfaces.</span>
</div>
<div class="padding-sample" style="--pad: 16px">
<span class="measure-tag">16px</span>
<div class="padding-content">
<strong>Card / surface content</strong>
<p class="muted">
Text, Aktionen oder Formularfelder haben Luft zum Rand.
</p>
</div>
</div>
</div>
<div>
<div class="sample-title">
<strong>Grid / Card Gap</strong>
<span class="small">Kein Padding: Abstand zwischen Karten.</span>
</div>
<div class="gap-sample" style="--gap: 16px">
<div class="gap-item">Card 1</div>
<div class="gap-item">Card 2</div>
<div class="gap-item">Card 3</div>
</div>
</div>
</div>
</div>
</section>
<section id="d03" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D03 Text-Rhythmus</h2>
<p class="section-desc">
Text-Rhythmus meint vertikale Abstaende zwischen Textbloecken:
zum Beispiel Page Title, Beschreibung und erstem Content. Die
Beispiele nutzen echte Text-Tokens, weil Line-height die sichtbare
Hoehe eines Textblocks veraendert.
</p>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Entscheidung D03</span>
</div>
<div>
<p class="decision-kicker">Was du festlegst</p>
<h3>Wie eng stehen Textbloecke und der erste Inhalt zusammen?</h3>
<p>
D03 ist validiert. Die Regel betrifft die vertikalen Gaps
zwischen gerenderten Textbloecken und Inhalt. Beschreibende
Page- und Section-Texte muessen 150%-Texttokens nutzen, weil
die Line-height die optische Hoehe des Blocks beeinflusst.
</p>
<div class="rhythm-legend">
<span class="value-chip">Title -> Description</span>
<span class="value-chip">Header -> First content</span>
<span class="value-chip">Section title -> Section description</span>
<span class="value-chip">Description -> Section content</span>
<span class="value-chip">Tokens: Heading / Body 150</span>
</div>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Sehr kompakt</strong>
<span>0px / 16px / 0px / 8px. Sehr dicht, nur fuer stark verdichtete Teilbereiche.</span>
</div>
<div class="decision-option recommended">
<strong>Token-aware Standard</strong>
<span>0px / 24px / 0px / 12px. Finaler Vorschlag mit 150%-Texttokens.</span>
</div>
<div class="decision-option">
<strong>Luftig</strong>
<span>0px / 32px / 0px / 16px. Ruhiger, aber nimmt in Settings mehr Platz weg.</span>
</div>
</div>
<div class="decision-question">
Validiert: D03 nutzt 0px zwischen Titel und Beschreibung, 24px bis
zum ersten Content, 0px zwischen Section Title und Beschreibung
sowie 12px zwischen Section Beschreibung und Inhalt. Page-/Section-
Beschreibungen muessen dafuer 150%-Texttokens nutzen.
</div>
</div>
<div class="rhythm-comparison">
<div
class="rhythm-sample"
style="--title-desc-gap: 0px; --header-content-gap: 16px; --section-title-desc-gap: 0px; --section-content-gap: 8px"
>
<div class="rhythm-sample-head">
<div class="rhythm-sample-title">
<strong>Option A: Sehr kompakt</strong>
<span class="small">Dicht, scanbar, wenig Ruhe.</span>
</div>
<span class="value-chip">A</span>
</div>
<div class="rhythm-page-header-preview">
<span class="rhythm-eyebrow">Settings</span>
<h3 class="rhythm-title">Mitarbeiter</h3>
<div class="gap-marker vertical zero" style="--gap-size: var(--title-desc-gap)" data-label="Title -> Desc" data-size="0px"></div>
<p class="rhythm-desc">
Verwalte Einladungen, Rollen und Status fuer alle Personen im
Workspace.
</p>
<div class="gap-marker vertical" style="--gap-size: var(--header-content-gap)" data-label="Header -> Content" data-size="16px"></div>
</div>
<div class="rhythm-section-preview">
<h4 class="rhythm-section-title">Aktive Mitarbeiter</h4>
<div class="gap-marker vertical zero" style="--gap-size: var(--section-title-desc-gap)" data-label="Section -> Desc" data-size="0px"></div>
<p class="rhythm-desc">
Die Liste zeigt eingeladene und aktive Nutzer.
</p>
<div class="gap-marker vertical" style="--gap-size: var(--section-content-gap)" data-label="Desc -> Content" data-size="8px"></div>
<div class="rhythm-content-preview">
<div class="rhythm-card-row">
<div class="rhythm-mini-card">
<strong>12 aktiv</strong>
<div class="rhythm-line"></div>
<div class="rhythm-line short"></div>
</div>
<div class="rhythm-mini-card">
<strong>3 offen</strong>
<div class="rhythm-line"></div>
<div class="rhythm-line short"></div>
</div>
</div>
<div class="rhythm-list" style="margin-top: 12px">
<div class="rhythm-list-row">
<span class="rhythm-dot"></span>
<span class="rhythm-line"></span>
<span class="rhythm-pill"></span>
</div>
<div class="rhythm-list-row">
<span class="rhythm-dot"></span>
<span class="rhythm-line"></span>
<span class="rhythm-pill"></span>
</div>
</div>
</div>
</div>
</div>
<div
class="rhythm-sample recommended"
style="--title-desc-gap: 0px; --header-content-gap: 24px; --section-title-desc-gap: 0px; --section-content-gap: 12px"
>
<div class="rhythm-sample-head">
<div class="rhythm-sample-title">
<strong>Option B: Token-aware Standard</strong>
<span class="small">Finaler Arbeitsstandard mit 150%-Texttokens.</span>
</div>
<span class="value-chip">B</span>
</div>
<div class="rhythm-page-header-preview">
<span class="rhythm-eyebrow">Settings</span>
<h3 class="rhythm-title">Mitarbeiter</h3>
<div class="gap-marker vertical zero" style="--gap-size: var(--title-desc-gap)" data-label="Title -> Desc" data-size="0px"></div>
<p class="rhythm-desc">
Verwalte Einladungen, Rollen und Status fuer alle Personen im
Workspace.
</p>
<div class="gap-marker vertical" style="--gap-size: var(--header-content-gap)" data-label="Header -> Content" data-size="24px"></div>
</div>
<div class="rhythm-section-preview">
<h4 class="rhythm-section-title">Aktive Mitarbeiter</h4>
<div class="gap-marker vertical zero" style="--gap-size: var(--section-title-desc-gap)" data-label="Section -> Desc" data-size="0px"></div>
<p class="rhythm-desc">
Die Liste zeigt eingeladene und aktive Nutzer.
</p>
<div class="gap-marker vertical" style="--gap-size: var(--section-content-gap)" data-label="Desc -> Content" data-size="12px"></div>
<div class="rhythm-content-preview">
<div class="rhythm-card-row">
<div class="rhythm-mini-card">
<strong>12 aktiv</strong>
<div class="rhythm-line"></div>
<div class="rhythm-line short"></div>
</div>
<div class="rhythm-mini-card">
<strong>3 offen</strong>
<div class="rhythm-line"></div>
<div class="rhythm-line short"></div>
</div>
</div>
<div class="rhythm-list" style="margin-top: 12px">
<div class="rhythm-list-row">
<span class="rhythm-dot"></span>
<span class="rhythm-line"></span>
<span class="rhythm-pill"></span>
</div>
<div class="rhythm-list-row">
<span class="rhythm-dot"></span>
<span class="rhythm-line"></span>
<span class="rhythm-pill"></span>
</div>
</div>
</div>
</div>
</div>
<div
class="rhythm-sample"
style="--title-desc-gap: 0px; --header-content-gap: 32px; --section-title-desc-gap: 0px; --section-content-gap: 16px"
>
<div class="rhythm-sample-head">
<div class="rhythm-sample-title">
<strong>Option C: Luftig</strong>
<span class="small">Ruhiger, aber weniger dicht.</span>
</div>
<span class="value-chip">C</span>
</div>
<div class="rhythm-page-header-preview">
<span class="rhythm-eyebrow">Settings</span>
<h3 class="rhythm-title">Mitarbeiter</h3>
<div class="gap-marker vertical zero" style="--gap-size: var(--title-desc-gap)" data-label="Title -> Desc" data-size="0px"></div>
<p class="rhythm-desc">
Verwalte Einladungen, Rollen und Status fuer alle Personen im
Workspace.
</p>
<div class="gap-marker vertical" style="--gap-size: var(--header-content-gap)" data-label="Header -> Content" data-size="32px"></div>
</div>
<div class="rhythm-section-preview">
<h4 class="rhythm-section-title">Aktive Mitarbeiter</h4>
<div class="gap-marker vertical zero" style="--gap-size: var(--section-title-desc-gap)" data-label="Section -> Desc" data-size="0px"></div>
<p class="rhythm-desc">
Die Liste zeigt eingeladene und aktive Nutzer.
</p>
<div class="gap-marker vertical" style="--gap-size: var(--section-content-gap)" data-label="Desc -> Content" data-size="16px"></div>
<div class="rhythm-content-preview">
<div class="rhythm-card-row">
<div class="rhythm-mini-card">
<strong>12 aktiv</strong>
<div class="rhythm-line"></div>
<div class="rhythm-line short"></div>
</div>
<div class="rhythm-mini-card">
<strong>3 offen</strong>
<div class="rhythm-line"></div>
<div class="rhythm-line short"></div>
</div>
</div>
<div class="rhythm-list" style="margin-top: 12px">
<div class="rhythm-list-row">
<span class="rhythm-dot"></span>
<span class="rhythm-line"></span>
<span class="rhythm-pill"></span>
</div>
<div class="rhythm-list-row">
<span class="rhythm-dot"></span>
<span class="rhythm-line"></span>
<span class="rhythm-pill"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="rhythm-detail-grid">
<div class="rhythm-detail-card">
<p class="decision-kicker">Was D03 regelt</p>
<h3>Page- und Section-Textbloecke</h3>
<p class="muted">
D03 entscheidet die Gaps zwischen Text und Inhalt, damit Screens
gleich getaktet wirken. Die Inputs, Buttons, Tabellen und Cards
behalten ihre eigenen Komponentenabstaende.
</p>
<div class="rhythm-metric-list">
<div class="rhythm-metric">
<span>Page Title zu Beschreibung</span>
<strong>0px definiert</strong>
</div>
<div class="rhythm-metric">
<span>Page Header zu erstem Content</span>
<strong>24px</strong>
</div>
<div class="rhythm-metric">
<span>Section Title zu Beschreibung</span>
<strong>0px definiert</strong>
</div>
<div class="rhythm-metric">
<span>Section Beschreibung zu Inhalt</span>
<strong>12px</strong>
</div>
</div>
</div>
<div class="rhythm-detail-card">
<p class="decision-kicker">Nicht Teil von D03</p>
<h3>Keine Typography- oder Komponentenentscheidung</h3>
<p class="muted">
Textgroessen, 150%-Line-height bei mehrzeiligem Text,
Input-Label-Abstaende, Tabellenzeilen und Button-Hoehen bleiben
in den jeweiligen Tokens oder Komponenten. D03 soll nur klaeren,
wie Page-/Section-Text gegen den Content rhythmisiert wird.
</p>
</div>
</div>
<div class="token-impact">
<div class="token-impact-card warning">
<div>
<p class="decision-kicker">Wrap-Risiko</p>
<h3>`body-default-regular-0`</h3>
<p class="small">16px Text / 17px Line-height. Gut fuer echte Einzeiler, aber eng sobald Text umbricht.</p>
</div>
<div class="token-text-box tight">
Verwalte Einladungen, Rollen und Status fuer alle Personen im Workspace.
</div>
</div>
<div class="token-impact-card recommended">
<div>
<p class="decision-kicker">Wrap-sicher</p>
<h3>`body-default-regular-150`</h3>
<p class="small">16px Text / 24px Line-height. Besser fuer Texte, die ein- oder mehrzeilig sein koennen.</p>
</div>
<div class="token-text-box readable">
Verwalte Einladungen, Rollen und Status fuer alle Personen im Workspace.
</div>
</div>
</div>
<div class="token-rule-panel">
<p class="decision-kicker">Regel-Kandidat fuer Text-Wrapping</p>
<h3>Wenn Text umbrechen kann, nutzt er einen 150%-Token.</h3>
<p>
D03 nutzt bewusst 0px zwischen Titel und Beschreibung, weil der
150%-Texttoken bereits genug optische Hoehe im Textblock erzeugt.
Diese 0px sind ein definierter Auto-Layout-Gap und kein fehlender
Abstand. Wenn ein Description-Text von einer auf zwei Zeilen
springt, wird nur der Textblock hoeher. Der Gap zum naechsten
Content bleibt 24px im Page Header oder 12px in Sections.
</p>
</div>
</section>
<section id="d04" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D04 Button Component Ownership</h2>
<p class="section-desc">
Button-Hoehen, Innenpadding und Varianten werden durch die
Button-Komponente abgedeckt, nicht durch Screen-Layout-Regeln.
</p>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Komponenten-Ownership</span>
</div>
<div>
<p class="decision-kicker">Was fuer Screens gilt</p>
<h3>Standardaktionen nutzen die Default-Variante der Button-Komponente.</h3>
<p>
Die Default-Variante ist `Medium` und 36px hoch. Screen-Prompts
sollen Button-Hoehen oder Button-Padding nicht manuell nachbauen.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Small</strong>
<span>32px. Kommt aus der Komponente und wird nur genutzt, wenn der Kontext klein/dicht ist.</span>
</div>
<div class="decision-option recommended">
<strong>Medium / Default</strong>
<span>36px. Standard fuer normale lokale Aktionen in Screens.</span>
</div>
<div class="decision-option">
<strong>Large</strong>
<span>48px. Kommt aus der Komponente und wird nur bewusst eingesetzt.</span>
</div>
</div>
<div class="decision-question">
Keine eigene D04-Layoutentscheidung: Button Default/Medium 36px fuer Standardaktionen verwenden.
</div>
</div>
<div class="grid three">
<div class="card">
<h3>Small, 32px high</h3>
<div class="button-row">
<span class="button sm">Save</span>
<span class="button sm secondary">Cancel</span>
<span class="button sm ghost">More</span>
</div>
</div>
<div class="card">
<h3>Medium / Default, 36px high</h3>
<div class="button-row">
<span class="button">Save changes</span>
<span class="button secondary">Cancel</span>
</div>
</div>
<div class="card">
<h3>Large, 48px high</h3>
<div class="button-row">
<span class="button lg">Create workspace</span>
<span class="button lg danger">Delete</span>
</div>
</div>
</div>
</section>
<section id="d05" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D05 Form Layout Gap</h2>
<p class="section-desc">
Formular-Layout meint hier nur den Abstand zwischen kompletten
Field-Komponenten. Label, Beschreibung, Control und Message
gehoeren zur jeweiligen Form-Input-Komponente.
</p>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Entscheidung D05</span>
</div>
<div>
<p class="decision-kicker">Was du festlegst</p>
<h3>Wie dicht stehen komplette Formularfelder bzw. Field-Komponenten?</h3>
<p>
Validiert: komplette Field-Komponenten stehen standardmaessig
16px auseinander. Beschreibung/Help/Error wird innerhalb der
Komponente ueber deren Props/Slots gepflegt.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Kompakter Sonderfall</strong>
<span>12px nur fuer sehr dichte Teilbereiche, nicht als Formularstandard.</span>
</div>
<div class="decision-option recommended">
<strong>Standard</strong>
<span>16px zwischen kompletten Field-Komponenten.</span>
</div>
<div class="decision-option">
<strong>Luftig</strong>
<span>24px nur fuer bewusst getrennte Formular-Sections.</span>
</div>
</div>
<div class="decision-question">
Entschieden: Form Field Gap 16px. Field-Anatomy selbst kommt aus der jeweiligen Komponente.
</div>
</div>
<div class="grid two">
<div class="card">
<h3>Standard form density</h3>
<form class="form">
<div class="field">
<label for="name">Workspace name</label>
<input id="name" value="HiveGrid Demo" />
<p class="help">Visible to all members in this workspace.</p>
</div>
<div class="field">
<label for="slug">URL shortcut</label>
<input id="slug" value="hivegrid-demo" />
</div>
<div class="field">
<label for="desc">Description</label>
<textarea id="desc">Internal demo workspace for layout review.</textarea>
<p class="error">Use at least 12 characters.</p>
</div>
<div class="button-row">
<span class="button">Save</span>
<span class="button secondary">Cancel</span>
</div>
</form>
</div>
<div class="card">
<h3>Compact form density</h3>
<form class="form" style="gap: 16px">
<div class="field">
<label for="first">First name</label>
<input id="first" value="David" />
</div>
<div class="field">
<label for="last">Last name</label>
<input id="last" value="Bertram" />
</div>
<div class="field">
<label for="department">Department</label>
<select id="department">
<option>Operations</option>
<option>Sales</option>
<option>Admin</option>
</select>
</div>
<div class="button-row">
<span class="button">Update profile</span>
<span class="button secondary">Reset</span>
</div>
</form>
</div>
</div>
</section>
<section id="d06" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D06 Table Component Ownership</h2>
<p class="section-desc">
Tabellen-Row-Height, Cell Padding und Header-Dichte gehoeren zur
Table-Komponente. D-D0b dokumentiert nur die Referenzlogik fuer
Screen-Prompts.
</p>
</div>
<div class="toolbar">
<input style="width: 260px" value="Search employees" />
<span class="button secondary">Filter</span>
<span class="button">Invite</span>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Komponenten-Ownership</span>
</div>
<div>
<p class="decision-kicker">Carbon-Referenz</p>
<h3>Die Table-Komponente fuehrt die Dichte; Screens bauen keine Tabellen-Paddings manuell.</h3>
<p>
IBM Carbon arbeitet bei Data Tables mit mehreren Row Sizes. Die
Werte sind xs 24px, sm 32px, md 40px, lg 48px und xl 64px.
Columns haben 16px Padding. Die Header Row soll zur
Tabellen-Row-Groesse passen; sehr grosse Rows sind fuer zwei
Inhaltszeilen gedacht.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Carbon kompakt</strong>
<span>XS/SM fuer sehr dichte Datenlisten, wenn die Table-Komponente das anbietet.</span>
</div>
<div class="decision-option recommended">
<strong>Carbon Standard</strong>
<span>MD/LG als normale Table-Dichte; Header, Row und Toolbar muessen zusammenpassen.</span>
</div>
<div class="decision-option">
<strong>Carbon gross</strong>
<span>XL nur, wenn zwei Zeilen Inhalt oder bewusst mehr Leseraum gebraucht wird.</span>
</div>
</div>
<div class="decision-question">
Keine eigene D06-Layoutentscheidung: Table-Komponente nutzen; Carbon als Referenz fuer passende Row-Size-Systematik.
</div>
</div>
<div class="table-shell">
<table>
<thead>
<tr>
<th>Name</th>
<th>Role</th>
<th>Department</th>
<th>Status</th>
<th style="text-align: right">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>David Bertram</td>
<td>Admin</td>
<td>Operations</td>
<td><span class="pill">Active</span></td>
<td style="text-align: right">...</td>
</tr>
<tr>
<td>Anna Keller</td>
<td>Finance Lead</td>
<td>Finance</td>
<td><span class="pill">Active</span></td>
<td style="text-align: right">...</td>
</tr>
<tr>
<td>Max Hoffmann</td>
<td>Employee</td>
<td>Support</td>
<td><span class="pill warning">Pending</span></td>
<td style="text-align: right">...</td>
</tr>
</tbody>
</table>
</div>
</section>
<section id="d07" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D07 Dialog Sizes</h2>
<p class="section-desc">
Validierte Breiten fuer zentrierte Dialoge und Fullscreen
Dialoge. In Subframe muessen diese Beispiele mit echten Dialog
Layouts gebaut werden.
</p>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Entscheidung D07</span>
</div>
<div>
<p class="decision-kicker">Was du festlegst</p>
<h3>Welche Breiten bekommen kleine, normale und grosse Dialoge?</h3>
<p>
Dialogbreite und Dialogpadding sind getrennte Entscheidungen. Die
Beispiele unten zeigen Breitenklassen und die zwei validierten
Dialog-Padding-Varianten.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>XS / S</strong>
<span>XS 420px fuer kurze Bestaetigung, S 560px fuer kleine Formulare.</span>
</div>
<div class="decision-option recommended">
<strong>M / L</strong>
<span>M 720px fuer normale Formulare, L 1200px max fuer grosse Editor-Dialoge.</span>
</div>
<div class="decision-option">
<strong>Fullscreen</strong>
<span>Fill in Breite und Hoehe mit 24px aeusserem Rand, aber maximal 2512px breit.</span>
</div>
</div>
<div class="decision-question">
Entschieden: XS 420px, S 560px, M 720px, L 1200px max.
Fullscreen Dialog nutzt Fill mit 24px aeusserem Rand pro Seite und `max-width: 2512px`.
</div>
</div>
<div class="pattern-grid">
<div class="pattern-card">
<div class="pattern-mini">
<div class="pattern-shell">
<div class="pattern-page-content"></div>
</div>
</div>
<strong>Page</strong>
<p class="small">Eigener App-Ort mit Navigation oder Subnavigation. Settings ist eine Page, kein Dialog.</p>
</div>
<div class="pattern-card">
<div class="pattern-mini">
<div class="pattern-shell">
<div class="pattern-page-content"></div>
</div>
<div class="pattern-overlay"></div>
<div class="pattern-dialog-box"></div>
</div>
<strong>Dialog</strong>
<p class="small">Temporäres Overlay ueber der Page. Blockiert den Hintergrund und wird wieder geschlossen.</p>
</div>
<div class="pattern-card">
<div class="pattern-mini">
<div class="pattern-shell">
<div class="pattern-page-content"></div>
</div>
<div class="pattern-overlay"></div>
<div class="pattern-fullscreen-box"></div>
</div>
<strong>Fullscreen Dialog</strong>
<p class="small">Fill in Breite und Hoehe mit aeusserem Rand und 2512px Maxbreite. Wird geschlossen und ist kein dauerhafter App-Bereich.</p>
</div>
<div class="pattern-card">
<div class="pattern-mini">
<div class="pattern-shell">
<div class="pattern-page-content"></div>
</div>
<div class="pattern-drawer-box"></div>
</div>
<strong>Drawer / Side Panel</strong>
<p class="small">Seitliche Bearbeitung, waehrend der Kontext sichtbar bleibt. Eigene Breitenregeln, nicht D07.</p>
</div>
</div>
<div class="modal-version-grid">
<div class="modal-version recommended">
<div class="modal-version-head">
<div>
<h3>Validierte zentrierte Dialoggroessen</h3>
<p class="small">Vier neutrale Groessen fuer Confirm, kleine Formulare, normale Formulare und grosse Editor-Dialoge.</p>
</div>
<span class="pill">Validiert</span>
</div>
<div class="modal-size-row four">
<div class="modal-size-card">
<div class="modal-size-label"><strong>XS</strong><span>420px</span></div>
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 35%">420</div></div>
</div>
<div class="modal-size-card">
<div class="modal-size-label"><strong>S</strong><span>560px</span></div>
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 47%">560</div></div>
</div>
<div class="modal-size-card">
<div class="modal-size-label"><strong>M</strong><span>720px</span></div>
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 60%">720</div></div>
</div>
<div class="modal-size-card">
<div class="modal-size-label"><strong>L</strong><span>1200px max</span></div>
<div class="modal-width-track"><div class="modal-width-block" style="--preview-pct: 100%">1200</div></div>
</div>
</div>
</div>
</div>
<div class="viewport-behavior">
<div>
<h3>Verhalten auf breiten Monitoren</h3>
<p class="small">
Dialoge wachsen nicht automatisch mit 4K-Viewports mit. Die Breitenklasse bleibt fix,
der Dialog bleibt zentriert und der aeussere Overlay-Abstand wird groesser. Fullscreen Dialoge
nutzen `width: calc(100vw - 48px)`, aber hoechstens 2512px Breite.
</p>
</div>
<div class="viewport-row">
<strong>1440px</strong>
<div class="viewport-track"><div class="viewport-dialog" style="--dialog-ratio: 83%"></div></div>
<span class="small">1200px wirkt gross</span>
</div>
<div class="viewport-row">
<strong>2560px</strong>
<div class="viewport-track"><div class="viewport-dialog" style="--dialog-ratio: 47%"></div></div>
<span class="small">1200px bleibt fix</span>
</div>
<div class="viewport-row">
<strong>3840px</strong>
<div class="viewport-track"><div class="viewport-dialog" style="--dialog-ratio: 31%"></div></div>
<span class="small">mehr Rand, nicht breiter</span>
</div>
</div>
<div class="modal-grid">
<div class="modal-demo modal-xs">
<div class="modal-header">
<h3>XS - 420px</h3>
<p class="small">Kurze Bestaetigung oder knapper Hinweis.</p>
</div>
<div class="modal-body">
<p>Mitarbeiter deaktivieren?</p>
<p class="small">Der Zugriff wird sofort gesperrt. Bestehende Daten bleiben erhalten.</p>
</div>
<div class="modal-footer">
<span class="button secondary">Abbrechen</span>
<span class="button danger">Deaktivieren</span>
</div>
</div>
<div class="modal-demo modal-small">
<div class="modal-header">
<h3>S - 560px</h3>
<p class="small">Kleines Formular mit wenigen Feldern.</p>
</div>
<div class="modal-body">
<div class="field">
<label>Workspace name</label>
<input value="HiveGrid Demo" />
</div>
<div class="field">
<label>Kategorie</label>
<select>
<option>CRM Workspace</option>
<option>Operations</option>
</select>
</div>
</div>
<div class="modal-footer">
<span class="button secondary">Abbrechen</span>
<span class="button">Anlegen</span>
</div>
</div>
<div class="modal-demo modal-medium">
<div class="modal-header">
<h3>M - 720px</h3>
<p class="small">Normales Formular mit mehreren Feldern oder kurzer Section-Struktur.</p>
</div>
<div class="modal-body">
<div class="field">
<label>Role name</label>
<input value="Finance Lead" />
</div>
<div class="field">
<label>Description</label>
<textarea>Can approve invoices and review financial records.</textarea>
</div>
<div class="field">
<label>Bereich</label>
<select>
<option>Finance</option>
<option>Sales</option>
<option>Administration</option>
</select>
</div>
</div>
<div class="modal-footer">
<span class="button secondary">Abbrechen</span>
<span class="button">Weiter</span>
</div>
</div>
<div class="modal-demo modal-large modal-spacious">
<div class="modal-header">
<h3>L - 1200px max</h3>
<p class="small">Grosser Editor mit Navigation, Suche und komplexeren Einstellungen. Nutzt die 32px Dialog-Variante.</p>
</div>
<div class="modal-body" style="grid-template-columns: 220px 1fr; align-items: start">
<div class="card tight" style="background: var(--surface-subtle)">
<p><strong>Role</strong></p>
<p class="small">General</p>
<p class="small">Contacts</p>
<p class="small">Reports</p>
<p class="small">Advanced</p>
</div>
<div class="form">
<div class="field">
<label>Permission search</label>
<input value="Search permissions" />
</div>
<div class="card tight">
<h3>Contacts</h3>
<p class="muted">Read, create and update contact records.</p>
</div>
<div class="card tight">
<h3>Reports</h3>
<p class="muted">View exported reports and analytics.</p>
</div>
</div>
</div>
<div class="modal-footer">
<span class="button secondary">Abbrechen</span>
<span class="button">Rolle speichern</span>
</div>
</div>
</div>
</section>
<section id="d08" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D08 Dialog Internal Gaps</h2>
<p class="section-desc">
Validierte Entscheidung: Balanced ist der Standard. Diese Werte
betreffen nur Abstaende zwischen Elementen innerhalb normaler
Dialoge, nicht die bereits validierte Dialogbreite oder das
Dialog-Padding.
</p>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Entscheidung D08 validiert</span>
</div>
<div>
<p class="decision-kicker">Was du festlegst</p>
<h3>Welche Gaps gelten zwischen Dialog-Header, Body, Feldern, Sections und Footer?</h3>
<p>
Bereits validiert: Dialog Padding 16px Default und 32px Spacious.
Jetzt validiert: Balanced ist die Standard-Gap-Logik fuer normale
Dialoge, damit Dialoge nicht je Screen unterschiedlich wirken.
Mehrzeilige Texte nutzen die 150%-Texttoken; dadurch wird der
Textblock selbst hoeher, ohne zusaetzlichen Sonder-Gap.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Kompakt</strong>
<span>Sehr dicht. Gut fuer kurze Confirm-Dialoge, aber fuer Formulare schnell gedrueckt.</span>
</div>
<div class="decision-option recommended">
<strong>Balanced</strong>
<span>Orientiert sich an 8px-Rhythmus und Carbon-nahem Modal-Denken: kompakt, aber lesbar.</span>
</div>
<div class="decision-option">
<strong>Ruhig</strong>
<span>Mehr Luft fuer groessere Dialoge, kann bei XS/S aber zu luftig wirken.</span>
</div>
</div>
<div class="decision-question">
Entschieden: Balanced wird Standard. Title Gap 8px, Field Gap 16px, Section Gap 24px, Button Gap 8px.
</div>
</div>
<div class="dialog-gap-grid">
<div class="dialog-gap-card" style="--title-gap: 4px; --field-gap: 12px; --section-gap-demo: 20px; --button-gap: 8px">
<div>
<h3>Kompakt</h3>
<p class="small">Fuer sehr kurze Dialoge. Spart Hoehe, trennt Inhalte aber weniger stark.</p>
</div>
<ul class="gap-spec-list">
<li><span>Title -> Description</span><strong>4px</strong></li>
<li><span>Field/Form Row Gap</span><strong>12px</strong></li>
<li><span>Section Gap</span><strong>20px</strong></li>
<li><span>Footer Button Gap</span><strong>8px</strong></li>
</ul>
<div class="dialog-gap-demo">
<div class="dialog-gap-header">
<div class="dialog-gap-title"></div>
<div class="gap-marker vertical" style="--gap-size: var(--title-gap)" data-label="Title Gap" data-size="4px"></div>
<div class="dialog-gap-description"></div>
</div>
<div class="dialog-gap-body">
<div class="dialog-gap-field">
<div class="dialog-gap-label"></div>
<div class="dialog-gap-input"></div>
</div>
<div class="gap-marker vertical" style="--gap-size: var(--field-gap)" data-label="Field Gap" data-size="12px"></div>
<div class="dialog-gap-field">
<div class="dialog-gap-label"></div>
<div class="dialog-gap-input"></div>
</div>
<div class="gap-marker vertical" style="--gap-size: var(--section-gap-demo)" data-label="Section Gap" data-size="20px"></div>
<div class="dialog-gap-section">
<div class="dialog-gap-row"></div>
<div class="dialog-gap-row"></div>
</div>
</div>
<div class="dialog-gap-footer">
<div class="dialog-gap-button"></div>
<div class="gap-marker horizontal" style="--gap-size: var(--button-gap)" data-label="Button Gap" data-size="8px"></div>
<div class="dialog-gap-button primary"></div>
</div>
</div>
</div>
<div class="dialog-gap-card recommended" style="--title-gap: 8px; --field-gap: 16px; --section-gap-demo: 24px; --button-gap: 8px">
<div>
<h3>Balanced</h3>
<p class="small">Validierter Default. Passt zu 16px Dialog-Padding und bleibt nah an D02.</p>
</div>
<ul class="gap-spec-list">
<li><span>Title -> Description</span><strong>8px</strong></li>
<li><span>Field/Form Row Gap</span><strong>16px</strong></li>
<li><span>Section Gap</span><strong>24px</strong></li>
<li><span>Footer Button Gap</span><strong>8px</strong></li>
</ul>
<div class="dialog-gap-demo">
<div class="dialog-gap-header">
<div class="dialog-gap-title"></div>
<div class="gap-marker vertical" style="--gap-size: var(--title-gap)" data-label="Title Gap" data-size="8px"></div>
<div class="dialog-gap-description"></div>
</div>
<div class="dialog-gap-body">
<div class="dialog-gap-field">
<div class="dialog-gap-label"></div>
<div class="dialog-gap-input"></div>
</div>
<div class="gap-marker vertical" style="--gap-size: var(--field-gap)" data-label="Field Gap" data-size="16px"></div>
<div class="dialog-gap-field">
<div class="dialog-gap-label"></div>
<div class="dialog-gap-input"></div>
</div>
<div class="gap-marker vertical" style="--gap-size: var(--section-gap-demo)" data-label="Section Gap" data-size="24px"></div>
<div class="dialog-gap-section">
<div class="dialog-gap-row"></div>
<div class="dialog-gap-row"></div>
</div>
</div>
<div class="dialog-gap-footer">
<div class="dialog-gap-button"></div>
<div class="gap-marker horizontal" style="--gap-size: var(--button-gap)" data-label="Button Gap" data-size="8px"></div>
<div class="dialog-gap-button primary"></div>
</div>
</div>
</div>
<div class="dialog-gap-card" style="--title-gap: 8px; --field-gap: 20px; --section-gap-demo: 32px; --button-gap: 12px">
<div>
<h3>Ruhig</h3>
<p class="small">Mehr Luft fuer grosse Dialoge. Koennte eher zur 32px-Spacious-Variante passen.</p>
</div>
<ul class="gap-spec-list">
<li><span>Title -> Description</span><strong>8px</strong></li>
<li><span>Field/Form Row Gap</span><strong>20px</strong></li>
<li><span>Section Gap</span><strong>32px</strong></li>
<li><span>Footer Button Gap</span><strong>12px</strong></li>
</ul>
<div class="dialog-gap-demo">
<div class="dialog-gap-header">
<div class="dialog-gap-title"></div>
<div class="gap-marker vertical" style="--gap-size: var(--title-gap)" data-label="Title Gap" data-size="8px"></div>
<div class="dialog-gap-description"></div>
</div>
<div class="dialog-gap-body">
<div class="dialog-gap-field">
<div class="dialog-gap-label"></div>
<div class="dialog-gap-input"></div>
</div>
<div class="gap-marker vertical" style="--gap-size: var(--field-gap)" data-label="Field Gap" data-size="20px"></div>
<div class="dialog-gap-field">
<div class="dialog-gap-label"></div>
<div class="dialog-gap-input"></div>
</div>
<div class="gap-marker vertical" style="--gap-size: var(--section-gap-demo)" data-label="Section Gap" data-size="32px"></div>
<div class="dialog-gap-section">
<div class="dialog-gap-row"></div>
<div class="dialog-gap-row"></div>
</div>
</div>
<div class="dialog-gap-footer">
<div class="dialog-gap-button"></div>
<div class="gap-marker horizontal" style="--gap-size: var(--button-gap)" data-label="Button Gap" data-size="12px"></div>
<div class="dialog-gap-button primary"></div>
</div>
</div>
</div>
</div>
<div class="decision-panel" style="margin-top: 24px">
<div>
<span class="decision-tag">Zusatzfrage validiert</span>
</div>
<div>
<p class="decision-kicker">Footer Buttons</p>
<h3>Sollen Buttons in kleinen Dialogen rechts ausgerichtet bleiben oder die Breite fuellen?</h3>
<p>
Das ist getrennt vom Button-Gap. Es geht um die Button-Verteilung
im Footer: klassische Desktop-Dialoge richten Actions oft rechts
aus; bei sehr kleinen Dialogen kann Fill ergonomischer wirken.
</p>
</div>
<div class="decision-options">
<div class="decision-option recommended">
<strong>Default: rechts</strong>
<span>Alle Dialoggroessen behalten rechts ausgerichtete Actions. Ruhig und desktop-typisch.</span>
</div>
<div class="decision-option">
<strong>XS/S: Fill</strong>
<span>Nur kleine Dialoge mit genau zwei Actions duerfen beide Buttons gleich breit fuellen.</span>
</div>
<div class="decision-option">
<strong>Immer Fill</strong>
<span>Sehr klare Buttonflaechen, aber fuer M/L-Dialoge meistens zu dominant.</span>
</div>
</div>
<div class="decision-question">
Entschieden: Footer Actions bleiben standardmaessig rechts ausgerichtet. XS/S-Fill bleibt nur eine optionale Sondervariante, falls sie spaeter bewusst gebraucht wird.
</div>
</div>
<div class="footer-layout-grid">
<div class="footer-layout-card recommended">
<div>
<h3>Default: rechts ausgerichtet</h3>
<p class="small">Klassischer Desktop-Dialog. Der freie Bereich links ist bewusst, weil die Actions nicht mit dem Inhalt konkurrieren.</p>
</div>
<div class="footer-preview">
<div class="footer-preview-body">
<div class="dialog-gap-title"></div>
<div style="height: 8px"></div>
<div class="dialog-gap-description"></div>
</div>
<div class="footer-preview-actions">
<div class="dialog-gap-button"></div>
<div class="dialog-gap-button primary"></div>
</div>
</div>
</div>
<div class="footer-layout-card">
<div>
<h3>XS/S Sonderfall: Fill Buttons</h3>
<p class="small">Kann bei sehr kleinen Dialogen mit genau zwei Actions sinnvoll sein. Sollte keine globale M/L-Regel werden.</p>
</div>
<div class="footer-preview fill-actions">
<div class="footer-preview-body">
<div class="dialog-gap-title"></div>
<div style="height: 8px"></div>
<div class="dialog-gap-description"></div>
</div>
<div class="footer-preview-actions">
<div class="dialog-gap-button"></div>
<div class="dialog-gap-button primary"></div>
</div>
</div>
</div>
</div>
</section>
<section id="d09" class="section">
<div class="section-head">
<div class="section-copy">
<h2>D09 States / Component Ownership</h2>
<p class="section-desc">
Klarstellung: States sind inline Inhaltszustaende und werden ueber
Komponenten abgedeckt. Sie sind keine Modale und aktuell keine
eigene Layout-Entscheidung in D-D0b.
</p>
</div>
</div>
<div class="decision-panel">
<div>
<span class="decision-tag">Komponenten-Ownership</span>
</div>
<div>
<p class="decision-kicker">Was hier gemeint ist</p>
<h3>Empty, Error und No-Permission ersetzen inline den betroffenen Inhaltsbereich.</h3>
<p>
Beispiel: Eine leere Tabelle zeigt einen Empty State im Tabellen-
oder Listenbereich. Ein Ladefehler zeigt einen Error State im
betroffenen Bereich. Das oeffnet nicht automatisch einen Dialog.
</p>
</div>
<div class="decision-options">
<div class="decision-option">
<strong>Empty State</strong>
<span>Im Komponenten-Index vorhanden: Data Display / Empty State.</span>
</div>
<div class="decision-option recommended">
<strong>Error State</strong>
<span>Im Komponenten-Index vorhanden: Feedback / Error State bzw. Partial page failure.</span>
</div>
<div class="decision-option">
<strong>No Permission</strong>
<span>Nicht als eigene lokale Komponenten-MD gefunden. Falls noetig als Variante/Komponente klaeren.</span>
</div>
</div>
<div class="decision-question">
Keine neue D09-Layout-Regel: Screens sollen die vorhandenen State-Komponenten verwenden. No-Permission muss bei Bedarf als Komponentenfrage validiert werden.
</div>
</div>
<div class="grid three">
<div class="state">
<div class="state-inner">
<h3>Empty</h3>
<p class="muted">No roles have been created yet.</p>
<div style="height: 16px"></div>
<span class="button">Create role</span>
</div>
</div>
<div class="state">
<div class="state-inner">
<h3>Error</h3>
<p class="muted">The list could not be loaded.</p>
<div style="height: 16px"></div>
<span class="button secondary">Try again</span>
</div>
</div>
<div class="state">
<div class="state-inner">
<h3>No permission</h3>
<p class="muted">You do not have access to this area.</p>
<div style="height: 16px"></div>
<span class="button secondary">Back to overview</span>
</div>
</div>
</div>
</section>
</main>
<script>
const gapToggle = document.getElementById("gapToggle");
gapToggle?.addEventListener("click", () => {
const hidden = document.body.classList.toggle("hide-gap-markers");
gapToggle.setAttribute("aria-pressed", String(!hidden));
});
</script>
</body>
</html>