@font-face {
    font-family: 'Geist';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/Geist[wght].woff2') format('woff2');
}

:root {
    --bpu-background: #FFFFFF;
    --bpu-background-gray: #FAFAFA;
    --bpu-surface: #FFFFFF;
    --bpu-text: #0A0A0A;
    --bpu-text-muted: #71717A;
    --bpu-primary: #18181B;
    --bpu-primary-text: #FAFAFA;
    --bpu-primary-hover: #27272A;
    --bpu-lines: #E4E4E7;
    --bpu-radius: 0.5rem;
    --bpu-warning-surface: #FEF9C3;
    --bpu-warning-line: #CA8A04;
    --bpu-warning-text: #713F12;

    color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bpu-background: #09090B;
        --bpu-background-gray: #0A0A0A;
        --bpu-surface: #09090B;
        --bpu-text: #FAFAFA;
        --bpu-text-muted: #A1A1AA;
        --bpu-primary: #FAFAFA;
        --bpu-primary-text: #18181B;
        --bpu-primary-hover: #E4E4E7;
        --bpu-lines: #27272A;
        --bpu-warning-surface: #292524;
        --bpu-warning-line: #A16207;
        --bpu-warning-text: #FEF08A;
    }
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    background: var(--bpu-background);
    color: var(--bpu-text);
    font-family: 'Geist', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    font-size: 1rem;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
}

a {
    color: inherit;
}

.wrap {
    width: 100%;
    max-width: 68rem;
    margin: 0 auto;
    padding: 0 1.5rem;
}

/* Header */

.site-header {
    position: sticky;
    top: 0;
    z-index: 10;
    border-bottom: 1px solid var(--bpu-lines);
    background: color-mix(in srgb, var(--bpu-background) 88%, transparent);
    backdrop-filter: blur(8px);
}

.site-header .wrap {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: 4rem;
}

.brand {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    font-size: 1.0625rem;
    font-weight: 700;
    text-decoration: none;
    letter-spacing: -0.01em;
}

.brand-mark {
    flex: none;
    display: block;
    width: 2rem;
    height: 2rem;
    --bpu-mark-plate: var(--bpu-primary);
    --bpu-mark-ink: var(--bpu-primary-text);
}

.brand-word {
    letter-spacing: -0.021em;
}

.brand-word-light {
    font-weight: 400;
}

.site-nav {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    font-size: 0.9375rem;
}

.site-nav a:not(.button) {
    color: var(--bpu-text-muted);
    text-decoration: none;
}

.site-nav a:not(.button):hover {
    color: var(--bpu-text);
}

/* Buttons */

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.625rem 1.125rem;
    border: 1px solid transparent;
    border-radius: var(--bpu-radius);
    font-size: 0.9375rem;
    font-weight: 500;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

.button-primary {
    background: var(--bpu-primary);
    color: var(--bpu-primary-text);
}

.button-primary:hover {
    background: var(--bpu-primary-hover);
}

.button-secondary {
    background: transparent;
    border-color: var(--bpu-lines);
    color: var(--bpu-text);
}

.button-secondary:hover {
    background: var(--bpu-background-gray);
}

/* Hero */

.hero {
    position: relative;
    overflow: hidden;
    border-bottom: 1px solid var(--bpu-lines);
    background:
        radial-gradient(120% 120% at 15% 10%, var(--bpu-surface), transparent 60%),
        linear-gradient(160deg, var(--bpu-surface), var(--bpu-background-gray));
}

.hero::before {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0.5;
    pointer-events: none;
    background-image:
        linear-gradient(var(--bpu-lines) 1px, transparent 1px),
        linear-gradient(90deg, var(--bpu-lines) 1px, transparent 1px);
    background-size: 2.25rem 2.25rem;
    -webkit-mask-image: radial-gradient(80% 80% at 30% 20%, #000 30%, transparent 75%);
    mask-image: radial-gradient(80% 80% at 30% 20%, #000 30%, transparent 75%);
}

.hero .wrap {
    position: relative;
    z-index: 1;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 25rem);
    align-items: center;
    gap: 3rem;
    padding-top: 5.5rem;
    padding-bottom: 5.5rem;
}

.hero h1 {
    margin: 0 0 1rem;
    max-width: 20ch;
    font-size: clamp(2.25rem, 6vw, 3.5rem);
    line-height: 1.1;
    letter-spacing: -0.03em;
    font-weight: 700;
}

.hero p {
    margin: 0 0 2rem;
    font-size: 1.125rem;
    color: var(--bpu-text-muted);
    max-width: 34rem;
}

.hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* The board: what the customer sees, running by itself.

   Three lanes and a handful of tickets that walk from Offen through In Bearbeitung to Abholbereit and
   then leave, which is exactly what the Monitor does in the shop. Built from the same four states the
   domain has (OrderStatus), so the picture cannot promise a flow the product does not have. */

.board {
    --gap: 0.5rem;
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    padding: 1rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
    box-shadow: 0 24px 48px -32px rgba(0, 0, 0, 0.55);
}

.board-head {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--gap);
    margin-bottom: 0.625rem;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bpu-text-muted);
}

