wutzcalc/client/src/styles.css
iris d2742751ba tablet: make pending-transaction cart list scrollable
.cart-items clipped overflow instead of scrolling, so once the cart
had more line items than fit in the 38vh cart panel the extra rows
were just invisible. overflow-y: auto lets it scroll while still
anchoring to the bottom (justify-content: flex-end) when short.

Closes #39.
2026-07-30 09:08:08 +02:00

308 lines
7.7 KiB
CSS

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
:root {
--bg: #111;
--fg: #eee;
--surface: #1a1a1a;
--surface-2: #2a2a2a;
--surface-3: #3a3a3a;
--border: #444;
--border-soft: #333;
--pfand: #9ab;
--danger: #ff8a8a;
}
:root[data-theme="light"] {
--bg: #f4f4f5;
--fg: #18181b;
--surface: #ffffff;
--surface-2: #e7e7ea;
--surface-3: #d8d8dc;
--border: #bcbcc2;
--border-soft: #dddde2;
--pfand: #4a6a8a;
--danger: #c0392b;
}
html, body, #app {
margin: 0;
padding: 0;
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg);
color: var(--fg);
font-weight: 600;
overscroll-behavior: none;
-webkit-user-select: none;
user-select: none;
}
button {
font: inherit;
font-weight: 700;
color: inherit;
background: var(--surface-2);
border: 1px solid var(--border);
border-radius: 8px;
padding: 12px 16px;
cursor: pointer;
}
button:active { background: var(--surface-3); }
button:disabled { opacity: 0.4; }
button.danger { background: #5a2a2a; border-color: #7a3a3a; color: #fff; }
/* ---------- Tablet UI (portrait) ---------- */
.tablet {
display: flex;
flex-direction: column;
height: 100%;
max-width: 100vw;
overflow: hidden;
}
.bar-picker {
display: flex;
flex-direction: column;
gap: 16px;
justify-content: center;
align-items: center;
height: 100%;
padding: 24px;
}
.bar-picker h1 { margin: 0 0 16px; }
.bar-picker button {
width: 280px;
height: 96px;
font-size: 30px;
}
.theme-toggle {
margin-top: 24px;
background: transparent;
border: 1px solid var(--border);
font-size: 18px;
padding: 10px 18px;
}
.topbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 16px;
background: var(--surface);
border-bottom: 1px solid var(--border-soft);
flex: 0 0 auto;
}
.topbar .brand { display: flex; align-items: center; gap: 10px; min-width: 0; overflow: hidden; }
.topbar .logo { flex: 0 0 auto; }
.topbar .bar-name { font-size: 26px; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar .change { font-size: 17px; padding: 10px 14px; }
/* Drink grid: 3 equal columns. Rows no longer assume a fixed count (the old
"exactly 5 rows fill the area" formula squeezed every row into 1/5 of the
height regardless of how many rows actually existed — 4 rows of drinks
looked cramped, with a wasted empty row's worth of space below them).
`minmax(min-content, 1fr)`: the floor is each row's own natural content
height (name + price + Pfand at whatever font-size is active — this
already tracks the smaller mobile font sizes below with no separate
number needed) rather than a guessed pixel value, and 1fr means rows are
equal height and stretch to fill any leftover space when there's room —
but never shrink below that content-derived floor. When there are enough
rows that even their natural height doesn't fit the visible area, the
grid holds every row at that floor and the whole thing scrolls
(overflow-y: auto) instead of cramming rows smaller — "otherwise go for
what fits". */
.grid {
--gap: 8px;
flex: 1 1 0;
min-height: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(min-content, 1fr);
align-content: start;
gap: var(--gap);
padding: var(--gap);
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
@media (max-width: 480px) {
.grid { grid-template-columns: repeat(2, 1fr); }
.topbar { padding: 8px 12px; }
.topbar .bar-name { font-size: 20px; }
.topbar .change { font-size: 15px; padding: 8px 10px; }
.drink { font-size: 17px; padding: 6px; }
.drink .price { font-size: 17px; }
.drink .pfand { font-size: 12px; }
.cart { flex: 0 0 34vh; padding: 6px 12px; }
.cart-line { font-size: 16px; }
.cart-total { font-size: 38px; padding: 2px 0 6px; }
.actions button { height: 52px; font-size: 18px; }
}
.drink {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 8px;
font-size: 22px;
overflow: hidden;
}
.drink .name { font-weight: 800; line-height: 1.25; max-width: 100%; word-break: break-word; overflow-wrap: break-word; }
.drink .price { font-size: 22px; font-weight: 700; margin-top: 8px; }
.drink .pfand { font-size: 15px; font-weight: 600; color: var(--pfand); margin-top: 4px; }
.drink.pfand-return {
background: #5a2a2a;
border-color: #7a3a3a;
color: #fff;
}
.picker-backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.55);
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
.picker {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 20px;
width: min(320px, 86vw);
display: flex;
flex-direction: column;
align-items: stretch;
gap: 14px;
}
.picker-title {
font-size: 22px;
font-weight: 800;
text-align: center;
}
.picker-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 8px;
}
.picker-count {
height: 64px;
font-size: 26px;
font-weight: 800;
}
.picker-cancel {
background: transparent;
border-color: var(--border-soft);
}
.cart {
flex: 0 0 38vh;
background: var(--surface);
border-top: 1px solid var(--border-soft);
padding: 8px 16px;
display: flex;
flex-direction: column;
min-height: 0;
}
.cart-items {
flex: 1 1 0;
min-height: 0;
overflow-y: auto;
margin-bottom: 6px;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.cart-line {
display: flex;
justify-content: space-between;
align-items: center;
padding: 3px 0;
font-size: 20px;
font-weight: 600;
}
.cart-line.pfand { color: var(--pfand); }
.cart-line.return { color: var(--danger); }
.cart-line.muted { opacity: 0.5; }
.cart-line-label {
display: flex;
align-items: center;
gap: 8px;
}
.qty-btn {
flex: 0 0 auto;
width: 28px;
height: 28px;
padding: 0;
line-height: 1;
font-size: 18px;
border-radius: 6px;
}
.cart-total {
font-size: 56px;
font-weight: 800;
text-align: right;
line-height: 1.1;
padding: 4px 0 8px;
}
.cart-total.negative { color: var(--danger); }
.actions {
display: flex;
gap: 8px;
}
.actions button {
flex: 1;
height: 64px;
font-size: 22px;
font-weight: 800;
color: #fff;
}
.actions .cancel { background: #5a2a2a; border-color: #7a3a3a; }
.actions .confirm { background: #2a5a2a; border-color: #3a7a3a; }
.actions .crew { background: #2a3a5a; border-color: #3a4a7a; }
/* ---------- Admin ---------- */
.admin {
max-width: 960px;
margin: 0 auto;
padding: 16px;
}
.admin h1, .admin h2 { margin-top: 24px; }
.admin table { width: 100%; border-collapse: collapse; margin-bottom: 16px; }
.admin th, .admin td { padding: 6px 8px; border-bottom: 1px solid var(--border-soft); text-align: left; }
.admin input, .admin select {
background: var(--surface); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; padding: 6px;
}
.admin .row { display: flex; gap: 8px; align-items: center; margin-bottom: 8px; flex-wrap: wrap; }
.admin .muted { opacity: 0.6; }
.admin .login { max-width: 320px; margin: 80px auto; display: flex; flex-direction: column; gap: 12px; }
.dnd-list { list-style: none; padding: 0; margin: 0 0 8px; }
.dnd-item {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 8px;
margin-bottom: 4px;
background: var(--surface);
border: 1px solid var(--border-soft);
border-radius: 6px;
cursor: grab;
}
.dnd-item:active { cursor: grabbing; }
.dnd-item.drop-target { border-color: #6aa; background: var(--surface-2); }
.dnd-item .grip { opacity: 0.4; cursor: grab; user-select: none; }
.dnd-item .dnd-name { flex: 1; }
.dnd-item button { padding: 2px 8px; font-size: 13px; }
.dnd-list li.muted { padding: 6px 8px; }