/* Schwarzweiss mit Grau als Hierarchiestufe. Harte Kanten, keine Rundungen. Mobile first. Drei Ebenen, konsequent durchgehalten: Flaeche weiss -> --fill (gruppiert) -> schwarz (das eine Wichtige) Text --ink -> --ink-2 (erlaeuternd) -> --ink-3 (Beiwerk) Linie 3px schwarz (traegt) -> 1px schwarz (gliedert) -> --rule (trennt) */ :root { color-scheme: light; --ink: #000; --ink-2: #4a4a4a; --ink-3: #8a8a8a; --bg: #fff; --fill: #f4f4f4; --page: #e4e4e4; --rule: #d4d4d4; --sans: -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif; --pad: 18px; } * { box-sizing: border-box; } html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); font-family: var(--sans); font-size: 15px; line-height: 1.45; -webkit-text-size-adjust: 100%; } body { overflow-x: hidden; overscroll-behavior-y: none; -webkit-tap-highlight-color: transparent; } /* Bedienelemente verhalten sich wie in einer App, nicht wie Fliesstext. */ .btn, .chip, .tab, .row, .badge, .pill, .action, .label, .topbar { -webkit-user-select: none; user-select: none; } button, input, textarea, select { font: inherit; color: inherit; border-radius: 0; -webkit-appearance: none; appearance: none; } a { color: inherit; } /* ------------------------------------------------------------------ Typografie */ .display { font-weight: 800; font-stretch: 85%; letter-spacing: -0.025em; text-transform: uppercase; line-height: 0.94; margin: 0; } .d-xl { font-size: 42px; } .d-lg { font-size: 30px; } .d-md { font-size: 19px; letter-spacing: -0.01em; } .label { font-size: 10px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; margin: 0; } .muted { color: var(--ink-2); } .hint { font-size: 12.5px; line-height: 1.5; color: var(--ink-3); } .mono-num { font-variant-numeric: tabular-nums; } /* ---------------------------------------------------------------------- Geruest */ .app { max-width: 560px; margin: 0 auto; min-height: 100vh; background: var(--bg); display: flex; flex-direction: column; } .topbar { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 12px; padding: 13px var(--pad); padding-top: calc(13px + env(safe-area-inset-top)); background: var(--bg); border-bottom: 3px solid var(--ink); } .mark { width: 32px; height: 32px; flex: 0 0 32px; background: var(--ink); display: grid; place-items: center; } .mark svg { width: 19px; height: 19px; } .wordmark { line-height: 1; } .wordmark .d-md { display: block; } .wordmark .label { color: var(--ink-3); margin-top: 4px; } .topbar .spacer { margin-left: auto; } main { flex: 1; display: flex; flex-direction: column; } .screen { flex: 1; padding: var(--pad) var(--pad) 30px; animation: rise 0.18s ease-out; } @keyframes rise { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } } .screen[hidden] { display: none; } .stack > * + * { margin-top: 12px; } .stack-tight > * + * { margin-top: 8px; } /* ---------------------------------------------------------------------- Bloecke */ /* Oberste Ebene: das eine Wichtige pro Ansicht. Nur einmal verwenden. */ .block-invert { background: var(--ink); color: var(--bg); padding: 20px 18px; } .block-invert .muted { color: #a9a9a9; } .block-invert .label { color: #a9a9a9; } /* Mittlere Ebene: gruppiert, tritt zurueck. */ .block { background: var(--fill); border: 1px solid var(--rule); padding: 16px; } /* Kopfband ueber einer Liste - ordnet zu, konkurriert aber nicht. */ .strip { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 11px 14px; background: var(--fill); border: 1px solid var(--ink); border-bottom: none; } .strip .label { color: var(--ink-2); } .section-label { display: flex; align-items: center; gap: 12px; margin: 34px 0 12px; } .section-label .label { color: var(--ink); } .section-label::after { content: ""; flex: 1; height: 1px; background: var(--rule); } .figures { display: flex; gap: 32px; margin-top: 20px; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, 0.28); } .figure { display: flex; flex-direction: column; } .figure .label { margin-bottom: 6px; } /* --------------------------------------------------------------------- Buttons */ .btn { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%; min-height: 54px; padding: 16px; background: var(--bg); border: 2px solid var(--ink); font-weight: 800; font-size: 14px; letter-spacing: 0.06em; text-transform: uppercase; text-decoration: none; cursor: pointer; text-align: left; } /* Die eine Sache, die man auf der Startseite tut. Grosse Flaeche statt Textzeile - auf dem Telefon zaehlt die Trefferflaeche, nicht die Kante. */ .action { display: flex; align-items: center; gap: 16px; padding: 22px 18px; background: var(--ink); color: var(--bg); cursor: pointer; } .action:active { background: #1f1f1f; } .action-icon { flex: 0 0 42px; color: var(--bg); } .action-icon svg { width: 42px; height: 42px; display: block; } .action-body { display: flex; flex-direction: column; gap: 7px; } .action-hint { font-size: 12.5px; line-height: 1.45; color: #a9a9a9; } /* Was man hier tun soll. */ .btn-primary { background: var(--ink); color: var(--bg); border-color: var(--ink); } /* Vorhanden, aber leise. */ .btn-quiet { border: 1px solid var(--rule); color: var(--ink-2); font-weight: 700; } .btn:disabled { opacity: 0.35; cursor: not-allowed; } .btn .arrow { font-weight: 400; font-size: 17px; } .btn-quiet .arrow { color: var(--ink-3); } /* --------------------------------------------------------------------- Formular */ .field { display: block; } .field .label { color: var(--ink-3); margin-bottom: 6px; } .field input, .field textarea { width: 100%; padding: 11px 12px; background: var(--bg); border: 1px solid var(--ink); } .field input:focus, .field textarea:focus { outline: 2px solid var(--ink); outline-offset: 1px; } .field textarea { min-height: 88px; resize: vertical; } /* iOS rendert Datumsfelder eigenwillig: der Wert sitzt zentriert, die Hoehe sackt ein, der Innenabstand kommt vom System. Das zieht sie auf die Form der uebrigen Felder. */ .field input[type="datetime-local"] { min-height: 46px; line-height: 1.2; text-align: left; font-variant-numeric: tabular-nums; } .field input[type="datetime-local"]::-webkit-date-and-time-value { text-align: left; margin: 0; min-height: 20px; } .field input[type="datetime-local"]::-webkit-calendar-picker-indicator { opacity: 0.5; filter: grayscale(1); } .search { display: flex; border: 2px solid var(--ink); } .search input { flex: 1; border: none; padding: 13px 14px; background: var(--bg); } .search input:focus { outline: none; } .search button { border: none; border-left: 1px solid var(--rule); background: var(--fill); color: var(--ink-2); padding: 0 16px; cursor: pointer; font-weight: 700; } .chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; } /* Ungewaehlt zurueckgenommen, damit die Auswahl ueberhaupt auffaellt. */ .chip { padding: 9px 12px; border: 1px solid var(--rule); background: var(--bg); color: var(--ink-3); font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; cursor: pointer; } .chip[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--bg); } /* --------------------------------------------------------------------- Listen */ .rows { border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); } .row { display: block; width: 100%; text-align: left; background: var(--bg); border: none; border-bottom: 1px solid var(--rule); padding: 14px; cursor: pointer; } .row:last-child { border-bottom: none; } .row-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; } .row-title { font-weight: 800; font-size: 17px; letter-spacing: -0.01em; } .row-sub { color: var(--ink-2); font-size: 13.5px; margin-top: 3px; } .row-meta { font-size: 10px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); white-space: nowrap; } .row-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; } .pill { display: inline-block; padding: 3px 7px; border: 1px solid var(--rule); background: var(--bg); color: var(--ink-3); font-size: 9px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; } .pill-solid { background: var(--ink); border-color: var(--ink); color: var(--bg); } .badge { display: inline-block; padding: 5px 9px; border: 1px solid var(--ink); background: var(--bg); color: var(--ink); font-size: 9px; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; text-decoration: none; cursor: pointer; } /* --------------------------------------------------------------------- Tabelle */ .data { width: 100%; border-collapse: collapse; border-top: 1px solid var(--ink); border-bottom: 1px solid var(--ink); } .data tr:nth-child(even) { background: var(--fill); } .data th, .data td { padding: 10px 12px; text-align: left; vertical-align: top; } .data th { width: 36%; font-weight: 600; font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); padding-top: 13px; } .data td { font-weight: 600; word-break: break-word; } /* ----------------------------------------------------------------------- Bilder */ .card-image { display: block; width: 100%; border: 1px solid var(--ink); background: var(--fill); } /* -------------------------------------------------------------------- Navigation */ .tabs { position: sticky; bottom: 0; z-index: 20; display: flex; background: var(--bg); border-top: 3px solid var(--ink); } .tab { position: relative; flex: 1; padding: 10px 4px calc(10px + env(safe-area-inset-bottom)); background: var(--bg); border: none; border-left: 1px solid var(--rule); color: var(--ink-3); font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; cursor: pointer; } .tab:first-child { border-left: none; } .tab[aria-selected="true"] { background: var(--ink); color: var(--bg); } .tab-icon { display: block; width: 24px; height: 24px; margin: 0 auto 4px; } .tab-icon svg { width: 24px; height: 24px; display: block; } .tab-label { display: block; } .tab-badge { position: absolute; top: 6px; right: 50%; transform: translateX(26px); min-width: 18px; padding: 1px 4px; background: var(--ink); color: var(--bg); border: 1px solid var(--bg); font-size: 10px; font-weight: 800; letter-spacing: 0; } .tab-badge[hidden] { display: none; } .tab[aria-selected="true"] .tab-badge { background: var(--bg); color: var(--ink); border-color: var(--ink); } /* ------------------------------------------------------------------- Zustaende */ .empty { border: 1px dashed var(--rule); background: var(--fill); padding: 30px 18px; text-align: center; } .empty .label { color: var(--ink-2); } .overlay { position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, 0.86); display: grid; place-items: center; padding: var(--pad); } .overlay[hidden] { display: none; } .overlay .block { background: var(--bg); border: 3px solid var(--ink); width: 100%; max-width: 380px; } .spinner { width: 26px; height: 26px; border: 3px solid var(--bg); border-top-color: transparent; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .toast { position: fixed; left: 50%; bottom: 96px; transform: translateX(-50%); z-index: 70; max-width: 90vw; padding: 12px 16px; background: var(--ink); color: var(--bg); font-size: 13px; font-weight: 600; } .toast[hidden] { display: none; } /* Nur am grossen Bildschirm ein Rahmen - auf dem Telefon fuellt die App den Schirm, wie eine App das tut. */ @media (min-width: 600px) { :root { --pad: 26px; } body { background: var(--page); } .app { border: 1px solid var(--ink); margin: 26px auto; min-height: calc(100vh - 52px); } .d-xl { font-size: 52px; } }