.board-lanes,
.board-flow {
    grid-row: 2;
    grid-column: 1;
}

.board-lanes {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--gap);
    min-height: 11rem;
}

.board-lanes span {
    border: 1px dashed var(--bpu-lines);
    border-radius: 0.375rem;
}

.board-flow {
    position: relative;
}

.ticket {
    position: absolute;
    top: calc(0.5rem + var(--slot) * 3.25rem);
    left: 0;
    width: calc((100% - 2 * var(--gap)) / 3);
    display: grid;
    gap: 0.125rem;
    padding: 0.5rem 0.625rem;
    border: 1px solid var(--bpu-lines);
    border-left: 3px solid var(--bpu-lines);
    border-radius: 0.375rem;
    background: var(--bpu-background);
    animation:
        ticket-flow 9.6s var(--delay) infinite ease-in-out,
        ticket-accent 9.6s var(--delay) infinite step-end;
}

.ticket-no {
    font-size: 0.9375rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.ticket-state {
    grid-row: 2;
    grid-column: 1;
    font-size: 0.6875rem;
    color: var(--bpu-text-muted);
    opacity: 0;
}

.ticket .s1 {
    animation: state-open 9.6s var(--delay) infinite step-end;
}

.ticket .s2 {
    animation: state-progress 9.6s var(--delay) infinite step-end;
}

.ticket .s3 {
    animation: state-ready 9.6s var(--delay) infinite step-end;
}

@keyframes ticket-flow {
    0% { transform: translate3d(0, 8px, 0); opacity: 0; }
    4% { transform: translate3d(0, 0, 0); opacity: 1; }
    30% { transform: translate3d(0, 0, 0); opacity: 1; }
    36% { transform: translate3d(calc(100% + var(--gap)), 0, 0); opacity: 1; }
    63% { transform: translate3d(calc(100% + var(--gap)), 0, 0); opacity: 1; }
    69% { transform: translate3d(calc(200% + 2 * var(--gap)), 0, 0); opacity: 1; }
    94% { transform: translate3d(calc(200% + 2 * var(--gap)), 0, 0); opacity: 1; }
    100% { transform: translate3d(calc(200% + 2 * var(--gap)), -10px, 0); opacity: 0; }
}

@keyframes ticket-accent {
    0% { border-left-color: var(--bpu-lines); }
    36% { border-left-color: #F59E0B; }
    69% { border-left-color: #16A34A; }
}

@keyframes state-open {
    0% { opacity: 1; }
    36% { opacity: 0; }
}

@keyframes state-progress {
    0% { opacity: 0; }
    36% { opacity: 1; }
    69% { opacity: 0; }
}

@keyframes state-ready {
    0% { opacity: 0; }
    69% { opacity: 1; }
}

/* Whoever asked their system not to animate things gets the same picture standing still: one ticket
   parked in each lane, each showing the state of the lane it sits in. */
@media (prefers-reduced-motion: reduce) {
    .ticket,
    .ticket-state {
        animation: none;
    }

    .ticket:nth-child(2) {
        transform: translate3d(calc(100% + var(--gap)), 0, 0);
        border-left-color: #F59E0B;
    }

    .ticket:nth-child(3) {
        transform: translate3d(calc(200% + 2 * var(--gap)), 0, 0);
        border-left-color: #16A34A;
    }

    .ticket:nth-child(1) .s1,
    .ticket:nth-child(2) .s2,
    .ticket:nth-child(3) .s3 {
        opacity: 1;
    }
}

/* Sections */

section {
    padding: 4.5rem 0;
    border-bottom: 1px solid var(--bpu-lines);
}

section:last-of-type {
    border-bottom: 0;
}

h2 {
    margin: 0 0 0.5rem;
    font-size: 1.75rem;
    line-height: 1.25;
    letter-spacing: -0.02em;
    font-weight: 700;
}

.section-lead {
    margin: 0 0 2.5rem;
    color: var(--bpu-text-muted);
    max-width: 40rem;
}

h3 {
    margin: 0 0 0.375rem;
    font-size: 1.0625rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.cards {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.card {
    padding: 1.5rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
}

.card p {
    margin: 0;
    color: var(--bpu-text-muted);
    font-size: 0.9375rem;
}

.steps {
    counter-reset: step;
    display: grid;
    gap: 1.25rem;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    margin: 0;
    padding: 0;
    list-style: none;
}

.steps li {
    counter-increment: step;
    padding-top: 1rem;
    border-top: 2px solid var(--bpu-lines);
}

.steps li::before {
    content: counter(step);
    display: block;
    margin-bottom: 0.5rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--bpu-text-muted);
}

.steps strong {
    display: block;
    margin-bottom: 0.25rem;
    font-weight: 600;
}

.steps span {
    color: var(--bpu-text-muted);
    font-size: 0.9375rem;
}

/* The flow section: a Control Panel that sends and a Monitor that receives.

   Its four states are driven by the reader's scroll position where the browser supports
   scroll-driven animations, so the bestellung walks along with them instead of looping past. Where it
   does not, the very same keyframes run on a timer -- nobody gets a still picture, and there is no
   script on this page either way.

   The travelling dot is deliberately NOT scroll-bound: a signal that only moves when the reader moves
   reads as a scrollbar, not as a signal. */

.flow-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 21rem);
    gap: 3.5rem;
    align-items: start;
}

.flow-stage {
    position: sticky;
    top: 6rem;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.35fr);
    align-items: center;
    gap: 1rem;
}

/* One signal, two receivers: the screen on the wall and the phone in the customer's hand. They show
   the same state because they are told by the same event, which is the point of the picture. */
.flow-receivers {
    display: grid;
    justify-items: center;
    gap: 1rem;
}

.device {
    display: grid;
    gap: 0.75rem;
    padding: 1rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
    box-shadow: 0 20px 40px -30px rgba(0, 0, 0, 0.6);
}

.device-label {
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bpu-text-muted);
}

.panel-order {
    display: grid;
    gap: 0.125rem;
    padding: 0.625rem 0.75rem;
    border: 1px solid var(--bpu-lines);
    border-radius: 0.375rem;
}

.panel-no {
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.panel-sub {
    font-size: 0.75rem;
    color: var(--bpu-text-muted);
}

.panel-buttons {
    display: grid;
    gap: 0.375rem;
}

.pb {
    padding: 0.375rem 0.625rem;
    border: 1px solid var(--bpu-lines);
    border-radius: 0.375rem;
    font-size: 0.8125rem;
    color: var(--bpu-text-muted);
}

.signal {
    position: relative;
    width: 4.5rem;
    height: 2px;
    background: var(--bpu-lines);
}

.signal-dot {
    position: absolute;
    top: 50%;
    left: 0;
    width: 0.5rem;
    height: 0.5rem;
    margin-top: -0.25rem;
    border-radius: 50%;
    background: var(--bpu-text);
    animation: signal-run 2.4s infinite ease-in-out;
}

@keyframes signal-run {
    0% { transform: translateX(0); opacity: 0; }
    15% { opacity: 1; }
    85% { opacity: 1; }
    100% { transform: translateX(4rem); opacity: 0; }
}

.monitor-screen {
    display: grid;
    gap: 0.25rem;
    padding: 1.25rem 0.75rem;
    border-radius: 0.375rem;
    background: var(--bpu-background-gray);
    text-align: center;
}

.monitor-no {
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.monitor-state {
    grid-row: 2;
    grid-column: 1;
    font-size: 0.8125rem;
    color: var(--bpu-text-muted);
    opacity: 0;
}

/* A phone, drawn rather than photographed: a device shot ages the moment the hardware does, and a
   picture of a screenshot cannot show the state changing with the rest of the stage. */

/* The monitor, as the thing it actually is: a screen on a wall. The number crosses it from left to
   right while the reader scrolls, on the same timeline as the panel and the phone, so all three are
   telling one story rather than three. */

.device-tv {
    --tv-gap: 0.375rem;
    display: grid;
    justify-items: center;
    gap: 0;
}

.device-tv .device-label {
    margin-bottom: 0.5rem;
}

.tv {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid var(--bpu-lines);
    border-radius: 0.625rem;
    background: var(--bpu-surface);
    box-shadow: 0 20px 40px -30px rgba(0, 0, 0, 0.7);
}

.tv-screen {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    padding: 0.5rem;
    border-radius: 0.375rem;
    background: var(--bpu-background-gray);
}

.tv-head {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--tv-gap);
    margin-bottom: 0.375rem;
    font-size: 0.5625rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--bpu-text-muted);
}

.tv-lanes,
.tv-flow {
    grid-row: 2;
    grid-column: 1;
}

.tv-lanes {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--tv-gap);
    min-height: 3.25rem;
}

.tv-lanes span {
    border: 1px dashed var(--bpu-lines);
    border-radius: 0.25rem;
}

.tv-flow {
    position: relative;
}

.tv-ticket {
    position: absolute;
    top: 0.375rem;
    left: 0;
    width: calc((100% - 2 * var(--tv-gap)) / 3);
    padding: 0.375rem 0.25rem;
    border: 1px solid var(--bpu-lines);
    border-left: 3px solid var(--bpu-lines);
    border-radius: 0.25rem;
    background: var(--bpu-surface);
    text-align: center;
    font-size: 0.8125rem;
    font-weight: 700;
    animation:
        tv-move 12s infinite ease-in-out,
        tv-accent 12s infinite step-end;
}

@keyframes tv-move {
    0% { transform: translateX(0); opacity: 1; }
    25% { transform: translateX(calc(100% + var(--tv-gap))); opacity: 1; }
    50% { transform: translateX(calc(200% + 2 * var(--tv-gap))); opacity: 1; }
    72% { transform: translateX(calc(200% + 2 * var(--tv-gap))); opacity: 1; }
    85% { transform: translateX(calc(200% + 2 * var(--tv-gap))) translateY(-0.5rem); opacity: 0; }
    100% { transform: translateX(calc(200% + 2 * var(--tv-gap))) translateY(-0.5rem); opacity: 0; }
}

@keyframes tv-accent {
    0% { border-left-color: var(--bpu-lines); }
    25% { border-left-color: #F59E0B; }
    50% { border-left-color: #16A34A; }
}

.tv-neck {
    width: 0.625rem;
    height: 0.75rem;
    background: var(--bpu-lines);
}

.tv-foot {
    width: 3.5rem;
    height: 0.25rem;
    border-radius: 999px;
    background: var(--bpu-lines);
}

.device-phone {
    display: grid;
    justify-items: center;
    gap: 0.5rem;
}

.phone {
    position: relative;
    width: 8.25rem;
    padding: 1.25rem 0.5rem 1rem;
    border: 2px solid var(--bpu-lines);
    border-radius: 1.375rem;
    background: var(--bpu-surface);
    box-shadow: 0 18px 36px -26px rgba(0, 0, 0, 0.65);
}

.phone-notch {
    position: absolute;
    top: 0.5rem;
    left: 50%;
    transform: translateX(-50%);
    width: 2.25rem;
    height: 0.25rem;
    border-radius: 999px;
    background: var(--bpu-lines);
}

.phone-home {
    display: block;
    width: 2.75rem;
    height: 0.1875rem;
    margin: 0.625rem auto 0;
    border-radius: 999px;
    background: var(--bpu-lines);
}

.phone-screen {
    display: grid;
    justify-items: center;
    gap: 0.25rem;
    padding: 0.875rem 0.5rem 1rem;
    border-radius: 0.875rem;
    background: var(--bpu-background-gray);
    text-align: center;
}

.phone-brand {
    font-size: 0.5625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bpu-text-muted);
}

.phone-no {
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.phone-screen .monitor-state {
    grid-row: 3;
    grid-column: 1;
    font-size: 0.6875rem;
}

.phone-dots {
    grid-row: 4;
    display: flex;
    gap: 0.25rem;
    margin-top: 0.375rem;
}

.pd {
    width: 0.3125rem;
    height: 0.3125rem;
    border-radius: 50%;
    background: var(--bpu-lines);
}

.pd1 { animation: dot-1 12s infinite step-end; }
.pd2 { animation: dot-2 12s infinite step-end; }
.pd3 { animation: dot-3 12s infinite step-end; }
.pd4 { animation: dot-4 12s infinite step-end; }

@keyframes dot-1 { 0% { background: var(--bpu-text); } 25% { background: var(--bpu-lines); } }
@keyframes dot-2 { 0% { background: var(--bpu-lines); } 25% { background: #F59E0B; } 50% { background: var(--bpu-lines); } }
@keyframes dot-3 { 0% { background: var(--bpu-lines); } 50% { background: #16A34A; } 75% { background: var(--bpu-lines); } }
@keyframes dot-4 { 0% { background: var(--bpu-lines); } 75% { background: var(--bpu-text); } }

.flow-steps {
    counter-reset: flowstep;
    margin: 0;
    padding: 0;
    list-style: none;
}

.flow-steps li {
    counter-increment: flowstep;
    display: grid;
    gap: 0.25rem;
    align-content: center;
    min-height: 60vh;
    padding-left: 2.5rem;
    position: relative;
}

.flow-steps li::before {
    content: counter(flowstep);
    position: absolute;
    left: 0;
    top: calc(50% - 0.875rem);
    display: grid;
    place-items: center;
    width: 1.75rem;
    height: 1.75rem;
    border: 1px solid var(--bpu-lines);
    border-radius: 50%;
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--bpu-text-muted);
}

.flow-steps strong {
    font-weight: 600;
}

.flow-steps span {
    color: var(--bpu-text-muted);
    font-size: 0.9375rem;
}

/* The four states, as keyframes shared by both drives below. */

@keyframes panel-press-1 {
    0% { border-color: var(--bpu-text); color: var(--bpu-text); background: var(--bpu-background-gray); }
    25% { border-color: var(--bpu-lines); color: var(--bpu-text-muted); background: transparent; }
}

@keyframes panel-press-2 {
    0% { border-color: var(--bpu-lines); color: var(--bpu-text-muted); background: transparent; }
    25% { border-color: #F59E0B; color: var(--bpu-text); background: transparent; }
    50% { border-color: var(--bpu-lines); color: var(--bpu-text-muted); background: transparent; }
}

@keyframes panel-press-3 {
    0% { border-color: var(--bpu-lines); color: var(--bpu-text-muted); background: transparent; }
    50% { border-color: #16A34A; color: var(--bpu-text); background: transparent; }
    75% { border-color: var(--bpu-lines); color: var(--bpu-text-muted); background: transparent; }
}

@keyframes panel-press-4 {
    0% { border-color: var(--bpu-lines); color: var(--bpu-text-muted); background: transparent; }
    75% { border-color: var(--bpu-text); color: var(--bpu-text); background: var(--bpu-background-gray); }
}

@keyframes monitor-state-1 { 0% { opacity: 1; } 25% { opacity: 0; } }
@keyframes monitor-state-2 { 0% { opacity: 0; } 25% { opacity: 1; } 50% { opacity: 0; } }
@keyframes monitor-state-3 { 0% { opacity: 0; } 50% { opacity: 1; } 75% { opacity: 0; } }
@keyframes monitor-state-4 { 0% { opacity: 0; } 75% { opacity: 1; } }

@keyframes monitor-tint {
    0% { box-shadow: inset 0 0 0 1px var(--bpu-lines); }
    25% { box-shadow: inset 0 0 0 1px #F59E0B; }
    50% { box-shadow: inset 0 0 0 2px #16A34A; }
    75% { box-shadow: inset 0 0 0 1px var(--bpu-lines); }
}

.pb1 { animation: panel-press-1 12s infinite step-end; }
.pb2 { animation: panel-press-2 12s infinite step-end; }
.pb3 { animation: panel-press-3 12s infinite step-end; }
.pb4 { animation: panel-press-4 12s infinite step-end; }
.ms1 { animation: monitor-state-1 12s infinite step-end; }
.ms2 { animation: monitor-state-2 12s infinite step-end; }
.ms3 { animation: monitor-state-3 12s infinite step-end; }
.ms4 { animation: monitor-state-4 12s infinite step-end; }
.monitor-screen { animation: monitor-tint 12s infinite step-end; }

/* Where the browser can bind an animation to scroll progress, the timer is replaced by the reader:
   the states advance as the four steps go past, and standing still means standing still. */
@supports (animation-timeline: view()) {
    /* The steps are what scrolls, so they carry the timeline -- but the panel and the monitor are
       their SIBLINGS, and a named timeline only reaches descendants. timeline-scope on the common
       parent is what lets the stage read a clock that lives next door. Without it the animations
       resolve to no timeline at all and simply never run. */
    .flow-grid {
        timeline-scope: --flow;
    }

    .flow-steps {
        view-timeline-name: --flow;
        view-timeline-axis: block;
    }

    .pb,
    .pd,
    .tv-ticket,
    .monitor-state,
    .monitor-screen {
        animation-timeline: --flow;
        animation-duration: auto;
        animation-iteration-count: 1;
        animation-range: cover 15% cover 85%;

        /* Without this the elements fall back to their own styles outside the range, which for the
           state labels means opacity 0 -- an empty monitor until the section is halfway up the
           screen. `both` holds the first frame before the range and the last one after it. */
        animation-fill-mode: both;
    }
}

@media (max-width: 60rem) {
    .flow-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
    }

    .flow-stage {
        top: 4.5rem;
        grid-template-columns: minmax(0, 1fr);
        justify-items: stretch;
    }

    .signal {
        justify-self: center;
        width: 2px;
        height: 3rem;
    }

    .signal-dot {
        left: 50%;
        margin-left: -0.25rem;
        animation-name: signal-run-down;
    }


    .flow-steps li {
        min-height: 45vh;
    }
}

@media (prefers-reduced-motion: reduce) {
    .signal-dot {
        animation: none;
        opacity: 1;
        transform: translateX(2rem);
    }
}

.cta {
    background: var(--bpu-background-gray);
}

.cta-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 22rem);
    gap: 3rem;
    align-items: start;
}

.cta-facts dl {
    margin: 0;
    display: grid;
    gap: 0.25rem;
}

.cta-facts dt {
    font-weight: 600;
}

.cta-facts dd {
    margin: 0 0 1rem;
    color: var(--bpu-text-muted);
}

.cta-facts a {
    color: var(--bpu-text);
}

.cta-action {
    padding: 1.5rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
}

.cta-action p {
    margin: 0;
}

.cta-note {
    margin-top: 1rem !important;
    font-size: 0.875rem;
    color: var(--bpu-text-muted);
}

@media (max-width: 60rem) {
    .cta-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 2rem;
    }
}

/* The trend picture. Illustrative, not measured -- it shows which way the three numbers are supposed
   to move once the waiting stops being guesswork, and the legend names them so nobody mistakes it for
   a report. The lines draw themselves as the figure comes into view where the browser can bind an
   animation to scroll; otherwise they are simply there. */

.analytics-panel {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    gap: 1.75rem 2.5rem;
    margin-bottom: 2.5rem;
    padding: 1.5rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
}

.kpi-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
}

.kpi {
    display: grid;
    gap: 0.125rem;
    align-content: start;
    padding: 0.875rem 1rem;
    border: 1px solid var(--bpu-lines);
    border-radius: 0.5rem;
    background: var(--bpu-background-gray);
}

.kpi-label {
    font-size: 0.75rem;
    color: var(--bpu-text-muted);
}

.kpi-value {
    font-size: 1.625rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.15;
}

.kpi-unit {
    margin-left: 0.1875rem;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--bpu-text-muted);
}

.kpi-delta {
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--bpu-text-muted);
}

.kpi-good {
    color: #16A34A;
}

.analytics-note {
    grid-column: 1 / -1;
    margin: 0;
    font-size: 0.75rem;
    color: var(--bpu-text-muted);
}

.chart {
    display: grid;
    align-content: center;
    margin: 0;
}

.chart svg {
    display: block;
    width: 100%;
    height: 8.5rem;
}

.chart-grid line {
    stroke: var(--bpu-lines);
    stroke-width: 1;
}

.chart-line {
    fill: none;
    stroke-width: 2.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    pathLength: 1;
    stroke-dasharray: 1;
    stroke-dashoffset: 0;
}

.chart-line-money { stroke: #16A34A; }
.chart-line-wait { stroke: #F59E0B; }
.chart-line-smile { stroke: #38BDF8; }

/* Seven columns, and the seven points sit in their centres - that is why the polylines start at
   x=34 and not at x=8: a label under its own point, not next to it. */
.chart-days {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 0;
    margin: 0.5rem 0 0;
    padding: 0;
    list-style: none;
    font-size: 0.6875rem;
    color: var(--bpu-text-muted);
    text-align: center;
}

.chart-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 0.75rem;
    font-size: 0.75rem;
    color: var(--bpu-text-muted);
}

.chart-key {
    display: inline-flex;
    align-items: center;
    gap: 0.4375rem;
}

.chart-key::before {
    content: '';
    width: 0.75rem;
    height: 0.1875rem;
    border-radius: 999px;
}

.chart-key-money::before { background: #16A34A; }
.chart-key-wait::before { background: #F59E0B; }
.chart-key-smile::before { background: #38BDF8; }

@keyframes chart-draw {
    from { stroke-dashoffset: 1; }
    to { stroke-dashoffset: 0; }
}

@supports (animation-timeline: view()) {
    .chart-line {
        animation: chart-draw linear both;
        animation-timeline: view();
        animation-range: entry 20% cover 45%;
    }
}

@media (prefers-reduced-motion: reduce) {
    .chart-line {
        animation: none;
        stroke-dashoffset: 0;
    }
}

/* Audience cards. The one example board shows only what the product does today: numbers and their
   state. Counters and room numbers belong to the lane feature that does not exist yet, so they are
   not on this page. */

.audiences {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    align-items: start;
}

.audience {
    display: grid;
    gap: 0.75rem;
    align-content: start;
    padding: 1.5rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
}

.audience h3 {
    margin: 0;
}

.audience p {
    margin: 0;
    color: var(--bpu-text-muted);
    font-size: 0.9375rem;
}

.mini-board {
    display: grid;
    gap: 0.5rem;
    padding: 0.75rem;
    border-radius: 0.375rem;
    background: var(--bpu-background-gray);
}

.mini-brand {
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bpu-text-muted);
}

.mini-cols {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
}

.mini-cols > div {
    display: grid;
    gap: 0.25rem;
    align-content: start;
    padding: 0.5rem;
    border: 1px dashed var(--bpu-lines);
    border-radius: 0.25rem;
}

.mini-head {
    font-size: 0.5625rem;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--bpu-text-muted);
}

.mini-no {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

.mini-call {
    display: grid;
    gap: 0;
    line-height: 1.2;
}

.mini-dest {
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    color: var(--bpu-text-muted);
}

.mini-ref {
    font-size: 0.9375rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.mini-ready {
    color: #16A34A;
}

/* Prose pages */

.prose {
    max-width: 44rem;
    padding: 3.5rem 0 5rem;
}

.prose h1 {
    margin: 0 0 0.5rem;
    font-size: 2rem;
    letter-spacing: -0.02em;
}

.prose h2 {
    margin: 2.5rem 0 0.5rem;
    font-size: 1.25rem;
}

.prose p,
.prose li {
    color: var(--bpu-text);
}

.prose .lead {
    color: var(--bpu-text-muted);
    margin-top: 0;
}

.prose dl {
    margin: 0;
}

.prose dt {
    margin-top: 1rem;
    font-weight: 600;
}

.prose dd {
    margin: 0.125rem 0 0;
    color: var(--bpu-text-muted);
}

/* Placeholder — must be impossible to mistake for finished text */

.platzhalter {
    display: inline-block;
    padding: 0.0625rem 0.375rem;
    border: 1px dashed var(--bpu-warning-line);
    border-radius: 0.25rem;
    background: var(--bpu-warning-surface);
    color: var(--bpu-warning-text);
    font-size: 0.875rem;
    font-weight: 600;
}

.platzhalter-hinweis {
    padding: 1rem 1.25rem;
    margin: 0 0 2rem;
    border: 1px dashed var(--bpu-warning-line);
    border-radius: var(--bpu-radius);
    background: var(--bpu-warning-surface);
    color: var(--bpu-warning-text);
    font-size: 0.9375rem;
}

.platzhalter-hinweis strong {
    display: block;
    margin-bottom: 0.25rem;
}

/* Pricing */

.preise {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(12.5rem, 1fr));
}

.preis-karte {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    padding: 1.5rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
}

.preis-betrag {
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

.preis-karte ul {
    margin: 0;
    padding-left: 1.125rem;
    color: var(--bpu-text-muted);
    font-size: 0.9375rem;
}

/* The privacy notice: an announcement, not a gate.

   It says what does NOT happen here, so it may not behave like the banners it distinguishes itself
   from: nothing is blocked, nothing is dimmed, and putting it away is one button. The dismissal is
   remembered in local storage, which is disclosed on /datenschutz -- a notice about not storing
   things has no business storing something quietly. */

.privacy-banner {
    position: fixed;
    left: 1.5rem;
    bottom: 1.5rem;
    z-index: 20;
    display: grid;
    gap: 0.75rem;
    max-width: 24rem;
    padding: 1rem 1.125rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: var(--bpu-surface);
    box-shadow: 0 24px 48px -28px rgba(0, 0, 0, 0.6);
    font-size: 0.875rem;
    animation: banner-in 320ms ease-out;
}

.privacy-banner[hidden] {
    display: none;
}

.privacy-banner p {
    margin: 0;
    color: var(--bpu-text-muted);
}

.privacy-banner-close {
    justify-self: start;
    padding: 0.375rem 0.875rem;
    border: 1px solid var(--bpu-lines);
    border-radius: var(--bpu-radius);
    background: transparent;
    color: var(--bpu-text);
    font: inherit;
    font-size: 0.8125rem;
    cursor: pointer;
}

.privacy-banner-close:hover {
    background: var(--bpu-background-gray);
}

@keyframes banner-in {
    from { transform: translateY(0.75rem); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
}

@media (max-width: 40rem) {
    .privacy-banner {
        left: 1rem;
        right: 1rem;
        bottom: 1rem;
        max-width: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .privacy-banner {
        animation: none;
    }
}

/* Footer */

.site-footer {
    border-top: 1px solid var(--bpu-lines);
    background: var(--bpu-background-gray);
    padding: 2.5rem 0;
    color: var(--bpu-text-muted);
    font-size: 0.9375rem;
}

.site-footer .wrap {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1.5rem;
}


.footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
}

.site-footer a {
    color: var(--bpu-text-muted);
    text-decoration: none;
}

.site-footer a:hover {
    color: var(--bpu-text);
    text-decoration: underline;
}

@media (max-width: 40rem) {
    .site-nav {
        gap: 1rem;
        font-size: 0.875rem;
    }

    .site-nav .nav-hide-small {
        display: none;
    }

    .hero .wrap {
        padding-top: 3.5rem;
        padding-bottom: 3.5rem;
    }

    section {
        padding: 3rem 0;
    }
}

@media (max-width: 60rem) {
    .hero .wrap {
        grid-template-columns: minmax(0, 1fr);
        gap: 2.5rem;
    }
}

@keyframes signal-run-down {
    0% { transform: translateY(0); opacity: 0; }
    15% { opacity: 1; }
    85% { opacity: 1; }
    100% { transform: translateY(2.5rem); opacity: 0; }
}

@media (max-width: 60rem) {
    .analytics-panel {
        grid-template-columns: minmax(0, 1fr);
    }
}

@media (max-width: 30rem) {
    .kpi-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    /* The board on a phone. Three lanes stay three lanes - that IS the picture - but at 360px a lane
       is 87px wide, and "In Bearbeitung" needs 74 of the 67 that remain inside a ticket. It wrapped to
       two lines, the ticket grew to 79px, and the slots are 52px apart: every ticket sat on top of the
       next one. Smaller type and less padding buy the line back, and the slots get room to spare. */
    .board {
        --gap: 0.375rem;
        padding: 0.75rem;
    }

    .board-head {
        font-size: 0.5625rem;
        letter-spacing: 0.04em;
    }

    .board-lanes {
        min-height: 12.5rem;
    }

    .ticket {
        top: calc(0.5rem + var(--slot) * 3.75rem);
        padding: 0.375rem 0.5rem;
    }

    .ticket-no {
        font-size: 0.875rem;
    }

    .ticket-state {
        font-size: 0.625rem;
    }
}

.prose .table-scroll {
    overflow-x: auto;
    margin: 1rem 0 1.5rem;
    border: 1px solid var(--bpu-lines);
    border-radius: 0.5rem;
}

.prose table {
    width: 100%;
    min-width: 34rem;
    border-collapse: collapse;
    font-size: 0.9375rem;
}

.prose th,
.prose td {
    text-align: left;
    vertical-align: top;
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--bpu-lines);
}

.prose th {
    font-weight: 600;
    white-space: nowrap;
}

.prose tbody tr:last-child th,
.prose tbody tr:last-child td {
    border-bottom: 0;
}

a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 3px;
    border-radius: 2px;
}

.skip-link {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 100;
    padding: 0.75rem 1rem;
    background: var(--bpu-bg);
    color: var(--bpu-text);
    border: 1px solid var(--bpu-lines);
    border-radius: 0 0 0.5rem 0;
}

.skip-link:focus {
    left: 0;
}
