/* app.css — the app's one stylesheet (CI: design/DESIGN.md + design/styleguide.html, colors: tokens.css).
   Structure: structural tokens → base → auth → chrome (header/overlays/drawer/footer) →
   shared components → dashboard → calendar → notes → baby → entity manager/settings →
   system indicators. Every color runs through the tokens — no hex in component rules. */

/* Fonts — SELF-HOSTED (assets/fonts/), not a CDN: the service worker precaches them with the
   rest of the shell, so headings and body text look the same offline as online, and no
   third-party sees a request per page load. Both are VARIABLE files, so one file per subset
   covers 400–700 and `font-weight: 400 700` lets the browser interpolate any weight between.
   latin + latin-ext only (DE/EN plus accented names); the unicode-range split means the browser
   fetches latin-ext only when a glyph actually needs it.
   Updating: refetch from fonts.googleapis.com/css2, drop the woff2 in, bump the SW. */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/inter-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/inter-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'Newsreader';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/newsreader-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Newsreader';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/newsreader-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* structural tokens — layout/type constants; the color system lives in tokens.css */
:root {
    --font-family: 'Inter', system-ui, sans-serif;
    /* Display serif — ONLY the big module headings (see the rule at the end of this file).
       Nothing else in the app gets a second font. */
    --disp: 'Newsreader';
    --pad: 16px;                 /* screen-edge padding */
    --r-card: 16px;              /* cards */
    --r-ctl: 12px;               /* inputs, segmented controls */
    --r-pill: 99px;              /* pills, chips, round buttons */
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
    --transition-fast: 120ms ease;
    --transition-base: 200ms ease;
    --transition-sheet: 280ms cubic-bezier(.3, .9, .3, 1); /* surfaces that travel (sheet, drawer) */
    --button-click-scale: 0.9;
    /* --scrim / --scrim-strong / --scroll-shadow live in tokens.css (shared with the landing) */
    /* theme-independent constants — these paint OVER photos / the lightbox scrim, where the
       page theme must not change them (same family as --moon-glyph/--pdf-paper in tokens.css) */
    --photo-edge: rgba(0, 0, 0, 0.10);           /* hairline inset on photo thumbnails */
    --photo-text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55); /* text legibility on photos */
    --page-shadow: 0 1px 4px rgba(0, 0, 0, 0.25); /* paper page on the lightbox scrim */
    /* type scale, set for a phone held at arm's length (360–430px wide): nothing a person
       reads is under 12px, a row title is 15px. One-off sizes stay inline where they occur once. */
    /* whole pixels only: a half-pixel step cannot be seen, only maintained */
    --fs-label: 12px;            /* the smallest labels (axis hours, tiny captions) */
    --fs-cap: 12px;              /* captions, counts, meta lines */
    --fs-sub: 13px;              /* secondary lines, times */
    --fs-ui: 13px;               /* tabs, small buttons, widget titles */
    --fs-hint: 13px;             /* hints, subtitles, empty states */
    --fs-body: 15px;             /* row titles */
    --fs-md: 15px;               /* event titles, menu items, inputs — one size with the row title */
    --fs-head: 13px;             /* section and card heads — the quiet head voice (13/500) */
    /* the app's muted ink is a step darker than the shared --ink3, which the frozen landing keeps
       (3.6:1 on the card instead of 2.5:1; tokens.css --ink3-app, per theme). Readable text uses
       --ink2; this one is for glyphs, placeholders and what is disabled. */
    --ink3: var(--ink3-app);
    --w-inset: 20px;             /* a dashboard card's side inset: its head and every row, the greeting's 20px */
    /* navigation cluster fill — ‹ Heute › steppers and head pencils: a tonal ink wash,
       deliberately its own family (chrome/navigation), distinct from bordered action
       buttons and ink-filled primaries. Derived from --ink, so it rides both themes. */
    --nav-fill: color-mix(in srgb, var(--ink) 8%, transparent);
    /* the fill of a field and of a segmented track — the same derivation a step lighter, so it
       reads on the card and on the page in both themes (--card2 on the card was 1.05:1) */
    --field: color-mix(in srgb, var(--ink) 6%, transparent);
}
/* under 1000px (phones and small tablets) only the dashboard inset narrows: the type scale is
   the same on every screen — a row title is 15px, read at arm's length */
@media (max-width: 1000px) {
    :root {
        --w-inset: 16px;
    }
}

/* focus — pointer interaction stays outline-free; keyboard focus gets a visible ink ring.
   Text fields are excluded (they always match :focus-visible) — they carry their own
   border/background focus treatment. */
*:focus {
    outline: none;
}
:focus-visible {
    outline: none;
}
input:not([type="checkbox"]):not([type="radio"]):focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: none;
}

/* selection — ink on paper, inverted with the theme (same rule as the landing) */
::selection {
    background: var(--ink);
    color: var(--bg);
}

/* keyframes */
@keyframes fadeSlideUp {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes sheetUp { from { transform: translateY(100%); } to { transform: none; } }
@keyframes menuIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

@keyframes pendingPulse {
    50% { opacity: 0.3; }
}

/* hidden means hidden. The UA's [hidden] { display: none } has the lowest weight there is, so
   any display rule on an element (flex, grid, block) outranks it and the element shows although
   the code hid it — a shut value card stood open that way, and a dozen elements had grown a
   "[hidden] { display: none }" patch each. One rule, for every element, instead. */
[hidden] { display: none !important; }

/* body */
body {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    position: fixed;
    left: 0;
    top: 0;
    font-weight: 400;
    line-height: 1.35;
    font-family: var(--font-family);
    background: var(--bg);
    color: var(--ink);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* offline — a red hairline across the very top of the screen; it vanishes the moment
   the connection is back. Red stays reserved for overdue and THIS. */
#offline {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: var(--due);
    z-index: 999;
}
#offline span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
}

/* iOS install nudge (B3/P7) — a quiet card pinned above everything, only ever rendered
   in a non-installed iOS Safari tab; the × dismisses it for good on this device */
/* IN THE FLOW, not floating: #app is a flex column, so the hint as its first child pushes the
   header/main/footer down instead of covering them. Fixed positioning put an opaque card over
   the header — search, bell and ⋮ were unreachable until it was dismissed. */
#ios-install-hint,
#install-prompt {
    flex: none;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 8px 8px 0;
    padding: 10px 12px;
    background: var(--card);
    color: var(--ink);
    border: 1px solid var(--line2);
    border-radius: var(--r-ctl);
    box-shadow: var(--shadow);
    font-size: var(--fs-ui);
    line-height: 1.45;
}
#ios-install-hint > i,
#install-prompt > i { margin-top: 2px; color: var(--ink2); }
#ios-install-hint span { flex: 1; }

/* Chromium install banner: text above a real Install button (ink pill, theme-inverting) */
#install-prompt .install-body {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
}
/* THE INK PILL — the app's primary-action voice, declared ONCE for every CTA that wears it.
   It lives here, early, so each surface below can still add the one thing its own row needs
   (a wider form button, a bordered sheet button, an icon+label flex) without re-stating the
   look. The two ink-pill CHIPS (.sleepBtn, .fm-selchip) are deliberately NOT in here: they
   are a different scale, not this button. */
#install-prompt .install-go,
#app form .formSubmit button,
.action-btn.reusable,
.wx-empty-btn {
    border: 0;
    border-radius: var(--r-pill);
    background: var(--ink);
    color: var(--card);
    font-family: var(--font-family);
    font-size: var(--fs-body);
    font-weight: 500;
    padding: 10px 16px;
    cursor: pointer;
    transition: transform var(--transition-fast);
}
#install-prompt .install-go:active { transform: scale(var(--button-click-scale)); }
.ios-hint-x {
    border: 0;
    background: none;
    padding: 2px;
    color: var(--ink3);
    cursor: pointer;
    font-size: 13px;
    -webkit-tap-highlight-color: transparent;
}

/* app */
#app {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    background: var(--line);   /* a step below the cards, so they stand out from the ground */
    color: var(--ink);
    font-size: var(--fs-md);
}
/* in the dark the cards are the lighter plane already: the ground stays the darker --bg */
#app.dark { background: var(--bg); }

/* THE LOGIN CARD (login / signup / forgot / reset / join): one card in the middle of the page —
   the wordmark with its dot and the language and theme pills at its head, the fields with their
   labels above (44 on the field tone, no frame, no glyph), the ink button over the passkey's
   field-tone one (both 44, the card's width), the message under them, the links left and right */
#app.login main { flex-direction: column; justify-content: center; padding: 16px; box-sizing: border-box; }
#app .auth { width: 100%; max-width: 380px; box-sizing: border-box; background: var(--card); border-radius: var(--r-card); padding: 18px 16px 16px; }
#app .auth-hdr { display: flex; align-items: center; margin-bottom: 16px; }
#app .auth-tools { display: flex; align-items: center; gap: 4px; margin-left: auto; }
#app .auth-tools > button { height: 30px; min-width: 30px; box-sizing: border-box; padding: 0 10px; border: 0; border-radius: var(--r-pill); background: var(--field); color: var(--ink2); font-family: var(--font-family); font-size: var(--fs-cap); font-weight: 500; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .auth-tools > #darkmode-toggle { width: auto; padding: 0 10px; font-size: 14px; }
#app form .formGroup { display: block; width: 100%; margin-bottom: 14px; }
/* two fields side by side (the new household's name and address), each half the card */
#app form .formPair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; margin-bottom: 14px; }
#app form .formPair > .formGroup { margin-bottom: 0; }
#app form .formGroup > label { display: block; margin-bottom: 6px; font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); }
#app form .formGroup input {
    display: block;
    width: 100%;
    height: 44px;
    box-sizing: border-box;
    padding: 0 13px;
    border: 0;
    border-radius: var(--r-ctl);
    background: var(--field);
    font-family: var(--font-family);
    font-size: var(--fs-body);
    font-weight: 400;
    color: var(--ink);
}
#app form .formGroup input:focus { outline: none; box-shadow: 0 0 0 1px var(--ink2), 0 0 0 4px var(--nav-fill); }
#app form .formGroup input::placeholder { color: var(--ink2); }
/* the password's eye stands inside the field, at its right end */
#app form .fieldWrap { position: relative; }
#app form .fieldWrap > input { padding-right: 44px; }
#app form .formGroup .pwToggle {
    position: absolute;
    top: 0;
    right: 0;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--ink2);
    font-size: 17px;
    display: grid;
    place-items: center;
    cursor: pointer;
}
#app form .formSubmit { display: flex; flex-direction: column; gap: 10px; }
#app form .formSubmit button {
    width: 100%;
    height: 44px;
    padding: 0 16px;
    border-radius: var(--r-ctl);
    font-size: var(--fs-body);
    font-weight: 500;
}
#app form .formSubmit button:active { transform: scale(var(--button-click-scale)); }
/* the second way in: a passkey — the field-tone button under the ink one, its glyph first */
#app form .formSubmit .passkeyGo {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: var(--field);
    color: var(--ink);
}
#app form .formSubmit .passkeyGo i { font-size: 18px; }
#app form .formSubmit button:disabled {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
}

/* live password checklist (new-password forms): shared-policy rules flip per keystroke — a
   rule still open stands in --ink2 behind its open circle (--ink3), a met one in ink behind its
   check; before the first character every rule is open (.empty). No red: an unmet rule is a
   step still to take, not an error */
#app form .pwRules {
    list-style: none;
    margin: -6px 0 14px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
#app form .pwRules li {
    font-size: var(--fs-sub);
    line-height: 1.35;
    color: var(--ink2);
    display: flex;
    align-items: center;
    gap: 6px;
}
#app form .pwRules li > i { flex: none; font-size: 14px; color: var(--ink3); }
#app form .pwRules li > .fa-check,
#app form .pwRules:not(.empty) li:not(.fail) > .fa-circle { display: none; }
#app form .pwRules:not(.empty) li:not(.fail) { color: var(--ink); }
#app form .pwRules:not(.empty) li:not(.fail) > .fa-check { display: inline-flex; color: var(--ink); }

#app form .formMessage {
    font-size: var(--fs-sub);
    font-weight: 500;
    color: var(--due-ink);
    text-align: center;
    margin-top: 10px;
    animation: fadeSlideUp var(--transition-base) forwards;
}
#app form .formMessage:empty { display: none; }
/* a success (the link is on its way, the password is set) in ink */
#app form .formMessage.ok { color: var(--ink); }

/* what the card is for („Neuen Haushalt erstellen", „Neues Passwort setzen") and who invites:
   one quiet sentence each right under the wordmark, never a second heading */
#app form .authTitle,
#app form .authSubtitle {
    color: var(--ink2);
    font-size: var(--fs-sub);
    line-height: 1.35;
    margin: -10px 0 14px;
}
#app form .authTitle + .authSubtitle { margin-top: -10px; }
#app form .authLinks {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 8px 16px;
    margin-top: 14px;
}
#app form .authLinks a {
    color: var(--ink2);
    font-size: var(--fs-sub);
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
}
#app form .formMessage a {
    color: inherit;
    text-decoration: underline;
}

/* app main */
#app main {
    flex: auto;
    height: 100%;
    width: 100%;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* the form takes the card's width: a long message or link row wraps inside it */
#app main #login {
    display: flex;
    width: 100%;
    flex-direction: column;
}

/* app header */
#app header {
    display: flex;
    align-items: center;
    gap: 8px;
    box-sizing: border-box;
    padding: calc(var(--safe-top) + 6px) var(--pad) 6px; /* 56px: the field and the capsule are 44 */
    position: relative;
}
/* the scroll edge: a soft shadow under the head and over the footer once the page has moved
   (Render.updateScrollEdges sets .scrolled on both from the first pixel) */
#app header::after,
#app footer::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 10px;
    pointer-events: none;
    opacity: 0;
    transition: opacity var(--transition-fast);
    z-index: 2;
}
#app header::after { top: 100%; background: linear-gradient(to bottom, var(--scroll-shadow), transparent); }
#app footer::before { bottom: 100%; background: linear-gradient(to top, var(--scroll-shadow), transparent); }
#app header.scrolled::after,
#app footer.scrolled::before { opacity: 1; }

/* the wordmark at the login card's head — the serif word, the rosé person-dot raised after it */
#app .wm {
    line-height: 1;
    color: var(--ink);
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
#app .wm .wm-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--wm-dot); margin: 0 0 20px -6px; }

/* ── Boot preloader ────────────────────────────────────────────────────────────
   Static HTML in index.html so it paints on the FIRST frame, before the JS module
   loads. boot.js sets [data-theme] + html.is-offline beforehand, so it matches the
   theme and connectivity with no flash. Render.appReady() fades it out once everything
   is up — at boot that is when the LAST module has mounted, not when the empty shell has
   painted; Render.bootStep() names what is being loaded on the .pl-step line meanwhile.
   Above every popup layer (z 2000). */
#preloader {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 22px;
    background: var(--bg);
    padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
    opacity: 1;
    transition: opacity 0.32s ease;
}
html.app-ready #preloader { opacity: 0; pointer-events: none; }
#preloader .wm {
    font-weight: 600;
    font-size: 40px;
    letter-spacing: -0.03em;
    line-height: 1;
    color: var(--ink);
    display: inline-flex;
}
#preloader .wm .jj { position: relative; display: inline-block; }
#preloader .wm .jj i {
    position: absolute;
    font-style: normal;
    left: 50%;
    transform: translateX(-58%);
    top: -0.06em;
    width: 0.14em;
    height: 0.14em;
    border-radius: 50%;
    background: var(--wm-dot);
}
/* indeterminate three-dot loader — calm, understated */
/* What the boot is doing — one quiet line under the dots. It holds its height while empty
   so the mark and the dots do not jump when the first step arrives. */
#preloader .pl-step {
    min-height: 1.2em;
    margin-top: -12px;
    font-size: var(--fs-hint);
    color: var(--ink3);
    text-align: center;
    padding: 0 24px;
}
#preloader .pl-dots { display: flex; gap: 7px; }
#preloader .pl-dots span {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--ink3);
    animation: plPulse 1.1s ease-in-out infinite;
}
#preloader .pl-dots span:nth-child(2) { animation-delay: 0.16s; }
#preloader .pl-dots span:nth-child(3) { animation-delay: 0.32s; }
@keyframes plPulse {
    0%, 80%, 100% { opacity: 0.28; transform: scale(0.82); }
    40%           { opacity: 1;    transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    #preloader .pl-dots span { animation: none; opacity: 0.6; }
}
/* offline hint — swaps in for the dots while the browser reports no connection */
#preloader .pl-offline {
    display: none;
    align-items: center;
    gap: 7px;
    font-size: var(--fs-hint);
    font-weight: 600;
    color: var(--due-ink);
}
#preloader .pl-offline::before {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--due);
}
html.is-offline #preloader .pl-offline { display: inline-flex; }
html.is-offline #preloader .pl-dots { display: none; }

#app header #overdue-toggle,
#app header #pending-toggle {
    background: transparent;
    border: none;
    cursor: pointer;
    font-size: 22px;
    color: var(--ink);
    padding: 0;
    width: 36px;
    height: 36px;
    font-family: inherit;   /* the count discs inside inherit it; a button's own default is Arial */
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}

#app header #overdue-toggle:active {
    transform: scale(var(--button-click-scale));
}


/* The sync sign in the capsule — visible only while writes are queued: an amber dot (pending),
   the ↻ 15 and the number 12/500 in --ink2, inline, no disc */
#app header #pending-toggle { display: none; position: relative; width: auto; gap: 3px; padding: 0 6px 0 8px; font-size: 15px; color: var(--ink2); }
#app header #pending-toggle.show { display: flex; }
#app .pending-mark { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--pend); }
/* changes arriving from another device: the mark turns, without a number of its own */
#app header #pending-toggle.receiving i { animation: wx-spin 1.2s linear infinite; }
#app header #pending-toggle.receiving .pending-badge { display: none; }
@media (prefers-reduced-motion: reduce) {
    #app header #pending-toggle.receiving i { animation: pendingPulse 1.6s ease-in-out infinite; }
}
#app .pending-badge { font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); font-variant-numeric: tabular-nums; }
/* its popover, in the menu's idiom (280 wide, r14, no line), right under the head: the heading on
   --card2 with the count, an entry per queued change (glyph, what it is about, what happened),
   then behind a 7px gap in the ground the sentence about syncing and files */
.pending-pop {
    position: absolute;
    top: calc(var(--safe-top) + 56px);
    right: var(--pad);
    z-index: 900;
    width: 280px;
    max-width: calc(100vw - 16px);
    overflow: hidden;
    background: var(--card);
    border-radius: 14px;
    box-shadow: var(--shadow);
    animation: menuIn var(--transition-fast) forwards;
}
.pending-head {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 34px;
    padding: 0 16px;
    font-size: var(--fs-label);
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink2);
    background: var(--card2);
}
.pending-head > .n { margin-left: auto; letter-spacing: 0; font-variant-numeric: tabular-nums; }
.pending-row {
    display: flex;
    align-items: center;
    gap: 10px;
    min-height: 46px;
    padding: 0 14px 0 16px;
    border-top: 1px solid var(--line);
    font-size: var(--fs-body);
    font-weight: 500;
    color: var(--ink);
    white-space: nowrap;
}
.pending-row > i { flex: none; font-size: 17px; color: var(--ink2); }
.pending-row > b { font-weight: 500; overflow: hidden; text-overflow: ellipsis; }
.pending-row > small { font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); }
.pending-more > b { color: var(--ink2); }
.pending-note {
    position: relative;
    margin-top: 8px;
    padding: 10px 16px;
    border-top: 1px solid var(--line);
    font-size: var(--fs-sub);
    font-weight: 500;
    color: var(--ink2);
    line-height: 1.4;
}
.pending-note::before { content: ""; position: absolute; left: 0; right: 0; top: -9px; height: 7px; border-top: 1px solid var(--line); background: var(--line); }
#app.dark .pending-note::before { background: var(--bg); }

/* The bell's count disc — red is meaning: it counts OVERDUE items. */
#app header #overdue-toggle { position: relative; }
#app .overdue-badge {
    display: none;
    position: absolute;
    top: -1px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    box-sizing: border-box;
    padding: 0 4px;
    border-radius: var(--r-pill);
    background: var(--due);
    color: var(--badge-fg);
    font-size: 11px;
    font-weight: 700;
    line-height: 14px;
    letter-spacing: -0.01em;
    text-align: center;
    border: 2px solid var(--card);   /* the capsule's own tone: no halo, the count sits on the bell's shoulder */
    font-variant-numeric: tabular-nums;
}
#app .overdue-badge.show { display: block; }
/* „!" — a module could not be read: attention, not overdue */
#app .overdue-badge.is-bang { background: var(--pend-soft); color: var(--pend-ink); }
/* THE HEAD — two forms in one row (66px): left the FIELD of the page (.toolbar — the search,
   with the „Für" and view chips as words at its end), right the CAPSULE of the member (.me —
   the bell and the avatar in one pill, no line between them; the sync mark before them while
   anything waits). No title: the footer names the place, the page carries its own title in its
   head, and the module's menu hangs there (.hero-tools). OPEN (.is-open — a tap into the field
   or a word typed) the field takes the row: the capsule steps back, the chips keep the field's
   end, the ✕ that cancels stands at its right, the hits list under the header (.tb-panel, in
   flow) — the page itself answers below. No form here wears a line: the card tone alone. */
#app .toolbar { display: flex; align-items: center; gap: 5px; flex: 1 1 0; min-width: 0; height: 44px; box-sizing: border-box; padding: 0 5px 0 12px; border-radius: var(--r-pill); background: var(--card); color: var(--ink3); }
#app .toolbar > i { font-size: 18px; flex: none; }
#app .tb-input { flex: 1 1 0; width: 0; min-width: 0; border: 0; background: transparent; padding: 0; font-family: var(--font-family); font-size: var(--fs-md); color: var(--ink); }
#app .tb-input:focus { outline: none; }
#app .tb-input::placeholder { color: var(--ink2); font-size: 14px; }
#app .tb-input::-webkit-search-cancel-button { -webkit-appearance: none; }
#app .tb-clear { flex: none; width: 30px; height: 30px; border: 0; border-radius: 50%; background: transparent; color: var(--ink2); font-size: 13px; cursor: pointer; display: flex; align-items: center; justify-content: center; -webkit-tap-highlight-color: transparent; }
#app .tb-chips { display: flex; gap: 4px; flex: none; }
#app .tb-chips:empty { display: none; }
#app .tb-chip { height: 32px; padding: 0 7px 0 9px; border: 0; border-radius: var(--r-pill); background: var(--field); color: var(--ink); font-family: var(--font-family); font-size: var(--fs-sub); font-weight: 500; display: inline-flex; align-items: center; gap: 3px; white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .tb-chip .tb-chip-k { color: var(--ink2); font-weight: 500; margin-right: 2px; }
#app .tb-chip .tb-chip-chev { font-size: 12px; color: var(--ink3); margin-left: 1px; }
#app .tb-chip .tb-chip-word { max-width: 120px; overflow: hidden; text-overflow: ellipsis; }
#app .tb-chip.on { background: var(--ink); color: var(--card); }
#app .tb-chip.on .tb-chip-k, #app .tb-chip.on .tb-chip-chev { color: inherit; opacity: .75; }
/* the compact form (.min, only in the open field when the word needs the room): glyph + chevron */
#app .tb-chip > .tb-chip-ic { display: none; font-size: 15px; }
#app .tb-chip.min { padding: 0 6px 0 8px; }
#app .tb-chip.min > .tb-chip-ic { display: inline-flex; }
#app .tb-chip.min .tb-chip-k, #app .tb-chip.min .tb-chip-word { display: none; }
/* the view chip names what it switches („Ansicht: Datum") only where the row has the room */
#app .tb-chip.tb-view .tb-chip-k { display: none; }
/* the capsule: sync (when it has something to say), bell, avatar — one pill, no lines */
#app .me { flex: none; height: 44px; box-sizing: border-box; display: flex; align-items: center; gap: 2px; padding: 0 4px 0 2px; border-radius: var(--r-pill); background: var(--card); }
#app header.is-searching .me { display: none; }
/* the hits under the header: „Woanders n" as the section head over the card, in the card the
   groups as chips with their counts, then the rows — a bare glyph, the title with the typed part
   marked, the sub, whose it is */
#app .tb-panel { margin: 4px var(--pad) 0; display: flex; flex-direction: column; }
#app .tb-card { display: flex; flex-direction: column; padding: 10px 12px 0; background: var(--card); border-radius: var(--r-card); }
#app .tb-groups { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding-bottom: 10px; }
#app .tb-group { height: 28px; padding: 0 10px; border: 0; border-radius: var(--r-pill); background: var(--field); color: var(--ink); font-family: var(--font-family); font-size: var(--fs-sub); font-weight: 500; display: inline-flex; align-items: center; gap: 5px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .tb-group small { font-size: var(--fs-label); font-weight: 400; color: var(--ink2); font-variant-numeric: tabular-nums; }
#app .tb-group.on { background: var(--ink); color: var(--card); }
#app .tb-group.on small { color: inherit; opacity: .75; }
#app .tb-rows { display: flex; flex-direction: column; }
#app .tb-rows .search-result { align-items: center; gap: 10px; min-height: 44px; padding: 8px 2px; border-bottom: 0; border-top: 1px solid var(--line); }
#app .tb-rows .search-hit-ic { flex: none; font-size: 17px; color: var(--ink2); }
#app .tb-rows .search-result-text { min-height: 0; }
#app .tb-rows .search-result-title { font-size: 14px; font-weight: 500; line-height: 1.35; }
#app .tb-rows .search-result-sub { font-size: var(--fs-cap); line-height: 1.35; margin-top: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .tb-card .search-empty { padding: 4px 2px 14px; }
/* the typed part of a search, wherever it was found (Render.markMatches) */
#app mark { background: var(--nav-fill); color: inherit; border-radius: 3px; padding: 0 1px; }
@media (max-width: 639px) {
    /* a narrow field beside two chips: the chips keep their words, only the field's word yields */
    #app .tb-chip { padding: 0 6px 0 8px; }
    #app .tb-chip .tb-chip-word { max-width: 88px; }
}
@media (min-width: 640px) {
    #app .toolbar { flex: 0 1 560px; }
    #app header { gap: 12px; }
    #app .me { margin-left: auto; }
}

/* THE PAGE HEAD'S TOOLS — behind every page title (Module.heroTools): the module's menu as a
   small circle ˅, and the sign that only the viewer sees this page, in the viewer's colour */
#app .hero-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
#app .hero-row > :first-child { min-width: 0; }
#app .hero-tools { display: inline-flex; align-items: center; gap: 6px; flex: none; }
#app .hero-menu { width: 28px; height: 28px; border: 0; border-radius: 50%; background: var(--nav-fill); color: var(--ink2); font-size: 13px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform var(--transition-fast); }
#app .hero-menu:active { transform: scale(var(--button-click-scale)); }
#app main .private-mark { flex: none; width: 24px; height: 24px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--pc-soft, var(--card2)); color: var(--pc, var(--ink2)); font-size: 14px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* THE LEAN HERO — the head of a page without a hero of its own: the name in the serif, the
   tools behind it, the page's state as one quiet line (a tappable part in ink) */
#app .hero-lean { margin: 8px var(--pad) 10px; padding: 12px 13px; background: var(--card); border-radius: var(--r-card); }
#app .hero-lean > .hero-row { min-height: 32px; }
#app .hero-title { margin: 0; line-height: 1.1; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .hero-sub { margin-top: 4px; font-size: 13px; line-height: 1.4; color: var(--ink2); }
#app .hero-act { border: 0; padding: 0; background: transparent; color: var(--ink); font-family: var(--font-family); font-size: 13px; font-weight: 500; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .hero-act:active { opacity: .6; }

/* The bell's sheet „Offen": its title in the sheet voice, trimmed to the capital so it sits on the
   middle of the ✕ */
#app .notif-title { flex: 1; display: block; line-height: 1; text-box: trim-both cap alphabetic; min-width: 0; }

/* search / notifications overlay — card at the top, click-scrim behind */
#app .search-overlay {
    position: fixed;
    inset: 0;
    background: var(--scrim);
    z-index: 40;
    display: flex;
    justify-content: center;
    align-items: flex-start;
}

/* a sheet from the top: the whole width, starting under the status bar, only its lower corners
   round — no line, no shadow (a plane over the scrim) */
#app .search-panel {
    width: 100%;
    max-width: 560px;
    margin-top: var(--safe-top);
    box-sizing: border-box;
    background: var(--card);
    color: var(--ink);
    border: 0;
    border-radius: 0 0 22px 22px;
    box-shadow: none;
    display: flex;
    flex-direction: column;
    max-height: 86dvh;
    overflow: hidden;
}

#app .search-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 52px;
    box-sizing: border-box;
    padding: 4px 6px 4px 16px;
    border-bottom: 0;
}

#app .search-close {
    flex: none;
    width: 44px;
    height: 44px;
    padding: 0;
    background: transparent;
    border: none;
    color: var(--ink);
    cursor: pointer;
    font-size: 18px;
    display: grid;
    place-items: center;
    -webkit-tap-highlight-color: transparent;
}

/* the bell's list is one grid, its rows subgrids of it: the day column (as wide as the longest
   day, 50 at least, so every row's slot and text stand on one edge), the 30 slot, the text,
   whose it is; the fold foot and a line above the rows span them all */
#app .search-results {
    overflow-y: auto;
    padding: 0 16px 14px;
    display: grid;
    grid-template-columns: minmax(50px, max-content) 30px minmax(0, 1fr) auto;
    column-gap: 12px;
    align-content: start;
}
#app .search-results > * { grid-column: 1 / -1; }
/* the bell's rows: the day, the 30 slot (a to-do's tick, else the tile), the text (its title
   wraps), whose it is on the first line's axis — a hairline between two */
#app .search-results > .search-result { display: grid; grid-template-columns: subgrid; column-gap: 12px; align-items: start; padding: 8px 0; border-bottom: 0; border-top: 1px solid var(--line); }
#app .search-results > .search-result:first-of-type,
#app .search-results > .search-empty + .search-result { border-top: 0; }
#app .search-results .search-result-title { white-space: normal; overflow: visible; overflow-wrap: break-word; hyphens: auto; line-height: 1.35; }
#app .search-results .search-result-sub { line-height: 1.35; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .search-results > .search-result.done .search-result-title { color: var(--ink2); text-decoration: line-through; }
#app .search-results > .search-result > .who { justify-self: end; min-height: 30px; margin-left: 0; }
#app .bell-tick { flex: none; width: 22px; height: 22px; margin: 4px; box-sizing: border-box; border-radius: 50%; border: 1.5px solid var(--line2); display: grid; place-items: center; color: var(--card); font-size: 13px; cursor: pointer; }
#app .bell-tick > i { visibility: hidden; }
#app .bell-tick.on { background: var(--ink); border-color: var(--ink); }
#app .bell-tick.on > i { visibility: visible; }
/* the rest behind the fold foot under the list (Module.expandFoot) — the foot itself as on a
   card, no line over it */
#app .search-results:not(.open) > .search-result.w-xtra { display: none; }
#app .search-results > .w-foot i { color: var(--ink3); }
#app .search-results.open > .w-foot i { transform: rotate(180deg); }
#app .search-results.open > .w-foot .w-more { display: none; }
#app .search-results.open > .w-foot .w-less { display: inline; }

#app .search-result {
    display: flex;
    align-items: start;
    gap: 10px;
    width: 100%;
    box-sizing: border-box;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--line);
    color: inherit;
    text-align: left;
    font-family: var(--font-family);
    padding: 11px 14px;
    cursor: pointer;
}
#app .search-result:last-child { border-bottom: 0; }

#app .search-result:active {
    background: var(--card2);
}

#app .search-result-text {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

#app .search-result-title {
    font-size: var(--fs-body);
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#app .search-result-sub {
    font-size: var(--fs-sub);
    color: var(--ink2);
    margin-top: 1px;
}

#app .search-empty {
    padding: 14px;
    color: var(--ink2);
    font-size: var(--fs-ui);
    text-align: center;
}
/* in the bell: the line stands left over the rows — „Nichts offen." in --ink2, and a module the
   bell could not read, which this line names: the list is short — attention amber, not the red
   that means "you are late" */
#app .search-results > .search-empty { padding: 0 0 10px; text-align: left; line-height: 1.45; }
#app .search-empty.overdue-failed { color: var(--pend-ink); font-weight: 500; }


/* the bell's leading date column („gestern", „5. Okt", „heute", a clock) — its width is the
   list's first grid column; red only when late; one line sits on the middle of the 30 slot */
#app .search-result-when {
    max-width: 96px;
    min-height: 30px;
    display: flex;
    align-items: center;
    font-size: var(--fs-sub);
    font-weight: 500;
    color: var(--ink2);
    font-variant-numeric: tabular-nums;
    line-height: 1.35;
}
#app .search-result-when.late { color: var(--due-ink); }

/* NUR DU — steht IN der Pille des Modulnamens, hinter dem Namen: ein durchgestrichenes Auge in der FARBE DES BENUTZERS,
   dieselbe, die sein Avatar zwei Zentimeter links davon trägt (`applyOwnColor` setzt beiden den
   Slot `pc-N`). Die Seite gehört dem Menschen, den der Avatar zeigt — und in dieser App IST
   eine Person ihre Farbe; eine eigene Privat-Farbe wäre eine zweite Bedeutung zum Lernen
   gewesen. Ohne Slot (kein Mitglied, kein Snapshot) bleibt der neutrale Fallback.
   NUR das Zeichen: derselbe Satz daneben geschrieben nahm auf einem Telefon dem Modulnamen die
   letzten Buchstaben (gemessen: 380 px Kopf = 36 Avatar + 88 Name + 4 Aktionen; für „Nur du
   siehst diese Seite“ blieben 20 px). Der Satz steht daher EINEN TIPP dahinter
   (openPrivateSheet) — ein Tooltip wäre auf einem Touchgerät gar keine Antwort. In der Pille
   gehört es zum Namen: EIN Zeichen „hier bist du, und das sieht nur du“, kein zweites Ding in der
   Zeile; die Aktionen rechts halten ihre Kante über `margin-left: auto`. */

/* header avatar — the last thing in the row, opens the drawer */
#app header .profile {
    margin-left: 0;
    font-size: 13px;
    font-weight: 600;
    color: var(--pc-ink, var(--ink));
    width: 32px;
    height: 32px;
    box-sizing: border-box;
    background: var(--pc-soft, var(--card));
    /* the ring mirrors the member's person color (their auto slot without a chosen one) */
    box-shadow: inset 0 0 0 2px var(--pc, var(--line2));
    border-radius: 50%;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    flex-shrink: 0;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}

/* the photo fills the disc; the colour ring stays visible on top of it */
#app header .profile { position: relative; }
#app header .profile img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
#app header .profile::after { content: ""; position: absolute; inset: 0; border-radius: 50%; box-shadow: inset 0 0 0 2px var(--pc, var(--line2)); pointer-events: none; }
#app header .profile:active {
    transform: scale(var(--button-click-scale));
}


/* profile drawer */
#app .profile-overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0);
    z-index: 30;
    transition: background var(--transition-base);
}

#app .profile-overlay.open {
    background: var(--scrim);
}

#app .profile-drawer {
    position: fixed;
    top: 0;
    right: 0;
    height: 100dvh;
    width: 300px;
    max-width: 86vw;
    box-sizing: border-box;
    background: var(--card);
    color: var(--ink);
    display: flex;
    flex-direction: column;
    z-index: 31;
    padding: 0 18px;
    transform: translateX(102%);
    transition: transform var(--transition-sheet);
}

#app .profile-drawer.open {
    transform: translateX(0);
}

/* the head block: the badge 56, the name and the role, 52px under the top edge, no line under it */
#app .profile-drawer-user {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: calc(52px + var(--safe-top)) 0 14px;
}

#app .profile-drawer-avatar {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--pc-soft, var(--card2));
    box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--pc, var(--line2));
    box-sizing: border-box;
    color: var(--pc-ink, var(--ink2));
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    font-weight: 500;
    flex-shrink: 0;
    overflow: hidden;
}

#app .profile-drawer-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 50%;
}

#app .profile-drawer-info {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

#app .profile-drawer-username {
    font-weight: 500;
    font-size: 16px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#app .profile-drawer-role {
    font-size: var(--fs-sub);
    color: var(--ink2);
}

/* the access mark on its own line: "Gültig bis {date}" — its state class tints it (soon = pend,
   expired = due) */
#app .profile-drawer-access {
    display: flex;
    align-items: center;
    gap: 5px;
    flex: none;
    height: 24px;
    box-sizing: border-box;
    font-size: var(--fs-label);
    font-weight: 500;
    font-family: inherit;
    color: var(--ink2);
    background: var(--field);
    border: 0;
    padding: 0 9px;
    border-radius: 6px;
    margin: 0 0 8px;
    cursor: pointer;
}
#app .profile-drawer-access.access-soon { color: var(--pend-ink); background: var(--pend-soft); }
#app .profile-drawer-access.access-expired { color: var(--due-ink); background: var(--due-soft); }

#app .profile-drawer-menu {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 0;
    overflow-y: auto;
}

/* the rows: 46 high, a hairline at each, glyph 18 and the state word right */
#app .profile-drawer-menu button {
    display: flex;
    align-items: center;
    gap: 13px;
    width: 100%;
    min-height: 46px;
    padding: 0;
    background: transparent;
    border: 0;
    border-top: 1px solid var(--line);
    border-radius: 0;
    font-family: var(--font-family);
    font-size: var(--fs-md);
    font-weight: 500;
    color: var(--ink);
    cursor: pointer;
    text-align: left;
    transition: background var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}

#app .profile-drawer-menu button:hover,
#app .profile-drawer-menu button:active {
    background: var(--card2);
}

#app .profile-drawer-menu button i {
    color: var(--ink2);
    width: 18px;
    font-size: 18px;
    text-align: center;
    flex-shrink: 0;
}

/* the running version at the drawer's foot — the quietest line in it, for a report to name */
#app .profile-drawer-version {
    flex: none;
    padding: 14px 0 calc(18px + var(--safe-bottom, 0px));
    font-size: var(--fs-cap);
    color: var(--ink2);
}

/* logout — in the app's red ink */
#app .profile-drawer-menu button#drawer-logout-btn {
    color: var(--due-ink);
}
#app .profile-drawer-menu button#drawer-logout-btn i {
    color: var(--due-ink);
}

/* a row's state word at its end — the theme (Automatisch/Dunkel/Hell, updated on each cycle),
   how many members, how many trail lines */
#app .profile-drawer-menu .drawer-val {
    margin-left: auto;
    color: var(--ink2);
    font-size: var(--fs-sub);
    font-weight: 500;
    flex-shrink: 0;
}

/* app footer — the tab bar of an app: each tab its symbol with its NAME under it, the open one
   in an ink pill. At most five stand in the row; from six modules on the first four stay and
   the rest wait behind "Mehr" (Render.layoutNav) — so the row never scrolls and never needs a
   symbol to be guessed. */
#app footer {
    display: flex;
    /* Die Leiste gibt NIE Höhe ab. main ist height:100% + flex:auto, also war der Footer der
       einzige Schrumpfkandidat der Spalte — er verlor ein paar Pixel, und die gingen vom Label
       ab, bis dessen Zeile abgeschnitten war. Nicht schrumpfen, dann stimmt die Höhe. */
    flex: 0 0 auto;
    align-items: stretch;
    justify-content: space-around;
    background: var(--card);
    box-sizing: border-box;
    padding: 6px 4px calc(var(--safe-bottom) + 8px);
}

/* a tab: 66 wide, its pill 6 under the bar's top edge, the word 3 under the pill */
#app footer > div,
#app footer > .nav-more {
    display: flex;
    flex: 0 1 66px;
    min-width: 0;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    box-sizing: border-box;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: var(--ink2);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
/* a tab without a slot in the row — reached through "Mehr" */
#app footer > div.nav-over { display: none; }

#app footer > div i,
#app footer > .nav-more i {
    width: 52px;
    height: 30px;
    border-radius: var(--r-pill);
    font-size: 24px;
    line-height: 1;
    transition: transform var(--transition-fast), background var(--transition-fast);
}

#app footer > div:not(.active):active i,
#app footer > .nav-more:not(.active):active i {
    transform: scale(var(--button-click-scale));
}

#app footer > div span,
#app footer > .nav-more span {
    max-width: 100%;
    font-size: 11px;
    font-weight: 500;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

#app footer > div.active,
#app footer > .nav-more.active {
    color: var(--ink);
}
#app footer > div.active i,
#app footer > .nav-more.active i { background: var(--nav-fill); }
#app footer > div.active span,
#app footer > .nav-more.active span { font-weight: 600; }
/* while the bar counts what fits (navKeep), every name stands in the active word's weight, so the
   count is the same whichever tab is open */
#app footer.nav-measure > div span,
#app footer.nav-measure > .nav-more span { font-weight: 600; }

/* THE TILES (.tiles.three — the sheet behind "Mehr", the help's overview, Health's choosers): three
   columns, the whole tile a --field square r12 with its glyph over its word (12/500 --ink2), the
   open one in ink. The Mehr sheet's and Health's are roomier (glyph 22), the help's sit tighter
   over its text (glyph 18). */
.popup-body.nav-more-grid, .help-jump { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.popup-body.nav-more-grid { padding: 2px 16px 22px; }
.help-jump { padding: 0; }
.nav-more-tile, .help-jump-tile, #app .hl-tile { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0;
    border: 0; border-radius: var(--r-ctl); background: var(--field); font: inherit; font-size: var(--fs-cap);
    font-weight: 500; color: var(--ink2); cursor: pointer; transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent; }
.nav-more-tile, #app .hl-tile { padding: 14px 4px 10px; }
.help-jump-tile { padding: 8px 2px 6px; }
.nav-more-tile i, #app .hl-tile i { font-size: 22px; color: var(--ink); }
.help-jump-tile i { font-size: 18px; color: var(--ink); }
.nav-more-tile:active, .help-jump-tile:active, #app .hl-tile:active { transform: scale(var(--button-click-scale)); }
.nav-more-tile.active, .help-jump-tile.active { background: var(--ink); color: var(--card); }
.nav-more-tile.active i, .help-jump-tile.active i { color: var(--card); }
.nav-more-tile span, .help-jump-tile span, #app .hl-tile span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The ONE sortable list (Render.bindRowDrag): the Leiste's tabs, the planner's columns, the
   weather places — a lead (glyph or badge), the name, an optional × and the arrange grip at the
   end; a lifted row wears .drag-src, a swipe over a resting row scrolls */
.sort-list { display: flex; flex-direction: column; user-select: none; -webkit-user-select: none; }
.sort-row { display: flex; align-items: center; gap: 12px; padding: 10px 8px; margin: 0 -8px;
    border-top: 1px solid var(--line); font-size: var(--fs-body); color: var(--ink);
    touch-action: pan-y; cursor: grab; }
.sort-row:first-child { border-top: 0; }
.sort-row > i.fa-solid { font-size: 18px; color: var(--ink2); }
.sort-row .sort-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sort-row .w-grip { margin-left: auto; }
.sort-row .sort-name + .w-grip, .sort-row .sort-x + .w-grip { margin-left: 0; }
.sort-row .sort-x { flex: none; width: 32px; height: 32px; border: 0; background: transparent; color: var(--ink3);
    border-radius: var(--r-pill); font-size: 13px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.sort-row .sort-x:active { background: var(--nav-fill); }
.sort-row.drag-src { background: var(--nav-fill); border-radius: var(--r-ctl); box-shadow: var(--shadow); cursor: grabbing; position: relative; z-index: 2; }
.sort-row.drag-src + .sort-row { border-top-color: transparent; }
/* the planner's columns: ONE list — the grip left, the badge 30, the name, the tick flush at the
   row's end (ink while the person has a column); a tap on the row flips it, the grip drags. The
   rows (and their hairlines) keep to the sheet's 16 gutter, 48 high */
.sort-row.mp-col-row { cursor: pointer; margin: 0; padding: 4px 0; min-height: 48px; box-sizing: border-box; }
.mp-col-row > .w-grip { margin-left: 0; cursor: grab; touch-action: none; }
.mp-col-row > .m { width: 30px; height: 30px; font-size: 12px; }
.mp-col-row > .sort-name { font-weight: 500; }
.mp-col-row > .new-tick { margin: 0; }
.mp-col-row.on > .new-tick { background: var(--ink); border-color: var(--ink); color: var(--card); }
/* the Leiste's rows in the builder idiom: 42 high on --field, the grip LEFT, glyph, name, and
   the mini chip „Fußleiste" on the tabs that stand in the bar */
.sort-list.nav-order { gap: 6px; margin: 4px 0 10px; }
.sort-row.bl { gap: 6px; min-height: 42px; padding: 0 6px 0 4px; margin: 0; border: 0; border-radius: var(--r-ctl); background: var(--field); }
.sort-row.bl > .w-grip { margin: 0; width: 24px; display: grid; place-items: center; color: var(--ink3); }
.sort-row.bl > i.fa-solid { font-size: 18px; }
.bl-mini { flex: none; height: 20px; padding: 0 6px; border-radius: var(--r-pill); background: var(--nav-fill); font-size: 11px; font-weight: 500; color: var(--ink2); display: inline-flex; align-items: center; }
/* the greeting's weather mark as a dropdown of the places (several places): the pill itself */
.hero-mark.hero-mark-btn { cursor: pointer; }
/* an empty planner cell invites a new entry */
.cal-mp-cell { cursor: pointer; }

#app main > div[data-module] {
    display: none;
    width: 100%;
    height: 100%;
    overflow-y: auto;
    position: absolute;
    top: 0;
    left: 0;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    /* module panels are container-query roots: grids inside respond to the PANEL's
       width (the PWA runs embedded at arbitrary widths), not the viewport's */
    container-type: inline-size;
}

#app main > div[data-module].active {
    display: flex;
    flex-direction: column;
}

/* the module's menu (items from the active module's menuActions(), under its name) and the view
   chip's menu (.is-view, 210 wide) — no inner padding: a heading row, entries parted by hairlines */
.head-menu {
    position: absolute;
    top: calc(var(--safe-top) + 66px);
    left: var(--pad);
    z-index: 960;
    background: var(--card);
    border-radius: 14px;
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
    width: 270px;
    max-width: calc(100vw - 16px);
    animation: menuIn var(--transition-fast) forwards;
    /* Never taller than the viewport allows — long filter lists scroll inside the menu. */
    max-height: calc(100dvh - var(--safe-top) - 70px);
    overflow-y: auto;
    scrollbar-width: thin;
}
.head-menu.is-view { width: 210px; }
.menu-veil { position: fixed; inset: 0; z-index: 959; background: var(--scrim); opacity: .35; animation: fadeIn var(--transition-fast); }
/* the heading row: the module's name (or a section's) in the menu-head voice on --card2 */
.head-menu-heading {
    flex: none;
    min-height: 34px;
    box-sizing: border-box;
    padding: 0 16px;
    display: flex;
    align-items: center;
    font-size: var(--fs-label);
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink2);
    background: var(--card2);
}
.head-menu-item {
    flex: none;
    font-family: var(--font-family);
    font-size: var(--fs-md);
    font-weight: 500;
    color: var(--ink);
    background: transparent;
    border: 0;
    border-top: 1px solid var(--line);
    border-radius: 0;
    min-height: 46px;
    padding: 0 14px 0 16px;
    text-align: left;
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
    display: flex;
    align-items: center;
    gap: 10px;
}
.head-menu > .head-menu-item:first-child { border-top: 0; }
.head-menu-item:hover { background: var(--card2); }
/* „Hilfe" stands last, behind a 7px gap in the page's ground */
.head-menu-help:not(:first-child) { margin-top: 8px; position: relative; }
.head-menu-help:not(:first-child)::before { content: ""; position: absolute; left: 0; right: 0; top: -9px; height: 7px; border-top: 1px solid var(--line); background: var(--line); }
#app.dark .head-menu-help:not(:first-child)::before { background: var(--bg); }
/* subject filter entries lead with a 22px avatar circle: the photo when the subject has one,
   else the initial in the person color */
.head-menu-item .fava img { width: 100%; height: 100%; object-fit: cover; display: block; }
.head-menu-item .fava {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 11px;
    font-weight: 600;
    background: var(--pc-soft, var(--card2));
    color: var(--pc-ink, var(--ink2));
}

/* Derselbe Ring für die kleinen Kreise außerhalb der .m-Familie: die Auswahl im ⋮-Menü. */
#app .head-menu-item .fava {
    border: 0;
    box-shadow: inset 0 0 0 2px var(--pc, var(--line2));
}

/* an entry's glyph stands at its right end, 18px, after the count it concerns; a view option
   leads with its 17px glyph and ends in the ✓ of the current pick */
.head-menu-item .mic { font-size: 18px; color: var(--ink2); flex-shrink: 0; }
.head-menu-item .menu-lead { font-size: 17px; color: var(--ink2); flex-shrink: 0; }
.head-menu-item .n { color: var(--ink2); font-weight: 500; font-variant-numeric: tabular-nums; flex-shrink: 0; }
.head-menu-item .n + .mic { margin-left: -2px; }
.head-menu-item .menu-hint { color: var(--ink3); font-size: var(--fs-cap); font-weight: 400; }
.head-menu-item .menu-label { flex: 1; min-width: 0; white-space: normal; line-height: 1.25; text-align: left; }
.head-menu-item .menu-check { font-size: 18px; color: var(--ink2); flex-shrink: 0; }
.head-menu-item.active { color: var(--ink); }
/* the page head's circle ˅ while its menu stands: inked */
#app .hero-menu.open { background: var(--ink); color: var(--card); }

/* ============================== shared components ============================== */

/* borderless icon buttons (row pens, ×, stars …) */
.icon-btn {
    width: 34px;
    height: 34px;
    border: 0;
    background: transparent;
    color: var(--ink3);
    cursor: pointer;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    font-size: 15px;
    line-height: 1;
    transition: color var(--transition-fast), transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.icon-btn:hover { color: var(--ink); }
.icon-btn:active { transform: scale(var(--button-click-scale)); }
.icon-btn svg { width: 15px; height: 15px; }

/* action buttons — filled ink pill; cancel = ghost; delete = red text */
/* the ink pill in an ACTION ROW: it sits next to ghost/red siblings, so it carries a border of
   its own ink (that is what .cancel-btn recolours), never wraps, and keeps a hair of margin */
.action-btn.reusable {
    border: 0;
    white-space: nowrap;
    height: 36px;
    padding: 0 16px;
    box-sizing: border-box;
    margin: 2px;
    -webkit-tap-highlight-color: transparent;
}
.action-btn.reusable:active {
    transform: scale(var(--button-click-scale));
}
/* Settings → Anmeldung: one row per sign-in passkey — the glyph, where it was set up and when it
   was last used, × at the end */
.passkey-list { display: flex; flex-direction: column; }
.passkey-row { display: flex; align-items: center; gap: 12px; min-height: 48px; box-sizing: border-box; padding: 4px 0; border-top: 1px solid var(--line); }
.passkey-row:first-child { border-top: 0; }
.passkey-row > i { color: var(--ink2); font-size: 20px; }
.passkey-text { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.passkey-name { font-weight: 500; font-size: var(--fs-body); line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.passkey-when, .passkey-none { color: var(--ink2); font-size: var(--fs-hint); }
.passkey-none { margin: 4px 0; }
.passkey-x { flex: none; width: 32px; height: 32px; border: 0; border-radius: 50%; background: none; color: var(--ink); font-size: 15px; display: grid; place-items: center; cursor: pointer; }
/* an action that adds to the list above it, as a field row: „+ Passkey anlegen" */
#app .set-field-btn { display: flex; align-items: center; gap: 8px; width: 100%; height: 44px; box-sizing: border-box; margin: 6px 0 4px; padding: 0 13px; border: 0; border-radius: var(--r-ctl); background: var(--field); color: var(--ink2); font-family: var(--font-family); font-size: var(--fs-body); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .set-field-btn > i { font-size: 16px; }
.action-btn.reusable.cancel-btn {
    background: var(--field);
    color: var(--ink);
    font-weight: 500;
}
/* Destructive action — always red, in every context (sheet or centered modal). */
.action-btn.reusable.delete-btn {
    background: transparent;
    color: var(--due-ink);
    border-color: transparent;
}


/* tab pill rows (notes kinds, baby tabs, entity categories) — hairline pills, active = ink */
.seg-tabs {
    display: flex;
    gap: 6px;
    padding: 2px;
    margin: 12px var(--pad) 0;
    flex: none;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.seg-tabs::-webkit-scrollbar { display: none; }
.seg-tab {
    flex: none;
    /* No outline: the FILLED pill carries the active state, and a box around every word made a
       row of five of them read as five boxes. Kept as a transparent border so the active pill's
       own border-color still paints and nothing shifts by a pixel when it turns on. */
    border: 1px solid transparent;
    background: var(--card);
    font-family: var(--font-family);
    cursor: pointer;
    color: var(--ink2);
    font-size: var(--fs-ui);
    font-weight: 500;
    padding: 7px 13px;
    min-height: 38px;   /* a thumb target, whatever the label's height */
    border-radius: var(--r-pill);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    white-space: nowrap;
    transition: background var(--transition-base), color var(--transition-base);
    -webkit-tap-highlight-color: transparent;
}
.seg-tab .seg-count {
    font-size: 11px;
    font-weight: 500;
    color: var(--ink2);
    font-variant-numeric: tabular-nums;
    transition: color var(--transition-base), opacity var(--transition-base);
}
.seg-tab.active {
    background: var(--ink);
    color: var(--card);
    border-color: var(--ink);
}
.seg-tab.active .seg-count {
    color: var(--card);
    opacity: 0.65;
}

/* segmented variant (notes kinds, baby views) — one shared track like the calendar
   view switcher; more tabs than fit scroll horizontally inside the track */
/* every segmented track: 44px, 38px segments inside, the field fill (the fill groups the strip;
   an outline on top of it drew a box around a box — the FILLED pill is the state) */
.seg-tabs.seg-track {
    gap: 2px;
    background: var(--field);
    border-radius: var(--r-ctl);
    padding: 3px;
    height: 36px;
    box-sizing: border-box;
}
.seg-tabs.seg-track .seg-tab {
    flex: 1 0 auto;
    border: 0;
    background: transparent;
    border-radius: 9px;
    padding: 0 8px;
    /* the track IS the target: the pill fills it (38px in the 44px strip, 34px in a hero's 40px
       one) — a 38px floor in a 40px hero strip hung it 4px low, more air above than below */
    min-height: 0;
}
.seg-tabs.seg-track .seg-tab.active { background: var(--ink); color: var(--card); }

/* overflow folding (Render.segOverflow) — the strip only shows the tabs that fit; folded
   ones live in the chevron chip's dropdown */
.seg-tabs .seg-hidden,
.cal-views .seg-hidden { display: none; }
.seg-tabs.seg-track .seg-more,
.cal-views .seg-more {
    flex: 0 0 auto;
    padding: 0 9px;
    color: var(--ink2);
}
.cal-views .seg-more {
    border: 0;
    background: transparent;
    border-radius: 9px;
}
.seg-tabs.seg-track .seg-more i,
.cal-views .seg-more i { font-size: 11px; }
.seg-more-menu { min-width: 150px; }
.seg-more-menu .mg-select-opt {
    display: flex;
    align-items: center;
    gap: 10px;
}
.seg-more-menu .seg-count {
    margin-left: auto;
    font-size: 11px;
    font-weight: 600;
    color: var(--ink3);
    font-variant-numeric: tabular-nums;
}

/* segmented variant (Settings You|Group) — one inset track, buttons share it */
#app .settings-tabs {
    background: var(--field);
    border-radius: var(--r-ctl);
    padding: 3px;
    gap: 2px;
    margin: 2px 16px 12px;
    height: 36px;
    box-sizing: border-box;
}
#app .settings-tabs .seg-tab {
    flex: 1;
    border: 0;
    background: transparent;
    border-radius: 9px;
    padding: 0;
    min-height: 0;   /* the pill fills the 36 track (30 inside its padding), never overhangs it */
    font-size: var(--fs-ui);
    font-weight: 500;
}
#app .settings-tabs .seg-tab.active {
    background: var(--ink);
    color: var(--bg);
}

/* segmented visibility toggle (Everyone / Only me) */
.seg-toggle {
    display: flex;
    gap: 2px;
    background: var(--field);
    padding: 3px;
    border-radius: var(--r-ctl);
    height: 40px;
    box-sizing: border-box;
}
.seg-toggle button {
    flex: 1;
    border: 0;
    background: transparent;
    font-family: var(--font-family);
    cursor: pointer;
    color: var(--ink2);
    font-size: var(--fs-ui);
    font-weight: 600;
    padding: 0 4px;
    border-radius: 9px;
    display: flex;
    gap: 6px;
    align-items: center;
    justify-content: center;
    transition: background var(--transition-base), color var(--transition-base);
}
.seg-toggle button svg { width: 13px; height: 13px; }
.seg-toggle button.active {
    background: var(--ink);
    color: var(--bg);
}
.seg-toggle button:disabled { opacity: 0.55; cursor: default; }
.seg-hint {
    color: var(--ink2);
    font-size: var(--fs-label);
    margin: 7px 2px 0;
}

/* visibility as a text line (form law G3): "Sichtbar für alle · Ändern" — the segmented
   control only appears behind the Ändern tap */
.vis-line {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--fs-body);
    color: var(--ink2);
}
.vis-line > span:nth-child(2) { color: var(--ink3); }
.vis-change {
    border: 0;
    background: none;
    padding: 0;
    font-family: inherit;
    font-size: var(--fs-body);
    font-weight: 600;
    color: var(--ink);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* zone line (form law G3): "🕐 Zeit gilt in: Wien", 13 in --ink2 with the city in ink — a tap on
   the city opens the picker; it hangs 6 under the times; the entered start's viewer-clock
   equivalent sits beneath it as a quiet hint when the zone is not the viewer's */
.popup-body .form-row:has(> .zone-line) { margin: -8px 0 12px; }
.vis-line.zone-line { flex-wrap: wrap; gap: 4px; font-size: var(--fs-sub); line-height: 1.45; }
.vis-line.zone-line > i { font-size: 13px; }
/* .vis-line > span:nth-child(2) (0,2,1) would otherwise mute the words to --ink3 */
.vis-line.zone-line .zone-cap { color: var(--ink2); }
.vis-line.zone-line .zone-val { font-size: var(--fs-sub); font-weight: 500; color: var(--ink); }
.vis-line.zone-line .zone-val:disabled { cursor: default; }
.zone-hint {
    margin-top: 3px;
    font-size: var(--fs-cap);
    color: var(--ink2);
}
.zone-hint:empty { display: none; }
.zone-select { margin-top: 4px; }

/* "Für" as tappable avatar chips (form law G3) — active picks wear the ink ring,
   matching the msTile.on selection language */
.fuer-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.fuer-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 32px;
    box-sizing: border-box;
    padding: 0 11px 0 5px;
    background: var(--field);
    border: 0;
    border-radius: var(--r-pill);
    font-family: inherit;
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--ink2);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.fuer-chip.on {
    background: var(--ink);
    color: var(--card);
}
/* the avatar badge inside a chip — every .m rule elsewhere is context-scoped, so the
   chip needs its own (the .fm-chiplink .m twin) */
.fuer-chip .m {
    width: 22px;
    height: 22px;
    font-size: 11px;
}
.fuer-chip .m.m-glyph i { font-size: 11px; }
/* on the chosen chip's ink the card ring around the badge is a finer 1.5 */
.fuer-chip.on .m { box-shadow: inset 0 0 0 2px var(--pc, var(--line2)), 0 0 0 1.5px var(--card); }
/* rotation order on selected chips (chore context): tap order is the stored order —
   the number makes it visible */
.fuer-ord {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--ink);
    color: var(--bg);
    font-size: 9px;
    font-weight: 700;
    display: none;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}
.fuer-chips.ordered .fuer-chip.on .fuer-ord { display: flex; }
/* the „Für" of a big household (Module.subjectPicks — an event's, a running cost's): the chosen as
   filled chips, the select behind them
   as the add chip — 32 high on --field, + and „Hinzufügen" 13/500 in --ink2. Its button takes the
   rest of the line, bare, so the list it opens is as wide as that; the chip stands inside it */
.cal-fuer-picks > .mg-select { flex: 1 1 120px; min-width: 0; }
#app .cal-fuer-picks .mg-select-btn { height: 32px; padding: 0; border: 0; background: none; box-shadow: none; justify-content: flex-start; }
.cal-fuer-add { display: inline-flex; align-items: center; gap: 6px; height: 32px; min-width: 0; padding: 0 11px;
    border-radius: var(--r-pill); background: var(--field); font-size: var(--fs-ui); font-weight: 500; color: var(--ink2); }
.cal-fuer-add > i { flex: none; font-size: 13px; }
.cal-fuer-picks .mg-select-chev { display: none; }
/* in a half column (a field pair) the add chip beside a chosen chip is the + alone, so the Für
   stays one line; its name stays on the button for assistive tech */
.form-pair .cal-fuer-picks:has(> .fuer-chip) > .mg-select { flex: 0 0 32px; }
.form-pair .cal-fuer-picks:has(> .fuer-chip) .cal-fuer-add { width: 32px; padding: 0; justify-content: center; }
.form-pair .cal-fuer-picks:has(> .fuer-chip) .cal-fuer-add > .mg-select-label { display: none; }

/* form pairs (form law G2): two labelled fields share one line — minmax(0,…) tracks,
   or a long native date/select control forces horizontal overflow */
.form-pair {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px;
    margin-bottom: 14px;
}
/* bottom-align the cells: a wrapping label (narrow column) must not push its input
   out of line with its neighbour's. .popup-body prefix: outranks the later
   `.popup-body .form-row { margin-bottom }` rule regardless of file order */
.popup-body .form-pair > .form-row {
    margin-bottom: 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}
/* a pair whose field carries a projection hint under it (the event's Erinnerung) aligns at the
   top instead: bottom-aligned, the hint's lines pushed the neighbour's field down */
.popup-body .form-pair:has(.proj-hint) > .form-row { justify-content: flex-start; }
/* two chip rows side by side (Zahler · Für) line up at their labels: their heights differ */
.popup-body .form-pair.fin-pair-top > .form-row { justify-content: flex-start; }
.form-pair.form-pair-qty { grid-template-columns: 88px minmax(0, 1fr); }
/* three short fields on one line — the recipe's Personen · Dauer · Schwierigkeit — 8 apart */
.form-pair.form-pair-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
/* a date or time said the way the app says a day („Sa 17. Okt" ˅, „18:30"; notes _dayFace): the
   face and the native input share the field's cell — the input unseen on top of it, so a tap opens
   its picker — the label above, a projection hint below. The .popup-body prefix outranks the
   pair's flex column. */
.popup-body .form-row.day-faced { display: grid; grid-template-columns: minmax(0, 1fr); }
/* in a pair it sits at the bottom like its neighbour's field: a two-line label beside it must
   not stretch the face */
.popup-body .form-pair:not(:has(.proj-hint)) > .form-row.day-faced { align-content: end; }
.form-row.day-faced > label { grid-row: 1; }
.form-row.day-faced > input, .form-row.day-faced > .date-wrap, .form-row.day-faced > .day-face { grid-row: 2; grid-column: 1; }
.form-row.day-faced > .proj-hint { grid-row: 3; }
.form-row.day-faced input { position: relative; opacity: 0; cursor: pointer; }
.form-row.day-faced input::-webkit-calendar-picker-indicator { position: absolute; inset: 0; width: auto; height: auto; margin: 0; padding: 0; cursor: pointer; }
.day-face { display: flex; align-items: center; gap: 8px; min-width: 0; min-height: 44px; box-sizing: border-box; padding: 0 13px;
    background: var(--field); border-radius: var(--r-ctl); font-size: var(--fs-md); color: var(--ink); white-space: nowrap;
    font-variant-numeric: tabular-nums; pointer-events: none; }
.day-face.is-empty { color: var(--ink2); }
/* a third of a line holds „Mi 25. März" whole: the face pads 10 there */
.form-pair-3 .day-face { padding: 0 10px; }
.day-face-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.day-face-chev { flex: none; margin-left: auto; font-size: 11px; color: var(--ink3); }
/* a set date's ✕ (dateClearButtons) stands where the chevron stood; a fixed day has no ✕ */
.form-row.day-faced:not(.day-fixed):has(.date-clear:not([hidden])) .day-face-chev { visibility: hidden; }
.form-row.day-fixed .date-clear { display: none; }
/* the field's focus frame (.popup-body input:focus) drawn on the face while its unseen input has
   focus; a typed key (.day-typing, notes _dayFace) shows the input itself until it is left */
.popup-body .form-row.day-faced:has(input:focus) > .day-face { box-shadow: 0 0 0 1px var(--ink2), 0 0 0 4px var(--nav-fill); }
.form-row.day-faced.day-typing input { opacity: 1; }
.form-row.day-faced.day-typing input::-webkit-calendar-picker-indicator { opacity: 0; }
.form-row.day-faced.day-typing > .day-face { visibility: hidden; }

/* the attachments are a section of their own, under their own label — not glued to the field
   above them */
.kuer-body > .ent-files { margin-top: 18px; }

/* the sheet head's switches, left of the ✕: who sees it („Alle | Nur ich“) and, on a note, the
   ★ — the chosen side and a pinned star in ink */
.popup-head-ctl {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
/* beside the switches the title may take two lines rather than lose its end — the ✕ box is
   that tall anyway */
.popup-header:has(> .popup-head-ctl) > span {
    white-space: normal;
    text-wrap: balance;
    line-height: 1.1;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
/* who sees it — „Haushalt | Nur ich" as a rail of two words in the sheet's body, the chosen
   one in ink */
.vis-switch {
    display: flex;
    gap: 2px;
    height: 36px;
    box-sizing: border-box;
    padding: 3px;
    border-radius: var(--r-ctl);
    background: var(--field);
}
.vis-switch button {
    flex: 1 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 8px;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: var(--ink2);
    font-family: var(--font-family);
    font-size: var(--fs-ui);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.vis-switch button.active { background: var(--ink); color: var(--card); }
/* the rail's field goes with the rail when a form hides it */
.vis-row:has(> .cal-hidden) { display: none; }
/* an Alle | Nur ich choice names only the side that is chosen — the other stands as its icon */
.seg-toggle button:not(.active) .seg-word { display: none; }
/* the thumbtack in the sheet's head that pins the row: a 36 disc, ink while pinned */
.pin-switch {
    width: 36px;
    height: 36px;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: 50%;
    background: var(--nav-fill);
    color: var(--ink);
    font-size: 17px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.pin-switch.on { background: var(--ink); color: var(--card); }
.vis-locked {
    font-size: var(--fs-cap);
    font-weight: 600;
    color: var(--ink2);
}
/* „Nur ich“ says itself once more where the form begins */
.vis-note {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 12px;
    font-size: var(--fs-cap);
    color: var(--ink2);
}

/* the editor's LINES: a todo/shopping note's own checkable entries and a recipe's ingredients —
   one pill per line (a to-do line: the grip, the tick, the text, its day and badges, the ⋮; an
   ingredient: the grip, the line „500 g Spaghetti", the ⋮). */
.items-rows { display: flex; flex-direction: column; gap: 6px; }
/* a row whose text ticks its box on tap, and the › that is its one visible way into the editor */
.tick { cursor: pointer; }
.item-line { display: flex; flex-direction: column; gap: 4px; }
/* a line's own day and "Für" inside its pill: a small day chip — its date field laid over it,
   out of sight — and the badges */
.item-line .item-tags { display: inline-flex; align-items: center; gap: 4px; flex: none; }
.item-mini { position: relative; display: inline-flex; align-items: center; gap: 3px; height: 20px; padding: 0 6px;
    border-radius: var(--r-pill); background: var(--nav-fill); color: var(--ink2); font-size: 11px; font-weight: 500;
    white-space: nowrap; font-variant-numeric: tabular-nums; }
.item-mini > i { font-size: 11px; }
.item-mini > .date-wrap { position: absolute; inset: 0; }
#app .popup-body .item-mini input.item-due, .item-mini input.item-due { position: absolute; inset: 0; width: 100%; height: 100%;
    margin: 0; padding: 0; border: 0; opacity: 0; cursor: pointer; }
.item-mini .date-clear { display: none; }
.item-who .m { width: 22px; height: 22px; font-size: 11px; }
/* a line without a day of its own keeps its date field in the pill, only out of sight */
.item-line .item-tags.no-due .item-mini { display: none; }
/* in the feed the line's own day stands UNDER its text, in the meta voice */
.nc-line .nc-line-sub { display: flex; align-items: center; gap: 8px; margin-top: 1px; font-size: var(--fs-sub); }
.nc-line .nc-line-sub .notes-by { font-size: var(--fs-sub); margin-top: 0; }
/* two class parts on purpose: the popup's generic `input` rule (width:100% + a text field's
   padding, border and border-radius) outranks the bare .notes-check inside a sheet — a 100%-wide
   checkbox eats the line, and the leaked padding/radius warped the box (oval, off-centre tick).
   Reset all of it so the editor tick matches the feed; .mg-round keeps a shopping line round. */
.item-line .notes-check { flex: none; width: 22px; height: 22px; padding: 0; margin: 0; border: 1.5px solid var(--line2); border-radius: 50%; background: var(--card); }
.item-line .notes-check:checked { border-color: var(--ink); }
.item-line .notes-check.mg-round { border-radius: 50%; }
.item-line .item-qty { width: 88px; flex: none; min-width: 0; }
.item-line .item-text { flex: 1 1 auto; min-width: 0; }
.item-line .notes-linkx { flex: none; height: 32px; }
/* the line's ONE field: the grip at its start, amount and text in a single pill, the ⋮ at its end.
   The pill draws the field and its focus; the inputs inside are bare, a shopping amount set off by
   a short hairline. */
.item-field { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 6px; min-height: 42px; padding: 0 6px 0 4px;
    background: var(--field); border: 1px solid transparent; border-radius: var(--r-ctl); box-sizing: border-box; }
.item-field:focus-within { border-color: var(--ink2); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ink) 8%, transparent); }
.popup-body .item-field input:not([type="checkbox"]):not([type="radio"]):not(.prep-title) {
    height: 40px; background-color: transparent; border: 0; box-shadow: none; }
/* the tick (an ingredient: the grip) leads the amount and the text, the pill's 6 apart */
.popup-body .items-rows .item-field input.item-text,
.popup-body .items-rows .item-field input.item-qty { padding-left: 0; }
.popup-body .items-rows .item-field input.item-qty { width: 60px; padding-right: 8px; }
.item-line .item-field .item-qty { width: 84px; padding-left: 12px; padding-right: 8px;
    background-image: linear-gradient(var(--line2), var(--line2)); background-size: 1px 20px;
    background-position: right center; background-repeat: no-repeat; }
/* the grip: the line is lifted by it (a press into the text stays typing). It looks 24 px wide but
   takes a finger: its ::after reaches 12 px out to the left (the pill's padding and the edge before
   it) and 2 px toward the tick, so a press at the line's start lands on the grip — at 24 px beside
   the tick a phone's press missed it and the line never lifted. */
.item-grip { position: relative; flex: none; width: 24px; height: 40px; align-items: center; justify-content: center; touch-action: none; color: var(--ink3);
    -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.item-grip::after { content: ""; position: absolute; top: 0; bottom: 0; left: -12px; right: -2px; }
.item-field .item-menu { width: 28px; height: 28px; padding: 0; justify-content: center; color: var(--ink2); }
/* the blank line at the end invites the next: its grip and tick stand like every line's, the grip
   lifts nothing, and there is no ⋮ to open */
.item-line.is-new .item-grip { pointer-events: none; }
.item-line.is-new .item-menu { visibility: hidden; }
.item-line.drag-src { background: var(--nav-fill); box-shadow: var(--shadow); border-radius: var(--r-ctl); position: relative; z-index: 2; }
/* a heading line: no tick, no amount — only its text, in the heading weight */
.item-line.is-section .notes-check,
.item-line.is-section .item-qty,
.item-line.is-section .item-tags { display: none; }
#app .popup-body .item-line.is-section .item-text { font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); }
/* the queued moves: one quiet sentence per line that leaves this list on Save, each with its ✕ */
.items-moved { display: flex; flex-direction: column; gap: 2px; margin-top: 8px; }
.items-moved:empty { display: none; }
.items-moved-row { display: flex; align-items: center; gap: 6px; font-size: var(--fs-hint); color: var(--ink2); }
.items-moved-row > span { flex: 1; min-width: 0; }
.items-moved-row .notes-linkx { flex: none; height: 28px; }

/* ── Zubereitung: die Faltliste ────────────────────────────────────────────────────
   A saved recipe opens with every section shut, so nine heading rows fit on one screen
   before any of the words do. The per-row × are gone into a ⋮ menu — nine sections used
   to put 27 armed deletes in front of a thumb. */
.prep { display: flex; flex-direction: column; gap: 6px; }
.prep-sec { border-radius: var(--r-ctl); overflow: hidden; }
.prep-head {
    padding: 0 4px 0 10px;
    min-height: 44px;   /* PLAN_UX D2: a row you tap is at least this tall */
}
.prep-sum { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prep-sum.untitled { color: var(--ink3); }
.prep-cnt {
    flex: none;
    color: var(--ink3);
    font-size: var(--fs-ui);
    font-variant-numeric: tabular-nums;
}
/* the heading of the OPEN section stays put while you type in it — at 19 steps you
   otherwise lose track of what you are writing under */
.prep-sec.open > .prep-head {
    position: sticky;
    top: 0;
    z-index: 1;
}
/* the sticky open head needs something opaque behind it while the steps scroll under it */
.prep-sec.open > .prep-head { background: var(--card); }
.popup-body .prep-title {
    flex: 1;
    min-width: 0;
    font-weight: 600;
    background: none;
    border: none;
    padding: 0;
}
.popup-body .prep-title:focus { outline: none; }
.prep-dots {
    flex: none;
    background: none;
    border: none;
    color: var(--ink3);
    width: 32px;
    height: 40px;
    padding: 0;
    cursor: pointer;
}
.prep-body { display: flex; flex-direction: column; gap: 6px; padding: 4px 4px 8px 8px; }
.prep-step { display: flex; align-items: flex-start; gap: 6px; }
.prep-no {
    flex: none;
    width: 18px;
    padding-top: 12px;
    color: var(--ink3);
    font-size: var(--fs-ui);
    font-variant-numeric: tabular-nums;
    text-align: right;
}
/* a step wears the line field of the to-do editor: its text grows, the grip and the ⋮ stand
   beside its FIRST line; the field draws the frame and the focus, the text inside is bare */
.prep-step > .prep-field { align-items: flex-start; }
.popup-body .prep-field > textarea {
    flex: 1;
    min-width: 0;
    min-height: 44px;
    /* 16px and not --fs-md: below 16px iOS zooms the page in when the field takes focus,
       and a sheet that jumps on every step is unusable one-handed */
    font-size: 16px;
    overflow: hidden;
    background-color: transparent;
    border: 0;
}
.popup-body .prep-field > textarea:focus { box-shadow: none; }
.prep-field > .item-grip,
.prep-field > .prep-dots { height: 44px; }
.prep-field > .prep-dots { width: 28px; }
/* the invitation line has nothing to lift: its grip keeps the place, unseen and untouchable */
.prep-field > .item-grip.is-idle { visibility: hidden; }
.prep-add { align-self: flex-start; margin-top: 6px; }
.prep-menu .mg-select-opt { white-space: nowrap; }

/* the recipe photo: a tile in the editor, and the list's lead column */
.rcp-photo { display: flex; align-items: center; gap: 10px; }
.rcp-tile {
    width: 84px;
    height: 84px;
    flex: none;
    border: 1px dashed var(--line2);
    border-radius: var(--r-ctl);
    background: var(--card2);
    color: var(--ink3);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    font-size: 11px;
    padding: 4px;
    overflow: hidden;
    cursor: pointer;
}
.rcp-tile img { width: 100%; height: 100%; object-fit: cover; border-radius: calc(var(--r-ctl) - 1px); }
.rcp-tile:has(img) { border-style: solid; padding: 0; }
.rcp-photo-status, .rcp-photo-hint { color: var(--ink3); font-size: var(--fs-ui); }

/* a card's photo (a recipe's cover, a note's first picture) under its text, from the text column
   to the card's edge */
.notes-thumb {
    grid-column: 2 / -1;
    height: 96px;
    margin-top: 8px;
    border-radius: 10px;
    box-shadow: inset 0 0 0 1px var(--photo-edge);
    background: var(--card2);
    color: var(--ink3);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.notes-thumb img { width: 100%; height: 100%; object-fit: cover; }

/* the cooking mode's photo: small, in the HEAD. A band above step 1 would push the step
   down at exactly the moment you look at it, and be gone by step 2 */
.cook-shot {
    flex: none;
    width: 36px;
    height: 36px;
    padding: 0;
    border: none;
    border-radius: 8px;
    overflow: hidden;
    background: var(--card2);
    cursor: pointer;
}
.cook-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* the recipe → shopping picker: every ingredient pre-ticked, one already on the list
   unticked and saying so under its text — rows of 48 between hairlines */
.pick-list { display: flex; flex-direction: column; }
.pick-line {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 48px;
    box-sizing: border-box;
    padding: 4px 0;
    border-top: 1px solid var(--line);
    cursor: pointer;
}
.pick-line:first-child { border-top: none; }
/* `.popup-body input` sets width:100%, a text field's padding and its filled ground — right for a
   text field, and it beats .w-check on specificity, so the checkbox came out 484px wide (pushing
   the ingredient off the sheet), then a filled disc without its ring. Two classes to outrank it;
   the size and the ring are .w-check's own. The vault's ticks in their box sit the same way. */
.pick-line > .w-check,
.pw-extra > .w-check {
    width: 22px;
    height: 22px;
    padding: 0;
    box-sizing: border-box;
}
.pick-line > .w-check { border: 1.5px solid var(--line2); background: transparent; }
.pick-line > .w-check:checked { background: var(--ink); border-color: var(--ink); }
.pick-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pick-text { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; }
.pick-hint { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }

/* ── Kochen ──────────────────────────────────────────────────────────────────────────
   A MODE, not a sheet: it covers the footer nav on purpose, because a thumb reaching for
   "›" at the bottom of the screen would otherwise land on a module tab. Opaque on the card
   ground, no scrim — there is nothing behind it worth seeing while the pan is hot. */
.cook-overlay {
    position: fixed;
    inset: 0;
    z-index: 1100;
    background: var(--card);
    color: var(--ink);
    display: flex;
    flex-direction: column;
    padding-bottom: env(safe-area-inset-bottom);
}
/* the head: ✕ · the title in the serif over „Schritt 3 / 7" · the photo small at the right */
.cook-head {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 52px;
    box-sizing: border-box;
    padding: env(safe-area-inset-top) 6px 0 16px;
    flex: none;
}
.cook-x {
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    border: none;
    border-radius: 50%;
    background: none;
    color: var(--ink);
    font-size: 18px;
    padding: 0;
    cursor: pointer;
    flex: none;
}
.cook-titles { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.cook-title {
    min-width: 0;
    line-height: 1.15;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cook-pos { margin-top: 1px; color: var(--ink2); font-size: var(--fs-cap); font-variant-numeric: tabular-nums; }

/* One step at a time — the mode IS the current step, big and legible from across the kitchen.
   The section it belongs to sits quietly above it; tapping the stage advances. */
.cook-stage {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    gap: 10px;
    padding: 28px 24px;
}
.cook-stage-sec {
    font-size: var(--fs-sub);
    font-weight: 500;
    color: var(--ink2);
}
.cook-stage-step {
    font-size: 22px;
    line-height: 1.4;
    color: var(--ink);
    max-width: 30rem;
    cursor: pointer;
}
/* ‹ Zutaten › at the foot; the ingredient list opens above them */
.cook-foot {
    flex: none;
    padding: 0 var(--pad) 14px;
}
.cook-nav { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.cook-prev,
.cook-next {
    width: 52px;
    height: 44px;
    display: grid;
    place-items: center;
    border: none;
    border-radius: var(--r-ctl);
    background: var(--field);
    color: var(--ink);
    font-size: 18px;
    padding: 0;
    cursor: pointer;
    flex: none;
}
.cook-prev:disabled { opacity: 0.3; }
.cook-prev:active, .cook-next:active { transform: scale(var(--button-click-scale)); }
.cook-ing-toggle {
    height: 44px;
    padding: 0 20px;
    border: none;
    border-radius: var(--r-ctl);
    background: var(--field);
    color: var(--ink);
    font-family: var(--font-family);
    font-size: var(--fs-md);
    font-weight: 500;
    cursor: pointer;
}
.cook-ing-toggle.on { background: var(--ink); color: var(--card); }
.cook-ing { max-height: 34vh; overflow-y: auto; padding: 0 0 10px; }
.cook-ing-line {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 5px 0;
    font-size: var(--fs-body);
}
.cook-ing-line > span:first-child { flex: 1; min-width: 0; }
/* information ("still on the shopping list"), not a deadline — amber, never the deadline red */
.cook-ing-open { color: var(--pend-ink); font-size: var(--fs-ui); flex: none; }

/* timers: the running ones as ink pills counting down (a done one pulses) with their ✕, then a
   „Timer" pill per time the step names */
.cook-tmrs { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 var(--pad) 12px; flex: none; }
.cook-tmr { display: inline-flex; align-items: center; height: 36px; box-sizing: border-box; padding: 0 6px 0 14px; border-radius: var(--r-pill); background: var(--ink); color: var(--card); font-size: var(--fs-ui); font-weight: 500; font-variant-numeric: tabular-nums; }
.cook-tmr button { border: 0; background: transparent; color: inherit; font: inherit; cursor: pointer; padding: 0; -webkit-tap-highlight-color: transparent; }
.cook-tmr-go { display: inline-flex; align-items: center; gap: 4px; height: 100%; }
.cook-tmr-x { width: 24px; height: 24px; display: grid; place-items: center; margin-left: 4px; border-radius: 50%; font-size: 11px; }
.cook-tmr.is-done { animation: cook-tmr-pulse 1s ease-in-out infinite; }
@keyframes cook-tmr-pulse { 50% { opacity: .45; } }
.cook-tmr-start { display: inline-flex; align-items: center; gap: 6px; height: 36px; padding: 0 16px; border: 0; border-radius: var(--r-pill); background: var(--field); color: var(--ink); font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 500; cursor: pointer; }
.cook-tmr-start > i { font-size: 14px; }
.cook-tmr-start:active, .cook-tmr button:active { transform: scale(var(--button-click-scale)); }
/* the "is done" banner — over everything, the cooking mode included, under the head */
.cook-alarm { position: fixed; z-index: 1300; left: var(--pad); right: var(--pad); top: calc(60px + env(safe-area-inset-top)); display: flex; align-items: center; gap: 10px; padding: 12px 12px 12px 16px; border-radius: var(--r-card); background: var(--ink); color: var(--card); font-size: 14px; line-height: 1.35; box-shadow: var(--shadow); }
.cook-alarm > i { flex: none; font-size: 20px; }
.cook-alarm-t { flex: 1; min-width: 0; }
.cook-alarm-t b { font-weight: 500; }
.cook-alarm-ok { flex: none; height: 36px; padding: 0 16px; border: 0; border-radius: var(--r-pill); background: var(--card); color: var(--ink); font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 500; cursor: pointer; }

/* recipe read view — a full-screen card layered above the sheets (like the file viewer), on the
   card ground */
#recipe-view-overlay {
    position: fixed;
    inset: 0;
    z-index: 1100;
    background: var(--card);
    color: var(--ink);
    display: flex;
    flex-direction: column;
    padding-bottom: env(safe-area-inset-bottom);
}
/* the head: ✕ at the left, the title in the serif, ♥ and ✎ as discs at the right */
.rv-head { display: flex; align-items: center; gap: 6px; min-height: 52px; box-sizing: border-box; padding: env(safe-area-inset-top) 6px 4px 16px; flex: none; }
.rv-x { width: 44px; height: 44px; display: grid; place-items: center; flex: none; border: 0; border-radius: 50%; background: none; color: var(--ink); font-size: 18px; padding: 0; cursor: pointer; }
#recipe-view-overlay .rv-title { flex: 1; min-width: 0; margin: 0; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rv-hb { width: 36px; height: 36px; display: grid; place-items: center; flex: none; border: 0; border-radius: 50%; background: var(--nav-fill); color: var(--ink); font-size: 17px; padding: 0; cursor: pointer; }
/* the heart: an ink disc once you want to cook it (ON = ink, never a hue) */
#app .rv-hb.rv-want.on { background: var(--ink); color: var(--card); }
.rv-body { flex: 1; overflow-y: auto; box-sizing: border-box; padding: 2px var(--pad) 14px; width: 100%; max-width: 40rem; margin: 0 auto; }
.rv-hero {
    display: block;
    width: 100%;
    height: 150px;
    margin: 0 0 10px;
    border: none;
    padding: 0;
    border-radius: var(--r-ctl);
    overflow: hidden;
    background: var(--card2);
    cursor: pointer;
}
.rv-hero img { width: 100%; height: 100%; object-fit: cover; }
/* the facts as marks: minutes, difficulty, diet, the source, who wants to cook it */
#recipe-view-overlay .rv-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.rv-mk { display: inline-flex; align-items: center; gap: 5px; height: 26px; box-sizing: border-box; padding: 0 10px; border-radius: var(--r-pill);
    background: var(--nav-fill); color: var(--ink2); font-size: var(--fs-cap); font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums; text-decoration: none; }
.rv-mk > i { font-size: 13px; }
/* the badges sit in their .ppl group, whose 22px rule comes later — the group in the selector outranks it */
.rv-wants .ppl .m { width: 20px; height: 20px; font-size: 11px; box-shadow: inset 0 0 0 1.5px var(--pc, var(--line2)), 0 0 0 1.5px var(--card); }
.rv-wants .ppl .m + .m { margin-left: -5px; }
/* what somebody may not eat — information in amber on the quiet wash, the ingredient a touch
   heavier; a box of dislikes alone stays grey */
.rv-warn { margin: 0 0 12px; padding: 10px 12px; border-radius: var(--r-ctl); background: var(--nav-fill); color: var(--pend-ink); font-size: 14px; line-height: 1.4; }
.rv-warn-line b { font-weight: 500; }
.rv-warn.is-mild, .rv-warn-line.is-mild { color: var(--ink2); }
.rv-warn-line.is-mild b { font-weight: 400; }
.mw-warn { flex: none; font-size: 12px; color: var(--pend-ink); }
.mw-warn.is-severe { color: var(--pend-ink); }
/* a section of the view: its head (the name, at the right the stepper or the count), then its rows */
.rv-sec { margin-top: 12px; }
.rv-sec-h { display: flex; align-items: center; gap: 6px; min-height: 36px; margin: 0 0 6px; }
.rv-sec-n { margin-left: auto; font-weight: 400; font-variant-numeric: tabular-nums; }
.rv-serv { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; }
.rv-serv-btn { width: 28px; height: 28px; display: grid; place-items: center; flex: none; border: 0; border-radius: 50%; background: var(--nav-fill); color: var(--ink2); font-size: 13px; padding: 0; cursor: pointer; }
.rv-serv-btn:disabled { opacity: 0.3; }
.rv-serv-lab { color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }
/* an ingredient: the name at the left, the amount at the right, a hairline over every row — the
   first one too, under the section head */
.rv-ing { display: flex; justify-content: space-between; gap: 12px; padding: 9px 14px; border-top: 1px solid var(--line); font-size: 14px; }
.rv-ing-t { color: var(--ink2); min-width: 0; }
.rv-ing-q { color: var(--ink); text-align: right; flex: none; font-variant-numeric: tabular-nums; }
.rv-step-sec { font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); margin: 12px 0 4px; }
/* a step: its number in the serif in a column of 50, the text beside it */
.rv-step { display: grid; grid-template-columns: 50px minmax(0, 1fr); align-items: start; padding: 8px 0; }
.rv-step-n { min-height: 30px; display: flex; align-items: center; color: var(--ink); }
.rv-step-t { min-height: 30px; display: flex; align-items: center; font-size: var(--fs-body); font-weight: 500; line-height: 1.35; color: var(--ink); }
/* the foot: „Jetzt kochen" (ink) and „Einkaufsliste" side by side, the same width */
.rv-foot { flex: none; display: flex; gap: 9px; padding: 10px var(--pad) 22px; }
.rv-btn { flex: 1; height: 44px; display: flex; align-items: center; justify-content: center; gap: 6px; border: 0; border-radius: var(--r-ctl);
    background: var(--ink); color: var(--card); font-family: var(--font-family); font-size: var(--fs-md); font-weight: 500; white-space: nowrap; cursor: pointer; }
.rv-btn > i { font-size: 18px; }
.rv-btn.rv-cart { background: var(--field); color: var(--ink); }

/* ── Weiterkochen (dashboard-pinned) + Rezepte widget — the wk-* family ─────────────────────── */
/* The pinned "Weiterkochen" card rides full-width at the very top; it is NOT an arrangeable widget
   and has no head: one row per recipe — the utensils tile (.wk-ki), „Weiterkochen · <recipe>"
   (14/400) over the step and a running timer (12 --ink2), the ink pill „Weiter" (36). */
#app .dash-grid > .wk-card { grid-column: 1 / -1; position: relative; background: var(--card); border-radius: var(--r-card); overflow: hidden; }
.wk-cook { display: flex; align-items: center; gap: 10px; padding: 10px 14px; cursor: pointer; }
.wk-cook + .wk-cook { border-top: 1px solid var(--line); }
.wk-cook-main { flex: 1; min-width: 0; }
.wk-cook-main > b { display: block; font-size: 14px; font-weight: 400; line-height: 1.35; color: var(--ink); overflow-wrap: break-word; }
.wk-cook-meta { font-size: var(--fs-cap); line-height: 1.35; color: var(--ink2); font-variant-numeric: tabular-nums; }
.wk-go { flex: none; height: 36px; padding: 0 16px; border: 0; border-radius: var(--r-pill); background: var(--ink); color: var(--card);
    font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 500; white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; }

/* the notes cards (Übersicht, To-dos …): the feed's cards as a flat list inside the widget — no
   card in a card, a hairline between rows, the row inset 14; a card's tick stands in its tile's
   slot (_tickInSlot); the kinds fold as quiet bands — the kind and its count, the chevron at the
   right (˅ shut, ˄ open). From the ninth card on they wait behind the "n weitere" line. */
.widget .w-feed .notes-item { background: transparent; border-radius: 0; margin: 0; padding: 8px 14px; min-height: 44px; border-top: 1px solid var(--line); }
.widget .w-feed .notes-item > .notes-check { margin: 4px; }
.widget .w-feed .notes-title { font-size: 14px; }
.widget .w-feed > .sec-fold > summary { min-height: 0; margin: 0; padding: 8px 14px 2px; font-size: var(--fs-cap); color: var(--ink2); }
/* a SHUT band stands with even air above and below: shut bands read as calm rows, and the last one
   keeps a gap to the card's edge (an open band brings its rows instead) */
.widget .w-feed > .sec-fold:not([open]) > summary { padding: 10px 14px; }
.widget .w-feed > .sec-fold > summary > .sec-head-label { color: var(--ink2); }
.widget .w-feed > .sec-fold > summary .fold-chev { transform: none; }
.widget .w-feed > .sec-fold[open] > summary .fold-chev { transform: rotate(180deg); }
.widget .w-feed > .sec-fold + .sec-fold { margin-top: 0; }
.widget:not(.open) .w-feed .notes-item.w-xtra { display: none; }

/* the Rezepte card: the recipes as cards two by two — the photo 70 high, the title, a small
   line with the minutes and who wants to cook it */
.rc-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; padding: 4px 14px 12px; }
.rc-card { border-radius: 10px; overflow: hidden; background: var(--card2); cursor: pointer; min-width: 0; }
.widget:not(.open) .rc-card.w-xtra { display: none; }
.rc-card-shot { display: block; width: 100%; height: 70px; object-fit: cover; }
.rc-blank { display: grid; place-items: center; background: var(--field); color: var(--ink3); font-size: 18px; }
.rc-card > b { display: block; padding: 6px 8px 0; font-size: var(--fs-sub); font-weight: 400; color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-card-sub { display: flex; align-items: center; gap: 4px; min-height: 20px; padding: 1px 8px 8px; font-size: 11px; color: var(--ink2); }
.rc-card-sub .ppl .m { width: 20px; height: 20px; font-size: 11px; box-shadow: inset 0 0 0 1.5px var(--pc, var(--line2)), 0 0 0 1.5px var(--card2); }

/* the "Kochen planen" sheet: the recipes as rows to tick — the photo 40, the title over its
   minutes and diet, the selection circle at the right (chosen = ink with its check) — between
   hairlines; what does not fit somebody as quiet amber lines under them */
.cook-plan-recipes { display: flex; flex-direction: column; }
.cook-plan-recipe { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; box-sizing: border-box; padding: 4px 0;
    border: 0; border-top: 1px solid var(--line); background: none; color: var(--ink); font-family: var(--font-family); text-align: left; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
.cook-plan-recipe:first-child { border-top: 0; }
.cook-plan-shot { width: 40px; height: 40px; flex: none; display: grid; place-items: center; overflow: hidden; border-radius: 8px;
    background: var(--field); color: var(--ink3); font-size: 16px; box-shadow: inset 0 0 0 1px var(--photo-edge); }
.cook-plan-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.cook-plan-recipe-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.cook-plan-recipe-t b { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cook-plan-recipe-t small { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }
.cook-plan-tick { flex: none; width: 22px; height: 22px; box-sizing: border-box; display: grid; place-items: center; border-radius: 50%;
    border: 1.5px solid var(--line2); color: var(--card); font-size: 13px; }
.cook-plan-tick > i { visibility: hidden; }
.cook-plan-recipe.on .cook-plan-tick { background: var(--ink); border-color: var(--ink); }
.cook-plan-recipe.on .cook-plan-tick > i { visibility: visible; }
.cook-plan-warn:not(:empty) { margin-top: 6px; }
.cook-plan-warn-line { font-size: var(--fs-sub); line-height: 1.45; font-weight: 500; color: var(--pend-ink); }
.cook-plan-warn-line.is-mild { font-weight: 400; color: var(--ink2); }
.cook-plan-warn-line > i { font-size: 14px; vertical-align: -2px; }
/* „Jetzt kochen" beside „Planen": the foot's second button */
.popup-modal.sheet .popup-footer .action-btn.cook-plan-now { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
/* the Wochenplan card: Monday to Sunday side by side, the day over one pill — what is cooked (in
   ink today), a "+" in a hairline on an empty day ahead */
.mw-strip { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 4px; padding: 2px 14px 12px; }
.mw-col { display: grid; gap: 3px; justify-items: center; min-width: 0; font-size: 11px; color: var(--ink2); }
.mw-col > b { font-size: 11px; font-weight: 500; color: var(--ink); }
.mw-pill { width: 100%; height: 22px; box-sizing: border-box; padding: 0 3px; border: 0; border-radius: 6px; background: var(--field);
    color: var(--ink); font-family: var(--font-family); font-size: 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; }
.mw-pill.on { background: var(--ink); color: var(--card); }
.mw-pill.add { background: none; box-shadow: inset 0 0 0 1px var(--line2); color: var(--ink2); }
.mw-pill:disabled { cursor: default; }

/* the Wochenplan sheet: ‹ week › at the left and „Heute" at the right, then one hairline row of
   48 per day — the day („Mo" over „5."; today with an ink bar and „heute"), its Kochtermine as
   marks, the + at its end */
.mw-nav { display: flex; align-items: center; gap: 6px; min-height: 32px; margin-bottom: 8px; }
.mw-arrow { width: 30px; height: 30px; display: grid; place-items: center; flex: none; border: 0; border-radius: 50%; background: var(--nav-fill);
    color: var(--ink); font-size: 14px; padding: 0; cursor: pointer; }
.mw-when { min-width: 0; padding: 0 2px; font-size: var(--fs-ui); font-weight: 500; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.mw-now { margin-left: auto; flex: none; height: 28px; padding: 0 11px; border: 0; border-radius: var(--r-pill); background: var(--field); color: var(--ink);
    font-family: var(--font-family); font-size: var(--fs-cap); font-weight: 500; cursor: pointer; }
.mw-day { display: flex; align-items: center; gap: 12px; min-height: 48px; box-sizing: border-box; padding: 4px 0; border-top: 1px solid var(--line); font-size: var(--fs-body); }
.mw-days > .mw-day:first-child { border-top: 0; }
.mw-day.is-today { box-shadow: inset 3px 0 0 var(--ink); padding-left: 10px; margin-left: -10px; }
.mw-d { flex: 0 0 64px; display: flex; flex-direction: column; line-height: 1.35; font-weight: 500; color: var(--ink); }
.mw-wd { font-size: var(--fs-sub); font-weight: 400; color: var(--ink2); }
.mw-day.is-past .mw-d, .mw-day.is-past .mw-wd { color: var(--ink2); }
.mw-meals { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.mw-meal { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; height: 26px; box-sizing: border-box; padding: 0 10px; border: 0;
    border-radius: var(--r-pill); background: var(--nav-fill); color: var(--ink2); font-family: var(--font-family); font-size: var(--fs-cap);
    font-weight: 500; text-align: left; white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.mw-meal.on { background: var(--ink); color: var(--card); }
.mw-meal.on .mw-warn { color: inherit; }
.mw-meal-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.mw-meal-time { flex: none; font-variant-numeric: tabular-nums; }
.mw-meal .ppl .m { width: 20px; height: 20px; font-size: 11px; box-shadow: inset 0 0 0 1.5px var(--pc, var(--line2)), 0 0 0 1.5px var(--card); }
.mw-meal .ppl .m + .m { margin-left: -5px; }
.mw-plus { margin-left: auto; flex: none; width: 28px; height: 28px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%;
    background: var(--nav-fill); color: var(--ink2); font-size: 13px; cursor: pointer; }
.mw-shop { margin: 10px var(--w-inset) 14px; }
.popup-body .mw-shop { margin-inline: 0; width: 100%; }



/* "Zuletzt gekauft" quick-adds: the pill is a SPAN holding two buttons (file + forget) —
   text-only, so the avatar-sized left padding gives way to a symmetric one; the × a small disc
   at its end */
.recent-chips .fuer-chip { padding: 0 5px 0 11px; gap: 4px; }
.recent-chips .fuer-chip .notes-linkx { width: 18px; height: 18px; padding: 0; justify-content: center; border-radius: 50%;
    color: var(--ink); font-size: 11px; }
/* a word chip (the recipe's diet): text alone, even on both sides */
.fuer-chip.word { padding: 0 11px; }
.recent-chips .recent-add {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* baby chips (Wann-row backdating + Brei suggestions): plain text pills — the avatar-sized
   left padding gives way to a symmetric one */
.baby-chips .fuer-chip { padding: 0 11px; }

/* the EXPECTED baby's status card (due date still ahead — derived state): a quiet
   countdown instead of a day that is not running yet */
.baby-expect {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 28px 16px;
    gap: 6px;
}
.baby-expect-count { font-size: 24px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; color: var(--ink); }
.baby-expect-date { color: var(--ink2); font-size: var(--fs-body); }
.baby-expect-sub { color: var(--ink3); font-size: var(--fs-label); margin: 4px 0 0; max-width: 32ch; }

/* Kür fold (form law G1): the editor's Für/Verknüpft/Sichtbarkeit/Anhänge fields sit
   behind ONE collapsed state line; a tap unfolds the real controls */
.kuer-fold { margin: 8px 0 16px; }
/* the fold family above carries the box, the border and the open state — this only adds what
   a form line needs of its own: full width, its type, and a left-aligned label */
.kuer-line {
    width: 100%;
    box-sizing: border-box;
    min-height: 44px;
    padding: 8px 0;
    background: none;
    color: var(--ink2);
    font-family: inherit;
    font-size: var(--fs-body);
    text-align: left;
}
.kuer-line .kuer-sum {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.kuer-title { font-size: var(--fs-body); font-weight: 500; color: var(--ink); flex: none; white-space: nowrap; }
.kuer-line .fold-chev { font-size: 12px; }
.kuer-body { padding-top: 8px; }
/* the body holds display:flex/grid rows — collapsed must WIN over them */

/* generic swipeable tab layer (calendar views, baby card tabs) — 1:1 finger follow via
   --tab-drag (CSSOM, CSP-safe), spring-back, directional slide-in; pan-y keeps vertical
   scrolling native AND stops horizontal ancestor scrollers from grabbing gestures here */
.tab-layer {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
    touch-action: pan-y;
    transform: translateX(var(--tab-drag, 0px));
    transition: transform var(--transition-base);
}
.tab-layer.dragging { transition: none; }
/* a layer that scrolls ITSELF (Passwörter, Gesundheit, Reisen) keeps every child at its own
   height: a flex column would squeeze a child with overflow:hidden (the vault's list) to fit the
   screen and clip its last rows instead of scrolling */
#app .module-passwords .tab-layer > *,
#app .module-health .tab-layer > *,
#app .module-travel .tab-layer > * { flex-shrink: 0; }
.tab-layer.slide-from-right { animation: notesSlideFromRight var(--transition-base); }
.tab-layer.slide-from-left  { animation: notesSlideFromLeft  var(--transition-base); }
@media (prefers-reduced-motion: reduce) {
    .tab-layer.slide-from-right, .tab-layer.slide-from-left { animation: none; }
    .tab-layer { transition: none; }
}

/* popup / modal system (Module.openFormPopup) — card modal or bottom sheet */
.popup-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: var(--scrim);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
    animation: fadeIn var(--transition-base);
}
.popup-modal {
    background: var(--card);
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: var(--r-card);
    width: 90%;
    max-width: 420px;
    max-height: 80vh;
    overflow: auto;
    box-shadow: var(--shadow);
    display: flex;
    flex-direction: column;
}
.popup-header {
    padding: 12px 16px;
    display: flex;
    align-items: center;
    gap: 6px;
    font-weight: 400;
    font-size: 16px;
    letter-spacing: -0.01em;
    flex-shrink: 0;
}
/* the title stands left, like the app bar's — its serif voice comes from the display list; the
   box is trimmed to the capital, and a padding above and below that the margins take back keeps
   its ascenders and umlauts (l, Ä) and its descenders (g, p) inside the clip */
.popup-header > span {
    flex: 1;
    display: block;
    line-height: 1.15;
    text-box: trim-both cap alphabetic;
    padding-block: 0.3em;
    margin-block: -0.3em;
    text-align: left;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* a sheet's line under its title (Render.sheetSub): the title and the line stack in the first
   column, every control of the head (its tools, the ✕) stands over both rows; the line sits at
   the foot of the head, a step under the title's descenders */
.popup-header:has(> .popup-sub),
#app .search-bar:has(> .popup-sub) {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto;
    grid-auto-flow: column;
    grid-auto-columns: auto;
    align-items: center;
    row-gap: 5px;
}
.popup-header:has(> .popup-sub) > span,
#app .search-bar:has(> .popup-sub) > span { grid-row: 1; grid-column: 1; align-self: end; }
.popup-header:has(> .popup-sub) > :not(span):not(.popup-sub),
#app .search-bar:has(> .popup-sub) > :not(span):not(.popup-sub) { grid-row: 1 / 3; }
.popup-header > .popup-sub,
#app .search-bar > .popup-sub {
    grid-row: 2;
    grid-column: 1;
    align-self: end;
    min-width: 0;
    font-family: var(--font-family);
    font-size: var(--fs-cap);
    font-weight: 400;
    letter-spacing: 0;
    line-height: 1.35;
    color: var(--ink2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.popup-close {
    background: none;
    border: none;
    font-size: 18px;
    color: var(--ink);
    cursor: pointer;
    line-height: 1;
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    padding: 0;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}
.popup-back {
    background: none;
    border: 0;
    color: var(--ink);
    font-size: 19px;
    line-height: 1;
    cursor: pointer;
    padding: 8px 10px 8px 0;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}
.popup-body {
    padding: 16px;
    flex: 1;
    overflow: auto;
    scrollbar-width: none;
}
.popup-body::-webkit-scrollbar { display: none; }
.popup-footer {
    padding: 12px 16px;
    border-top: 1px solid var(--line);
    display: flex;
    gap: 9px;
    align-items: center;
    justify-content: flex-end;
    flex-shrink: 0;
}
/* the footer of a sheet that saves as it goes: the sentence where a Save button would stand;
   .flash is the moment after a write ("Gespeichert") */
.popup-autosave { flex: 1; display: flex; align-items: center; justify-content: center;
    min-height: 24px; font-size: var(--fs-cap); color: var(--ink2); text-align: center; transition: color 200ms ease; }
.popup-autosave.flash { color: var(--ink); }
/* Footer-less sheets end at the physical screen edge — the body then carries its own 14 plus
   the empty foot's 26 (4 over, 22 under) and the safe-area inset the footer used to provide
   (footer-bearing sheets keep theirs) */
.popup-modal.sheet .popup-body:last-child { padding-bottom: calc(40px + var(--safe-bottom)); }
.popup-body .form-row {
    margin-bottom: 14px;   /* the field gap */
}
/* every native date input carries a ✕ that empties it (kit.js dateClearButtons) — iOS's picker
   has no Clear; the wrap stands where the input stood. In a form the ✕ sits INSIDE the field at
   its right end — the input's padding moves the native calendar icon left of it — so a date
   field is exactly as wide as every other field; a line's small date chip keeps it beside. */
.date-wrap { display: flex; align-items: center; gap: 6px; position: relative; }
.date-wrap > input { flex: 1 1 auto; min-width: 0; }
.date-clear {
    flex: none;
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--ink3);
    display: inline-flex;
    align-items: center;
    padding: 3px 7px 3px 3px;
    font-size: 12px;
    line-height: 1;
}
.date-clear:hover, .date-clear:active { color: var(--due-ink); }
/* the small inline ✕ / "Ändern" keep their look but get a finger-sized target around it */
.date-clear, .vis-change, .notes-linkx { position: relative; }
.date-clear::after, .vis-change::after, .notes-linkx::after { content: ""; position: absolute; inset: -13px -6px; }
.form-row .date-wrap:not(:has(> .item-due)) > input[type="date"],
#app .set-row > .date-wrap > input[type="date"],
#app .ent-attr-field > .date-wrap > input[type="date"] { padding-right: 40px; }
.form-row .date-wrap:not(:has(> .item-due)) > .date-clear,
#app .set-row > .date-wrap > .date-clear,
#app .ent-attr-field > .date-wrap > .date-clear { position: absolute; top: 0; bottom: 0; right: 0; width: 40px; justify-content: center; padding: 0; }
/* form vocabulary — small labels over filled fields. A field is FILLED, not framed (the tab
   track's rule); the transparent border keeps its box, and focus draws it in. */
.popup-body label {
    display: block;
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--ink2);
    margin-bottom: 6px;   /* 6 to its field, 16 to the next row */
}
.popup-body input,
.popup-body select,
.popup-body textarea {
    width: 100%;
    font-family: var(--font-family);
    font-size: var(--fs-md);
    color: var(--ink);
    background: var(--field);
    border: 1px solid transparent;
    border-radius: var(--r-ctl);
    padding: 11px 13px;
    box-sizing: border-box;
}
/* the app's own select button is a field like the rest; its open state draws the frame */
.popup-body .mg-select-btn { border-color: transparent; background: var(--field); }
/* ONE control height: every field and every sheet-footer button is 44px (the touch floor), so the
   halves of a pair line up whatever their native type — the height is set, the vertical padding
   dropped. The recipe's title line is a heading, not a field. */
.popup-body input:not([type="checkbox"]):not([type="radio"]):not(.prep-title),
.popup-body select,
.popup-body .mg-select:not(.mg-pill) > .mg-select-btn { height: 44px; padding-top: 0; padding-bottom: 0; }
.popup-body input:focus,
.popup-body select:focus,
.popup-body textarea:focus,
.popup-body .mg-select.open .mg-select-btn {
    outline: none;
    border-color: transparent;
    box-shadow: 0 0 0 1px var(--ink2), 0 0 0 4px var(--nav-fill);
}
.popup-body input::placeholder,
.popup-body textarea::placeholder { color: var(--ink2); }
.popup-body textarea { resize: none; min-height: 60px; line-height: 1.45; }
/* the note editor's TEXT field — it holds the note's whole body, so it gets real height */
.popup-body textarea.ta-tall { min-height: 200px; }

/* bottom-sheet variant */
.popup-overlay.sheet { align-items: flex-end; }
/* a sheet grows with what it holds, up to 94 % of the screen — its top then stands just under
   the status bar */
.popup-modal.sheet {
    width: 100%;
    max-width: 520px;
    max-height: 94dvh;
    margin: 0 auto;
    border: 0;            /* a sheet is a plane over the scrim: no line, no shadow */
    box-shadow: none;
    border-radius: 22px 22px 0 0;
    animation: sheetUp var(--transition-sheet) forwards;
}
.popup-modal.sheet::before {
    content: "";
    display: block;
    flex-shrink: 0;
    width: 36px;
    height: 4px;
    border-radius: var(--r-pill);
    background: var(--line2);
    margin: 8px auto 0;
}
.popup-modal.sheet .popup-header {
    border-bottom: 0;
    min-height: 52px;
    box-sizing: border-box;
    padding: 4px 6px 4px 16px;   /* the × is a 44px box: 4 + 44 + 4 = the 52px head */
}
.popup-modal.sheet .popup-body { padding: 2px 16px 14px; }
.popup-modal.sheet .popup-footer {
    border-top: 0;
    padding: 10px 16px calc(22px + var(--safe-bottom));
}
.popup-modal.sheet .popup-footer .action-btn {
    flex: 1;
    height: 44px;
    padding: 0 12px;
    font-size: var(--fs-md);
    border-radius: var(--r-ctl);
    margin: 0;
}
.popup-modal.sheet .popup-footer .action-btn.delete-btn {
    flex: 0 0 auto;
    margin-right: auto;
    background: transparent;
    border-color: transparent;
    color: var(--due-ink);
    font-size: var(--fs-body);
    font-weight: 500;
    padding: 0 6px;
}

/* the „Für" filter sheet (Module._openSubjectFilterSheet): its own search field, then the
   household under group heads — a row per subject: badge 30, the name over what it is, the
   selection circle 22 at the right (chosen = ink with its check) */
#app .subj-search { flex: none; display: flex; align-items: center; gap: 8px; height: 44px; box-sizing: border-box; padding: 0 13px; margin-bottom: 6px; border-radius: var(--r-ctl); background: var(--field); color: var(--ink3); }
#app .subj-search > i { font-size: 16px; }
#app .subj-search:focus-within { box-shadow: 0 0 0 1px var(--ink2), 0 0 0 4px var(--nav-fill); }
#app .popup-body .subj-search input { flex: 1; min-width: 0; height: auto; padding: 0; border: 0; border-radius: 0; background: transparent; box-shadow: none; }
#app .subj-head { min-height: 36px; display: flex; align-items: center; margin-top: 4px; font-size: var(--fs-head); font-weight: 500; color: var(--ink2); }
#app .subj-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; box-sizing: border-box; padding: 4px 0; border: 0; border-top: 1px solid var(--line); background: none; font-family: var(--font-family); color: var(--ink); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .subj-head + .subj-row { border-top: 0; }
#app .subj-badge { flex: none; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--pc-soft, var(--card2)); color: var(--pc-ink, var(--ink2)); box-shadow: inset 0 0 0 2px var(--pc, var(--line2)); font-size: 12px; font-weight: 600; }
#app .subj-badge.thing { border-radius: 9px; font-size: 16px; }
#app .subj-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
#app .subj-t b { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .subj-t small { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }
#app .subj-tick { flex: none; width: 22px; height: 22px; box-sizing: border-box; border-radius: 50%; border: 1.5px solid var(--line2); display: grid; place-items: center; color: var(--card); font-size: 13px; }
#app .subj-tick > i { visibility: hidden; }
#app .subj-row.on .subj-tick { background: var(--ink); border-color: var(--ink); }
#app .subj-row.on .subj-tick > i { visibility: visible; }
#app .subj-none { margin: 12px 0 0; font-size: var(--fs-sub); color: var(--ink2); text-align: center; }

/* custom monochrome <select> replacement — the menu is portaled to #app (fixed-positioned) */
.mg-select { position: relative; }
/* a select locked by the form (the reminder without any date): faded, its button disabled */
.mg-select.locked .mg-select-btn { opacity: 0.5; }
.mg-select-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    background: var(--card2);
    border: 1px solid var(--line);
    border-radius: var(--r-ctl);
    padding: 11px 13px;
    cursor: pointer;
    text-align: left;
    box-sizing: border-box;
    font-family: var(--font-family);
    font-size: var(--fs-md);
    color: var(--ink);
    transition: border-color var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.mg-select.open .mg-select-btn { border-color: var(--line2); }
.mg-select-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mg-select-chev { flex: none; color: var(--ink3); font-size: 11px; transition: transform var(--transition-fast); }
.mg-select.open .mg-select-chev { transform: rotate(180deg); }
/* .mg-pill — a pick worn as a pill (_pickPill), with the word that says WHAT it governs in
   front of its value. It wears the app's CHROME (the ‹ › Heute cluster: an ink wash, pill, no
   border) rather than the full form control: that one brings a border, 11px of padding and a
   116px floor to a word and a chevron. Content-wide, so the pill hugs "Alltag: Ø 591 €". */
.mg-pill { flex: none; width: max-content; min-width: 0; }
.mg-pill .mg-select-label { white-space: nowrap; }
/* the field's NAME carries the ink, its value the quiet colour — the pill says what it governs
   first and what it is set to second */
.mg-select-pre {
    flex: none;
    color: var(--ink) !important;
}
.mg-pill .mg-select-btn {
    justify-content: flex-start;
    background: var(--nav-fill);
    border: 0;
    border-radius: var(--r-pill);
    padding: 0 10px;
    height: 26px;
    gap: 4px;
    font-size: var(--fs-cap);
    font-weight: 600;
    color: var(--ink2);
}
.mg-pill .mg-select-chev { font-size: 9px; }
.mg-select-menu {
    position: fixed;
    box-sizing: border-box;   /* the width it is given is its field's — padding and border included */
    z-index: 1000;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--r-ctl);
    box-shadow: var(--shadow);
    padding: 5px;
    overflow-y: auto;
    scrollbar-width: thin;
}
.mg-select-opt {
    width: 100%;
    text-align: left;
    background: transparent;
    border: 0;
    border-radius: 9px;
    min-height: 44px;
    padding: 9px 10px;
    cursor: pointer;
    font-family: var(--font-family);
    font-size: var(--fs-md);
    font-weight: 500;
    color: var(--ink);
    transition: background var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.mg-select-hint { color: var(--ink2); font-size: var(--fs-cap); margin-right: 6px; }
.mg-select-opt:hover { background: var(--card2); }
.mg-select-heading {
    font-size: var(--fs-ui);
    font-weight: 600;
    color: var(--ink3);
    padding: 10px 10px 3px;
}
.mg-select-opt.active { font-weight: 600; }
/* options that carry an avatar / glyph line up as a row; the lead sits in a FIXED column so
   every label starts on the same line, whether it follows a 20px avatar or a thin glyph */
.mg-select-opt { display: flex; align-items: center; gap: 7px; }
.mg-select-opt > i.fa-solid { flex: 0 0 20px; justify-content: center; }
.mg-select-opt .m {
    flex: 0 0 20px;
    height: 20px;
    font-size: 10px;
}
.mg-select-opt .mg-select-check { margin-left: auto; }
/* collapsible groups (link pickers): the heading becomes the fold control, carrying
   "selected/total" so a folded group still says what is picked inside it */
button.mg-select-heading {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    background: transparent;
    border: 0;
    cursor: pointer;
    font-family: var(--font-family);
    padding: 9px 10px 6px;
    -webkit-tap-highlight-color: transparent;
}
button.mg-select-heading:hover { color: var(--ink2); }
.mg-fold-label { flex: 1; text-align: left; }
.mg-fold-count {
    font-size: var(--fs-cap);
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink3);
}
.mg-fold-count.has-sel { color: var(--ink); }
.mg-fold-chev { font-size: 10px; transition: transform var(--transition-fast); }
.mg-select-fold.open .mg-fold-chev { transform: rotate(180deg); }
/* type-to-filter box — sticky so it stays reachable while the options scroll under it */
.mg-select-filter {
    position: sticky;
    top: -5px;
    z-index: 1;
    background: var(--card);
    padding: 3px 2px 6px;
    margin: -2px 0 0;
}
.mg-filter-input {
    width: 100%;
    background: var(--field);
    border: 1px solid var(--line);
    border-radius: 9px;
    padding: 8px 10px;
    color: var(--ink);
    font-family: var(--font-family);
    font-size: var(--fs-body);
}
.mg-filter-input::placeholder { color: var(--ink3); }
.mg-filter-input:focus { outline: none; border-color: var(--ink2); }
.mg-filter-input:focus { outline: none; border-color: var(--ink3); }
.mg-select-nohit {
    padding: 10px;
    color: var(--ink3);
    font-size: var(--fs-body);
    text-align: center;
}
/* two classes deep: must outweigh icons.css's `i.fa-solid { display:inline-flex }`,
   which would otherwise show every option's ✓ */
.mg-select-opt .mg-select-check { display: none; }
.mg-select-opt.active .mg-select-check {
    /* inline-flex, not inline-block: the mask icon's ::before only takes its 1em size
       as a flex item; floated, this computes to a flex container */
    display: inline-flex;
    float: right;
    margin-top: 2px;
    font-size: 10px;
    color: var(--ink);
}

/* misc CSP-safe helpers */
.hidden-file-input {
    display: none;
}

/* person palette slots — each sets the element-scoped color vars; no class = neutral.
   Slots are chosen explicitly or assigned deterministically (members then entities). */
.pc-1  { --pc: var(--p1);  --pc-soft: var(--p1-soft);  --pc-ink: var(--p1-ink); }
.pc-2  { --pc: var(--p2);  --pc-soft: var(--p2-soft);  --pc-ink: var(--p2-ink); }
.pc-3  { --pc: var(--p3);  --pc-soft: var(--p3-soft);  --pc-ink: var(--p3-ink); }
.pc-4  { --pc: var(--p4);  --pc-soft: var(--p4-soft);  --pc-ink: var(--p4-ink); }
.pc-5  { --pc: var(--p5);  --pc-soft: var(--p5-soft);  --pc-ink: var(--p5-ink); }
.pc-6  { --pc: var(--p6);  --pc-soft: var(--p6-soft);  --pc-ink: var(--p6-ink); }
.pc-7  { --pc: var(--p7);  --pc-soft: var(--p7-soft);  --pc-ink: var(--p7-ink); }
.pc-8  { --pc: var(--p8);  --pc-soft: var(--p8-soft);  --pc-ink: var(--p8-ink); }
.pc-9  { --pc: var(--p9);  --pc-soft: var(--p9-soft);  --pc-ink: var(--p9-ink); }
.pc-10 { --pc: var(--p10); --pc-soft: var(--p10-soft); --pc-ink: var(--p10-ink); }
.pc-11 { --pc: var(--p11); --pc-soft: var(--p11-soft); --pc-ink: var(--p11-ink); }
.pc-12 { --pc: var(--p12); --pc-soft: var(--p12-soft); --pc-ink: var(--p12-ink); }
.pc-13 { --pc: var(--p13); --pc-soft: var(--p13-soft); --pc-ink: var(--p13-ink); }
.pc-14 { --pc: var(--p14); --pc-soft: var(--p14-soft); --pc-ink: var(--p14-ink); }
.pc-15 { --pc: var(--p15); --pc-soft: var(--p15-soft); --pc-ink: var(--p15-ink); }
.pc-16 { --pc: var(--p16); --pc-soft: var(--p16-soft); --pc-ink: var(--p16-ink); }
.pc-17 { --pc: var(--p17); --pc-soft: var(--p17-soft); --pc-ink: var(--p17-ink); }
.pc-18 { --pc: var(--p18); --pc-soft: var(--p18-soft); --pc-ink: var(--p18-ink); }
.pc-19 { --pc: var(--p19); --pc-soft: var(--p19-soft); --pc-ink: var(--p19-ink); }
.pc-20 { --pc: var(--p20); --pc-soft: var(--p20-soft); --pc-ink: var(--p20-ink); }

/* DAS BADGE — eine Gestalt, überall dieselbe: ein Kreis mit dem Foto der Person, und ihre
   Initiale in ihrer Farbe, solange keines hinterlegt ist. Der Ring in der Kartenfarbe trennt
   das Badge von dem, worauf es liegt, und lässt überlappende Badges als Stapel lesen.
   Die Varianten darunter sagen nur noch, wie groß und wie eng — Form, Ring und Foto stehen
   hier, weil dieselben sechs Zeilen sonst in sieben Regeln stehen und in sechs davon der Ring
   fehlte: dieselbe Person sah im Haushalt anders aus als auf dem Dashboard. */
.m {
    border-radius: 50%;
    font-weight: 600;
    line-height: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    overflow: hidden;
    /* Der Farbring liegt INNEN (die Farbe ist am Ring deutlich, die Initiale bleibt lesbar);
       der Kartenring außen stellt das Badge vom Untergrund frei und lässt überlappende
       Badges als Stapel lesen. */
    border: 0;
    box-shadow: inset 0 0 0 2px var(--pc, var(--line2)), 0 0 0 2px var(--card);
    background: var(--pc-soft, var(--card2));
    color: var(--pc-ink, var(--ink2));
}
.m img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* THE INITIAL (Render.initialInto): a block of its own inside the disc, its line box trimmed to
   the capital, so the centred disc centres the ink — not the font's ascent and descent */
.ini { display: block; line-height: 1; text-box: trim-both cap alphabetic; }
.uMem > .av { display: inline-flex; align-items: center; justify-content: center; }

/* person badges: 19px initials circles, overlapping; .who sits right-aligned in rows,
   .ppl clusters under titles/in meta rows */
/* Mehrere Badges sind EINE Gruppe: gestapelt, der Kartenring trennt sie — keine Pille dahinter. */
.who { display: flex; align-items: center; margin-left: auto; flex-shrink: 0; }
.ppl { display: inline-flex; align-items: center; flex-shrink: 0; }
.who .m, .ppl .m, .notes-avs .m {
    box-sizing: border-box;
    width: 22px;
    height: 22px;
    font-size: 11px;   /* fixed, not a type token: the letter fills the 22px circle, it is not read text */
    margin-left: -6px;
}
.who .m:first-child, .ppl .m:first-child, .notes-avs .m:first-child { margin-left: 0; }
/* the eye leads the capsule when a row is private; the badge behind it tucks under it a little
   less than stacked badges tuck under each other */
.notes-av.lock + .m { margin-left: -4px; }
/* the same lock inside a Monatsplaner capsule, which is already the pill */
.cal-mp-lock { font-size: 0.8em; margin-right: 3px; opacity: 0.85; }
/* non-person subjects wear their type glyph in the badge circle instead of a letter */
.m.m-glyph { background: var(--card2); color: var(--ink2); }
.m.m-glyph i { font-size: 11px; }
/* subject badges inside strip chips (the Für / links strips, the entity hub) */
.notes-chip .m, .ent-link-go .m {
    width: 20px;
    height: 20px;
    font-size: 11px;
    margin-left: -3px;
}
.notes-chip .m.m-glyph, .ent-link-go .m.m-glyph { background: var(--card2); color: var(--ink2); }

/* the color chooser: an "auto" dot (deterministic assignment) and every palette swatch, dots of
   26 that wrap with a gap of 8 */
.color-pick { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.color-dot {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 0;
    background: var(--pc, var(--card2));
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}
.color-dot.auto {
    background: linear-gradient(135deg, var(--card2) 48%, var(--line2) 48%, var(--line2) 52%, var(--card2) 52%);
    box-shadow: inset 0 0 0 1px var(--line2);
}
.color-dot.on { box-shadow: 0 0 0 2px var(--card), 0 0 0 3.5px var(--ink); }

/* the birthdays card: the person's badge leads the row, 30 wide */
.w-row > .gift-ava { box-sizing: border-box; width: 30px; height: 30px; font-size: var(--fs-cap); }
.w-row.gift-row { flex-wrap: nowrap; gap: 12px; }


/* ============================== dashboard ============================== */

.module-dashboard {
    display: flex;
    flex-direction: column;
    height: 100%;
    position: relative;
}

/* widget grid — 2 columns on phones, 4 from 600px container width */
.dash-grid {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 8px var(--pad) 96px;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-auto-rows: min-content;
    gap: 8px;
    align-content: start;
}
/* the greeting heads the FIRST page across all its columns: it scrolls with that page's cards and
   swipes away with it. The grid's padding aligns it. */
.dash-grid > .pageTitle { grid-column: 1 / -1; min-width: 0; padding: 0; }
/* home-screen paging: the grid(s) live inside a horizontal scroll-snap pager, one .dash-grid per
   page. A single page keeps today's look (the pager has one child — no dots, no horizontal scroll).
   Each page scrolls vertically on its own, exactly like the calendar/baby pagers. */
.dash-pager {
    flex: 1;
    min-height: 0;
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.dash-pager::-webkit-scrollbar { display: none; }
/* border-box so flex-basis:100% INCLUDES the grid's L/R padding — without it the padding is added
   on top, the page runs ~32px wider than the pager, and the surplus scrolls sideways (the right
   gutter looks eaten). Same reason .baby-page carries box-sizing. */
.dash-pager > .dash-grid { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; box-sizing: border-box; }
/* page dots — the page switcher under the last card of every page, scrolling with it: comfortably
   tappable buttons, the page's own one a wide pill */
.dash-dots {
    grid-column: 1 / -1;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0;
    padding: 2px 0 0;
}
.dash-dot {
    position: relative;
    border: 0;
    background: transparent;
    cursor: pointer;
    padding: 8px 5px;
    display: flex;
    align-items: center;
    -webkit-tap-highlight-color: transparent;
}
/* the tap area: ~40px tall around the 6px dot, without spreading the dots apart */
.dash-dot::after { content: ""; position: absolute; inset: -10px -3px; }
.dash-dot::before {
    content: "";
    width: 5px;
    height: 5px;
    border-radius: var(--r-pill);
    background: var(--line2);
    transition: width var(--transition-base), background var(--transition-base);
}
.dash-dot.on::before { width: 14px; background: var(--ink); }
/* a page that belongs to someone wears their colour: the dot in the person's colour, quieter
   while another page shows; a dot without a person stays as above */
.dash-dot[class*="pc-"]::before { background: var(--pc); opacity: .45; }
.dash-dot.on[class*="pc-"]::before { opacity: 1; }
.dash-dot[class*="pc-"].on::before { opacity: 1; }
/* weather widget with no place yet — a real call to action to add one (opens Settings → Gruppe):
   a warm sun disc over an ink pill button, so it reads as a button, not a label. */
.wx-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    width: 100%;
    border: 0;
    background: transparent;
    padding: 24px 16px 28px;
    cursor: pointer;
    font-family: var(--font-family);
    -webkit-tap-highlight-color: transparent;
}
.wx-empty-ic {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--pend-soft);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--pend-ink);
    font-size: 22px;
}
/* the ink pill carrying an ICON beside its label */
.wx-empty-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
}
.wx-empty-btn i { font-size: 12px; }
.wx-empty:active .wx-empty-btn { transform: scale(var(--button-click-scale)); }
/* arranging: every page opens with its ‹ Seite n von N › — a card like the greeting's, the two
   28 circles of the heads' navigation, the words beside the left one — and closes with the two
   ways to add, „+ Karte hinzufügen" and „+ Seite", as quiet pills */
.dash-pagenav { grid-column: 1 / -1; display: flex; align-items: center; gap: 8px; padding: 14px 14px 12px;
    border-radius: var(--r-card); background: var(--card); font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); }
.dash-pagenav-btn { flex: none; width: 28px; height: 28px; display: grid; place-items: center; padding: 0; border: 0;
    border-radius: 50%; background: var(--nav-fill); color: var(--ink); font-size: 16px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.dash-pagenav-btn:last-child { margin-left: auto; }
.dash-pagenav-btn:disabled { opacity: 0.3; cursor: default; }
.dash-add-row { grid-column: 1 / -1; display: flex; justify-content: center; align-items: center; gap: 8px; min-height: 44px; }
.dash-add-row > .action-btn { display: inline-flex; align-items: center; gap: 6px; margin: 0; font-size: var(--fs-sub); }
.dash-add-row > .action-btn i { font-size: 14px; }

.pageTitle { display: flex; align-items: flex-start; gap: 10px; padding: 0; }
.pageTitle .tx { flex: 1; min-width: 0; }
/* the greeting card — a plain card without colour: the welcome in the display serif, the amount
   that waits in the 500 ink, then the day's small marks */
.pageTitle .dash-hello {
    padding: 14px 14px 12px;
    border-radius: var(--r-card);
    background: var(--card);
}
.pageTitle .dash-hello-greet { margin: 0; line-height: 1.1; }
.pageTitle .dash-hello-count { margin: 4px 0 0; font-size: var(--fs-body); line-height: 1.35; color: var(--ink2); }
.pageTitle .dash-hello-count b { font-weight: 500; color: var(--ink); }
/* the small marks under a hero (the greeting, the finance status): one quiet pill per fact */
/* ONE line, never a second: what does not fit scrolls sideways under a soft edge */
.hero-marks { display: flex; flex-wrap: nowrap; gap: 6px; margin-top: 10px; overflow-x: auto; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent); }
.hero-marks::-webkit-scrollbar { display: none; }
.hero-mark { display: inline-flex; align-items: center; gap: 5px; height: 26px; padding: 0 10px; flex: none;
    border-radius: var(--r-pill); background: var(--nav-fill);
    font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); white-space: nowrap;
    font-variant-numeric: tabular-nums; }
.hero-mark i { font-size: 13px; color: var(--ink2); }
.hero-mark .m { width: 20px; height: 20px; font-size: 11px; box-shadow: inset 0 0 0 1.5px var(--pc, var(--line2)), 0 0 0 1.5px var(--card); }
/* the pager dots over a hero's tab strip (health: one per pass; baby: one per child) */
#app .hero-lean > .hero-dots { display: flex; justify-content: center; gap: 5px; margin: 8px 0 0; }
#app .hl-hero > .hero-dots, #app .baby-hero > .hero-dots { flex: 1 0 100%; display: flex; justify-content: center; gap: 5px; margin: 0; padding: 0; }
/* the dot itself is the box (5 high, 10 apart centre to centre); its ::after keeps the tap area */
#app .hero-dots > .dash-dot { padding: 0; }
/* In a MODULE hero and on the two finance cards (not the greeting) the marks are ONE line,
   whatever the width: tighter pills, and what does not fit scrolls sideways under a soft edge —
   a third mark wrapping into a row of its own made the card a line taller for one word. */
#app .hl-hero .hero-marks, #app .baby-hero .hero-marks, #app .fin-hero-card .hero-marks,
#app .tv-hero .hero-marks, #app .fin-w-sec .hero-marks, #app .pw-hero .hero-marks {
    flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; gap: 6px;
    -webkit-mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent); }
#app .hl-hero .hero-marks::-webkit-scrollbar, #app .baby-hero .hero-marks::-webkit-scrollbar,
#app .fin-hero-card .hero-marks::-webkit-scrollbar, #app .tv-hero .hero-marks::-webkit-scrollbar,
#app .fin-w-sec .hero-marks::-webkit-scrollbar { display: none; }
#app .hl-hero .hero-mark, #app .baby-hero .hero-mark, #app .fin-hero-card .hero-mark,
#app .tv-hero .hero-mark, #app .fin-w-sec .hero-mark, #app .pw-hero .hero-mark {
    flex: none; gap: 5px; padding: 0 10px; }
/* the finance hero's marks speak the mark's own voice (12/500 --ink2); one that wants a look
   (a budget over, entries open) in the amber; the participants' badges overlap inside theirs */
#app .fin-hero-card .hero-mark { font-size: var(--fs-cap); color: var(--ink2); }
#app .fin-hero-card .hero-mark.pend { background: var(--pend-soft); color: var(--pend-ink); }
#app .fin-hero-card .hero-mark.warn { color: var(--due-ink); }
.hero-mark .m + .m { margin-left: -5px; }
/* a private row's eye inside a mark is the size of the mark's badges (20, the card ring 1.5) and
   meets the badge behind it as they meet each other */
.hero-mark .notes-av.lock { width: 20px; height: 20px; box-shadow: 0 0 0 1.5px var(--card); }
.hero-mark .notes-av.lock i { font-size: 11px; }
.hero-mark .notes-av.lock + .m { margin-left: -5px; }
/* in the finance card the marks keep the mark's own voice (12/500 --ink2), not the hero's spans' */
#app .fin-w-sec .hero-mark { font-size: var(--fs-cap); color: var(--ink2); }
#app .fin-w-sec .hero-mark.warn { color: var(--due-ink); }
/* the chosen range keeps its light word on ink — the line above would dim it to the second ink */
#app .fin-w-sec .hero-mark.fin-pick.on { color: var(--card); }
/* a mark that asks for something — an open debit, last month's leftover — in the due colour */
.fin-hero-card .hero-mark.warn,
.fin-w-sec .hero-mark.warn,
#app .pw-hero .hero-mark.warn { background: var(--due-soft); color: var(--due-ink); }
/* Notizen: the Datum/Kategorie group switch, right of the title — plain text labels like the
   calendar's view switcher, the active one inked + bold. */
/* the Datum/Kategorie switch is a segmented control, like the calendar's view switch and the
   baby tabs: a raised track holding two pills, the active one filled INK (design system: ON=ink) */
/* column ladder: phones stack every widget full-width; wider containers get 2, then 4 tracks */
@container (min-width: 600px) {
    .dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
    .widget.full { grid-column: span 2; }
}
/* three equal columns: every card one column wide, the greeting across all three; a card keeps
   its own height (start), no row stretches it to its tallest neighbour. The Monatsplaner while
   it is „Groß" — a column per person, a row per day — stands across all three like the
   greeting: in one column it ran four times as tall and left the two beside it empty */
@container (min-width: 1000px) {
    .dash-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: start; }
    .widget.full { grid-column: auto; }
    .widget.full.cal-planner { grid-column: 1 / -1; }
}

/* widget anatomy — a card: head (title · count · + · ›), rows — borderless, shadowless */
.widget {
    background: var(--card);
    border-radius: var(--r-card);
    overflow: hidden;
    position: relative;
    display: flex;
    flex-direction: column;
    min-width: 0;
    box-sizing: border-box;
}

/* a card's head: the card inset on every side, the greeting card's 20px */
.w-head {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 12px 14px 6px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
/* what stands at the head's end (avatar, gear, pill, badges) hangs into its padding, so every
   head is the title's height — the first row starts at the same depth in every card */
.w-head > .w-add, .w-head > .tv-pill, .w-head > .who, .w-head > .wx-chev { margin-block: -6px; }
/* the quiet words behind a card's title — a count, a scope, a place, an age; a split card's
   page name leads them, a dot between it and the words after it */
.w-head > .w-n { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: var(--fs-head); font-weight: 400; color: var(--ink2); }
/* the dot between them sits 4px from either word: the count steps into the head's 7px gap */
.w-head > .w-page + .w-n { margin-left: -3px; }
.w-head > .w-page + .w-n::before { content: "·"; margin-right: 4px; }
.w-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
.w-spacer { flex: 1; }
/* the + — a quiet hairline disc in every widget head */
#app .w-add {
    width: 28px;
    height: 28px;
    box-sizing: border-box;
    border: 0;
    border-radius: 50%;
    background: var(--nav-fill);
    color: var(--ink2);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    font-size: 13px;
    line-height: 1;
    flex-shrink: 0;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
#app .w-add:active { transform: scale(var(--button-click-scale)); }
/* a card's own settings (⚙) in its head: a bare glyph, not a disc, the tap area around it */
#app .w-add.w-pen { width: 24px; border: 0; background: transparent; color: var(--ink3); font-size: 14px; }
.w-chev { color: var(--ink3); font-size: 14px; line-height: 1; flex-shrink: 0; }

.w-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }

/* widget rows — hairline-separated, vertically centered */
/* The line belongs UNDER a row, and the last row SHOWN has none — a card must not end in a
   hairline that promises another row. "Shown" is two cases: the last row of all, and, while the
   fold is shut, the last one before the rows it hides. */
.w-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    min-height: 44px;
    box-sizing: border-box;
    padding: 8px 14px;
    border-bottom: 1px solid var(--line);
    font-size: var(--fs-body);
    line-height: 1.35;
}
.w-row:last-child,
.widget:not(.open) .w-row:has(+ .w-row.w-xtra) { border-bottom: 0; }
/* settings folds (Du → Mitteilungen · Daten & Konto): a native <details> wearing the quiet
   upper-case section label, chevron at the right; closed by default so the page stays short */
/* ── Falt-Sektionen: EIN Aussehen, überall ──────────────────────────────────────────
   A named group you open and shut looks the same wherever it stands: the HEAD is the handle — a
   heading that ends in the app's own chevron (.fold-chev), which turns when it opens. The body
   gets air before its first row. No bar, no outline, no box: these sections live inside forms
   and feeds, between other rows, and a frame on every second one reads as a card that is not one.
   Three markups share it, because their surroundings differ, not their behaviour:
     .settings-fold  <details><summary>            — the settings sheet
     .sec-fold       <details><summary.sec-head>   — a section of a feed (Module.foldSection)
     .prep-sec       div.prep-head + .open class   — the recipe's preparation sections
   NOT this family: the "+ n weitere" expanders (.w-foot / .fy-*-foot / expandFoot) — those have
   no head at all, their handle is a FOOT under a truncated list. */
.settings-fold > summary,
.sec-fold > summary.sec-head,
.prep-sec > .prep-head,
.kuer-fold > .kuer-line {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    list-style: none;
    border: 0;
    border-radius: var(--r-ctl);
    -webkit-tap-highlight-color: transparent;
}
.settings-fold > summary::-webkit-details-marker,
.sec-fold > summary.sec-head::-webkit-details-marker { display: none; }
/* the editor's „Weitere Angaben" is the sheet's fold head: a hairline over it, square */
.kuer-fold > .kuer-line { border-top: 1px solid var(--line); border-radius: 0; }

/* open: the head takes full ink; the turned chevron is the mark — a frame or a fill repeated
   down a surface where most sections stand open shouts the same thing a dozen times */
.sec-fold[open] > summary.sec-head,
.prep-sec.open > .prep-head { color: var(--ink); }

/* What is WAITING in a section, beside what is in it: a word right behind the name (and its
   sum) — red once a day has passed, amber while it is still to come or wants a look (not yet
   debited, a budget over), ink while it is only due today (the app paints "today" in ink; red
   is reserved for late). The plain count keeps its own place at the right. */
.sec-head-alert {
    font-size: var(--fs-sub);
    font-weight: 500;
    color: var(--ink2);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.sec-fold-late .sec-head-alert { color: var(--due-ink); }
.sec-fold-pend .sec-head-alert { color: var(--pend-ink); }
.sec-fold-due .sec-head-alert { color: var(--ink); }

/* the one chevron: the app's own stroke (icons.css), pushed to the right edge, always the
   glyph ink — shut it points on (›), open it points down (˅) */
.fold-chev { flex: none; margin-left: auto; font-size: 12px; color: var(--ink3); transform: rotate(-90deg);
    transition: transform var(--transition-fast); }
.settings-fold[open] > summary .fold-chev,
.sec-fold[open] > summary.sec-head .fold-chev,
.prep-sec.open > .prep-head .fold-chev,
.kuer-fold.open > .kuer-line .fold-chev { transform: none; }
/* the label takes its own width — its sum and its alert follow right behind it; the count (or
   the chevron alone) is pushed to the right edge, the chevron then stands beside the count */
.sec-fold > summary.sec-head > .sec-head-label {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--ink);
}
.sec-head-meta + .fold-chev, .sec-head-add + .fold-chev { margin-left: 0; }
.prep-sec > .prep-head .fold-chev { margin-left: 4px; }

/* THE SHEET'S FOLD HEAD (.kfold — the settings groups, an editor's „Weitere Angaben", the help's
   headings): 44 high, a hairline over it, the title in ink 15/500, what is inside in --ink2 behind
   it, the chevron at the right; head and body stand on the sheet's edge like every other row */
.settings-fold { margin: 0; }
.settings-fold > summary,
.help-body .sec-fold > summary.sec-head {
    min-height: 44px;
    box-sizing: border-box;
    margin: 0;
    padding: 8px 0;
    border-top: 1px solid var(--line);
    border-radius: 0;
    font-size: var(--fs-body);
    font-weight: 400;
    color: var(--ink2);
    gap: 8px;
}
.settings-panel > .settings-fold:first-child > summary { border-top: 0; }
.settings-fold > summary > b,
.help-body .sec-fold > summary.sec-head > .sec-head-label { flex: none; font-weight: 500; color: var(--ink); white-space: nowrap; }
.settings-fold > summary > .fold-sub { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.settings-fold > summary > .fold-sub:empty { display: none; }
.settings-fold[open] > summary > .fold-sub.when-shut { display: none; }
.settings-fold > summary > .set-info { margin: -6px 0 -6px -6px; }
/* the body's rows follow the head directly and the next head follows the last row — the rows'
   own height is the air (a list or a field keeps its margins) */
.settings-fold > .settings-fold-body { padding: 0; }
.settings-fold-body > :last-child { border-bottom: 0; }

/* a section of a feed keeps .sec-head's voice and only gains the chevron; 2px to its card, the
   page's gap above it (12 between sections, 8 on the dense pages) */
.sec-fold > summary.sec-head {
    gap: 6px;
    padding: 0 2px;
    margin: 0 0 2px;
}
.sec-fold + .sec-fold { margin-top: 12px; }
.module-finances .sec-fold + .sec-fold,
.module-household .sec-fold + .sec-fold,
.module-travel .sec-fold + .sec-fold { margin-top: 8px; }
.sec-fold[open] > .sec-fold-body { padding-top: 0; }   /* the card stands 2 under its head (the head's own margin) */
/* the help sheet (the menu's last entry): the intro under the tiles, then its sections as the
   sheet's fold heads (above), one after the other, each a list of sentences on quiet dots */
.help-body .help-intro { margin: 10px 0 2px; font-size: 14px; line-height: 1.5; color: var(--ink2); }
.help-body .sec-fold { margin-top: 0; }
.help-body ul { list-style: none; margin: 0; padding: 0; }
.help-body li { position: relative; margin: 0; padding: 3px 0 3px 14px; font-size: 14px; line-height: 1.5; color: var(--ink); }
.help-body li::before { content: ""; position: absolute; left: 0; top: 11px; width: 5px; height: 5px; border-radius: 50%; background: var(--line2); }


/* ONE checkbox for the whole app — the drawn ink check. The #app-scoped selectors pull the
   sheets' native checkboxes (import preview, export, support consent, confirm extra) onto the
   same treatment, so no platform-styled box ever sits next to a drawn one. */
.w-check,
#app .hl-opt input,
#app .cal-imp-row input[type="checkbox"],
#app .exp-row input[type="checkbox"],
#app .confirm-sheet .confirm-extra input {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    padding: 0;           /* the generic .popup-body input padding must not inflate the box */
    box-sizing: border-box;
    cursor: pointer;
    flex: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1.5px solid var(--line2);
    background: transparent;
    position: relative;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
/* the finger gets a 40px square around a 17–18px box: an invisible ::before, so the drawn box
   and its ink tick (::after) stay exactly as they are */
.w-check::before,
.notes-check::before,
.fin-check::before {
    content: "";
    position: absolute;
    inset: -11px;
}
.w-check:checked,
#app .hl-opt input:checked,
#app .cal-imp-row input[type="checkbox"]:checked,
#app .exp-row input[type="checkbox"]:checked,
#app .confirm-sheet .confirm-extra input:checked { background: var(--ink); border-color: var(--ink); }
.w-check:checked::after,
#app .hl-opt input:checked::after,
#app .cal-imp-row input[type="checkbox"]:checked::after,
#app .exp-row input[type="checkbox"]:checked::after,
#app .confirm-sheet .confirm-extra input:checked::after {
    content: "";
    position: absolute;
    left: 7px;
    top: 3.5px;
    width: 5px;
    height: 10px;
    border: solid var(--card);
    border-width: 0 1.8px 1.8px 0;
    transform: rotate(43deg);
}

.w-row .txt {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
}
/* two-line row body: bold title line + muted subline (span, end time, kind, due state) */
.w-row .txt > b {
    display: block;
    font-size: 14px;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
}
.w-row .txt .w-sub {
    display: block;
    font-size: var(--fs-sub);
    font-weight: 400;
    color: var(--ink2);
    margin-top: 1px;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* calendar cards (Heute/Demnächst): titles wrap to TWO lines before ellipsizing, so an
   appointment name stays readable; the subline keeps its one-line clamp */
.cal-wcard .w-row .txt { white-space: normal; }
/* past the fold's last row: the way into the calendar, where the whole range lives */
.cal-wcard .cal-w-all .txt > b { font-weight: 500; color: var(--ink2); }
.cal-wcard .cal-w-all > i { margin-left: auto; color: var(--ink3); font-size: 12px; }
.cal-wcard .w-row .txt > b {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
}
.cal-wcard .w-row .txt .w-sub { white-space: nowrap; }
.w-row .q { color: var(--ink2); font-weight: 400; }
/* row linkages: glyph + label pills under the title; tapping opens the target's editor
   in place (no ×, no module switch — removal lives in the editors) */
.w-tags { display: flex; gap: 5px; margin: 4px 0 1px; flex-wrap: wrap; }
/* the meta chip (.mc.box): 22 high, a --field pill, 12/500 in --ink2 — the paperclip and the words */
.w-link {
    position: relative;   /* anchors the ::after tap area */
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 22px;
    box-sizing: border-box;
    font-size: var(--fs-label);
    font-weight: 500;
    padding: 0 7px;
    border-radius: var(--r-pill);
    background: var(--field);
    border: 0;
    color: var(--ink2);
    white-space: nowrap;
    flex-shrink: 0;
    cursor: pointer;
    font-family: inherit;
    -webkit-tap-highlight-color: transparent;
}
.w-link i { font-size: 13px; }
/* a 22px chip is too small a target: the finger gets 40px of height, the chip keeps its look */
.w-link::after { content: ""; position: absolute; inset: -9px 0; }
/* content-sized, unlike the field menus that inherit their anchor's width */
.w-linkmenu { min-width: 190px; max-width: min(320px, calc(100vw - 16px)); width: max-content; }
.w-linkmenu .mg-select-opt { display: flex; align-items: center; gap: 8px; }
/* one list row = the target (opens it) + an optional × (severs the link where it is stored) */
.w-linkrow { display: flex; align-items: center; gap: 2px; }
.w-linkrow .mg-select-opt { flex: 1; min-width: 0; }
.w-linkrow .mg-select-opt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.w-linkx {
    flex-shrink: 0;
    background: transparent;
    border: 0;
    color: var(--ink3);
    cursor: pointer;
    padding: 8px 8px;
    border-radius: 8px;
    font-size: 11px;
    -webkit-tap-highlight-color: transparent;
}
.w-linkx:hover, .w-linkx:active { color: var(--due-ink); background: var(--card2); }
/* person/thing chips lead with a mini initials circle in the subject's color */
.w-link .mi {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    font-size: 7.5px;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: var(--pc-soft, var(--card2));
    color: var(--pc-ink, var(--ink2));
}
/* rows with a form behind them */
.w-row.tap { cursor: pointer; }
/* the fold foot under a folded list: "n weitere" + chevron at the right end, no line; open flips
   the chevron and says "weniger" */
.w-foot {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 4px;
    width: 100%;
    border: 0;
    background: transparent;
    color: var(--ink2);
    font-size: var(--fs-cap);
    font-weight: 500;
    font-family: inherit;
    padding: 6px 14px 8px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.w-foot i { font-size: 12px; color: var(--ink3); transition: transform 250ms ease; }
.widget.open .w-foot i { transform: rotate(180deg); }
/* open, the line says "weniger" in place of "n weitere" — never a bare chevron */
.w-foot .w-less, .fy-band-head .w-less { display: none; }
.widget.open .w-foot .w-more { display: none; }
.widget.open .w-foot .w-less { display: inline; }
/* rows beyond the collapsed cap — revealed by the expander */
.w-row.w-xtra { display: none; }
.widget.open .w-row.w-xtra { display: flex; }
/* inline links: ink + underline, never browser blue. A card's TITLE link (bookmark, recipe) reads
   like every other card title — the address under it already says it is a link. */
a.notes-link { color: var(--ink); text-decoration: underline; text-underline-offset: 2px; }
a.notes-link:visited { color: var(--ink); }
/* a bookmark's title is its link: underlined quietly */
.notes-title > a.notes-link { text-decoration: underline; text-decoration-color: var(--line2); text-underline-offset: 3px; }
.notes-title > a.notes-link.notes-link-quiet { text-decoration: none; }
/* the one line an empty card says, centred, with its full stop */
.w-emptyline { padding: 14px; text-align: center; font-size: var(--fs-hint); color: var(--ink2); }

/* Heute card: the time column 44 — the start, the end under it on a short hairline — and the
   entry's colour bar beside the text */
.w-row.cal-w-ev { align-items: stretch; flex-wrap: nowrap; }
.cal-widget-time {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 30px;
    font-size: var(--fs-sub);
    font-weight: 500;
    line-height: 1.3;
    color: var(--ink2);
    width: 44px;
    flex: none;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.cal-widget-time > small { display: block; font-size: var(--fs-cap); font-weight: 400; color: var(--ink2); }
.cal-widget-time > small::before { content: ""; display: block; width: 1px; height: 6px; margin: 1px 0 1px 9px; background: var(--line2); }
.cal-w-bar { flex: none; align-self: stretch; width: 3px; min-height: 30px; border-radius: 2px; background: var(--pc, var(--line2)); }
/* Demnächst card: the left column, 34 wide, stacks the weekday over the day's number */
.cal-widget-time.cal-wdate {
    width: 34px;
    align-items: center;
    font-size: var(--fs-cap);
    font-weight: 400;
    line-height: 1.15;
}
.cal-widget-time.cal-wdate > b { font-size: 17px; font-weight: 400; color: var(--ink); }
.w-row.cal-w-dated { gap: 12px; }
/* both cards: the Für capsule sits on the row's first 30 — the axis of its first line — however
   many lines the text runs to */
.cal-wcard .w-row > .who { align-self: flex-start; min-height: 30px; }

/* Monatsplaner card — the wall planner: one row per day, one column per chosen person. The
   outer grid is day | content; the head row and every day's content hold the same inner grid
   with one auto column per person, so names and entries share their columns. No lines, no
   shades: the capsules carry the colour. */
.cal-planner { container-type: inline-size; } /* the wide block below measures the CARD, not the panel */
/* the days from the third week on wait behind the card's foot */
.cal-planner:not(.open) .cal-mp-row.w-xtra { display: none; }
.cal-planner.open > .w-foot i { transform: rotate(180deg); }
.cal-planner.open > .w-foot .w-more { display: none; }
.cal-planner.open > .w-foot .w-less { display: inline; }
/* scoped to the card: .cal-mp is also the calendar's month PICKER further down (a flex column
   with a 14px gap), and the later rule would otherwise flatten this grid into stacked rows and
   push its columns and days apart — every property that block sets has to be answered here */
.cal-planner .cal-mp { display: grid; grid-template-columns: 40px minmax(0, 1fr); gap: 0; padding: 0 10px 10px; }
/* the calendar's planner stands on a card of its own (no head over it) */
.cal-planner-card { background: var(--card); border-radius: var(--r-card); }
.cal-planner-card .cal-mp { padding-top: 8px; }
.cal-planner-card > .w-foot { padding-top: 0; }
.cal-planner-card > .cal-empty { padding: 0 14px 14px; }
.cal-mp-hd, .cal-mp-row { display: contents; }
.cal-mp-cols { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 0 2px; min-width: 0; }
.cal-mp-hd .cal-mp-cols { padding-bottom: 8px; }
/* a column's head: the person's badge over the name, centred over the column */
.cal-mp-who {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    min-width: 0;
    padding: 2px 3px 4px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.cal-mp-who .nm { max-width: 100%; font-size: 11px; font-weight: 500; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-mp-tight .cal-mp-who .nm { display: none; } /* six or more people: badges only */
/* the day: the number in the serif over the weekday, both left, at the top of the row however
   many lanes the day holds */
.cal-mp-day {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    padding: 5px 2px 3px 0;
    border: 0;
    background: transparent;
    font-family: inherit;
    font-size: 11px;
    font-weight: 400;
    line-height: 1.2;
    color: var(--ink2);
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.cal-mp-row > * { min-height: 23px; min-width: 0; }
.cal-mp-day b { display: block; color: var(--ink); font-weight: 400; text-align: left; font-variant-numeric: tabular-nums; }
.cal-mp-day i { font-style: normal; font-size: 11px; color: var(--ink2); overflow: hidden; }
.cal-mp-cell { display: flex; flex-direction: column; justify-content: center; gap: 2px; padding: 2px; }
/* the day's lanes: every capsule is placed by column, so one can span several — what collides
   with a spanning capsule moves a lane down */
.cal-mp-lanes { display: grid; gap: 2px; align-items: stretch; min-width: 0; }
/* an entry: a soft capsule 22 high in the column's person color — the badge's and the dot's color */
.cal-mp-ev {
    font-size: 11px;
    line-height: 22px;
    height: 22px;
    box-sizing: border-box;
    font-weight: 500;
    color: var(--pc-ink, var(--ink2));
    background: var(--pc-soft, var(--line));
    border-radius: 7px;
    padding: 0 7px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cal-mp-ev.tap { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.cal-mp-ev .t { display: none; font-weight: 500; opacity: 0.8; margin-right: 3px; font-variant-numeric: tabular-nums; }
.cal-mp-ev.band { text-align: center; color: var(--ink); background: var(--line); } /* for the whole household: every column's colour (inline) */
/* an entry for SEVERAL people: one capsule over their columns. Adjacent people share a run —
   one rounded capsule, their colours side by side, the title written once across it; a column
   that is not part of the entry is left unfilled and only crossed by the bridge, so colour alone
   ever says "belongs to". */
.cal-mp-ev.bundle { position: relative; display: grid; gap: 0 2px; padding: 0; background: none; }
.cal-mp-ev.bundle::before {
    content: "";
    position: absolute;
    left: 0; right: 0; top: 50%;
    height: 2px;
    margin-top: -1px;
    background: var(--line2);
    border-radius: 1px;
}
.cal-mp-run { position: relative; display: flex; min-width: 0; border-radius: 7px; overflow: hidden; }
/* a band: one person's colour, nothing written in it */
.cal-mp-part { flex: 1; min-width: 0; background: var(--pc-soft, var(--line)); }
/* the run's words, laid once over all its bands: the title ends in an ellipsis at the run's
   end, the +n after it stays in view */
.cal-mp-lbl { position: absolute; inset: 0; display: flex; align-items: center; gap: 3px; min-width: 0;
    padding: 0 7px; color: var(--ink); }
.cal-mp-lbl .tx { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* the people the entry is also for that have no column — without it a capsule would claim
   fewer people than the entry has */
.cal-mp-plus { flex: none; font-weight: 500; opacity: 0.75; }
@container (min-width: 560px) {
    .cal-mp-row > * { min-height: 26px; }
    .cal-mp-ev .t { display: inline; }
}

/* weather widget */
/* The condition family (wx-cond-* on each location page, mirrored on the widget root for the
   ACTIVE page) scopes the generic --wx vars — the pc-N idiom in weather colors. Every consumer
   carries a neutral fallback, so a missing class renders the plain card. */
.wx-cond-sun { --wx: var(--wx-sun); --wx-soft: var(--wx-sun-soft); --wx-ink: var(--wx-sun-ink); }
.wx-cond-suncloud { --wx: var(--wx-suncloud); --wx-soft: var(--wx-suncloud-soft); --wx-ink: var(--wx-suncloud-ink); }
.wx-cond-cloud { --wx: var(--wx-cloud); --wx-soft: var(--wx-cloud-soft); --wx-ink: var(--wx-cloud-ink); }
.wx-cond-fog { --wx: var(--wx-fog); --wx-soft: var(--wx-fog-soft); --wx-ink: var(--wx-fog-ink); }
.wx-cond-rain { --wx: var(--wx-rain); --wx-soft: var(--wx-rain-soft); --wx-ink: var(--wx-rain-ink); }
.wx-cond-snow { --wx: var(--wx-snow); --wx-soft: var(--wx-snow-soft); --wx-ink: var(--wx-snow-ink); }
.wx-cond-thunder { --wx: var(--wx-thunder); --wx-soft: var(--wx-thunder-soft); --wx-ink: var(--wx-thunder-ink); }
.wx-cond-night { --wx: var(--wx-night); --wx-soft: var(--wx-night-soft); --wx-ink: var(--wx-night-ink); }
/* Multiple weather locations swipe horizontally (one full-width snap page per place) */
.wx-pager { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.wx-pager::-webkit-scrollbar { display: none; }
.wx-page { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; }
/* now: the hour's glyph in its condition colour (no disc), the temperature in the serif 40 with
   its ° raised, the condition 14/500 over what comes (13 --ink2) */
.wx-now { display: flex; align-items: center; gap: 12px; padding: 4px 14px 8px; }
.wx-glyph { flex: none; font-size: 38px; color: var(--wx, var(--ink2)); }
/* the sun's rays drift, one turn per 90s — alive on a second glance, invisible on the first */
@media (prefers-reduced-motion: no-preference) {
    .wx-cond-sun > .wx-now > .wx-glyph { animation: wx-spin 90s linear infinite; }
}
@keyframes wx-spin { to { transform: rotate(360deg); } }
.wx-temp { line-height: 1; font-variant-numeric: tabular-nums; }
.wx-temp sup { font-size: 20px; vertical-align: 14px; }
.wx-desc { min-width: 0; font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }
.wx-desc b { display: block; font-size: 14px; font-weight: 500; color: var(--ink); }
.wx-next { display: block; }
/* the next seven hours: the hour, its glyph in its condition colour, the temperature */
.wx-hours { display: flex; justify-content: space-between; padding: 0 14px 8px; }
.wx-hours span { display: grid; justify-items: center; gap: 3px; font-size: 11px; color: var(--ink2); font-variant-numeric: tabular-nums; }
.wx-hours b { font-size: var(--fs-cap); font-weight: 500; color: var(--ink); }
.wx-hours i { font-size: 16px; color: var(--ink2); }
.wx-hours i.wx-cond-sun, .wx-hours i.wx-cond-rain, .wx-hours i.wx-cond-snow, .wx-hours i.wx-cond-thunder { color: var(--wx); }
/* the week from today: weekday, glyph, high, low and the day's condition as a 3px bar */
.wx-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; padding: 0 14px 10px; }
.wx-week span { display: grid; justify-items: center; gap: 2px; font-size: 11px; color: var(--ink2); font-variant-numeric: tabular-nums; }
.wx-week i { font-size: 16px; color: var(--ink2); }
.wx-week b { font-size: var(--fs-cap); font-weight: 500; color: var(--ink); }
.wx-week em { width: 100%; height: 3px; margin-top: 2px; border-radius: 2px; background: var(--wx, var(--wx-cloud)); }
/* the head's ˅ — unfolds the details, turns while they are open */
.wx-chev {
    margin-left: auto;
    border: 0;
    background: transparent;
    color: var(--ink3);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    font-size: 14px;
    flex-shrink: 0;
    transition: transform 250ms ease;
    -webkit-tap-highlight-color: transparent;
}
.widget.open .wx-chev { transform: rotate(180deg); }
.wx-detail { display: none; }
.widget.open .wx-detail { display: block; }
/* hourly strip: a full day from the starting hour, scrolled horizontally */
.wx-strip {
    display: flex;
    gap: 2px;
    padding: 8px 8px 2px;
    border-top: 1px solid var(--line);
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.wx-strip::-webkit-scrollbar { display: none; }
.wx-hour {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 1 0 44px;
    box-sizing: border-box;
    padding: 5px 2px;
    border-radius: 9px;
    font-size: 11px;
    font-weight: 600;
    color: var(--ink2);
    font-variant-numeric: tabular-nums;
}
/* the leading "Jetzt" chip is the anchored one — the only tinted cell in the strip (it shows
   the very code the card's tint comes from); the temperature stays --ink on every soft */
.wx-hour:first-child { background: var(--wx-soft, var(--card2)); border: 1px solid color-mix(in srgb, var(--wx, var(--line2)) 24%, transparent); color: var(--wx-ink, var(--ink2)); }
.wx-hour .i { font-size: 12px; color: var(--ink3); }
.wx-hour:first-child .i { color: var(--wx-ink, var(--ink3)); }
.wx-hour .t { font-weight: 600; font-size: var(--fs-sub); color: var(--ink); }

/* Swipe affordance on the hourly strip: a soft shadow at an edge means "more content that
   way". The cover gradients scroll WITH the content (local) and hide the shadow at the ends. */
.wx-strip {
    background:
        linear-gradient(to right, var(--card) 40%, transparent) left / 28px 100%,
        linear-gradient(to left,  var(--card) 40%, transparent) right / 28px 100%,
        radial-gradient(farthest-side at 0 50%, var(--scroll-shadow), transparent) left / 10px 100%,
        radial-gradient(farthest-side at 100% 50%, var(--scroll-shadow), transparent) right / 10px 100%;
    background-repeat: no-repeat;
    background-attachment: local, local, scroll, scroll;
}
/* the coming days as a CURVE (Wochenschau): the SVG holds only the min/max band geometry
   over a 0-100 viewBox stretched to the card — non-scaling strokes keep the lines hairline
   at every width. Labels, dots and rain bars are HTML pinned to the same percent space, so
   the type stays crisp instead of scaling with the SVG. */
.wxg { padding: 8px 13px 12px; }
.wxg-icons { display: grid; padding-bottom: 2px; }
/* each day's icon, inked in ITS OWN condition (the wx-cond class sits on the icon itself,
   so its --wx-ink beats the page's — today's tint never colors other days) */
.wxg-icons i { font-size: 14px; color: var(--wx-ink, var(--ink3)); justify-self: center; }
.wxg-plot { position: relative; height: 132px; }
.wxg-plot svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.wxg-area { fill: var(--line); fill-opacity: 0.45; }
.wxg-line { fill: none; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.wxg-line-max { stroke: var(--ink); stroke-width: 1.8px; }
.wxg-line-min { stroke: var(--ink3); stroke-width: 1.5px; }
/* the felt temperatures: faint dashed companions to their real twins */
.wxg-line-appmax { stroke: var(--ink); stroke-width: 1.1px; opacity: 0.4; stroke-dasharray: 3 3; }
.wxg-line-appmin { stroke: var(--ink3); stroke-width: 1.1px; opacity: 0.45; stroke-dasharray: 3 3; }
.wxg-dot { position: absolute; width: 6px; height: 6px; border-radius: 50%; background: var(--ink); transform: translate(-50%, -50%); }
.wxg-dot.min { width: 5px; height: 5px; background: var(--ink3); }
.wxg-hi { position: absolute; transform: translate(-50%, calc(-100% - 7px)); font-size: var(--fs-sub); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.wxg-lo { position: absolute; transform: translate(-50%, 7px); font-size: var(--fs-cap); color: var(--ink3); font-variant-numeric: tabular-nums; }
/* probability bars grow up from the base in the rain family — no rain, no bar */
.wxg-rain { position: absolute; bottom: 0; width: 12px; border-radius: 3px; background: var(--wx-rain); opacity: 0.8; transform: translateX(-50%); }
.wxg-days { display: grid; text-align: center; padding-top: 5px; }
.wxg-days b { display: block; font-size: var(--fs-sub); font-weight: 600; color: var(--ink2); }
.wxg-sub { display: block; font-size: var(--fs-label); color: var(--ink3); font-variant-numeric: tabular-nums; white-space: nowrap; }
.wxg-sub.wet { color: var(--wx-rain-ink, var(--ink2)); }
.weather-hourly-note {
    font-size: var(--fs-cap);
    color: var(--ink2);
    padding: 6px 4px;
    text-align: center;
    flex: 1;
}
/* Weather pager dots — which location page is active, and that there ARE more pages. */
/* the dots are buttons (a mouse's only way to the next place): the visible dot is ::before, the
   button around it the click area */
/* the places' dots stand in the head, between the place and the ˅ */
.wx-dots { display: flex; justify-content: center; margin-left: auto; margin-block: -6px; }
.wx-dot { border: 0; background: transparent; padding: 6px 2px; display: flex; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
.wx-dot::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--line2);
    transition: background var(--transition-fast); }
.wx-dot:hover::before { background: var(--ink3); }
.wx-dot.active::before { background: var(--ink); }

/* In stretched rows the body fills the card so bottom-pinned actions reach the bottom. */
.dash-grid .widget > .w-body { flex: 1; }
.dash-grid .widget > .wx-pager { flex: 1; }

/* EDIT MODE — drag & drop to reorder; each card stands as its compact arranging tile (.w-edit,
   _attachTools): the head — grip · name · × —, under it what the card shows and its switches;
   the card's own content waits until arranging is done */
.w-edit { display: none; }
.module-dashboard.editing .widget > :not(.w-edit),
#app .module-dashboard.editing .widget > :not(.w-edit) { display: none; }
.module-dashboard.editing .widget > .w-edit { display: block; }
.w-edit-head { display: flex; align-items: center; gap: 7px; padding: 12px 14px 6px; }
.w-edit-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--fs-head); font-weight: 500; color: var(--ink); }
.w-edit-body { display: flex; align-items: center; gap: 4px 10px; height: 56px; box-sizing: border-box; padding: 0 14px 10px; }
/* what the card shows wraps onto a second line beside the switches rather than lose its end
   ("zeigt die nächsten 12 Monate" keeps its window); only a third line ellipsizes */
.w-edit-desc { flex: 1; min-width: 0; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    line-clamp: 2; font-size: var(--fs-cap); line-height: 1.35; color: var(--ink2); }
.w-swgrp { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* × — the 26 circle on the field of the tile's head */
.w-del {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    border: 0;
    background: var(--field);
    color: var(--ink2);
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}
.w-del i { font-size: 12px; }
.w-grip { color: var(--ink3); display: flex; font-size: 16px; cursor: grab; }
.w-edit-lbl { font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); }
/* the little switch — ON is ink on the card, like every done/on control (never green); OFF is a
   muted knob on the grey track, so it reads as a switch in the dark theme too. A button
   says ON with .on; a checkbox drawn as the switch (the settings rows) with :checked. */
.swT {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    width: 44px;
    height: 26px;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--line2);
    position: relative;
    cursor: pointer;
    padding: 0;
    flex-shrink: 0;
    transition: background var(--transition-base);
    -webkit-tap-highlight-color: transparent;
}
.swT::after {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--ink3);
    transition: left var(--transition-base), background var(--transition-base);
}
.swT.on, .swT:checked { background: var(--ink); }
.swT.on::after, .swT:checked::after { left: 21px; background: var(--card); }
.swT:disabled { opacity: 0.5; cursor: default; }
/* in a sheet the generic field tone of .popup-body input must not repaint the track */
.popup-body input.swT { background: var(--line2); }
.popup-body input.swT:checked { background: var(--ink); }
.module-dashboard.editing .widget {
    box-shadow: inset 0 0 0 1.5px var(--line2);
    touch-action: pan-y;  /* swipes scroll normally; a LONG-PRESS lifts the card (see _bindDrag) */
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
}
.module-dashboard.editing .widget::before { display: none; }
.widget.drag-src {
    opacity: 0.85;
    transform: scale(0.97);
    box-shadow: var(--shadow);
    z-index: 4;
    cursor: grabbing;
}

/* the "Fertig" pill in the title row — leaves edit mode (changes save as they happen) */
.editBtn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 0;
    background: var(--field);
    border-radius: var(--r-pill);
    height: 32px;
    box-sizing: border-box;
    padding: 0 13px;
    font-family: var(--font-family);
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--ink2);
    cursor: pointer;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}
.editBtn i { font-size: 13px; }
/* In der Modul-Kopfzeile ist die Pille eine Nebensache neben dem Titel — kleiner als die
   Adder-Pillen in den Editoren, wo sie die Hauptsache ist. */
/* arranging: the bar over the foot on every page — how to arrange, and "Fertig" */
.dash-edit-bar { position: absolute; left: var(--pad); right: var(--pad); bottom: var(--pad); z-index: 5; height: 48px;
    box-sizing: border-box; display: flex; align-items: center; gap: 8px; padding: 0 8px 0 14px; border-radius: var(--r-card);
    background: var(--card); box-shadow: var(--shadow); font-size: var(--fs-sub); color: var(--ink2); }
.dash-edit-bar > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-edit-bar > .action-btn { flex: none; margin: 0; font-size: var(--fs-sub); }
.editBtn.on {
    background: var(--ink);
    color: var(--card);
}

/* The first-run setup (dashboard/setup.js): what an empty start page shows — the welcome card
   and the setup card from the top of the page, its band head and bar, its step rows (also in the
   bar's sheet), the themes sheet's chips and preview, and the one-line bar under the greeting
   while a step is still open. A done step wears the ink tick and its title struck through, the
   next one the small "Weiter". */
#app .setup-hello { grid-column: 1 / -1; box-sizing: border-box; background: var(--card); border-radius: var(--r-card); padding: 14px 14px 12px; }
#app .setup-title { line-height: 1.1; } /* the face and size come from the display-serif rule */
#app .setup-sub { font-size: var(--fs-body); color: var(--ink2); line-height: 1.35; margin: 4px 0 0; }
#app .setup-card {
    grid-column: 1 / -1;
    box-sizing: border-box;
    background: var(--card);
    border-radius: var(--r-card);
    padding: 0 0 2px;
}
/* the band head: "Schritt 3 von 5 · <next>" and how many are done at the right, over one bar */
#app .setup-band { display: flex; align-items: center; gap: 6px; padding: 8px 14px 2px; font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); }
#app .setup-band-next { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 400; }
#app .setup-band-done { margin-left: auto; flex: none; font-size: var(--fs-sub); font-weight: 500; }
#app .setup-bar-fill { position: relative; height: 6px; margin: 4px 14px 12px; border-radius: 3px; background: var(--field); overflow: hidden; }
#app .setup-bar-fill > i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: var(--ink); }
#app .setup-steps { display: flex; flex-direction: column; }
#app .setup-step {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    width: 100%;
    min-height: 44px;
    box-sizing: border-box;
    padding: 8px 14px;
    border: 0;
    border-top: 1px solid var(--line);
    background: none;
    color: var(--ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
/* in the bar's sheet the rows stand on the sheet's own inset */
#app .popup-body .setup-step, #app .popup-body .setup-band { padding-inline: 0; }
#app .popup-body .setup-bar-fill { margin-inline: 0; }
#app .setup-ck {
    width: 22px;
    height: 22px;
    margin: 4px;
    flex: none;
    box-sizing: border-box;
    border-radius: 50%;
    border: 1.5px solid var(--line2);
    display: flex;
    align-items: center;
    justify-content: center;
}
#app .setup-step.done .setup-ck { background: var(--ink); border-color: var(--ink); color: var(--card); }
#app .setup-ck i { font-size: 11px; }
/* a step holds the top: the tick in its 30 slot, the words and the pill on that slot's axis */
#app .setup-tx { flex: 1; min-width: 0; min-height: 30px; display: flex; flex-direction: column; justify-content: center; gap: 1px; }
#app .setup-tx b { font-weight: 500; font-size: var(--fs-body); line-height: 1.35; }
#app .setup-step.done .setup-tx b { color: var(--ink2); text-decoration: line-through; }
#app .setup-tx span { font-size: var(--fs-sub); color: var(--ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the next step's small "Weiter" at its right */
#app .setup-go { flex: none; height: 28px; margin-top: 1px; display: inline-flex; align-items: center; padding: 0 11px; border-radius: var(--r-pill);
    background: var(--ink); color: var(--card); font-size: var(--fs-cap); font-weight: 500; }
#app .setup-self {
    display: block;
    width: 100%;
    padding: 6px 14px 8px;
    border: 0;
    background: none;
    color: var(--ink2);
    font: inherit;
    font-size: var(--fs-cap);
    font-weight: 500;
    text-align: center;
    cursor: pointer;
}
#app .setup-bar {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    box-sizing: border-box;
    padding: 12px 14px;
    border: 0;
    border-radius: var(--r-card);
    background: var(--card);
    color: var(--ink2);
    font: inherit;
    font-size: var(--fs-sub);
    text-align: left;
    cursor: pointer;
}
#app .setup-bar span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .setup-bar i { font-size: 12px; color: var(--ink3); }
/* the themes sheet: the themes as word chips, then what comes onto the start page — a card on
   the sheet, one row per card the pick becomes */
#app .setup-themes { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; }
#app .setup-theme {
    display: inline-flex;
    align-items: center;
    height: 32px;
    box-sizing: border-box;
    padding: 0 11px;
    border-radius: var(--r-pill);
    border: 0;
    background: var(--field);
    color: var(--ink2);
    font: inherit;
    font-size: var(--fs-sub);
    font-weight: 500;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
#app .setup-theme.on { background: var(--ink); color: var(--card); }
#app .setup-preview-label { font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); margin: 0 0 6px; }
#app .setup-preview { background: var(--card2); border-radius: var(--r-card); padding: 4px 0; }
#app .setup-preview-row { display: flex; align-items: flex-start; gap: 12px; box-sizing: border-box; min-height: 50px; padding: 10px 14px; border-top: 1px solid var(--line); }
#app .setup-preview-row:first-child { border-top: 0; }
#app .setup-preview-ic { flex: none; width: 30px; height: 30px; display: grid; place-items: center; border-radius: 10px;
    background: var(--nav-fill); color: var(--ink2); font-size: 16px; }
#app .setup-preview-tx { min-width: 0; min-height: 30px; display: flex; flex-direction: column; justify-content: center; gap: 1px; }
#app .setup-preview-tx b { font-size: 15px; font-weight: 500; color: var(--ink); }
#app .setup-preview-tx span { font-size: var(--fs-sub); color: var(--ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the Übersicht sheet: its order as one segmented switch, then the word over the kind switches */
.ov-head { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.ov-head .seg-tabs { margin: 0; }
.ov-label { font-size: var(--fs-cap); color: var(--ink2); }

/* ============================== calendar ============================== */

.module-calendar { display: flex; flex-direction: column; height: 100%; position: relative; }

.cal-head { display: flex; align-items: center; gap: 6px; padding: 12px var(--pad); min-height: 70px; box-sizing: border-box; flex: none; }
/* the HERO: the head and the view switcher are ONE card, the switcher its last row — the finance
   hero's anatomy (12/13/12 padding, title and strip flush) */
.cal-hero { flex: none; margin: 8px var(--pad) 8px; padding: 12px 13px 12px; background: var(--card); border-radius: var(--r-card); }
.cal-hero > .cal-head { padding: 0; min-height: 0; }
.cal-hero > .cal-views { margin: 10px 0 0; height: 36px; }
/* the month's marks fade at their end only while they scroll (.more) */
.cal-hero > .hero-marks:not(.more) { -webkit-mask-image: none; mask-image: none; }
/* the view's state under the title („KW 41 · 5.–11. Okt · 9 Termine") */
.cal-sub { margin-top: 4px; font-size: var(--fs-sub); line-height: 1.4; color: var(--ink2); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the two-line title composition: the big serif MAIN line (type from the display-serif rule
   at the end of the file) beside or under a small sans part (year, weekday) — nothing gets
   cut off; each line ellipsizes on its own as a last resort */
.cal-title { flex: 1; min-width: 0; line-height: 1.1; }
/* in the calendar's head the title keeps its own width: the menu circle stands right behind it,
   ‹ Heute › at the row's end */
.cal-head > .cal-title { flex: 0 1 auto; }
.cal-head > .cal-steps { margin-left: auto; }
/* the title is a button now (it jumps months) — it must still read as a heading */
button.cal-title { appearance: none; border: 0; background: transparent; padding: 0; text-align: left; cursor: pointer; font: inherit; line-height: 1.1; color: inherit; }
/* month picker: ‹ the year in the serif › over twelve months on the field tone, the shown one inked */
.cal-mp { display: flex; flex-direction: column; gap: 12px; padding: 0; }
.cal-mp-year { display: flex; align-items: center; justify-content: center; gap: 10px; }
.cal-mp-year b { color: var(--ink); font-variant-numeric: tabular-nums; min-width: 4ch; text-align: center; }
#app .cal-mp-year .cal-nav { width: 32px; height: 32px; font-size: 15px; display: grid; place-items: center; }
.cal-mp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.cal-mp-m {
    appearance: none;
    border: 0;
    border-radius: var(--r-ctl);
    background: var(--field);
    color: var(--ink);
    font: inherit;
    font-size: var(--fs-body);
    font-weight: 400;
    height: 44px;
    padding: 0;
    cursor: pointer;
    position: relative;
}
.cal-mp-m.on { background: var(--ink); color: var(--card); }
/* the month the household is actually in, whatever is shown: one dot in the word's ink */
.cal-mp-m.now::after { content: ""; position: absolute; left: 50%; bottom: 6px; width: 4px; height: 4px; margin-left: -2px; border-radius: 50%; background: currentColor; }
.cal-title-main, .cal-title-info { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-title-main { line-height: 1.1; }
.cal-title-info {
    font-family: var(--font-family);
    font-size: var(--fs-sub);
    font-weight: 500;
    letter-spacing: 0.02em;
    color: var(--ink2);
    line-height: 1.3;
    margin-top: 1px;
}
/* the month (and the week, under its month): its year inline beside the serif, raised to the
   capitals; the day: its weekday as a caption above */
.cal-title.v-month .cal-title-main, .cal-title.v-month .cal-title-info,
.cal-title.v-week .cal-title-main, .cal-title.v-week .cal-title-info { display: inline; }
.cal-title.v-month .cal-title-info, .cal-title.v-week .cal-title-info { margin-left: 5px; vertical-align: 5px; }
/* ...on ONE line: what the head cannot hold even a size down (.long) ends in an ellipsis, so the
   year never runs under the menu circle */
.cal-title.v-month, .cal-title.v-week { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cal-title-cap { display: block; font-family: var(--font-family); font-size: var(--fs-sub); font-weight: 500; letter-spacing: 0.02em; color: var(--ink2); line-height: 1.35; margin-bottom: -3px; }
/* the nav cluster wears --nav-fill (see the structural tokens): navigation, not action */
.cal-nav {
    width: 28px;
    height: 28px;
    flex: none;
    border: 0;
    background: var(--nav-fill);
    color: var(--ink);
    border-radius: var(--r-pill);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    padding: 0;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.cal-nav:active { transform: scale(var(--button-click-scale)); }
/* the ONE edit control of a record page — the hero of a baby, a health subject, a trip: the pen
   on a nav-fill disc, the shape of the ‹ › and of the pen on a finance detail bar */
.head-edit {
    width: 28px;
    height: 28px;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--nav-fill);
    color: var(--ink2);
    font-size: 14px;
    display: grid;
    place-items: center;
    cursor: pointer;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.head-edit:active { transform: scale(var(--button-click-scale)); }
.cal-today {
    height: 32px;
    flex: none;
    font-family: var(--font-family);
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--ink);
    background: var(--nav-fill);
    border: 0;
    border-radius: var(--r-pill);
    padding: 0 10px;
    cursor: pointer;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.cal-today:active { transform: scale(var(--button-click-scale)); }
/* ‹ Heute › as ONE pill: 32 high on the field fill, the discs transparent inside it */
.cal-steps { display: inline-flex; align-items: center; height: 32px; flex: none; border-radius: var(--r-pill); background: var(--field); }
.cal-steps > .cal-nav { width: 26px; min-width: 26px; height: 32px; background: transparent; font-size: 18px; display: grid; place-items: center; }
.cal-steps > .cal-today { height: 32px; padding: 0 5px; background: transparent; }

/* view switcher — one segmented control (Monat/Woche/Tag/Demnächst), active = ink */
.cal-views {
    display: flex;
    gap: 2px;
    background: var(--field);
    height: 36px;
    box-sizing: border-box;
    padding: 3px;
    border-radius: var(--r-ctl);
    margin: 0 var(--pad) 12px;
    flex: none;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
.cal-views::-webkit-scrollbar { display: none; }
.cal-view-btn {
    flex: 1 0 auto;
    border: 0;
    background: transparent;
    cursor: pointer;
    font-family: var(--font-family);
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--ink2);
    padding: 0 8px;
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    transition: background var(--transition-base), color var(--transition-base);
    -webkit-tap-highlight-color: transparent;
}
.cal-view-btn.active { background: var(--ink); color: var(--card); }

/* month grid — one card, 8 under the hero; a 24 KW gutter (ISO week numbers) leads the 7 day
   columns under an empty corner */
.cal-grid {
    display: grid;
    grid-template-columns: 24px repeat(7, minmax(0, 1fr));
    gap: 0;
    margin: 0 var(--pad) 8px;
    padding: 6px 8px 8px;
    background: var(--card);
    border-radius: var(--r-card);
    flex: none;
}
.cal-wd, .cal-kwhd { text-align: center; font-size: 11px; font-weight: 500; color: var(--ink2); padding: 2px 0 6px; }
/* the week's number level with the middle of the day disc */
.cal-kw {
    padding-top: 9px;
    text-align: center;
    font-size: 10px;
    font-weight: 400;
    color: var(--ink2);
    font-variant-numeric: tabular-nums;
}
/* a day: 44 high, the disc at its top, the dots 1 under it */
.cal-cell {
    position: relative;
    height: 44px;
    border: 0;
    background: transparent;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 1px;
    border-radius: 10px;
    padding: 1px 0 0;
    -webkit-tap-highlight-color: transparent;
}
.cal-num {
    color: var(--ink);
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    /* one digit on a disc: proportional figures centre their ink (a tabular 7 sits right of
       its box); the figure stands in its own block whose line box is trimmed to the figure
       height, so the disc centres the ink, not the font's ascent and descent */
    font-variant-numeric: proportional-nums lining-nums;
}
.cal-num > span { display: block; line-height: 1; text-box: trim-both cap alphabetic; }
.cal-other .cal-num { color: var(--ink2); }
/* today = filled ink; a selected other day = ink ring */
/* three states of the day disc: today = a ring, chosen = filled, both = filled with an outer ring */
.cal-todaycell .cal-num { box-shadow: inset 0 0 0 1.5px var(--ink); }
.cal-selected .cal-num { background: var(--ink); color: var(--card); }
.cal-selected.cal-todaycell .cal-num { box-shadow: 0 0 0 2px var(--card), 0 0 0 3.5px var(--ink); }
/* a public holiday: its day's figure underlined — the figure's own block, so the line keeps to
   the ink */
.cal-hol .cal-num > span { text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 4px; text-decoration-color: var(--ink2); }
/* month-grid dots — one per person colour the day holds (the quiet ink without a person) */
.cal-dots { display: flex; gap: 3px; height: 4px; }
.cal-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--pc, var(--ink3)); }

/* month view: grid + agenda share ONE scroller; wide containers set them side by side */
.cal-cols {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    display: flex;
    flex-direction: column;
}
.cal-agenda { padding: 0 var(--pad) 96px; }
@container (min-width: 600px) {
    .cal-cols {
        display: grid;
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
        gap: 12px;
        align-items: start;
        align-content: start;
        padding: 0 var(--pad);
    }
    .cal-cols .cal-grid { margin: 0 0 8px; }
    .cal-cols .cal-agenda { padding: 0 0 96px; }
}
/* week/day/upcoming shells — day cards fill the shell's width (the shell is the centered
   app column on wide screens, so no separate cap is needed); the hero's 8 stand above */
.cal-week, .cal-day, .cal-upcoming {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 0 var(--pad) 96px;
}

/* day headers ARE the app's section heading now (Module.sectionHead / .sec-head); these three
   keep only their spacing: 10 to their card, a card 8 to the next day's head */
.sec-head.cal-agenda-label, .sec-head.cal-up-day, .sec-head.cal-week-hd { margin: 0 0 10px; }
/* the day head's forecast right behind the day: its glyph and „17°/7°" */
.cal-wx { display: inline-flex; align-items: center; gap: 4px; margin-left: 2px; font-size: var(--fs-sub); font-weight: 400; color: var(--ink); white-space: nowrap; font-variant-numeric: tabular-nums; }
.cal-wx > i { font-size: 14px; }

/* one CARD per day: event rows inside, hairline-separated — borderless like the notes cards */
.cal-daylist {
    background: var(--card);
    border-radius: var(--r-card);
    overflow: hidden;
    margin-bottom: 8px;
    padding-bottom: 0;
}

/* Upcoming — the heading of each later month above its days (the current one has none):
   6 over it beside the 8 every card keeps, 2 + the head's 8 under it */
.cal-up-month {
    color: var(--ink);
    margin: 14px 2px 10px;   /* the serif and its size come from the display list at the end */
}

.cal-empty { color: var(--ink2); font-size: var(--fs-hint); text-align: center; }

/* event row */
.cal-event {
    display: flex;
    gap: 10px;
    align-items: start;
    padding: 10px 14px;
    border-bottom: 1px solid var(--line);
    cursor: pointer;
}
.cal-event:last-child { border-bottom: 0; }
/* the "Für" capsule at the row's right edge (the pencil's old seat), centred on the row's 30 axis */
.cal-event > .notes-avs { margin-left: auto; flex: none; min-height: 30px; }
.cal-event.cal-static { cursor: default; } /* nothing to open (holiday, someone else's birthday) */
.cal-event.cal-static .cal-event-title { color: var(--ink2); }
.cal-event.cal-static .cal-bar { background: var(--line2); }
.cal-event.cal-tick .cal-bar { background: transparent; }
/* a subscribed event only its source changes reads like a static row — it still opens its
   read-only card */
.cal-event.cal-ro .cal-event-title, .cal-event.cal-ro .cal-time { color: var(--ink2); }
.cal-event.cal-ro .cal-bar { background: var(--line2); }
/* a write still waiting for the connection: an amber dot 5 at the row's left edge, on its middle */
.cal-event.cal-pending { position: relative; }
.cal-event.cal-pending::after { content: ""; position: absolute; left: 5px; top: 50%; width: 5px; height: 5px; margin-top: -2px;
    border-radius: 50%; background: var(--pend); }
/* an open to-do past its day: „Überfällig" and the date in the due ink */
.cal-late { font-size: var(--fs-sub); font-weight: 500; color: var(--due-ink); }
/* the time column: one time centred on the row's 30 axis; with its end the stack starts at the
   top */
.cal-time {
    font-size: var(--fs-sub);
    font-weight: 500;
    color: var(--ink2);
    width: 50px;
    flex: none;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    min-height: 30px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1.3;
}
/* „Ganztg." a step smaller, like the end time */
.cal-time.cal-allday { font-size: var(--fs-cap); }
.cal-time-end { display: block; font-size: var(--fs-cap); font-weight: 400; }
/* the vertical connector between a timed event's start and end */
.cal-time-line { display: block; width: 1px; height: 6px; background: var(--line2); margin: 1px 0 1px 9px; }
/* the 3px color bar beside the time — the first subject's person color */
.cal-bar {
    width: 3px;
    border-radius: var(--r-pill);
    align-self: stretch;
    flex-shrink: 0;
    background: var(--pc, var(--line2));
}
.cal-event-meta .ppl { margin-top: 0; }
.cal-event-body { min-width: 0; flex: 1; }
.cal-event-title { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; overflow-wrap: break-word; hyphens: auto; }
.cal-event-meta { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 3px; align-items: center; }
/* a meta chip: its glyph 13 and its words on one line — a long place ends in an ellipsis */
.cal-meta-chip { display: inline-flex; align-items: center; gap: 3px; min-width: 0; max-width: 100%; font-size: var(--fs-sub); color: var(--ink2); white-space: nowrap; }
.cal-meta-chip > i { flex: none; font-size: 13px; }
.cal-meta-tx { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* a span of days in a boxed pill */
.cal-meta-chip.box { height: 22px; box-sizing: border-box; padding: 0 7px; gap: 4px; border-radius: var(--r-pill); background: var(--field); font-size: var(--fs-cap); font-weight: 500; }
/* the meeting link („Link") and what hangs on the row („2 Dateien · 1 Link") read like the place
   beside them: glyph and words 13 in --ink2, no fill — only the span of days is boxed */
.cal-event-meta .w-link { height: auto; padding: 0; gap: 3px; background: none; font-size: var(--fs-sub); font-weight: 400; line-height: inherit; }
/* ...and its tap area reaches only half the 4 px line gap, never into the line above or below */
.cal-event-meta .w-link::after { inset: -2px 0; }
.cal-event-meta .w-tags { margin: 0; }
/* clickable attachment chip (attachChip): tap opens the viewer (or a menu when several).
   The host class carries the look; a button host gets the interactive basics here. */
/* the category line (TERMIN / EINKAUF / …) — quiet uppercase ABOVE the title */
.cal-badge {
    font-size: var(--fs-cap);
    font-weight: 500;
    color: var(--ink2);
    margin-bottom: 1px;
}


/* editor sheet extras */
.cal-hidden { display: none !important; }
.cal-skip-list { display: flex; flex-direction: column; gap: 6px; }
.cal-skip-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.cal-skip-date { font-size: var(--fs-body); color: var(--ink2); font-variant-numeric: tabular-nums; }
.cal-skip-row .cal-skip-restore { width: auto; flex: none; padding: 5px 12px; font-size: var(--fs-body); }
/* „Ganztägig": a setting row — its word 15/500 in ink left, the app's switch right, 48 high;
   the whole row is the label, so a tap anywhere flips it */
.popup-body .form-row.cal-check-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 48px; margin: -6px 0 6px;
    font-size: var(--fs-body); font-weight: 500; color: var(--ink); cursor: pointer;
}
/* the switch: the generic .popup-body input would make it a 100%-wide filled field */
.popup-body input.cal-check.swT { width: 44px; height: 26px; padding: 0; border: 0; border-radius: var(--r-pill); background: var(--line2); }
.popup-body input.cal-check.swT:checked { background: var(--ink); }
/* the birthday bridge under the title: the quiet sentence, the small pill that re-lands it */
.cal-bday-hint { display: flex; align-items: center; gap: 12px; min-height: 40px; padding-top: 6px; font-size: var(--fs-sub); color: var(--ink2); }
.cal-bday-hint > span { flex: 1; min-width: 0; }
.cal-bday-go {
    flex: none; height: 28px; padding: 0 11px; border: 0; border-radius: var(--r-pill);
    background: var(--field); color: var(--ink); font-family: var(--font-family); font-size: var(--fs-cap); font-weight: 500;
    white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent;
}

/* ============================== notes ============================== */

.module-notes {
    display: flex;
    flex-direction: column;
    height: 100%;
    position: relative;
}
/* the head stands in the feed's scroller and scrolls away with it: 8 under the page's head (the
   feed's own top padding), 12 to the first section — the page's gap (the dense pages, Reisen,
   keep 8) */
#app .notes-layer > .hero-lean { margin: 0 0 12px; }
#app .module-travel > .hero-lean { margin-bottom: 8px; }

/* the one scrolling feed — the dashboard's grid and the module panel (where the desktop's finance,
   calendar and dashboard pages scroll) included, or Windows draws its classic bar there alone and
   the + stands 15 further in than on the other pages */
.notes-layer, .tab-layer, .cal-upcoming, .dash-grid, #app .baby-page, #app main > div[data-module] { scrollbar-width: none; }
/* scrolled (bindScrollEdges), a list fades under the bar above it over 12px instead of being cut */
.notes-layer.is-scrolled, .tab-layer.is-scrolled, .dash-grid.is-scrolled, .cal-upcoming.is-scrolled, #app .baby-page.is-scrolled {
    -webkit-mask-image: linear-gradient(to bottom, transparent, currentColor 12px);
    mask-image: linear-gradient(to bottom, transparent, currentColor 12px);
}
.notes-layer::-webkit-scrollbar, .tab-layer::-webkit-scrollbar, .cal-upcoming::-webkit-scrollbar, .dash-grid::-webkit-scrollbar, #app .baby-page::-webkit-scrollbar,
#app main > div[data-module]::-webkit-scrollbar { display: none; }
/* the list ends 72 over the footer: the FAB (56) and 16 — nothing lies under the + */
.notes-layer {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
    padding: 8px var(--pad) 72px;
    display: flex;
    flex-direction: column;
}
/* A scrollable flex column SHRINKS its children once content overflows — every card lost
   a few px and overflow:hidden clipped the meta line (visible on phones). Never shrink. */
.notes-layer > * { flex-shrink: 0; }
/* a section's card ends its section: the next head stands the page's 12 under it, not 20 */
.notes-layer .sec-fold-body > :last-child { margin-bottom: 0; }
/* the Wochenplan of the Kategorie view: the week strip on a card; empty, a blank card that
   opens the week plan */
.notes-week { background: var(--card); border-radius: var(--r-card); overflow: hidden; }
.notes-week.tap { cursor: pointer; }
.notes-week .mw-strip { padding-top: 12px; }
.notes-layer .notes-week .notes-blank { margin-top: 0; padding: 12px 20px 14px; }
.notes-week .notes-blank .nb-mark { margin-bottom: 12px; }
.notes-week .notes-blank p { margin-top: 4px; line-height: 1.5; }
/* directional slide of the shared .tab-layer surfaces (baby, calendar, entity manager) */
@keyframes notesSlideFromRight { from { opacity: 0.5; transform: translateX(20px); } to { opacity: 1; transform: none; } }
@keyframes notesSlideFromLeft  { from { opacity: 0.5; transform: translateX(-20px); } to { opacity: 1; transform: none; } }

/* the "Für" capsule: the app's .m person badges stacked inside ONE quiet pill */
.notes-avs { display: inline-flex; align-items: center; }
.notes-av.all, .notes-av.more { height: 22px; display: inline-grid; place-items: center;
    border-radius: var(--r-pill); padding: 0 8px; font-size: var(--fs-label); font-weight: 500;
    background: var(--field); color: var(--ink2); box-shadow: 0 0 0 2px var(--card); }
/* „+n" tucks under the last badge like a badge under the one before it */
.m + .notes-av.more { margin-left: -6px; }
/* the lock of an entry only its source changes: a quiet disc the size of a badge, the glyph 11 */
.notes-av.ro { width: 22px; height: 22px; display: inline-grid; place-items: center; flex: none; border-radius: 50%;
    background: var(--field); color: var(--ink2); }
.notes-av.ro i { font-size: 11px; }
.notes-av.ro + .m, .notes-av.ro + .notes-av { margin-left: 4px; }
/* the private eye: a disc the size of a badge before it, in the owner's colour (quiet without
   one), the card's ring around it like a badge's */
.notes-av.lock { width: 22px; height: 22px; box-sizing: border-box; display: inline-grid; place-items: center;
    flex: none; border-radius: 50%; background: var(--pc-soft, var(--field)); color: var(--pc, var(--ink2));
    box-shadow: 0 0 0 2px var(--card); }
.notes-av.lock i { font-size: 12px; }



/* the editor's type rail (create only): every kind as a word on a rail that runs to the sheet's
   edges and fades out over 28px at an edge with words beyond it (.fade-l / .fade-r) */
.notes-typerail { display: flex; gap: 6px; overflow-x: auto; margin: 0 calc(-1 * var(--pad)) 14px; padding: 0 var(--pad);
    scrollbar-width: none; }
.notes-typerail.fade-r { -webkit-mask-image: linear-gradient(90deg, currentColor calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, currentColor calc(100% - 28px), transparent); }
.notes-typerail.fade-l { -webkit-mask-image: linear-gradient(90deg, transparent, currentColor 28px);
    mask-image: linear-gradient(90deg, transparent, currentColor 28px); }
.notes-typerail.fade-l.fade-r { -webkit-mask-image: linear-gradient(90deg, transparent, currentColor 28px, currentColor calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, transparent, currentColor 28px, currentColor calc(100% - 28px), transparent); }
.notes-typerail::-webkit-scrollbar { display: none; }
.notes-typ { display: inline-flex; align-items: center; flex: 0 0 auto; border: 0; background: var(--field); color: var(--ink2); border-radius: var(--r-pill); height: 32px; box-sizing: border-box; padding: 0 12px; font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 500; white-space: nowrap; cursor: pointer; }
.notes-typ.on { background: var(--ink); color: var(--card); }

.notes-empty {
    color: var(--ink2);
    font-size: var(--fs-hint);
    text-align: center;
    margin-top: 2rem;
}

/* blank state of a truly empty kind — icon tile, title, benefit line, create CTA */
/* in the Notes tabs the blank sits directly under the tab strip — give it the breathing
   room the Baby section cards get from their own card head */
.notes-layer .notes-blank { margin-top: 40px; }
.notes-blank,
.fin-blank {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 0 20px 28px;
}
.notes-blank .nb-mark,
.fin-blank .nb-mark {
    width: 46px;
    height: 46px;
    border-radius: 14px;
    background: var(--nav-fill);   /* the chrome wash reads on the page and on a card alike */
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--ink2);
    font-size: 21px;
    margin-bottom: 13px;
}
.notes-blank b,
.fin-blank b {
    font-size: var(--fs-body);
    font-weight: 500;
    color: var(--ink);
}
.notes-blank p,
.fin-blank p {
    font-size: var(--fs-hint);
    color: var(--ink2);
    margin-top: 5px;
    line-height: 1.55;
    max-width: 250px;
}
.notes-blank .action-btn,
.fin-blank .action-btn { margin-top: 15px; }
/* the first-entry card of an empty section (Anlagen, Einkommen): the blank on a card — mark 12 over
   the title, the line 4 under it at 1.5, the pill 13/500 14 under that, nothing below it */
.fin-blank.is-card { padding: 28px 20px 24px; background: var(--card); border-radius: var(--r-card); }
.fin-blank.is-card .nb-mark { margin-bottom: 12px; }
.fin-blank.is-card p { margin: 4px 0 0; line-height: 1.5; }
.fin-blank.is-card .action-btn { margin: 14px 0 0; }
/* the module's pills (an empty state's, the dock's „Abrechnen"): 36 high, 13/500 */
.module-finances .action-btn.reusable { font-size: var(--fs-ui); font-weight: 500; }

/* item card — checkbox/glyph + title + status + chips + authorship */
.notes-item {
    /* borderless card on the normal card ground — the card is a quiet field, not a box
       (the whole card opens the editor; only its buttons/inputs keep their taps). No
       min-height: the card is exactly as tall as its content; the 44px halo on every
       checkbox keeps the touch targets comfortable. */
    background: var(--card);
    border-radius: var(--r-card);
    padding: 10px 14px;
    min-height: 50px;
    box-sizing: border-box;
    margin-bottom: 8px;
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr) auto;
    gap: 2px 12px;
    /* icon, content and Für-capsule hold the top of the card; a one-line text and the capsule
       centre on the tile's axis (the symbol tile rule, further down) */
    align-items: start;
    position: relative;
    overflow: hidden;
    cursor: pointer;
}
/* the right column: the Für capsule (a list's fold mark beside it) */
.notes-right { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
/* a row that ticks wears its tick in the lead slot, the tile's 30 square (22 and 4 around it) */
.notes-item > .notes-check { margin: 4px; }
.notes-check {
    appearance: none;
    -webkit-appearance: none;
    margin: 0;
    cursor: pointer;
    flex: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1.5px solid var(--line2);
    background: transparent;
    position: relative;
    transition: background var(--transition-fast), border-color var(--transition-fast);
}
.notes-check:hover { border-color: var(--ink3); }
.notes-check:checked { background: var(--ink); border-color: var(--ink); }
/* ticked: the app's check glyph, 13 in the card's colour on the ink */
.notes-check:checked::after {
    content: "";
    position: absolute;
    inset: 0;
    margin: auto;
    width: 13px;
    height: 13px;
    background: var(--card);
    -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.3'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M5%2013l4%204L19%207'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2.3'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M5%2013l4%204L19%207'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* Einkauf reads as a ROUND box; todo/chore stay square (kind-shaped, feed + dashboard) */
.notes-check.mg-round, .w-check.mg-round { border-radius: 50%; }
/* someone else's wish: the bought tick is dashed until it is bought (then the ink fill) */
.notes-check.notes-check-na:not(:checked) { border-style: dashed; }
/* body: title + status + meta */
.notes-body { min-width: 0; }
.notes-title {
    font-size: var(--fs-md);
    font-weight: 500;
    line-height: 1.35;
    hyphens: auto;
    overflow-wrap: break-word;
    /* pre-line keeps the line breaks typed into a note's textarea (inherits into .notes-q) */
    white-space: pre-line;
}
.notes-q { color: var(--ink2); font-weight: 400; font-size: var(--fs-ui); }
/* a note's body under its title — TWO clipped preview lines (the editor holds the prose);
   unfolded from the title (.nc-head), the whole text stands as typed */
.notes-text { color: var(--ink2); font-size: var(--fs-sub); line-height: 1.4; white-space: pre-line; overflow-wrap: anywhere;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin-top: 2px; }
.notes-text.open { display: block; -webkit-line-clamp: unset; overflow: visible; }
/* a long to-do text clips to its line behind the same head, and stands whole once opened */
.notes-title.clip { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.notes-title.clip.open { white-space: pre-line; overflow: visible; }
/* status line: overdue = red + weight */
#app .notes-overdue { color: var(--due-ink); font-weight: 500; font-size: var(--fs-sub); }
.notes-item.done .notes-title { color: var(--ink2); text-decoration: line-through; }
/* a wish bought for its wisher: the title quiet and struck through, never dimmed */
.notes-item.notes-bought .notes-title { color: var(--ink2); text-decoration: line-through; }
/* container card (a todo/shopping note holding its own lines): every line carries its own
   tick, a hairline 6 under the head */
.nc-lines { display: flex; flex-direction: column; gap: 0; margin-top: 6px; padding-top: 4px; border-top: 1px solid var(--line); }
/* the lines run under the text column AND the badge column, so a line's own "Für" badge stands
   on the same right edge as the list's badges */
.notes-item > .nc-lines { grid-column: 1 / -1; padding-left: 42px; }
.nc-line .nc-text { min-height: 30px; display: flex; flex-direction: column; justify-content: center; } /* one line centres on the tick, more lines start at its top */
.nc-line > .ppl { margin-left: auto; margin-top: -2px; }
/* a titled list's title is its fold head; the progress and the turning chevron (.nc-fold) stand
   in the right column beside the Für capsule, on the tile's axis however tall the text runs */
/* head and mark are the fold's tap targets: 9px of padding above and below, taken back by the
   margin, so the finger has a taller target and the card stays exactly as tall */
.nc-head { display: flex; align-items: center; gap: 8px; padding: 9px 0; margin: -9px 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.nc-head .notes-title { flex: 1; min-width: 0; }
.notes-right:has(> .nc-fold) { flex-direction: row; align-items: center; gap: 8px; }
.nc-fold { display: inline-flex; align-items: center; gap: 5px; padding: 9px 0; margin: -9px 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.nc-head-meta { font-size: var(--fs-sub); color: var(--ink2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.nc-fold .fold-chev { font-size: 12px; color: var(--ink3); transform: none; transition: transform var(--transition-fast); }
.nc-fold.open .fold-chev { transform: rotate(180deg); }
.nc-line { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; gap: 0 12px; align-items: start; min-height: 40px; padding: 5px 0; box-sizing: border-box; }
.nc-line .notes-check { margin-top: 4px; justify-self: center; }
.nc-text { font-size: var(--fs-body); line-height: 1.35; word-break: break-word; min-width: 0; }
.nc-line.done .nc-text { color: var(--ink2); text-decoration: line-through; }
/* a heading among a list's lines — the lines under it, up to the next one, are its section; it
   stands on the lines' text axis, past their ticks */
.nc-sec { font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); padding: 10px 0 2px 42px; }
.nc-sec:first-child { margin-top: 0; }
.notes-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 1px;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
}
.notes-meta .notes-by { overflow: hidden; text-overflow: ellipsis; margin-top: 0; }
/* a name the meta line says („Als Nächstes: Lena") stands in ink */
.notes-meta .notes-name { color: var(--ink); font-weight: 500; }
/* on a card the meta is ONE line of words that runs on and clips once, at its end — a flex row
   shrank every word to its own „…" */
.notes-body > .notes-meta { display: block; text-overflow: ellipsis; font-size: var(--fs-sub); line-height: 1.35; }
.notes-body > .notes-meta > * { display: inline; vertical-align: baseline; }
.notes-body > .notes-meta > .ppl { display: inline-flex; vertical-align: middle; }
.notes-body > .notes-meta > * + *::before { margin: 0 6px; }
/* a "·" between the meta WORDS (never before the first); the tally chips are self-delimiting
   pills (border + gap), so no dot rides before a w-link or notes-chip */
.notes-meta > * + *::before { content: "·"; color: var(--ink3); margin-right: 6px; }
.notes-meta > * + .w-link::before,
.notes-meta > * + .notes-chip::before { content: none; }
/* landing pulse: a link chip navigated here — say WHICH row it meant, then fade out */
.notes-item.flash { animation: rowFlash 1.6s ease; }
@keyframes rowFlash {
    0%, 45% { box-shadow: inset 0 0 0 1.5px var(--line2); }
    100% { box-shadow: none; }
}
/* person chip — soft pill with a name */
/* a select whose chips stand under it names its action, quietly */
.mg-select[data-add-label] .mg-select-label { color: var(--ink2); }
.form-linkstrip { margin-top: 8px; gap: 6px; }
.form-linkstrip .notes-chip { height: 28px; padding: 0 6px 0 4px; border: 0; border-radius: var(--r-pill); background: var(--nav-fill); color: var(--ink); font-size: var(--fs-ui); }
.form-linkstrip .notes-chip.is-empty { padding: 0 10px; background: transparent; color: var(--ink3); }
.notes-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 22px;
    font-size: var(--fs-label);
    font-weight: 500;
    padding: 0 7px;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--field);
    color: var(--ink2);
    white-space: nowrap;
    flex: none;
}
button.notes-chip { cursor: pointer; }
button.notes-chip:hover, button.notes-chip:active { color: var(--ink); }
.notes-chip svg { width: 13px; height: 13px; }
/* projection hint — the quiet chips under a dated editor field saying where it will surface
   (calendar / bell). Reuses .notes-chip; the two hosts need different top spacing. */
.proj-hint { display: flex; flex-wrap: wrap; gap: 12px; }
/* the hint chips read as soft outlined pills — a quiet affordance, not a control */
.proj-hint .notes-chip { padding: 0; border: 0; background: none; color: var(--ink2); font-size: var(--fs-cap); font-weight: 500; }
.proj-hint .notes-chip i { font-size: 11px; color: var(--ink3); }
.form-row > .proj-hint { margin-top: 8px; }
/* the × on the editor's badge strip (the row chips fold into .w-linksum instead) */
.notes-linkx {
    border: 0;
    background: transparent;
    cursor: pointer;
    color: var(--ink3);
    display: inline-flex;
    align-items: center;
    padding: 3px 7px 3px 3px;
    font-size: 12px;
    line-height: 1;
}
.notes-linkx:hover, .notes-linkx:active { color: var(--due-ink); }
.notes-by { font-size: var(--fs-sub); color: var(--ink2); margin-top: 2px; }
.notes-by b { font-weight: 600; color: var(--ink2); }
/* a chore's undo band: under the whole card, from edge to edge behind a hairline — who did the
   turn (the name in ink) and „Rückgängig" at the right */
.chore-undo { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 8px;
    margin: 8px -14px -10px; padding: 8px 14px; border-top: 1px solid var(--line);
    font-size: var(--fs-sub); color: var(--ink2); cursor: default; }
.chore-undo-t { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chore-undo-t b { color: var(--ink); font-weight: 500; }
#app .chore-undo-btn {
    flex: none; border: 0; background: none; color: var(--ink);
    font-family: var(--font-family); font-size: var(--fs-sub); font-weight: 500;
    cursor: pointer; padding: 0;
}
#app .chore-undo-btn:active { transform: scale(var(--button-click-scale)); }

/* ── the ONE FAB ────────────────────────────────────────────────────────────────────
   Every module's + is the same button in the same corner: a 56px ink disc with the drawn +. One
   full declaration — a split into "shared position, per-module everything else" once left the
   notes button a naked absolute <button> with no size, no circle and no ink. Each module mounts
   it in its own position:relative surface; only Finanzen steps it over its docked line. */
.cal-fab,
.notes-fab,
.fin-fab,
.dash-fab,
#app .baby-fab,
#app .hl-fab,
#app .tv-fab,
#app .pw-fab {
    position: absolute;
    right: var(--pad);
    bottom: var(--pad);
    z-index: 5;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    border: 0;
    background: var(--ink);
    color: var(--card);
    cursor: pointer;
    box-shadow: var(--shadow);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.cal-fab:active,
.notes-fab:active,
.fin-fab:active,
.dash-fab:active,
#app .baby-fab:active,
#app .hl-fab:active,
#app .tv-fab:active,
#app .pw-fab:active { transform: scale(var(--button-click-scale)); }

/* the chooser sheets ("Neu", the widget picker, a delete fork): rows of icon tile · title over
   its sub on one line, nothing at the right — the row is the door */
.new-list { display: flex; flex-direction: column; }
.new-row {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    box-sizing: border-box;
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--line);   /* hairline divider between choices */
    min-height: 48px;
    padding: 9px 0;
    font-family: var(--font-family);
    cursor: pointer;
    text-align: left;
    color: var(--ink);
    -webkit-tap-highlight-color: transparent;
    transition: background var(--transition-fast);
}
.new-row:last-child { border-bottom: 0; }
/* a switch row that is ON: the tile fills in ink behind its glyph */
.new-row.on .new-ic { background: var(--ink); border-color: var(--ink); color: var(--bg); }
/* a switch row without a glyph (the card catalogue): a tick circle, ink with its check while on */
.new-tick { flex: none; width: 22px; height: 22px; margin: 4px; box-sizing: border-box; display: grid; place-items: center;
    border-radius: 50%; border: 1.5px solid var(--line2); background: var(--card); color: transparent; font-size: 13px; }
.new-row.on .new-tick { background: var(--ink); border-color: var(--ink); color: var(--card); }
.new-row:active { background: var(--card2); }
.new-tx { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.new-tx b { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; }
.new-tx span { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* "Für dich" — the per-member agenda pager card; recolored to the visible member via its pc-N
   class (--pc / --pc-soft / --pc-ink): the title and the dots in the head. */
.wg-you > .w-head { cursor: default; } /* aggregation, not a module — header doesn't navigate */
.fy-title { color: var(--pc-ink, var(--ink)); }
/* a menu entry that names a glyph instead of the initial — a pet's paw */
#app .head-menu-item .fava > i { font-size: 13px; }
.fy-pager { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
/* split widgets: the card follows the ACTIVE page's height (set per paint), tall neighbours clip */
.fy-pager.w-split { align-items: flex-start; overflow-y: hidden; transition: height var(--transition-base); }
.fy-pager::-webkit-scrollbar { display: none; }
.fy-page { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; }
/* a row: the time 44 · the slot 30 (the tick, or the row's tile) · the text · a private row's lock */
.fy-row { display: grid; grid-template-columns: 44px 30px minmax(0, 1fr) auto; align-items: start; gap: 2px 12px; min-height: 44px;
    box-sizing: border-box; padding: 8px 14px; border-top: 1px solid var(--line); }
.fy-tap { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fy-time { min-height: 30px; display: flex; align-items: center; font-size: var(--fs-cap); font-weight: 500; color: var(--ink2);
    font-variant-numeric: tabular-nums; white-space: nowrap; }
.fy-time.due { color: var(--due-ink); }
.fy-row > .fy-check { margin: 4px; }
.fy-ki { width: 30px; height: 30px; display: grid; place-items: center; border-radius: 10px; background: var(--nav-fill); color: var(--ink2); font-size: 16px; }
.fy-ki[class*="pc-"] { background: var(--pc-soft); color: var(--pc-ink); }
.fy-body { min-width: 0; min-height: 30px; display: flex; flex-direction: column; justify-content: center; overflow-wrap: anywhere; }   /* a 90px column at 360px must break "Geburtstagsparty" */
.fy-body b { display: block; font-size: 14px; font-weight: 500; }
.fy-sub { display: block; font-size: var(--fs-sub); color: var(--ink2); margin-top: 1px; }
.fy-sub:empty { display: none; }
.fy-sub.due { color: var(--due-ink); }
.fy-sub.pend { color: var(--pend-ink); }
.fy-sub.accent { color: var(--pc-ink, var(--ink2)); }
/* a reminder's subline opens with the bell — the lead keeps the day */
.fy-sub .fy-sub-bell { font-size: 11px; margin-right: 4px; color: var(--ink3); }
.fy-body .w-tags { margin-top: 4px; }
/* buttons, like the weather's: the visible dot is ::before, the button around it the click area;
   every paged card (Für dich, a split card) carries them in its head — quiet --line2 dots, the
   visible page's in ink (whose page it is, the head says in words) */
.fy-dots { display: flex; justify-content: center; padding: 3px 0 5px; }
.w-head > .fy-dots { padding: 0; margin-block: -6px; }
.w-head > .fy-dots button { padding: 6px 2px; }
.fy-dots:has(> button:only-child) { display: none; }   /* one page: nothing to page through */
.fy-dots button { border: 0; background: transparent; padding: 6px 3px; display: flex; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
.fy-dots button::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--line2);
    transition: background 0.15s; }
.fy-dots button:hover::before { background: var(--ink3); }
.fy-dots button.on::before { background: var(--ink); }
/* a card about ONE person (.w-person: a baby's card) wears that person's colour bar on its top
   edge; a card split into pages names the page's person in its head instead */
.widget.w-person::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: var(--pc, var(--ink)); z-index: 2; }
/* a card only the member sees: the header's eye as a bare glyph beside the card's › */
.w-private { flex: none; width: 20px; height: 20px; padding: 0; border: 0; background: transparent;
    display: flex; align-items: center; justify-content: center;
    color: var(--ink3); font-size: 14px; cursor: pointer; -webkit-tap-highlight-color: transparent; }

/* a band's head: its name at the left — „Überfällig" in the due ink, „Haushalt" in the pending
   ink, the day in the second ink —; the overdue and the shared band fold AS A WHOLE, their count
   and chevron at the right (˅ shut, ˄ open), shut by default — the bell keeps the complete list,
   this card is the app's first screen */
.fy-band-head {
    display: flex;
    align-items: center;
    gap: 6px;
    width: 100%;
    box-sizing: border-box;
    background: transparent;
    border: 0;
    padding: 8px 14px 2px;
    font-family: var(--font-family);
    font-size: var(--fs-cap);
    font-weight: 500;
    color: var(--ink2);
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}
button.fy-band-head { cursor: pointer; }
/* a SHUT folding band (Überfällig, Haushalt) stands with even air above and below, like the
   Übersicht's: calm rows, and a gap to the card's edge when it is the last */
.fy-due:not(.open) > .fy-band-head,
.fy-shared:not(.open) > .fy-band-head { padding: 10px 14px; }
.fy-due > .fy-band-head { color: var(--due-ink); }
.fy-shared > .fy-band-head { color: var(--pend-ink); }
.fy-band-fold { margin-left: auto; display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-sub); font-weight: 400;
    color: var(--ink2); font-variant-numeric: tabular-nums; }
.fy-band-fold i { font-size: 12px; color: var(--ink3); transition: transform var(--transition-fast); }
.fy-due.open > .fy-band-head .fy-band-fold i,
.fy-shared.open > .fy-band-head .fy-band-fold i { transform: rotate(180deg); }
.fy-due:not(.open) > .fy-row,
.fy-shared:not(.open) > .fy-row { display: none; }

/* the day band shows three rows and folds the rest behind the foot under them ("12 weitere",
   "weniger" once open) */
.fy-rest-xtra { display: none; }
.fy-rest.open .fy-rest-xtra { display: grid; }
.fy-rest.open > .fy-foot .w-more { display: none; }
.fy-rest.open > .fy-foot .w-less { display: inline; }
.fy-rest.open > .fy-foot i { transform: rotate(180deg); }

/* ============================== baby ============================== */

/* a full-height pager: each baby is ONE page between header and the swipe dots */
#app .baby-wrap { position: relative; height: 100%; display: flex; flex-direction: column; }
/* a section is a column of heads and cards (the design's tight feed, 8 apart); a card is the
   --card ground with its rows' hairlines */
#app .baby-page .tab-layer > div, #app .baby-timeline { display: flex; flex-direction: column; gap: 8px; }
#app .baby-card { background: var(--card); border-radius: var(--r-card); }
#app .baby-emptyline { font-size: var(--fs-sub); color: var(--ink2); text-align: center; padding: 14px; }
/* the low-diaper hint over the timeline: one amber line 13/400, its warning glyph 14 */
#app .baby-hint { padding: 0 4px; font-size: var(--fs-sub); font-weight: 400; line-height: 1.45; color: var(--pend-ink); }
#app .baby-hint i { font-size: 14px; vertical-align: -2px; }

#app .baby-pager {
    flex: 1;
    min-height: 0;
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
#app .baby-pager::-webkit-scrollbar { display: none; }
#app .baby-page {
    flex: 0 0 100%;
    min-width: 0;
    scroll-snap-align: start;
    box-sizing: border-box;
    padding: 8px var(--pad) 96px;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
/* wide containers: the Heute section sets its status block (max ~360px) beside the timeline;
   every other section keeps the full width */
@container (min-width: 600px) {
    /* rows max-content + 1fr: the status block spans both and its height lands in the flexible
       second row, so the timeline (row 1) starts at the top beside it */
    #app .baby-today { display: grid; grid-template-columns: minmax(0, 360px) minmax(0, 1fr); grid-template-rows: max-content 1fr; gap: 0 12px; align-items: start; }
    #app .baby-today > .baby-status { grid-column: 1; grid-row: 1 / span 2; }
    #app .baby-today > :not(.baby-status) { grid-column: 2; }
    #app .baby-today > :not(.baby-status) + :not(.baby-status) { margin-top: 14px; }
}

/* swipe indicator — directly above the footer, always visible */


/* hero: ringed avatar + name/age, today's counts right */
/* the record heroes (baby, health, travel) are ONE card: the greeting's plain card, 20px inside,
   the 56px portrait, a 15px line under the serif name, the pen in the top-right corner */
#app .baby-hero, #app .hl-hero, #app .tv-hero { position: relative; background: var(--card); border-radius: var(--r-card); padding: 20px; }
/* the tab strip is the hero card's last row (the health hero's block): 14/10/12 air, a 40px track */
#app .baby-hero { display: flex; align-items: center; gap: 8px 14px; flex-wrap: wrap; padding: 12px 13px 12px; }
#app .baby-hero-glyph {
    width: 72px;
    height: 72px;
    box-sizing: border-box;
    border-radius: 50%;
    /* the double ring: a 2px card-coloured gap, then 2px of the person's colour */
    box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--pc, var(--line2));
    flex: none;
    display: grid;
    place-items: center;
    font-size: 28px;
    font-weight: 500;
    background: var(--pc-soft, var(--card2));
    color: var(--pc-ink, var(--ink2));
    overflow: hidden;
}
#app .baby-hero-glyph img { width: 100%; height: 100%; object-fit: cover; }
#app .baby-hero-name { color: var(--ink); line-height: 1.2; } /* type comes from the display-serif rule at the end of the file */
#app .baby-hero-age { font-size: var(--fs-head); line-height: 1.3; color: var(--ink2); margin-top: 0; }
#app .baby-hero-wrap { display: flex; flex-direction: column; gap: 10px; }
/* the head's edit pill (icon-only) on the right */
/* the head pencil joins the nav family — same tonal fill as ‹ Heute › */
/* the pen stands in the head row at its right end, like ✎ in the finance and travel heads —
   in the corner it ran under a long name */
#app .baby-head-edit { margin-left: auto; align-self: flex-start; }
#app .baby-hero-text { flex: 1; min-width: 0; }
/* the expected baby's hero: label 10 under the title, the figure 2 under it, the sentence 2
   under that — rows of their own, without the hero's row gap */
#app .baby-hero.is-expected { row-gap: 0; }
#app .baby-hero-lbl { flex: 1 0 100%; font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); margin-top: 10px; }
#app .baby-hero-num { flex: 1 0 100%; color: var(--ink); line-height: 1.15; font-variant-numeric: tabular-nums; margin-top: 2px; }
#app .baby-hero-say { flex: 1 0 100%; font-size: var(--fs-sub); color: var(--ink2); margin-top: 2px; }
/* the avatar is its own door to the picture sheet */
#app .baby-hero-avatar { position: relative; flex: none; padding: 0; border: 0; background: none; border-radius: 50%;
    font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }

/* the tab bar is the hero card's last row, flush with its sides: all six tabs in ONE line that
   swipes sideways under a soft 28 edge (none folded away), each at its own width; a swipe that
   reaches its end stays in the strip and never pages to the next child */
#app .baby-hero > .baby-tabs { flex: 1 0 100%; margin: 4px 0 0; border: 0; height: 36px; overscroll-behavior-x: contain;
    -webkit-mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent); }
#app .baby-hero > .baby-tabs .seg-tab { flex: 0 0 auto; }
/* room behind the last tab, so scrolled to the end it stands clear of the soft edge */
#app .baby-hero > .baby-tabs::after { content: ""; flex: 0 0 25px; }
#app .baby-editable { cursor: pointer; -webkit-tap-highlight-color: transparent; }

/* status card — the module's one hero surface */
/* the status block heads the Heute section: a card of its own, its content on 12px sides */
#app .baby-status {
    background: var(--card);
    border-radius: var(--r-card);
    padding: 8px 12px 4px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: flex-start;
}
/* The arc's colour is the CHILD's people-&-things colour — the pc-N class this card also
   carries sets --pc/--pc-soft/--pc-ink. This is only the fallback for a child with no colour
   yet, and it sits in :where() so it has ZERO specificity: a pc-N class must always win.
   (The prototype's --jo does not exist in the app; reaching for it left --pc invalid, which
   silently painted the whole arc black.) */
:where(#app .baby-status) { --pc: var(--p5); --pc-soft: var(--p5-soft); --pc-ink: var(--p5-ink); }

/* ── the week strip: the last fortnight as fourteen narrow 24h columns under the arc (the
   design's 60 high, 3 apart, r3 on --field). Sleep drawn where it lay — night in the child's
   colour, naps in it at 55 % — meals as ink dots, the viewed day ringed 1.5 in ink; under the
   columns the axis words 11 in --ink2. Reading is the point; the tap target is the whole
   column. */
#app .bweek { align-self: stretch; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
/* its line runs the section card's full width: it reaches past the 12px sides, its columns sit
   14 in like the card's rows */
#app .baby-status > .bweek { margin-left: -12px; margin-right: -12px; padding: 10px 14px 10px; }
#app .bweek-avgs { color: var(--ink3); font-size: var(--fs-cap); margin-bottom: 8px; font-variant-numeric: tabular-nums; }
/* the averages line is the door to the Statistik sheet: a quiet line with its chevron */
#app button.bweek-avgs { display: flex; align-items: center; gap: 4px; width: 100%; padding: 0; border: 0; background: none;
    font-family: var(--font-family); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app button.bweek-avgs i { font-size: 9px; margin-left: auto; color: var(--ink3); }
/* the Statistik sheet: a card per kind — its title and trend, the average big, a column per day
   (stacked in the child's colour, today lighter) with the average dashed across, the axis words */
#app .bstat { padding: 14px; display: grid; gap: 6px; margin-top: 10px; }
#app .bstat-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
#app .bstat-head b { font-size: var(--fs-label); font-weight: 600; color: var(--ink2); }
#app .bstat-head small { font-size: var(--fs-cap); color: var(--ink3); white-space: nowrap; }
#app .bstat-fig { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
#app .bstat-big { font-size: 24px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); font-variant-numeric: tabular-nums; }
#app .bstat-sub { font-size: var(--fs-label); color: var(--ink2); }
#app .bstat-cols { position: relative; display: grid; column-gap: 3px; height: 110px; margin-top: 6px; align-items: end; }
#app .bstat-col { display: flex; flex-direction: column-reverse; height: 100%; min-width: 0; padding: 0; border: 0; background: none;
    cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .bstat-seg { display: block; flex: none; width: 100%; background: var(--pc); }
#app .bstat-seg:last-child { border-radius: 2px 2px 0 0; }
#app .bstat-seg.is-nap { opacity: .45; }
#app .bstat-col.is-live .bstat-seg { opacity: .35; }
#app .bstat-avg { position: absolute; left: 0; right: 0; height: 0; border-top: 1px dashed var(--ink2); pointer-events: none; }
#app .bstat-xl { display: flex; justify-content: space-between; font-size: 11px; color: var(--ink3); }
/* Fourteen tracks whatever the day count — three days of data are three thin columns hugging
   today at the right (the first one placed by grid-column-start), not three screen-wide slabs. */
#app .bweek-cols, #app .bweek-xl { display: grid; grid-template-columns: repeat(14, minmax(0, 1fr)); column-gap: 3px; }
#app .bweek-col {
    display: block;
    min-width: 0;
    background: none;
    border: none;
    padding: 0;
    border-radius: 3px;
    cursor: pointer;
}
#app .bweek-track {
    position: relative;
    display: block;
    height: 60px;
    box-sizing: border-box;
    border-radius: 3px;
    background: var(--field);
    overflow: hidden;
}
#app .bweek-col.sel .bweek-track { box-shadow: 0 0 0 1.5px var(--ink); }
/* nobody recorded ≠ nothing happened: the gap track is dashed and hollow */
#app .bweek-track.gap { background: none; border: 1px dashed var(--line2); }
#app .bweek-track .bwn, #app .bweek-track .bwp {
    position: absolute;
    left: 0;
    right: 0;
    border-radius: 2px;
    background: var(--pc);
}
#app .bweek-track .bwp { opacity: .55; }
#app .bweek-track .bwm {
    position: absolute;
    left: 50%;
    width: 4px;
    height: 4px;
    margin-left: -2px;
    border-radius: 50%;
    background: var(--ink);
}
/* the axis: the first day left over its column, the middle centred, „heute" right */
#app .bweek-xl { margin-top: 6px; font-size: 11px; line-height: 1.35; color: var(--ink2); font-variant-numeric: tabular-nums; }
#app .bweek-xl > span { white-space: nowrap; }
#app .bweek-xl > .is-mid { text-align: center; }
#app .bweek-xl > .is-end { text-align: right; }

/* Day stepper (G2), ONE line in the middle above the arc: the ‹ disc, the day 13/500
   („Heute · Do 8. Okt"), the › disc — 30 discs, 4 apart; a disc dims when there is no day to
   step to. A past day's name is the way back to today. */
#app .baby-daynav {
    align-self: stretch;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    height: 32px;
}
#app .baby-daynav .cal-nav { width: 30px; height: 30px; font-size: 14px; display: grid; place-items: center; }
#app .baby-daynav .cal-nav:disabled { opacity: .28; cursor: default; }
#app .baby-daynav-day { border: 0; background: none; padding: 0 8px; font-family: var(--font-family); font-size: var(--fs-ui);
    font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
#app .baby-daynav-day:disabled { cursor: default; color: var(--ink); }

/* ---- Tagesbogen (design/DESIGN.md Anhang "Baby-Tagesbogen") ---- */
/* the dial drawn 1:1 at 260 (the ring 14, the hours 10 in --ink2 outside it) */
#app .baby-status .ringWrap { position: relative; width: 260px; max-width: 100%; margin: 4px auto 0; }
#app .baby-arc-hour { font-family: var(--font-family); font-size: 10px; fill: var(--ink2); font-variant-numeric: tabular-nums; }
#app .baby-status .ringWrap svg { display: block; width: 100%; height: auto; }
#app .baby-status .ringWrap .rHit { cursor: pointer; }
#app .baby-status .ringWrap.night svg { opacity: .55; transition: opacity .3s; }
#app .baby-pulse { animation: babyPulse 1.6s ease-in-out infinite; }
@keyframes babyPulse { 0%, 100% { opacity: .9 } 50% { opacity: .35 } }

/* Ring centre — over the SVG only, 176 wide, its middle 2 % under the box's (the design's 52 %) */
#app .ringCtr {
    position: absolute;
    inset: 0;
    padding: 0 42px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    pointer-events: none;
    transform: translateY(2%);
}
/* the centre's figure is the serif (the display list at the end of the file) at 24 */
#app .ringCtr b { line-height: 1.1; font-variant-numeric: tabular-nums; }
#app .ringCtr span { font-size: var(--fs-sub); color: var(--ink2); margin-top: 2px; }
#app .ringCtr small { font-size: var(--fs-label); color: var(--pc-ink); margin-bottom: 3px; font-weight: 600; letter-spacing: .02em; }

/* The one inline action of the card: a running sleep is a TIMER, not a form. It is the app's
   pill (36, 0 16, 13/500, ink) INSIDE the ring-centre overlay: the overlay is pointer-events:none
   so arc taps pass through, and the button opts back in. Both states — Schlaf starten and
   Aufwecken — are the same primary action at two moments, so both wear it. */
#app .sleepBtn {
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: auto;
    height: 36px;
    box-sizing: border-box;
    margin: 10px auto 0;
    border: 0;
    background: var(--ink);
    color: var(--card);
    border-radius: var(--r-pill);
    padding: 0 16px;
    font-family: var(--font-family);
    font-size: var(--fs-ui);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
#app .sleepUndo {
    display: none;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin: 8px auto 0;
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--ink2);
}
#app .sleepUndo.on { display: flex; }
#app .sleepUndo button {
    border: 0; background: none; color: var(--pc-ink);
    font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 600; cursor: pointer; padding: 2px 4px;
}

/* Callout — anchored at the tapped element, caret follows */
#app .ringPop {
    display: none;
    position: absolute;
    z-index: 6;
    width: max-content;
    max-width: calc(100% - 4px);
    box-sizing: border-box;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--r-ctl);
    padding: 10px 12px;
    font-size: var(--fs-ui);
    color: var(--ink);
    box-shadow: var(--shadow);
}
#app .ringPop.on { display: block; }
#app .ringPop::after {
    content: "";
    position: absolute;
    left: var(--cx, 50%);
    width: 10px; height: 10px;
    background: var(--card);
    border: 1px solid var(--line);
    transform: translateX(-50%) rotate(45deg);
}
#app .ringPop.up::after { bottom: -6px; border-top: 0; border-left: 0; }
#app .ringPop.dn::after { top: -6px; border-bottom: 0; border-right: 0; }
#app .riHead { display: flex; align-items: baseline; gap: 8px; }
#app .riHead b { font-size: var(--fs-hint); font-weight: 600; }
#app .riHead .riSub { font-size: var(--fs-label); color: var(--ink3); }
#app .riHead button { margin-left: auto; border: 0; background: transparent; color: var(--ink3); cursor: pointer; font-size: 15px; line-height: 1; padding: 0; }
#app .riRow { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-top: 1px solid var(--line); }
#app .riRow:first-of-type { margin-top: 8px; }
#app .riRow .riIc { width: 26px; height: 26px; border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
#app .riRow .riT { font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); flex-shrink: 0; white-space: nowrap; font-variant-numeric: tabular-nums; }
#app .riRow .riL { font-size: var(--fs-ui); font-weight: 500; white-space: nowrap; }
/* a running nursing stands in the arc's place as its pending row, the card's full width, no
   hairline under the day stepper */
#app .baby-status > .baby-ev { align-self: stretch; margin: 0 -12px; border-top: 0; }
/* the first-entry greeting is a card of its own (the design's blank): 28 above its 46 glyph
   tile, 12 under it, the line 13 in --ink2, its pill 36 at 13/500 */
#app .baby-blank { width: auto; max-width: 100%; box-sizing: border-box; margin: 0; padding: 28px 20px 24px;
    background: var(--card); border-radius: var(--r-card); }
#app .baby-blank .nb-mark { margin-bottom: 12px; }
#app .baby-blank p { margin-top: 4px; line-height: 1.5; }
#app .baby-blank .action-btn { margin-top: 14px; font-size: var(--fs-ui); }
/* the page never scrolls sideways */
#app .baby-page { overflow-x: hidden; }
/* the shared .tab-layer rule says flex:1 1 0% — basis 0 collapses the layer in THIS flex
   scroller and its card PAINTS past it, over the page's own 84px bottom padding (which is
   the intended footer gap). Basis auto keeps content height as the floor while short tabs
   still stretch to fill the page. */
#app .baby-page > .tab-layer { flex: 1 0 auto; }

/* ---- Meilensteine — the memory timeline: the rows of the card (the symbol on its tile in the
   child's colour, the title, ONE line under it), and the photos as a band of 56 tiles r10 under
   the text, 6 apart, each with the photo's 1 px inner edge. */
#app .msShots { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
#app .msShot { width: 56px; height: 56px; flex: none; border-radius: 10px; overflow: hidden; display: grid; place-items: center;
    background: linear-gradient(135deg, var(--pc-soft), var(--card2)); color: var(--pc-ink); box-shadow: inset 0 0 0 1px var(--line); }
#app .msShot img { width: 100%; height: 100%; object-fit: cover; display: block; }
#app .msShot i { font-size: 18px; opacity: .75; }
/* sheet: collapsible suggestion grid (tile catalog) + full symbol palette — ink states only */
.msSugHead { display: flex; align-items: center; gap: 7px; width: 100%; background: none; border: 0; padding: 2px 2px 8px; cursor: pointer; text-align: left; font-family: inherit; }
.msSugHead span { font-size: var(--fs-cap); font-weight: 600; color: var(--ink2); }
.msSugHead i { font-size: 12px; color: var(--ink3); transition: transform .18s; }
.msSugHead[aria-expanded="false"] i { transform: rotate(-90deg); }
.msGrid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; max-height: 264px; overflow-y: auto; padding: 2px; margin-bottom: 10px; }
/* display:grid would beat the hidden attribute — collapsed must WIN (initial state!) */
.msTile { border: 1px solid var(--line); background: var(--card2); border-radius: var(--r-ctl); padding: 11px 6px 9px; display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer; text-align: center; font-family: inherit; color: var(--ink); }
.msTile i { font-size: 17px; }
.msTile b { font-size: var(--fs-label); font-weight: 600; line-height: 1.25; }
.msTile small { font-size: 11px; font-weight: 500; color: var(--ink3); font-variant-numeric: tabular-nums; }
.msTile.on { border-color: var(--ink); background: var(--card); box-shadow: 0 0 0 1px var(--ink) inset; }
.msIcons { display: flex; flex-wrap: wrap; gap: 8px; padding: 2px; margin-bottom: 10px; }
.msSym { width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--line2); background: var(--card); color: var(--ink2); display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0; }
.msSym i { font-size: 15px; }
.msSym.on { background: var(--ink); border-color: var(--ink); color: var(--bg); }
.msFieldLabel { font-size: var(--fs-cap); font-weight: 600; color: var(--ink2); margin: 2px 2px 7px; }
.msAgeLine { font-size: var(--fs-sub); color: var(--ink2); margin: -2px 2px 10px; }
.msMedia { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; margin: 2px 0 10px; border: 1.5px dashed var(--line2); border-radius: var(--r-ctl); background: transparent; color: var(--ink2); font-weight: 600; font-size: var(--fs-hint); font-family: inherit; padding: 12px; cursor: pointer; }
.msMediaList { display: flex; flex-wrap: wrap; gap: 6px; margin: -4px 0 10px; }

/* The day's counts as the hero's marks (the greeting's pills), a row of their own under the
   name: word and number one run of text in the mark's own voice (12/500 --ink2). */
#app .baby-hero > .hero-marks { flex: 1 0 100%; margin: 0; }

/* the sheets' tiles („Eintragen", Essen, Windel, Stillen): four to a line, the glyph 22 in ink
   over its word 11/500 in --ink2, on the --field square */
#app .baby-actions { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; align-self: stretch; }
#app .baby-action {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    min-width: 0;
    background: var(--field);
    border: 0;
    border-radius: var(--r-ctl);
    padding: 10px 4px 8px;
    color: var(--ink2);
    font-family: var(--font-family);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
#app .baby-action i { font-size: 22px; color: var(--ink); }
#app .baby-action span { max-width: 100%; font-size: 11px; font-weight: 500; text-align: center; line-height: 1.35; overflow-wrap: break-word; }
/* a sheet of tiles has no foot: the air of one under its last line */
#app .popup-body > .baby-actions:last-child { margin-bottom: 12px; }
#app .baby-action:active { transform: scale(0.96); }
/* the leading quick action (Schlaf) is the filled hero */
#app .baby-action.hero { background: var(--ink); color: var(--card); }
/* nursing: the side that is next wears the ink ring and says so under its name */
#app .baby-action.next { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
#app .baby-action small { font-size: 11px; color: var(--ink2); line-height: 1; }
#app .baby-nurse-last { font-size: var(--fs-hint); color: var(--ink2); margin: 2px 0 8px; }

/* THE row (_rowEl, the design's timeline row): time 50 · tile 30 · title 15/500 over its line
   13 in --ink2 · its end; 12 apart, 10 14 inside, a hairline between rows */
#app .baby-ev {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px 14px;
    min-height: 50px;
    box-sizing: border-box;
    border-top: 1px solid var(--line);
}
#app .baby-ev:first-child { border-top: 0; }
/* a running event is the PENDING row: an amber dot at its left edge, its state word amber */
#app .baby-ev.is-pending { position: relative; }
#app .baby-ev.is-pending::after { content: ""; position: absolute; left: 5px; top: 50%; width: 5px; height: 5px;
    margin-top: -2px; border-radius: 50%; background: var(--pend); }
#app .baby-ev-icon {
    width: 30px;
    height: 30px;
    box-sizing: border-box;
    border-radius: 10px;
    flex: none;
    display: grid;
    place-items: center;
    background: var(--nav-fill);
    border: 0;
    color: var(--ink2);
    font-size: 16px;
}
#app .baby-ev-icon.is-tint { background: var(--pc-soft, var(--nav-fill)); color: var(--pc-ink, var(--ink2)); }
/* the time column: 50 wide, 13/500 in --ink2, on the tile's middle */
#app .baby-ev-time {
    flex: 0 0 50px;
    min-height: 30px;
    display: flex;
    align-items: center;
    font-size: var(--fs-sub);
    font-weight: 500;
    color: var(--ink2);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
#app .baby-ev-body { flex: 1; min-width: 0; min-height: 30px; display: flex; flex-direction: column; justify-content: center; }
#app .baby-ev-desc { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; color: var(--ink); overflow-wrap: break-word; }
#app .baby-ev-meta { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); margin-top: 1px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
#app .baby-ev-meta .late { color: var(--due-ink); font-weight: 500; }
#app .baby-ev-meta .pendt { color: var(--pend-ink); font-weight: 500; }
#app .baby-ev-txt { font-size: var(--fs-sub); line-height: 1.4; color: var(--ink2); margin-top: 2px; overflow: hidden;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
#app .baby-ev-end { flex: none; min-height: 30px; display: flex; align-items: center; gap: 8px; }
/* a row that is no task (a window gone by, a suggestion) speaks in the second ink throughout */
#app .baby-ev.is-stat .baby-ev-desc { color: var(--ink2); }
/* the vaccine row's 22 tick in the tile slot: an empty ring, inked with its check once given,
   dashed when the window is gone */
#app .baby-tick { flex: none; width: 22px; height: 22px; margin: 4px; box-sizing: border-box; border-radius: 50%;
    border: 1.5px solid var(--line2); background: var(--card); color: transparent; display: grid; place-items: center; font-size: 13px; }
#app .baby-tick.on { background: var(--ink); border-color: var(--ink); color: var(--card); }
#app .baby-tick.na { border-style: dashed; }
/* the small pill at a row's end (28, --field, 12/500): „Geimpft" on an open dose */
#app .baby-pill { flex: none; height: 28px; padding: 0 11px; border: 0; border-radius: var(--r-pill); background: var(--field);
    color: var(--ink); font-family: var(--font-family); font-size: var(--fs-cap); font-weight: 500; white-space: nowrap;
    cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* the stop pill of a running timer is the ink one (the design's .pill.sm) */
#app .baby-pill.is-ink { background: var(--ink); color: var(--card); }
/* Wachstum: per measure a line — its label 13/500 in --ink2, the value in the serif 18, the
   percentile and day 12 — and its sparkline 120 × 44 in the child's colour */
#app .baby-vit { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-top: 1px solid var(--line); cursor: pointer; }
#app .baby-vit:first-child { border-top: 0; }
#app .baby-vit-tx { flex: 1; min-width: 0; }
#app .baby-vit-tx > b { display: block; font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); }
#app .baby-vit-tx > small { font-size: var(--fs-cap); color: var(--ink2); }
#app .baby-spark { position: relative; flex: 0 0 120px; height: 44px; }
#app .baby-spark svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
#app .baby-spark-line { fill: none; stroke: var(--pc); stroke-width: 1.8; vector-effect: non-scaling-stroke; stroke-linejoin: round; stroke-linecap: round; }
#app .baby-spark-area { fill: var(--pc); opacity: .18; stroke: none; }
/* Wachstum's chart: one measure over age against the WHO band — the chart standard (a 0–100
   viewBox, non-scaling strokes, the wash), its labels as HTML around the plot, a point a button */
#app .baby-gchart { padding: 14px 14px 12px; display: grid; gap: 10px; margin-bottom: 12px; }
#app .baby-gchart-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
#app .baby-gchart-head b { font-size: var(--fs-body); font-weight: 600; color: var(--ink); }
#app .baby-gchart-head small { font-size: var(--fs-cap); color: var(--ink3); }
#app .baby-gchart-kinds { margin: 0; }
#app .baby-gchart-plot { position: relative; height: 190px; margin: 14px 34px 22px 28px; }
#app .baby-gchart-plot svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
#app .baby-gchart-grid { stroke: var(--line); stroke-width: 1; vector-effect: non-scaling-stroke; }
#app .baby-gchart-band { fill: var(--pc); opacity: .13; stroke: none; }
#app .baby-gchart-median { fill: none; stroke: var(--ink3); stroke-width: 1.2; stroke-dasharray: 4 4; vector-effect: non-scaling-stroke; }
#app .baby-gchart-line { fill: none; stroke: var(--pc); stroke-width: 2.2; stroke-linejoin: round; stroke-linecap: round; vector-effect: non-scaling-stroke; }
#app .baby-gchart-lab { position: absolute; font-size: 11px; line-height: 1; color: var(--ink3); white-space: nowrap; }
#app .baby-gchart-lab.is-y { right: calc(100% + 8px); transform: translateY(-50%); }
#app .baby-gchart-lab.is-unit { right: calc(100% + 8px); top: -24px; }
#app .baby-gchart-lab.is-x { top: calc(100% + 6px); transform: translateX(-50%); }
#app .baby-gchart-lab.is-xunit { top: calc(100% + 6px); left: calc(100% + 10px); }
#app .baby-gchart-lab.is-p { left: calc(100% + 5px); transform: translateY(-50%); font-size: 10.5px; }
#app .baby-gchart-pt { position: absolute; width: 24px; height: 24px; margin: -12px 0 0 -12px; padding: 0; border: 0;
    background: none; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .baby-gchart-pt::after { content: ""; position: absolute; left: 50%; top: 50%; width: 6px; height: 6px; margin: -3px 0 0 -3px;
    border-radius: 50%; background: var(--pc); }
#app .baby-gchart-pt.on::after { width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; background: var(--card); box-shadow: inset 0 0 0 2.5px var(--pc); }
#app .baby-gchart-foot { font-size: var(--fs-label); color: var(--ink2); line-height: 1.4; }
#app .baby-gchart-foot b { color: var(--ink); font-weight: 600; }
/* the Gesundheit tab: the milk teeth as two arches, the ones that came in the child's colour, each
   a button (no focus ring, like everywhere); under them Health's illness log and its way back */
#app .baby-teeth { padding: 14px; display: grid; gap: 8px; margin-bottom: 12px; }
#app .baby-teeth-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
#app .baby-teeth-head b { font-size: var(--fs-body); font-weight: 600; color: var(--ink); }
#app .baby-teeth-head small { font-size: var(--fs-label); color: var(--ink2); }
#app .baby-teeth-jaw { display: block; width: 100%; max-width: 300px; justify-self: center; }
#app .baby-tooth { fill: var(--card); stroke: var(--line2); stroke-width: 1.5; cursor: pointer; outline: none; -webkit-tap-highlight-color: transparent; }
#app .baby-tooth.came { fill: var(--pc); stroke: var(--pc); }
#app .baby-teeth-word { font-size: 10px; fill: var(--ink3); }
#app .baby-teeth-foot { font-size: var(--fs-label); color: var(--ink2); line-height: 1.4; }
#app .baby-teeth-foot b { color: var(--ink); font-weight: 600; }
#app .hl-baby-record { display: grid; gap: 10px; }
#app .hl-baby-revoke { justify-self: start; margin: 2px; padding: 0; border: 0; background: none; font-family: var(--font-family);
    font-size: var(--fs-cap); color: var(--ink3); text-decoration: underline; cursor: pointer; }
#app .baby-spark-dot { position: absolute; width: 7px; height: 7px; border-radius: 50%; background: var(--card);
    box-shadow: inset 0 0 0 1.8px var(--pc); transform: translate(-50%, -50%); }
/* the picture sheet: the picture 200 round, the chips centred under it */
#app .baby-pic-big { display: grid; place-items: center; width: 200px; height: 200px; margin: 4px auto 16px; border-radius: 50%;
    overflow: hidden; background: var(--pc-soft, var(--card2)); color: var(--pc-ink, var(--ink2)); font-size: 64px; font-weight: 500; }
#app .baby-pic-big img { width: 100%; height: 100%; object-fit: cover; display: block; }
#app .baby-pic-chips { justify-content: center; margin-bottom: 12px; }
#app .baby-pic-chips .fuer-chip i { font-size: 14px; }

/* manual vaccine sheet: per dose a Geimpft|Fällig date pair under one legend */
#app .baby-dose-pair { display: flex; gap: 8px; flex: 1; min-width: 0; }
#app .baby-dose-pair > input { flex: 1; min-width: 0; }
#app .baby-dose-legend { display: flex; gap: 8px; margin: 4px 0 0; }
#app .baby-dose-legend span {
    flex: 1;
    font-size: var(--fs-cap);
    font-weight: 600;
    color: var(--ink3);
}

/* no child yet: the lean hero „Baby ˅" over the blank card, on the page's own sides */
#app .baby-empty { display: flex; flex-direction: column; gap: 8px; padding: 0 var(--pad) 96px; }
#app .baby-empty > .hero-lean { margin: 8px 0 0; }

/* the dashboard card: the status row — the tinted bed tile, what the baby does and what is
   expected, the small pill that changes it —, the three quick fields under it, then today's
   entries as timeline rows (time 50 · what over its detail). The Gesundheit card's illness row
   wears the same tile and pill. */
#app .baby-w-status { flex-wrap: nowrap; align-items: center; gap: 12px; border-bottom: 0; }
#app .baby-w-ki, #app .hl-w-ki { flex: none; width: 30px; height: 30px; display: grid; place-items: center; border-radius: 10px;
    background: var(--pc-soft, var(--nav-fill)); color: var(--pc-ink, var(--ink2)); font-size: 16px; }
#app .baby-w-pill, #app .hl-w-log { flex: none; height: 28px; padding: 0 11px; border: 0; border-radius: var(--r-pill); background: var(--field);
    color: var(--ink); font-family: var(--font-family); font-size: var(--fs-cap); font-weight: 500; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .baby-w-quick { display: flex; gap: 6px; padding: 0 14px 12px; }
#app .baby-w-quick > button { flex: 1; min-width: 0; height: 36px; display: flex; align-items: center; justify-content: center; gap: 6px;
    border: 0; border-radius: var(--r-ctl); background: var(--field); color: var(--ink); font-family: var(--font-family);
    font-size: var(--fs-sub); font-weight: 500; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .baby-w-quick > button i { font-size: 16px; color: var(--ink2); }
#app .baby-w-ev { flex-wrap: nowrap; align-items: flex-start; gap: 12px; border-bottom: 0; border-top: 1px solid var(--line); }
#app .baby-w-time { flex: none; width: 50px; min-height: 30px; display: flex; align-items: center; font-size: var(--fs-sub); font-weight: 500;
    color: var(--ink2); font-variant-numeric: tabular-nums; }
#app .baby-w-ev > .txt { min-height: 30px; display: flex; flex-direction: column; justify-content: center; white-space: normal; }
/* an expected baby: the days to the due date in the serif, the date under it */
#app .baby-w-due { padding: 4px 14px 12px; }
#app .baby-w-due > span { margin-top: 2px; font-size: var(--fs-sub); color: var(--ink2); }

/* ============================== entity sheet + settings ============================== */

/* the entity sheet's fields under its head — two to a line (a pair, 12 apart), 16px between the
   lines and 6px under a label, with no box of their own inside the sheet; a price, the colour,
   Für, a text or a choice too long for half of it (.is-wide), a field without a neighbour
   (.is-alone) and every block that is no field (the deadlines, a held date, the records, the
   folds) take the whole line */
#app .ent-attrs {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: start;
    gap: 16px 12px;
    margin: 0 0 16px;
}
#app .ent-attrs > :not(.ent-attr-row), #app .ent-attrs > .ent-attr-row.is-wide,
#app .ent-attrs > .ent-attr-row.is-alone { grid-column: 1 / -1; }
/* a row is a <label>: the generic label's own margin would double the rows' gap; under the label
   one box holds its field and what is said under it (a projection, the chosen option's line) */
#app .ent-attr-row {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0;
    min-width: 0;
}
#app .ent-attr-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
/* a half-line field is two rows of the form's grid — its label, its box — shared with its
   neighbour (subgrid): the fields of a pair stand level, a label that wraps sits on its field */
#app .ent-attrs > .ent-attr-row:not(.is-wide) { grid-row: span 2; display: grid; grid-template-rows: subgrid; row-gap: 6px; }
#app .ent-attrs > .ent-attr-row:not(.is-wide) > span { align-self: end; }
#app .ent-attr-row > span {
    display: flex;
    align-items: center;
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--ink2);
}
#app .ent-attrs .action-btn { align-self: flex-end; }
/* a date another module holds or follows (a pet's or a person's next vaccination): ONE row that
   is a door — the heart, the word with the holder's answer under it, the holder's name › */
#app .ent-held { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; padding: 4px 0; border: 0;
    background: none; color: var(--ink); font: inherit; font-size: var(--fs-md); text-align: left; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
#app .ent-held-lead { flex: none; font-size: 20px; color: var(--ink2); }
#app .ent-held-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
#app .ent-held-t > b { font-weight: 500; line-height: 1.35; }
#app .ent-held-t > small { font-size: var(--fs-sub); color: var(--ink2); }
#app .ent-held-t > small.pend { color: var(--pend-ink); font-weight: 500; }
#app .ent-held-t > small.late { color: var(--due-ink); font-weight: 500; }
#app .ent-held-val { flex: none; display: inline-flex; align-items: center; gap: 4px; font-size: 14px; color: var(--ink2); white-space: nowrap; }
#app .ent-held-val > i { font-size: 13px; color: var(--ink3); }
/* a section head of the sheet (secHead): 36 high, the word, its count at the right, the „+" disc;
   6 over its first row. A section (the deadlines, a person's records) stands 24 under a field and
   12 under the row of the section or the held date above it (the form's gap is 16) */
#app .ent-sec-head { display: flex; align-items: center; gap: 6px; min-height: 36px; margin-bottom: 6px; font-size: var(--fs-head); font-weight: 500; color: var(--ink2); }
#app .ent-attrs > .ent-attr-row + :is(.ent-records, .ent-deadlines) { margin-top: 8px; }
#app .ent-attrs > :is(.ent-records, .ent-held) + .ent-records { margin-top: -4px; }
#app .ent-sec-count { margin-left: auto; font-weight: 400; font-variant-numeric: tabular-nums; }
#app .ent-sec-add { flex: none; width: 28px; height: 28px; padding: 0; border: 0; border-radius: 50%; background: var(--nav-fill);
    color: var(--ink2); font-size: 13px; display: inline-grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* the sheet's head: the thing's lead (its badge, or its glyph on a tile r9) left of its name and
   the line under it; the name is the field it is written in */
#entity-edit-overlay .popup-header:has(> .ent-lead) { grid-template-columns: auto minmax(0, 1fr); }
#entity-edit-overlay .popup-header > .ent-lead { grid-row: 1 / 3; grid-column: 1; width: 30px; height: 30px; box-sizing: border-box; font-size: 12px; }
#entity-edit-overlay .popup-header:has(> .ent-lead) > span,
#entity-edit-overlay .popup-header:has(> .ent-lead) > .popup-sub { grid-column: 2; }
#entity-edit-overlay .popup-header:has(> .popup-back):has(> .ent-lead) { grid-template-columns: auto auto minmax(0, 1fr); }
#entity-edit-overlay .popup-header:has(> .ent-lead) > .popup-back { grid-row: 1 / 3; grid-column: 1; }
#entity-edit-overlay .popup-header:has(> .popup-back) > .ent-lead { grid-column: 2; }
#entity-edit-overlay .popup-header:has(> .popup-back):has(> .ent-lead) > span,
#entity-edit-overlay .popup-header:has(> .popup-back):has(> .ent-lead) > .popup-sub { grid-column: 3; }
#app .ent-lead-thing { border-radius: 9px; }
#app .ent-lead-thing > i { font-size: 16px; }
/* a thing for several members or the household: the neutral tile its row in the list wears */
#app .ent-lead-thing:not([class*="pc-"]) { background: var(--nav-fill); color: var(--ink2); box-shadow: none; }
#app .ent-name { outline: none; cursor: text; }
#app .ent-name:empty::before { content: attr(data-ph); color: var(--ink2); }

/* settings: the partner invite link (the address and its state: the profile head, further down) */
#app .settings-invite { display: flex; flex-direction: column; gap: 8px; align-items: stretch; }
/* its answer line (sent to …, the seat cap) in the hint voice; empty it takes no room */
#app .settings-invite > #inv-msg { font-size: var(--fs-sub); line-height: 1.45; color: var(--ink2); }
#app .settings-invite > #inv-msg:empty { display: none; }
/* a value to copy: the read-only field (13 --ink2, tabular — a link, a code) and its copy disc */
#app .copy-row { display: flex; align-items: center; gap: 8px; width: 100%; }
#app .copy-row > .fi-ro { flex: 1; min-width: 0; font-size: var(--fs-sub); color: var(--ink2); font-variant-numeric: tabular-nums; }
/* a sheet's tool: the 36px disc (copy, a head's tools beside the ✕) */
#app .sheet-tool { flex: none; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%; background: var(--nav-fill); color: var(--ink); font-size: 17px; display: inline-grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .sheet-tool:active { transform: scale(var(--button-click-scale)); }
/* the diagnostic trail: Inter, tabular, on the inset tone — no third typeface */
#app pre.diag { margin: 0; padding: 10px 12px; border-radius: 10px; background: var(--card2); color: var(--ink2); font: 400 12px/1.45 var(--font-family); font-variant-numeric: tabular-nums; white-space: pre-wrap; word-break: break-all; max-height: 60vh; overflow: auto; user-select: text; -webkit-user-select: text; }
#app #settings-invite-email { flex: 1; min-width: 0; }
#app #settings-invite-result { display: flex; gap: 8px; width: 100%; }
#app #settings-invite-link { flex: 1; min-width: 0; font-size: var(--fs-ui); }
#app #settings-invite-msg { font-size: var(--fs-cap); color: var(--ink2); }

/* attachments inside the attribute form */
#app .ent-files { display: flex; flex-direction: column; gap: 6px; }
#app .ent-files-list:empty, #app .ent-files-status:empty { display: none; }
#app .ent-files-head i { margin-right: 4px; }
#app .ent-file-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
#app .ent-file-name {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    text-align: left;
    font-family: var(--font-family);
    color: var(--ink);
    font-size: var(--fs-body);
    text-decoration: underline;
    text-underline-offset: 3px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1;
}
#app .ent-file-size { font-size: var(--fs-sub); color: var(--ink3); white-space: nowrap; }
#app .ent-file-menu { font-size: 15px; }
#app .ent-file-ren { font-size: var(--fs-ui); }
#app .ent-file-rename { flex: 1; min-width: 0; font-size: inherit; }
#app .ent-files .ent-file-add { align-self: flex-start; }
/* upload + pick-existing share one row (wraps on narrow sheets), in the tonal voice of a
   secondary action — the one filled button of an editor is its Speichern */
#app .ent-file-btns { display: flex; gap: 8px; flex-wrap: wrap; align-self: flex-start; }
#app .ent-file-btns .action-btn.reusable { margin: 0; background: var(--nav-fill); color: var(--ink); border-color: transparent; }
#app .ent-files-status { font-size: var(--fs-cap); color: var(--ink2); min-height: 0; }
/* the tiles mode (Health's documents, a vaccination's booklet): the files as 64 tiles r10 — the
   picture itself, else its type glyph — and the add tiles behind them on the same line */
#app .ent-files.is-tiles { flex-direction: row; flex-wrap: wrap; gap: 8px; }
#app .ent-files.is-tiles > .ent-files-list, #app .ent-files.is-tiles > .ent-file-btns { display: contents; }
#app .ent-files.is-tiles > .ent-files-status { flex: 1 0 100%; }
#app .ent-file-tile { width: 64px; height: 64px; box-sizing: border-box; flex: none; padding: 0; border: 0; border-radius: 10px;
    overflow: hidden; display: grid; place-items: center; align-content: center; gap: 2px; background: var(--field); color: var(--ink2);
    font-family: var(--font-family); font-size: 11px; font-weight: 500; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .ent-file-tile > img { width: 100%; height: 100%; object-fit: cover; display: block; }
#app .ent-file-tile > i { font-size: 18px; }
#app .ent-file-tile:active { transform: scale(var(--button-click-scale)); }

/* ---- pick-existing sheet (pickExistingFiles): thumbnail grid, select mode ---- */
.fp-search { width: 100%; }
.fp-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 10px; max-height: 46vh; overflow-y: auto; }
@media (max-width: 420px) { .fp-grid { grid-template-columns: repeat(2, 1fr); } }
.fp-tile { position: relative; display: flex; flex-direction: column; padding: 0; border: 2px solid var(--line); border-radius: var(--r-ctl); overflow: hidden; background: var(--card2); cursor: pointer; text-align: left; }
.fp-tile.sel { border-color: var(--ink); }
.fp-tile.fp-here { opacity: 0.55; cursor: default; }
.fp-thumb { position: relative; aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center; font-size: 24px; color: var(--ink3); }
.fp-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.fp-badge { position: absolute; top: 6px; right: 6px; width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: var(--fs-cap); background: var(--card); color: var(--ink3); border: 1px solid var(--line); }
.fp-tile.sel .fp-badge { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.fp-tile.fp-here .fp-badge { width: auto; border-radius: 6px; padding: 1px 6px; }
.fp-heretag { font-size: 11px; font-weight: 700; white-space: nowrap; }
.fp-meta { padding: 5px 7px; font-size: var(--fs-cap); border-top: 1px solid var(--line); background: var(--card); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fp-foot { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 12px; }
.fp-count { font-size: var(--fs-sub); color: var(--ink2); }
.fp-note { font-size: var(--fs-cap); color: var(--ink3); margin: 8px 0 0; }
/* attachment category headings + the per-file category picker (compact select) */
.ent-file-cat {
    font-size: var(--fs-ui);
    font-weight: 600;
    color: var(--ink2);
    margin: 8px 2px 2px;
}

/* related-entity / linked-note chips (the entity "hub") — link badges */
#app .ent-links { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
/* the folds of an entity sheet (Kosten, Weitere Angaben, Verknüpft) stand one under the other,
   a hairline between them and nothing more; the first stands 14 under a field (the grid's 16 less
   2) and 8 under the last row of the deadlines or of a person's records */
#app .ent-attrs > .kuer-fold { margin: -2px 0 0; }
#app .ent-attrs > .kuer-fold + .kuer-fold { margin-top: -16px; }
#app .ent-attrs > .ent-deadlines:not([hidden]) + .kuer-fold,
#app .ent-attrs > .ent-records + .kuer-fold { margin-top: -8px; }
/* the Kosten fold open: the finance list's rows on the field fill (the sheet is itself a card),
   the add button under them in the tonal voice */
#app .ent-costs .kuer-body { display: flex; flex-direction: column; gap: 6px; }
#app .ent-costs-list { display: flex; flex-direction: column; background: var(--field); border-radius: var(--r-ctl); }
#app .ent-cost-row {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    width: 100%; box-sizing: border-box; min-height: 44px; padding: 8px 12px;
    border: 0; border-bottom: 1px solid var(--line); background: transparent; color: var(--ink);
    font-family: inherit; text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent;
}
#app .ent-cost-row:last-child { border-bottom: 0; }
#app .ent-cost-body { display: flex; flex-direction: column; min-width: 0; }
/* a line says what it is in the row title's voice (15/500), how and how much under it in the meta
   voice (13/400), what it comes to a month in the amount's (15/500, tabular) */
#app .ent-cost-name { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; }
#app .ent-cost-body small { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }
#app .ent-cost-row > b { font-size: var(--fs-md); font-weight: 500; white-space: nowrap; font-variant-numeric: tabular-nums; }
#app .ent-costs-list .ent-files-status { padding: 10px 12px; }
#app .ent-cost-add { align-self: flex-start; margin-top: 2px; background: var(--nav-fill); color: var(--ink); border-color: transparent; }
/* a thing's deadlines: under their head one row per entry (48: the calendar glyph, what runs out
   with until when under it, the chevron) whose tap opens its form under it — what, until when,
   once or yearly, the cost, × —, then a row per usual one of the household's country, „Übernehmen" */
#app .ent-deadline-rows:empty { display: none; }
#app .ent-deadline, #app .ent-deadline-field { border-top: 1px solid var(--line); }
#app .ent-deadline:first-child, #app .ent-deadline-field:first-child { border-top: 0; }
#app .ent-deadline-face { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; padding: 4px 0; border: 0;
    background: none; color: var(--ink); font-family: var(--font-family); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .ent-deadline-lead { flex: none; font-size: 20px; color: var(--ink2); }
#app .ent-deadline-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
#app .ent-deadline-t > b { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .ent-deadline-t > small { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }
#app .ent-deadline-t > small.late { color: var(--due-ink); font-weight: 500; }
#app .ent-deadline-face .fold-chev { font-size: 13px; }
#app .ent-deadline.open > .ent-deadline-face .fold-chev,
#app .ent-deadline-field.open > .ent-deadline-face .fold-chev { transform: none; }
#app .ent-deadline-form { display: flex; flex-direction: column; gap: 6px; padding: 0 0 12px 32px; }
#app .ent-deadline-tip { display: flex; align-items: center; gap: 12px; min-height: 48px; box-sizing: border-box; border-top: 1px solid var(--line); font-size: var(--fs-sub); color: var(--ink2); }
#app .ent-deadline-tip > span { flex: 1; min-width: 0; }
#app .ent-deadline-take { flex: none; height: 28px; padding: 0 11px; border: 0; border-radius: var(--r-pill); background: var(--field);
    color: var(--ink); font-family: var(--font-family); font-size: 12px; font-weight: 500; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .ent-deadline-row { display: flex; align-items: center; gap: 6px; }
#app .ent-deadline-name, #app .ent-deadline-amt { flex: 1 1 auto; min-width: 0; }
#app .ent-deadline-amt { font-variant-numeric: tabular-nums; }
#app .ent-deadline-date, #app .ent-deadline .date-wrap { flex: 1 1 auto; min-width: 0; }
#app .ent-deadline-cycle { flex: 0 0 128px; }
#app .ent-deadline-cur { flex: 0 0 84px; }
#app .ent-deadline-x {
    flex: 0 0 32px; height: 32px; display: grid; place-items: center;
    border: 0; background: none; color: var(--ink3); font-size: 14px; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
#app .ent-link-chip {
    display: inline-flex;
    align-items: center;
    background: var(--card2);
    border: 1px solid var(--line);
    border-radius: 6px;
    font-size: var(--fs-label);
    font-weight: 600;
    color: var(--ink2);
    white-space: nowrap;
    flex-shrink: 0;
}
#app .ent-link-go {
    /* inline-block, not inline-flex: a long event title („Kinderärztin – Josephine, Mutter-Kind-
       Pass-Untersuchung · 2026-09-20“) ends in … inside the sheet instead of widening it — the
       ellipsis needs a block with inline content, so the icon keeps its gap by a margin */
    display: inline-block;
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
    background: transparent;
    border: 0;
    color: inherit;
    cursor: pointer;
    font: inherit;
    padding: 3px 2px 3px 8px;
    white-space: nowrap;
}
#app .ent-link-go > i, #app .ent-link-go > .m { margin-right: 5px; vertical-align: middle; }
#app .ent-link-chip { max-width: 100%; }
#app .ent-link-x {
    display: inline-flex;
    align-items: center;
    background: transparent;
    border: 0;
    cursor: pointer;
    color: var(--ink3);
    padding: 3px 7px 3px 3px;
    font-size: var(--fs-ui);
}
#app .ent-link-x:hover, #app .ent-link-x:active { color: var(--due-ink); }

/* person-bound records (notes + medications) in the entity editor */
/* a person's records (notes, medications, wishes): under their head (secHead) one row each, 48
   high with a hairline between — the text, then at the right a switch and the × 32 */
#app .ent-records { display: flex; flex-direction: column; }
#app .ent-rec-list { display: flex; flex-direction: column; }
#app .ent-rec-row { display: flex; align-items: center; gap: 12px; min-width: 0; min-height: 48px; padding: 4px 0; box-sizing: border-box; border-top: 1px solid var(--line); }
#app .ent-rec-row:first-child { border-top: 0; }
#app .ent-rec-txt { flex: 1; min-width: 0; font-size: var(--fs-body); color: var(--ink); overflow-wrap: anywhere; }
#app .ent-rec-off .ent-rec-txt { color: var(--ink2); text-decoration: line-through; }
/* the med's active switch — the app's little switch, not the generic full-width popup input */
.popup-body input.ent-rec-active.swT { width: 44px; height: 26px; padding: 0; border: 0; border-radius: var(--r-pill); background: var(--line2); }
.popup-body input.ent-rec-active.swT:checked { background: var(--ink); }
/* med row: the name with dose and plan under it, tap to edit */
#app .ent-med-txt {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
    background: none;
    border: 0;
    padding: 0;
    text-align: left;
    cursor: pointer;
    color: inherit;
    font: inherit;
}
#app .ent-med-txt b { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; }
#app .ent-med-sub { font-size: var(--fs-sub); color: var(--ink2); }
#app .ent-rec-off .ent-med-txt { color: var(--ink2); }
#app .ent-rec-off .ent-med-txt b { text-decoration: line-through; }
/* intake builder: one row per intake — slot/time picker · clock · per-intake dose · × */
#app .ent-med-intakes { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
#app .ent-med-intake { display: flex; gap: 6px; align-items: center; min-width: 0; }
#app .ent-med-intake .mg-select { flex: 1.3; min-width: 0; }
#app .ent-med-intake .ent-med-time,
#app .ent-med-intake .ent-med-idose { flex: 1; min-width: 0; }
#app .ent-med-addintake { align-self: flex-start; }
#app .ent-rec-del { width: 32px; height: 32px; flex: none; color: var(--ink); font-size: 15px; }
#app .ent-medform {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px;
    margin: 4px 0;
    background: var(--card2);
    border: 1px solid var(--line);
    border-radius: 10px;
}
#app .ent-medform input { background: var(--card); }
#app .ent-medform-actions { display: flex; gap: 8px; justify-content: flex-end; }


/* unified Settings sheet — You | Group */
#app .settings-panel { display: flex; flex-direction: column; }
/* every setting is a ROW: its word left, its control right, a hairline between two rows (none
   over the first of a fold or after a field pair); a control that needs the width (the colour
   dots) stands under its word (.set-block). */
#app .settings-fold-body > .set-row:first-child,
#app .settings-fold-body > :not(.set-row) + .set-row { border-top-color: transparent; }
/* the usage block is rows too: the row after it keeps its hairline */
#app .settings-fold-body > #settings-usage-host:not(:empty) + .set-row { border-top-color: var(--line); }
#app .set-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    min-height: 48px;
    margin: 0;
    padding: 4px 0;
    box-sizing: border-box;
    border: 0;
    border-top: 1px solid var(--line);
    border-radius: 0;
    background: none;
    font-family: var(--font-family);
    font-size: var(--fs-body);
    font-weight: 400;
    line-height: 1.35;
    color: var(--ink);
    text-align: left;
}
/* a row's word in the row-title voice (15/500); what it is under it reads at 400 */
#app .set-label { flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; margin: 0; font-size: var(--fs-body); font-weight: 500; color: inherit; }
#app .set-label > i { color: var(--ink2); font-size: 18px; }
/* a row's word with what it is under it („Morgen-Digest" · per E-Mail, „Personen & Dinge" · 12 Einträge) */
#app .set-label:has(> small) { flex-direction: column; align-items: flex-start; gap: 1px; }
#app .set-label > small { font-size: var(--fs-sub); font-weight: 400; color: var(--ink2); }
/* the word with its ⓘ as the first line, when what is set stands under it („Ernährung" ⓘ ·
   vegetarisch) */
#app .set-label > .set-word { display: inline-flex; align-items: center; gap: 10px; }
#app .set-word > .set-info { margin-left: -8px; }
#app .set-block { display: flex; flex-direction: column; gap: 6px; padding: 12px 0 8px; border-bottom: 1px solid var(--line); }
/* a block's word (Farbe) speaks in the field-label voice, like Geburtstag and Sprache beside it */
#app .set-block > .set-label { font-size: var(--fs-sub); color: var(--ink2); }
/* the last block of a fold leaves the line to the next fold's head — one hairline, not two */
#app .settings-fold-body > .set-block:last-child { border-bottom: 0; }
/* the ⓘ of an explanation (render/explain.js) beside the word, head or sheet title it belongs
   to: quiet, round, its tap opens the form's explanations as one sheet */
.set-info {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    margin: -6px 0 -6px 2px;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--ink3);
    font-size: 15px;
    vertical-align: middle;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.set-info:active { background: var(--nav-fill); }
#app .set-label > .set-info { margin-left: -8px; }
.popup-header > span > .set-info { margin-left: 4px; font-size: 16px; }
/* the explanations sheet: one fold per explanation, its text in the body voice */
.explain-sheet .explain-text { margin: 0; padding: 0 12px 8px; font-size: var(--fs-body); line-height: 1.5; color: var(--ink2); }
/* a row that IS an action (export, delete, Personen & Dinge): the whole row taps, its glyph right */
#app .set-act { cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .set-act > i { flex: none; color: var(--ink3); font-size: 13px; }
/* a row's leading glyph (Exportieren): the passkey rows' 20 in --ink2 */
#app .set-row > .set-lead { color: var(--ink2); font-size: 20px; }
#app .set-act.danger, #app .set-act.danger > i { color: var(--due-ink); }
#app .set-act:disabled { opacity: 0.5; cursor: default; }
/* a field in a row — text, date, choice — takes the same share of it, so their edges line up */
#app .set-row > input[type="text"],
#app .set-row > .date-wrap,
#app .set-row > .mg-select { flex: 0 0 52%; width: 52%; min-width: 0; }
/* a switch row: the checkbox itself, drawn as the app's little switch */
#app .set-row > input.swT { width: 44px; height: 26px; padding: 0; border: 0; border-radius: var(--r-pill); }
/* the sheet's small tonal buttons: the picture's three, the resend, Einrichten */
#app .set-pill {
    flex: none;
    height: 32px;
    padding: 0 11px;
    border: 0;
    border-radius: var(--r-pill);
    background: var(--field);
    color: var(--ink2);
    font-family: var(--font-family);
    font-size: var(--fs-sub);
    font-weight: 500;
    white-space: nowrap;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
#app .set-pill:disabled { opacity: 0.5; cursor: default; }
/* the profile's head: the member's badge 56 (the photo, the initial without one; ring 2 --card +
   4 in their colour), the name and the address with its state; the picture's pills under it */
#app .settings-avatar { display: flex; align-items: center; gap: 12px; min-height: 64px; padding: 4px 0; }
#app .settings-id { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
#app .settings-name { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; color: var(--ink); }
#app .settings-email { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .settings-email-state::before { content: " · "; }
#app .settings-avatar-preview {
    width: 56px;
    height: 56px;
    flex: none;
    box-sizing: border-box;
    margin: 4px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--pc-soft, var(--card2));
    box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--pc, var(--line2));
    display: grid;
    place-items: center;
    font-size: 22px;
    font-weight: 500;
    color: var(--pc-ink, var(--ink2));
}
#app .settings-avatar-preview img { width: 100%; height: 100%; object-fit: cover; }
#app .settings-avatar-actions { display: flex; flex-wrap: wrap; gap: 6px; margin: 4px 0 12px; }
#app .settings-pair { margin-bottom: 14px; }
/* the settings sheet has no Speichern, so none of its actions is the filled one: all tonal */
#app .settings-panel .action-btn.reusable:not(.cancel-btn):not(.delete-btn) { background: var(--nav-fill); color: var(--ink); border-color: transparent; }

/* weather places (Settings → Group): followed-location chips + geocoding search */
#app .settings-weather { display: flex; flex-direction: column; gap: 8px; }
#app #weather-current { display: flex; flex-direction: column; }
#app .weather-none { font-size: var(--fs-hint); color: var(--ink3); }
/* ONE field with its action at its end (the place search, a person's note, a new file category):
   the glyph button sits inside the field's right edge and does what Enter does */
.field-act { position: relative; }
.popup-body .field-act > input { flex: 1 1 auto; width: 100%; min-width: 0; padding-right: 46px; }
.field-act-go.is-busy { opacity: .4; animation: cook-tmr-pulse 1s ease-in-out infinite; }
.field-act-go {
    position: absolute;
    top: 0;
    right: 0;
    width: 44px;
    height: 44px;
    border: 0;
    background: transparent;
    color: var(--ink2);
    font-size: 17px;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
#app #weather-results { display: flex; flex-direction: column; gap: 2px; font-size: var(--fs-ui); color: var(--ink3); }
#app .weather-result {
    text-align: left;
    border: 0;
    background: transparent;
    cursor: pointer;
    padding: 9px 10px;
    border-radius: 8px;
    font-family: var(--font-family);
    font-size: var(--fs-body);
    color: var(--ink);
    transition: background var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
#app .weather-result:hover { background: var(--card2); }

/* household usage — a settings row each: the word 15/500, „4 von 6" under it, the bar 6 on the
   field tone under that; a hairline between two; over the limit = red */
#app .settings-usage { display: flex; flex-direction: column; }
#app .usage-row { display: flex; flex-direction: column; justify-content: center; min-height: 48px; box-sizing: border-box; padding: 4px 0; border-top: 1px solid var(--line); line-height: 1.35; }
#app .usage-row:first-child { border-top: 0; }
#app .usage-label { font-size: var(--fs-body); font-weight: 500; color: var(--ink); }
#app .usage-count { font-size: var(--fs-sub); color: var(--ink2); font-variant-numeric: tabular-nums; }
#app .usage-row > .usage-track { margin-top: 6px; }
#app .usage-track {
    height: 6px;
    border-radius: 3px;
    background: var(--field);
    overflow: hidden;
}
#app .usage-fill { display: block; height: 100%; border-radius: 3px; background: var(--ink); transition: width var(--transition-base); }
#app .usage-fill.over { background: var(--due); }

/* upload-in-flight bar (reuses .usage-track/.usage-fill) + its cancel button, laid out in one
   status line; shared by every upload surface */
#app .up-progress-wrap { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
#app .up-progress { display: block; flex: 1; }
#app .up-cancel { flex: none; font-size: var(--fs-cap); color: var(--ink2); background: none; border: none; padding: 2px 4px; cursor: pointer; text-decoration: underline; }
#app .up-status { font-size: var(--fs-cap); color: var(--ink2); }

#app .confirm-sheet .popup-footer .action-btn { flex: 1 1 0; margin: 0; }
#app .confirm-sheet .popup-footer .action-btn.delete-btn { background: var(--due); color: var(--badge-fg); padding: 0 16px; margin-right: 0; }
#app .confirm-sheet .confirm-message { margin: 0; padding: 2px 0 4px; font-size: var(--fs-md); line-height: 1.45; color: var(--ink2); }
/* Optional toggle inside a confirm sheet (e.g. "delete the N entries too"). The label and the
   checkbox both have to shed the .popup-body form-field styling (uppercase label, width:100% input)
   so the text reads as a sentence and wraps inside the box instead of being pushed off the edge. */
#app .confirm-sheet .confirm-extra { display: flex; align-items: center; gap: 10px; margin: 12px 0 0; padding: 11px 12px; border: 0; border-radius: 10px; background: var(--card2); cursor: pointer; text-align: left; font-size: 14px; font-weight: 400; letter-spacing: normal; text-transform: none; line-height: 1.35; color: var(--ink); }
/* its round tick is the 20 one, the ink check moved with it */
#app .confirm-sheet .confirm-extra input { flex: none; margin: 0; padding: 0; width: 20px; height: 20px; }
#app .confirm-sheet .confirm-extra input:checked::after { left: 6px; top: 2.5px; }
#app .confirm-sheet .confirm-extra span { flex: 1; min-width: 0; }
/* member area (design/prototype.html "Benutzer"): rows with a ⋮ kebab menu + an invite button */
#app .uList { display: flex; flex-direction: column; }
/* a member row: the 48px settings row — badge 30, the name 15/500, „role · last active" under it,
   the bare ⋮ at its end */
#app .uMem { display: flex; align-items: center; gap: 12px; min-height: 48px; box-sizing: border-box; padding: 4px 0; border-top: 1px solid var(--line); }
#app .uMem:first-child { border-top: 0; }
#app .uMem .av { width: 30px; height: 30px; box-sizing: border-box; border: 0; box-shadow: inset 0 0 0 2px var(--pc, var(--line2)); border-radius: 50%; display: flex; align-items: center; justify-content: center; font: 600 12px var(--font-family); flex-shrink: 0; background: var(--pc-soft, var(--card2)); color: var(--pc-ink, var(--ink2)); overflow: hidden; }
#app .uMem .av img { width: 100%; height: 100%; object-fit: cover; }
#app .uMem .info { flex: 1; min-width: 0; }
#app .uMem .nm { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; display: flex; align-items: center; gap: 5px; }
#app .uMem .nm .you { font-size: var(--fs-sub); font-weight: 400; color: var(--ink2); }
#app .uMem .uSub { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .uMem .uLastActive::before { content: " · "; }

/* the settings sheet's info lines */
#app .settings-support-info { font-size: var(--fs-sub); color: var(--ink2); line-height: 1.5; margin-top: 6px; }
/* the expired-access banner — a fixed bar in the due tone, with the „Mehr" button that
   opens the access sheet; body.access-expired shifts #app below it */
body.access-expired { --access-banner-h: 28px; }
.access-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 9999;
    height: var(--access-banner-h, 28px);
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    background: var(--due-soft);
    color: var(--due-ink);
    border-bottom: 1px solid color-mix(in srgb, var(--due) 30%, transparent);
    font-size: var(--fs-ui);
    font-weight: 600;
    line-height: 16px;
    padding: 0 10px;
    white-space: nowrap;
    overflow: hidden;
}
.access-banner span { overflow: hidden; text-overflow: ellipsis; }
.access-banner button {
    flex: none;
    border: 0;
    border-radius: var(--r-pill);
    padding: 2px 10px;
    font-family: inherit;
    font-size: var(--fs-cap);
    font-weight: 600;
    background: var(--due);
    color: var(--badge-fg);
    cursor: pointer;
}
body.access-expired #app {
    top: var(--access-banner-h);
    height: calc(100% - var(--access-banner-h));
}
#app .uMem .rl.blocked { color: var(--due-ink); font-weight: 500; }
#app .menuWrap { position: relative; flex-shrink: 0; }
#app .uKebab { width: 34px; height: 34px; margin-right: -8px; border-radius: 50%; border: 0; background: transparent; color: var(--ink3); display: flex; align-items: center; justify-content: center; cursor: pointer; }
#app .uKebab i { font-size: 16px; }
#app .uMenu { position: absolute; top: 40px; right: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-ctl); box-shadow: var(--shadow); padding: 5px; min-width: 210px; z-index: 60; display: none; }
#app .uMenu.on { display: block; }
#app .uMenu.up { top: auto; bottom: 40px; }
#app .uMenu button { display: flex; align-items: center; gap: 9px; width: 100%; border: 0; background: transparent; color: var(--ink); font: 500 13px var(--font-family); text-align: left; padding: 9px 10px; border-radius: 8px; cursor: pointer; }
#app .uMenu button:hover { background: var(--card2); }
#app .uMenu button:disabled { opacity: 0.4; cursor: not-allowed; }
#app .uMenu button i { font-size: 15px; flex-shrink: 0; color: var(--ink2); }
#app .uMenu button.danger { color: var(--due-ink); }
#app .uMenu button.danger i { color: var(--due); }
#app .uMenu .mDiv { height: 1px; background: var(--line); margin: 4px 6px; }
#app .uInvite { display: flex; align-items: center; justify-content: center; gap: 6px; }
#app .uInvite i { font-size: 18px; }

/* the access sheet (drawer → Zugang): ONE card — the period line (tinted by state), the
   two-sentence intro and the usage block */
/* the access card: the household's name, the end in the serif (soon amber, expired red ink) */
#app .access-now { background: var(--card2); border: 0; border-radius: var(--r-card); padding: 12px 14px; }
#app .access-now > .access-who { display: block; font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); }
#app .access-now > b { display: block; margin: 2px 0 4px; line-height: 1.15; font-variant-numeric: tabular-nums; }
#app .access-now.access-soon > b { color: var(--pend-ink); }
#app .access-now.access-expired > b { color: var(--due-ink); }
#app .access-now > p { font-size: var(--fs-ui); color: var(--ink2); line-height: 1.5; }
#app .access-now .settings-usage { margin-top: 6px; }

/* the calendar import (ONE page): the source rail (pills 32, the chosen in ink, scrolling under a
   soft edge), its how-to, the file button, then what the file holds — „Gefunden" with its count
   and free places, one row per event: the round tick left, the title over what happens to it */
#app .cal-imp-rail { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; margin: 0 -16px 14px; padding: 0 16px;
    -webkit-mask-image: linear-gradient(90deg, var(--ink) calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, var(--ink) calc(100% - 28px), transparent); }
#app .cal-imp-rail::-webkit-scrollbar { display: none; }
#app .cal-imp-rail > button { flex: none; height: 32px; padding: 0 12px; border: 0; border-radius: var(--r-pill); background: var(--field);
    font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 500; color: var(--ink2); white-space: nowrap; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
#app .cal-imp-rail > button.on { background: var(--ink); color: var(--card); }
#app .cal-imp-how { font-size: var(--fs-hint); color: var(--ink2); line-height: 1.45; }
#app .cal-imp-err { font-size: var(--fs-hint); color: var(--due-ink); margin-top: 10px; }
#app .cal-imp-file { display: none; }
#app .cal-imp-pick { display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; height: 44px; margin-top: 12px;
    border: 0; border-radius: var(--r-ctl); background: var(--field); color: var(--ink); font-family: var(--font-family);
    font-size: var(--fs-body); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
#app .cal-imp-pick > i { flex: none; font-size: 18px; }
#app .cal-imp-head { display: flex; align-items: center; gap: 6px; min-height: 36px; margin: 14px 2px 6px; font-size: var(--fs-head);
    font-weight: 500; color: var(--ink2); font-variant-numeric: tabular-nums; }
#app .cal-imp-meta { margin-left: auto; font-weight: 400; white-space: nowrap; }
#app .cal-imp-all {
    background: none;
    border: 0;
    padding: 8px 0 4px;
    font-family: inherit;
    font-size: var(--fs-ui);
    font-weight: 600;
    color: var(--ink2);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}
#app .cal-imp-list { display: flex; flex-direction: column; }
#app .cal-imp-row {
    display: flex;
    align-items: center;
    gap: 12px;
    box-sizing: border-box;
    min-height: 48px;
    padding: 4px 0;
    margin: 0;          /* a <label>: the form label's 6 under it, its weight and its --ink2 do not belong to a row */
    font-weight: 400;
    color: var(--ink);
    border-top: 1px solid var(--line);
    cursor: pointer;
    min-width: 0;
}
#app .cal-imp-row:first-child { border-top: 0; }
#app .cal-imp-row input[type="checkbox"] { flex: none; }
/* a double („Schon da") keeps its empty tick at full strength — states are never opacity */
#app .cal-imp-row input[type="checkbox"]:disabled { opacity: 1; cursor: default; }
#app .cal-imp-row.cal-imp-same .cal-imp-txt b { color: var(--ink2); }
#app .cal-imp-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
#app .cal-imp-txt b { font-size: var(--fs-body); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .cal-imp-sub { font-size: var(--fs-sub); color: var(--ink2); }
/* baby export selection sheet: a section label, then one checkbox row per section / document */
#app .exp-sec-lbl {
    margin: 20px 2px 6px;
}
#app .exp-row { display: flex; align-items: center; gap: 10px; padding: 9px 2px; cursor: pointer; font-size: var(--fs-body); }
#app .exp-row input[type="checkbox"] { flex: none; }

#app .cal-imp-done { font-size: 14px; font-weight: 600; }
#app .cal-imp-hint { font-size: var(--fs-ui); color: var(--ink2); margin-top: 6px; line-height: 1.5; }

/* the sheet „Abonnements": three sections under quiet heads (13/500 --ink2, a + or ⋮ at their
   right) — the member's own link (its rail, the copy field right after it was made, else how it
   stands), the subscriptions by address, the connections; a row: its glyph 20, the name over how
   it stands (a failing one in the due ink), the Für capsule, a ⋮ or „Verbunden ›". The read-only
   card of a subscribed event reuses the form rows with plain text values. */
#app .cal-sub-sec { display: flex; align-items: center; gap: 6px; min-height: 36px; margin: 10px 0 6px; padding: 0 2px; font-size: var(--fs-head);
    font-weight: 500; color: var(--ink2); }
#app .cal-sub-sec:first-child { margin-top: 0; }
#app .cal-sub-sec > span { flex: 1; min-width: 0; }
#app .cal-sub-sec-out { margin-top: 26px; }
#app .cal-sub-add:disabled { opacity: 0.5; cursor: default; }
#app .cal-sub-more { flex: none; width: 32px; height: 32px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%;
    background: transparent; color: var(--ink2); font-size: 16px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .cal-sub-more:active { background: var(--nav-fill); }
#app .cal-sub-danger { color: var(--due-ink); }
#app .cal-sub-out { margin-bottom: 4px; }
#app .cal-sub-out > .vis-switch { margin-bottom: 8px; }
#app .cal-sub-state { display: flex; flex-wrap: wrap; align-items: center; gap: 0 12px; min-height: 44px; }
#app .cal-sub-state > b { flex: 1; min-width: 0; font-size: var(--fs-body); font-weight: 500; }
#app .cal-sub-state > .cal-imp-sub { flex: 1 1 100%; }
#app .cal-sub-pill { flex: none; height: 32px; padding: 0 14px; border: 0; border-radius: var(--r-pill); background: var(--ink); color: var(--card);
    font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 500; cursor: pointer; }
#app .cal-sub-pill:disabled { opacity: 0.5; cursor: default; }
#app .cal-sub-copyrow { display: flex; align-items: center; gap: 8px; }
#app .popup-body .cal-sub-url { flex: 1; min-width: 0; font-size: var(--fs-sub); color: var(--ink2); font-variant-numeric: tabular-nums; }
#app .cal-sub-copy { flex: none; width: 36px; height: 36px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 50%;
    background: var(--nav-fill); color: var(--ink); font-size: 17px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .cal-sub-out > .cal-imp-how { margin-top: 6px; }
#app .cal-sub-item { display: flex; align-items: center; gap: 12px; box-sizing: border-box; min-height: 48px; padding: 4px 0;
    border-top: 1px solid var(--line); cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* a row's ⋮: its glyph flush with the row's end and 12 after the capsule, the 32 target around it */
#app .cal-sub-item > .cal-sub-more { margin: 0 -8px; }
#app .cal-sub-item + .cal-sub-sec { margin-top: 14px; }
#app .cal-sub-sec + .cal-sub-item, #app .cal-conn-add > .cal-sub-item:first-child { border-top: 0; }
#app .cal-sub-item + .cal-conn-add > .cal-sub-item:first-child { border-top: 1px solid var(--line); }
#app .cal-sub-lead { flex: none; font-size: 20px; color: var(--ink2); }
#app .cal-sub-item > .who { margin-left: 0; }
#app .cal-sub-val { display: inline-flex; align-items: center; gap: 4px; margin-left: auto; font-size: 14px; color: var(--ink2); white-space: nowrap; }
#app .cal-sub-val > i { font-size: 13px; color: var(--ink3); }
/* the connected accounts' pages (connections.js): the iCloud steps, a calendar per line with its
   button */
#app .cal-conn-steps { margin: 0 0 8px; padding-left: 1.2em; display: flex; flex-direction: column; gap: 4px; font-size: var(--fs-body); }
#app .cal-conn-link { display: inline-block; margin-bottom: 12px; font-size: var(--fs-hint); color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
#app .cal-conn-cals { display: flex; flex-direction: column; gap: 6px; margin-bottom: 4px; font-size: var(--fs-hint); color: var(--ink2); }
#app .cal-conn-cal { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-bottom: 1px solid var(--line); }
#app .cal-conn-cal:last-child { border-bottom: 0; }
#app .cal-conn-cal-name { font-size: var(--fs-body); color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
#app .cal-conn-cal-name small { color: var(--ink2); font-size: var(--fs-hint); }
#app .cal-conn-cal .action-btn { flex: 0 0 auto; }
#app .cal-sub-failing { color: var(--due-ink); font-weight: 500; }
#app .cal-sub-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
#app .cal-sub-value { margin: 0; font-size: var(--fs-body); color: var(--ink); line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
#app .cal-sub-from { margin-top: 14px; }

/* ============================== system indicators ============================== */


/* the failure toasts: a centred column above the footer, oldest at the top. Several failures
   can be on screen at once — a dead-lettered write must not be swallowed by a failed export a
   second later. Each pill leaves on its own deadline; the empty stack is removed with the last.
   The 20px here is the LOGIN screen's floor (no tab bar yet); once the bar exists, render/kit.js
   toast() measures it and lifts the column clear — one source for the bar's height, not two. */
.write-error-stack {
    position: fixed;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    max-width: calc(100% - 32px);
    z-index: 1000;
    /* Nothing here is tappable, and on the login screen the column still sits low. One pill
       already swallowed taps there; a stack of them would swallow a lot more. */
    pointer-events: none;
}

/* one message: a write that exhausted its retries, a failed export, an ended session */
.write-error-toast {
    min-height: 36px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    font-size: var(--fs-ui);
    font-weight: 500;
    color: var(--card);
    background: var(--ink);
    padding: 7px 15px;
    border-radius: var(--r-pill);
    box-shadow: var(--shadow);
    text-align: center;
    animation: fadeSlideUp var(--transition-base);
}
.write-error-toast.err { color: var(--badge-fg); background: var(--due); }
/* a sticky message is a band in the page's flow under the head — it hides nothing, it moves the
   page, and it never shrinks (a two-line message keeps its height); the bare ✕ in the band's ink
   takes it away */
#app .toast-band {
    display: flex;
    flex: none;
    align-items: center;
    gap: 8px;
    min-height: 44px;
    box-sizing: border-box;
    margin: 2px var(--pad) 0;
    padding: 10px 6px 10px 15px;
    background: var(--card);
    border-radius: var(--r-ctl);
    font-size: var(--fs-ui);
    font-weight: 500;
    line-height: 1.35;
    color: var(--ink);
}
#app .toast-band.err { color: var(--due-ink); }
#app .toast-band > span { flex: 1; min-width: 0; }
#app .toast-band > button { flex: none; width: 24px; height: 24px; margin-right: -8px; border: 0; border-radius: 50%; background: transparent; color: inherit; font-size: 15px; display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }

/* ============================== files manager (drawer → Dateien) ============================== */

/* the manager keeps room for the filter popover even when few files exist */
#files-popup-overlay .popup-body { min-height: 420px; }

/* ---- files as tiles (the gallery): the shot 100 high r10 without a frame, WHOSE it is in the
   capsule on its top corner, the name quiet under it ---- */
.fg-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.fg-tile { display: flex; flex-direction: column; min-width: 0; border: 0; background: none; padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; font-family: inherit; }
.fg-thumb { position: relative; height: 100px; display: block; border-radius: 10px; overflow: hidden; background: var(--field); }
.fg-thumb img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* a file that is no picture: its glyph on the field tone */
.fg-thumb.fg-vid { display: flex; align-items: center; justify-content: center; color: var(--ink2); font-size: 28px; }
.fg-thumb > .fm-who { position: absolute; top: 6px; right: 6px; margin: 0; }
.fg-name { margin-top: 4px; font-size: 11px; font-weight: 400; line-height: 1.35; color: var(--ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; }
/* pdf.js fallback viewer (browsers without a built-in one): stacked page canvases, capped to
   the body height so a long document scrolls inside the sheet */
.fv-pdf { display: flex; flex-direction: column; gap: 8px; align-items: center; width: 100%; max-height: 100%; overflow-y: auto; }
.fv-page { max-width: 100%; height: auto; background: var(--pdf-paper); border-radius: 4px; box-shadow: var(--page-shadow); }
/* one file per row (fileRowEl): its lead in the 30 slot, name + meta + carrier chips, the capsule */
.fm-file { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; align-items: start; gap: 2px 12px; padding: 10px 14px; border-bottom: 1px solid var(--line); cursor: pointer; }
.fm-file:last-child { border-bottom: 0; }
/* a PDF's tile says what it is; a picture shows itself in miniature, cut to the tile from its
   middle (the image lies over the whole tile: a grid cell gives a percentage height nothing to
   resolve against) */
.file-ic.is-pdf { font-size: 9px; font-weight: 600; letter-spacing: .02em; }
.file-ic.is-img { position: relative; border-radius: 8px; overflow: hidden; }
.file-ic.is-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

/* file viewer — full-screen lightbox above popups; media centers on a strong scrim */
#file-viewer-overlay {
    position: fixed;
    inset: 0;
    z-index: 1100;
    background: var(--scrim-strong);
    display: flex;
    flex-direction: column;
}
/* while the file's sheet stands over it (its pen), the viewer steps down to the sheets' layer —
   the sheet, its questions and its menus come after it and so lie above it */
#file-viewer-overlay:has(~ #file-edit-popup-overlay) { z-index: 1000; }
/* the viewer is the whole screen: the shell's search row and capsule, its tab bar and the
   module's + do not show through the scrim */
#app:has(> #file-viewer-overlay) > :is(header, footer),
#app:has(> #file-viewer-overlay) :is(.cal-fab, .notes-fab, .fin-fab, .dash-fab, .baby-fab, .hl-fab, .tv-fab, .pw-fab, .fin-dock-group) { visibility: hidden; }
/* its head is no bar: the name and the tools stand on the scrim, in its own ink */
#file-viewer-overlay .fv-head {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: calc(var(--safe-top, 0px) + 4px) 8px 8px 16px;
}
#file-viewer-overlay .fv-name {
    flex: 1;
    min-width: 0;
    font-size: 15px;
    font-weight: 500;
    color: var(--on-scrim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
#file-viewer-overlay .fv-btn { width: 44px; height: 44px; border-radius: 50%; background: transparent; color: var(--on-scrim); font-size: 18px; }
#file-viewer-overlay .fv-body {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 14px;
    overflow: hidden; /* tall content never paints over the head */
}
#file-viewer-overlay .fv-media { max-width: 100%; max-height: 100%; border-radius: var(--r-ctl); }
#file-viewer-overlay .fv-audio { width: min(100%, 420px); }
#file-viewer-overlay .fv-text {
    width: 100%;
    height: 100%;
    overflow: auto;
    background: var(--card);
    color: var(--ink);
    border-radius: var(--r-ctl);
    padding: 14px;
    font-size: var(--fs-body);
    white-space: pre-wrap;
    word-break: break-word;
}
#file-viewer-overlay .fv-none {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    background: var(--card);
    color: var(--ink);
    border-radius: var(--r-card);
    padding: 26px 30px;
    text-align: center;
}
#file-viewer-overlay .fv-none i { font-size: 44px; color: var(--ink2); }
#file-viewer-overlay .fv-none p { color: var(--ink2); font-size: var(--fs-md); }
.fm-tx { flex: 1; min-width: 0; }
/* the name is the row's title: 15/500, and a long one wraps rather than losing its end */
.fm-tx > b { display: block; font-size: var(--fs-md); font-weight: 500; line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }
.fm-tx > span { display: block; font-size: var(--fs-sub); color: var(--ink2); margin-top: 1px; }

/* carrier / link chips — the row's meta chip (22, the field tone, 12/500): a thing's glyph 13 or
   someone's colour as a dot (no initial below 20 px) + the label, optional × */
.fm-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.fm-chiplink {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 22px;
    box-sizing: border-box;
    max-width: 100%;
    background: var(--field);
    border: 0;
    border-radius: var(--r-pill);
    padding: 0 7px;
    font: 500 12px var(--font-family);
    color: var(--ink2);
    white-space: nowrap;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.fm-chiplink > i { font-size: 13px; }
.pdot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--pc, var(--ink3)); flex: none; }
.fm-chip-x { border: 0; background: transparent; color: var(--ink2); cursor: pointer; padding: 0 0 0 2px; font-size: var(--fs-cap); }
.fm-link-hint { font-size: var(--fs-sub); color: var(--ink2); }

/* the inline upload status line */
.fm-status { color: var(--due-ink); font-size: var(--fs-cap); margin-top: 8px; min-height: 1em; text-align: center; }

/* file editor: what the file belongs to leads with its carrier's dot or glyph; the meta line */
.fm-belongs .mg-select-btn > .pdot, .fm-belongs .mg-select-btn > i { margin-right: 8px; }
.fm-belongs .mg-select-btn > .mg-select-label { flex: 1; min-width: 0; }
.fm-belongs .mg-select-btn > i { font-size: 16px; color: var(--ink2); }
.fm-meta { font-size: var(--fs-cap); color: var(--ink2); margin-top: 12px; line-height: 1.6; }
.fm-meta b { font-weight: 500; color: var(--ink2); }

/* category manager: a row each (48, a hairline between) — a fixed one quiet with „fest" under
   it, an own one its name (a tap renames it in place) and its × — then the field that adds one */
.fm-cat { display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 4px 0; box-sizing: border-box; border-top: 1px solid var(--line); }
.fm-cat:first-child { border-top: 0; }
.fm-cat-t { flex: 1; min-width: 0; padding: 0; border: 0; background: none; text-align: left; font-family: var(--font-family);
    font-size: var(--fs-md); font-weight: 500; color: var(--ink); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fm-cat.is-fixed .fm-cat-t { color: var(--ink2); cursor: default; }
.fm-cat-t > small { display: block; font-size: var(--fs-sub); font-weight: 400; color: var(--ink2); }
.fm-cat-x { flex: none; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--ink);
    font-size: 15px; display: grid; place-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fm-cat-rename {
    flex: 1;
    min-width: 0;
    border: 0;
    background: var(--field);
    border-radius: var(--r-ctl);
    padding: 8px 10px;
    font-family: var(--font-family);
    font-size: var(--fs-md);
    color: var(--ink);
    outline: none;
}
.popup-body label.fm-cat-new { display: flex; align-items: center; gap: 8px; height: 44px; box-sizing: border-box; margin: 8px 0 0; padding: 0 13px;
    background: var(--field); border-radius: var(--r-ctl); color: var(--ink2); font-weight: 400; }
.fm-cat-add { flex: none; padding: 0; border: 0; background: none; color: var(--ink2); font-size: 16px; display: grid; place-items: center; cursor: pointer; }
.popup-body .fm-cat-new > input { flex: 1; min-width: 0; height: 100%; padding: 0; border: 0; background: transparent; box-shadow: none;
    font-size: var(--fs-md); color: var(--ink); outline: none; }
.popup-body .fm-cat-new > input::placeholder { color: var(--ink2); }

/* the sheet head's back arrow: a 44px box whose glyph stands on the sheet's edge */
.popup-header .popup-back {
    background: transparent;
    border: 0;
    color: var(--ink);
    cursor: pointer;
    font-size: 15px;
    width: 44px;
    height: 44px;
    display: grid;
    place-items: center;
    padding: 0;
    margin-left: -14px;
}

/* a field whose value is INHERITED from an entity: readable, obviously not yours to type — and
   the same look for a field a settled expense holds fixed (every disabled control in the sheet) */
.popup-body input.is-inherited,
.popup-body .is-inherited .mg-select-btn,
.popup-body input:disabled,
.popup-body .mg-select-btn:disabled { opacity: 0.6; }
.popup-body .mg-select-btn:disabled { cursor: default; }

/* a money attribute on an entity: amount · currency · since as three thirds of ONE line, the day
   said as its month („Okt. 2026") on a face the native picker lies over, unseen */
.ent-money { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; align-items: center; width: 100%; }
.ent-money .ent-money-amt { min-width: 0; font-variant-numeric: tabular-nums; }
.ent-money-day { position: relative; display: grid; min-width: 0; }
.ent-money-day > .day-face, .ent-money-day > input { grid-area: 1 / 1; }
/* the face is a field's value, 15/400, not its label's weight */
.ent-money-day > .day-face { font-weight: 400; }
.popup-body .ent-money-day > input { opacity: 0; min-width: 0; width: 100%; cursor: pointer; }
.popup-body .ent-money-day > input::-webkit-calendar-picker-indicator { position: absolute; inset: 0; width: auto; height: auto; margin: 0; padding: 0; cursor: pointer; }
#app .ent-attr-field > .form-hint { margin: 0; }
/* under a price what is said of it (a price announced for later, its Preisverlauf card) stands 8
   under its field and 8 apart — the grid's line gap less 8 —, and nothing while there is none */
#app .ent-attrs > .ent-price-slot { display: flex; flex-direction: column; gap: 8px; margin-top: -8px; }
#app .ent-attrs > .ent-price-slot:empty { display: none; }
#app .ent-price-slot > .price-hist, #app .ent-price-slot > .form-hint { margin: 0; }

/* the finance card's first row: the month total, without a checkbox column */
/* the finance cards speak the module's own voice: a hero amount, then aligned money.
   The widget card gives NO padding of its own — every row carries the card inset (--w-inset)
   itself, like .w-head and .w-row; content at 0 runs straight into the card edge. */
.fin-w-row {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 44px;
    box-sizing: border-box;
    padding: 8px 14px;
    border-top: 1px solid var(--line);
    cursor: pointer;
}
.fin-w-row > .fin-check { margin: 4px; }
.fin-w-name { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.fin-w-name b { font-size: 14px; font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fin-w-name span { font-size: var(--fs-sub); color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fin-w-name .late { color: var(--due-ink); font-weight: 500; }
.fin-w-amount { font-size: var(--fs-body); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ── Finanzen ─────────────────────────────────────────────────────────────────
   The Aufstellung: what runs every month and whether it has been debited. The row is the
   notes card's geometry (24px glyph · content · right rail) because it IS the same kind of
   object to the eye; only the right rail differs — a tick and an amount instead of avatars.
   Red appears in exactly one place: a debit whose day has passed unconfirmed. */
/* The module wrapper HOLDS, the tab layer SCROLLS — the notes anatomy. When the wrapper was
   the scroller as well, the FAB's `position:absolute` resolved against the scrolled content and
   the button drifted up the list; and a docked summary had nowhere to dock. */
.module-finances {
    display: flex;
    flex-direction: column;
    height: 100%;
    position: relative;
    min-height: 0;
}
/* the headline block insets to the screen edge like every other module's */
.module-finances .tab-layer {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 72px; /* the FAB must never sit on the last row */
}
/* with a dock the list keeps clear of it: dock and + share one line, 56 over the inset, + 16 air */
.module-finances:has(> .fin-dock-group) .tab-layer { padding-bottom: 96px; }
/* what a tab wants to say at all times, docked above the footer instead of scrolling away
   under it: the month's balance, and whatever a future tab needs there */
/* the docked answer — a floating card, not a bar glued to the footer: who pays whom is the
   page's one sentence, and it deserves the same card voice as everything else */
.fin-dock {
    flex: none;
    min-height: 56px;
    box-sizing: border-box;
    margin: 0;
    padding: 8px 10px 8px 14px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 6px;
    background: var(--card);
    border-radius: var(--r-card);
    box-shadow: var(--shadow);
    font-variant-numeric: tabular-nums;
}
/* a line: its tick, „Lena → Tom 85,00 €" over its quiet line, its one control */
.fin-dock .fin-balance-line { display: flex; align-items: center; gap: 10px; }
.fin-dock .fin-who { flex: 1; min-width: 0; font-size: 14px; line-height: 1.3; color: var(--ink); }
/* the names give way (ellipsis) before the amount does: it is the line's answer. A line the card
   cannot hold steps down to 13 first (.is-tight, _dockLine), so „du → tweety" stays whole beside
   „Abrechnen" */
.fin-dock .fin-who-top { display: flex; align-items: baseline; gap: 0.3em; white-space: nowrap; }
.fin-dock .fin-balance-line.is-tight .fin-who-top { font-size: var(--fs-ui); }
.fin-dock .fin-who-names { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.fin-dock .fin-who i { font-style: normal; color: var(--ink3); }
.fin-dock .fin-who .amt { flex: none; font-weight: 500; }
.fin-dock .fin-who small { display: block; font-size: var(--fs-cap); color: var(--ink2);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the tick at a household balance line: transferred this month — before the names, on the line */
.fin-dock .fin-balance-line > .fin-check { flex: none; margin: 0; }
/* „anstupsen" — a word in the line under the names: a push to the member who owes me (_nudge) */
.fin-dock .fin-nudge { display: inline; padding: 0; border: 0; background: none; font: inherit;
    font-weight: 500; color: var(--ink); cursor: pointer; }
.fin-nudge:disabled { opacity: .5; cursor: default; }
/* the dock's one control, „Abrechnen" */
.fin-dock .fin-settle-btn { flex: none; width: auto; margin: 0; padding: 0 14px; font-size: var(--fs-ui); }
/* the dock floats over the list, left of the + and level with it, as a card with its shadow */
.fin-dock-group { position: absolute; left: var(--pad); right: 88px; bottom: var(--pad); z-index: 4; }
.fin-feed { padding: 0 var(--pad) 16px; }
/* ── the ONE head voice ───────────────────────────────────────────────────────────────────────
   Every heading that names a section or a card — a widget's title, a feed section, a fold, a
   settings group, a recipe part — speaks alike: the written words in their own
   capitals, 13/500, in ink on the page ground and in the second ink on a card or a sheet.
   Upper-cased labels read as a form; these are the headings of an app.
   The rules of each keep only their spacing. */
.w-title, .sec-head, .rv-sec-h,
#app .exp-sec-lbl, #app .news-head, #app .ent-files-head {
    font-size: var(--fs-head);
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink);
}
.w-title, .rv-sec-h, #app .news-head, #app .ent-files-head { color: var(--ink2); }
/* ── the ONE section heading (Module.sectionHead) ────────────────────────────────────────────
   Finanzen, Kalender and Notizen each had their own; this is the shape they share now. */
.sec-head {
    display: flex;
    align-items: center;
    gap: 6px;
    min-height: 36px;
    padding: 0 2px;
    margin: 0 0 2px;
}
/* the part right behind the name — a day, a sum („· 212,00 €/Monat"): quieter by weight, never
   by fading — faded text is unreadable text (the head's own ink: --ink on the ground) */
.sec-head-sub {
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}
/* the right side carries the count, a forecast — in the head's ink, by weight the quiet part */
.sec-head-meta {
    margin-left: auto;
    font-size: var(--fs-sub);
    font-weight: 400;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* a glyph before the name (the pin of „Angepinnt"): small and quiet */
.sec-head-ic { flex: none; font-size: 12px; color: var(--ink2); }
/* the calendar's hairline disc, kept because it was the nicest of the three */
.sec-head-add {
    margin-left: auto;
    flex: none;
    width: 28px;
    height: 28px;
    box-sizing: border-box;
    border-radius: 50%;
    border: 0;
    background: var(--nav-fill);
    color: var(--ink2);
    cursor: pointer;
    font-size: 13px;
    line-height: 1;
    display: grid;
    place-items: center;
    transition: transform var(--transition-fast);
    -webkit-tap-highlight-color: transparent;
}
.sec-head-meta + .sec-head-add { margin-left: 8px; }
.sec-head-add:active { transform: scale(var(--button-click-scale)); }

/* ── the ONE symbol tile ────────────────────────────────────────────────────────────
   Every leading symbol of a row — a note's kind, a finance line, a thing, a file, a trip's line,
   an illness's entry, a search or bell hit, a choice in the Neu sheet — sits on the same soft
   rounded tile the baby's
   day list uses; there it wears the entry type's colour, everywhere else it is neutral. A
   person keeps the badge circle of their colour instead (.hh-ki .m).
   Its place never depends on how much text stands beside it: the tile holds the row's top-left
   corner, as far from the top as from the left (12px), and its centre line is the row's axis.
   A text of ONE line centres on that axis, a longer one starts at the top beside the tile; the
   right side (avatars, a tick, an amount) centres on the axis too. So a row of one line reads
   as centred, one of two or four keeps tile and badge where they are — nothing slides to the
   middle. Done without offsets: the text block and the right side are at least as tall as the
   tile, their content centred. Each row family says align-items: start in its own block (a
   later declaration would win over one here). A list's lines are a grid row of their OWN under
   the head (.nc-lines), so opening them moves nothing in the head row. */
/* the text block: at least the lead's height, one line centred, more lines from the top */
.notes-item > .notes-body, .hh-row > .hh-body, .fin-item > .fin-body, .fm-file > .fm-tx,
#app .search-result-text, #app .tv-row:has(> .tv-row-ic) > .tv-row-mid {
    display: flex; flex-direction: column; justify-content: center; min-height: 30px; box-sizing: border-box;
}
#app .hl-ev-txt { display: flex; flex-direction: column; justify-content: center; min-height: 30px; box-sizing: border-box; }
/* the right side, centred on the lead's axis */
.notes-item > .notes-right { justify-content: center; min-height: 30px; }
.hh-row > .hh-right, .fin-item > .fin-right, .fm-file > .fm-who { min-height: 30px; }
#app .tv-row:has(> .tv-row-ic) > .tv-amt { display: flex; align-items: center; min-height: 30px; }
#app .hl-ev > .hl-ev-tm { display: flex; align-items: center; min-height: 30px; }

.notes-ki,
.fin-ki,
.hh-ki:not(:has(> .m)),
.file-ic,
.new-ic,
.wk-ki,
#app .search-result-ic,
#app .tv-row-ic {
    width: 30px;
    height: 30px;
    box-sizing: border-box;
    flex: none;
    padding: 0;
    border: 0;
    border-radius: 10px;
    background: var(--nav-fill);
    color: var(--ink2);
    display: grid;
    place-items: center;
    font-size: 16px;
}
/* a note card, a household thing or a fixed cost for exactly one person (Module.soloTone): its
   tile in that person's tone, as their badge wears it */
.notes-ki[class*="pc-"],
.hh-ki[class*="pc-"],
.fin-ki[class*="pc-"] { background: var(--pc-soft); color: var(--pc-ink); }

/* ── the ONE list shape ─────────────────────────────────────────────────────────────
   Rows that stand one after another form ONE card: the first and the last carry its corners, a
   hairline parts them — the calendar day, the baby tab and the widgets read the same way, and so
   do the notes, the finance lines, the household's people and things and its files. (A file row
   in a sheet stays a plain hairline row: the sheet is the card there.) The hairline runs the
   card's full width, edge to edge — like every other row line in the app. */
.notes-item + .notes-item,
.fin-item + .fin-item,
.hh-row + .hh-row,
.module-household .fm-file + .fm-file {
    border-top: 1px solid var(--line); border-top-left-radius: 0; border-top-right-radius: 0;
}
.notes-item:has(+ .notes-item),
.fin-item:has(+ .fin-item),
.hh-row:has(+ .hh-row),
.module-household .fm-file:has(+ .fm-file) { margin-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.module-household .fm-file { background: var(--card); border-radius: var(--r-card); border-bottom: 0;
    padding: 10px 14px; margin-bottom: 8px; }
.fin-item {
    background: var(--card);
    border-radius: var(--r-card);
    padding: 10px 14px;
    min-height: 50px;
    box-sizing: border-box;
    margin-bottom: 8px;
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr) auto;
    gap: 2px 12px;
    align-items: start;   /* the row rule: the lead holds the top, see the symbol tile block */
    cursor: pointer;
}
.fin-ki { grid-row: 1; }
.fin-body { grid-row: 1; min-width: 0; }
.fin-title { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; overflow-wrap: break-word; hyphens: auto; }
/* ONE line, its end an ellipsis: a row says its rhythm, its day and its state — what more there
   is stands in its sheet. A word in its own voice at its end (.has-keep, _metaEl: „noch nicht
   abgebucht", „Stand vom 1. Okt") keeps a span of its own beside the run of bits before it; while
   the line has room both stand whole, and when it has not they give way together, each by its
   share of the length — neither shrinks to a stub */
.fin-meta {
    display: block;
    margin-top: 1px;
    min-width: 0;
    font-size: var(--fs-sub);
    line-height: 1.35;
    color: var(--ink2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.fin-meta.has-keep { display: flex; }
.fin-meta-run { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.fin-meta.has-keep > .fin-by { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fin-by:has(+ .fin-by)::after { content: " · "; color: var(--ink3); }
.fin-meta-run + .fin-by::before { content: "\00a0·\00a0"; color: var(--ink3); }
/* a word in its own voice: amber what wants a look (a stand gone old, not debited yet this month),
   red what is late */
.fin-by.pendt { color: var(--pend-ink); font-weight: 500; }
.fin-by.late { color: var(--due-ink); font-weight: 500; }
/* small boxed words 7 under the meta — a price that went up: „+20,00 € seit Sept." */
.fin-mcs { display: flex; flex-wrap: wrap; gap: 4px 10px; margin-top: 7px; }
.fin-mc { display: inline-flex; align-items: center; height: 22px; padding: 0 7px; border-radius: var(--r-pill);
    background: var(--field); font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); white-space: nowrap; }
/* a row done this month steps back — title and amount in the second ink, the amount lighter —
   without a strike: a rule is not a to-do */
.fin-item.is-past .fin-title, .fin-item.is-past .fin-val { color: var(--ink2); }
.fin-item.is-past .fin-val { font-weight: 400; }
/* a row without a lead (a budget, a month of the look back): text and amount only */
.fin-item:not(:has(> .fin-ki, > .fin-check)) { grid-template-columns: minmax(0, 1fr) auto; }
.fin-item:not(:has(> .fin-ki, > .fin-check)) > .fin-body { grid-column: 1; }
.fin-item:not(:has(> .fin-ki, > .fin-check)) > .fin-right { grid-column: 2; }
/* a person's badge as the lead (who paid, whose costs): the disc itself, the tile's size */
.fin-ki.is-badge { background: none; }
.fin-ki.is-badge > .m { box-sizing: border-box; width: 30px; height: 30px; font-size: 12px; }
/* a settled entry's lock, beside its amount */
.fin-lock { flex: none; width: 22px; height: 22px; border-radius: 50%; background: var(--field); color: var(--ink2);
    display: grid; place-items: center; font-size: 11px; }
/* „Plan ˅" — the word at the right of a row that opens more */
.fin-fold-word { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-sub); color: var(--ink2); white-space: nowrap; }
.fin-fold-word i { font-size: 12px; color: var(--ink3); }
/* „Alles ausgeglichen." closing a list on its card */
.fin-emptyline { font-size: var(--fs-sub); color: var(--ink2); text-align: center; padding: 14px;
    background: var(--card); border-top: 1px solid var(--line); border-radius: 0 0 var(--r-card) var(--r-card); }
.fin-item:has(+ .fin-emptyline) { margin-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.fin-right { grid-row: 1; grid-column: 3; display: flex; align-items: center; gap: 8px; }
.fin-val { font-size: var(--fs-md); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
.fin-val.muted { color: var(--ink2); font-weight: 500; }
/* under a due lump (a yearly bill whole) the month's share the sums count, quietly */
.fin-val > .fin-val-share { display: block; text-align: right; font-size: var(--fs-label); font-weight: 400; color: var(--ink2); }
/* a running cost's share („dein Teil 550,00 €", „20,00 €/Monat") is its own line, 2 under the amount */
.fin-val.is-col > .fin-val-share { margin-top: 2px; }
/* a budget or a savings goal: the bar in the row's text column under its line — filled to what was
   spent (or saved), a quiet tick where the month stands today, amber once over */
.fin-budget-bar { position: relative; height: 6px; margin-top: 6px; border-radius: 3px; background: var(--field); }
.fin-budget-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 3px; background: var(--ink); }
.fin-budget-pace { position: absolute; top: -3px; bottom: -3px; width: 1.5px; margin-left: -0.75px; border-radius: 1px;
    background: var(--ink2); }
.fin-budget.is-over .fin-budget-fill { background: var(--pend); }
.fin-budget.is-over .fin-val { color: var(--ink); }
/* a loan sheet's calculation (_loanBlock): what its fields add up to, a line each, under the
   fields; the plan's sum in the ink of an answer */
.fin-loan { display: flex; flex-direction: column; gap: 4px; margin: 2px 0 10px; font-size: var(--fs-sub); color: var(--ink2); }
.fin-loan > .is-ok { color: var(--ink); font-weight: 500; }
/* a Ratenzahlung's plan, one line per rate; the ones already due quieter */
.fin-loan-row { padding: 6px 0; border-bottom: 1px solid var(--line); font-size: var(--fs-cap); color: var(--ink); font-variant-numeric: tabular-nums; }
.fin-loan-row:last-child { border-bottom: 0; }
.fin-loan-row.is-past { color: var(--ink3); }
/* its fold stands in a form: the head on the fields' edge, not a page fold's inset */
.fin-loan-box .sec-fold > summary.sec-head { padding-left: 0; padding-right: 0; }

/* ── Household — the people & things list in the row idiom, member badges on the right. ──── */
.module-household {
    display: flex;
    flex-direction: column;
    height: 100%;
    position: relative;
    min-height: 0;
}
.module-household .tab-layer {
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 90px; /* the FAB must never sit on the last row */
}
/* the tab strip is the head card's last row */
#app .hero-lean > .hh-tabs { margin: 10px 0 0; height: 36px; }
/* „Was kommt dazu?": the types as tiles, four to a line — the glyph over its word */
.hh-new-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; padding-bottom: 8px; }
.hh-new-tile { display: flex; flex-direction: column; align-items: center; gap: 6px; min-width: 0; padding: 10px 4px 8px; border: 0;
    border-radius: var(--r-ctl); background: var(--field); font-family: var(--font-family); font-size: 11px; font-weight: 500;
    color: var(--ink2); cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform var(--transition-fast); }
.hh-new-tile:active { transform: scale(var(--button-click-scale)); }
.hh-new-tile i { font-size: 22px; color: var(--ink); }
.hh-new-tile span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hh-feed, .hh-files { padding: 0 var(--pad) 16px; }
/* the planner as the month's shape: the whole month scrolls in the layer, the column gear above it */
.cal-planner-view { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0 var(--pad) 96px; }
/* a way of LOOKING, not a filter: two quiet glyphs, the active one inked */
.notes-groupsw { display: flex; gap: 2px; flex-shrink: 0; }
.notes-groupsw-opt {
    appearance: none;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: var(--r-ctl);
    background: transparent;
    color: var(--ink3);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    cursor: pointer;
}
.notes-groupsw-opt.on { background: var(--card); color: var(--ink); }
/* the file row's own member capsule, right of the meta like every other row */
.fm-who { display: flex; align-items: center; flex-shrink: 0; margin-left: auto; }
.hh-files .fg-grid { padding: 4px 0 8px; }
.hh-row {
    background: var(--card);
    border-radius: var(--r-card);
    padding: 10px 14px;
    min-height: 50px;
    box-sizing: border-box;
    margin-bottom: 8px;
    display: grid;
    grid-template-columns: 30px minmax(0, 1fr) auto;
    gap: 2px 12px;
    align-items: start;   /* the row rule: the lead holds the top, see the symbol tile block */
    cursor: pointer;
}
/* neighbouring rows are ONE card: the hairline between them, the rounding only at the ends */
.notes-item:has(+ .notes-item), .fin-item:has(+ .fin-item), .hh-row:has(+ .hh-row) {
    margin-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.notes-item + .notes-item, .fin-item + .fin-item, .hh-row + .hh-row {
    border-top: 1px solid var(--line); border-top-left-radius: 0; border-top-right-radius: 0; }
.hh-ki { display: flex; justify-content: center; }
/* a person's lead is the badge circle every other surface draws — a little larger, photo inside */
.hh-ki .m {
    width: 30px;
    height: 30px;
    box-sizing: border-box;   /* the ring inside the 30px, level with the symbol tiles */
    font-size: 12px;
}
.hh-body { min-width: 0; }
.hh-title { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; word-break: break-word; }
/* the small line: one line of its bits, „ · " between them, what does not fit ends in „…" */
.hh-meta {
    margin-top: 0;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: var(--fs-sub);
    color: var(--ink2);
}
/* the „ · " between two bits is the line's own quiet text, also before a late or pending bit */
.hh-by + .hh-by::before { content: " · "; color: var(--ink2); font-weight: 400; }
.hh-by.late { color: var(--due-ink); font-weight: 500; }
.hh-by.pend { color: var(--pend-ink); font-weight: 500; }
.hh-right { display: flex; align-items: center; gap: 8px; color: var(--ink3); }
.fin-balance-line + .fin-balance-line { margin-top: 4px; }
.fin-balance {
    margin-top: 12px;
    padding: 11px 14px;
    border-radius: var(--r-ctl);
    background: var(--nav-fill);
    font-size: var(--fs-body);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
/* Status: the chart, the three tiles, the one warning.
   Built like the weather graph (.wxg): a 0-100 viewBox stretched to the card with non-scaling
   strokes, labels as HTML pinned to the same percent space so type never scales with the SVG. */
/* Colours here are --ink / --ink2 / --ink3, like everywhere else. Eight declarations in this
   block used to say --text and --text-soft, which no token file ever defined: an undefined
   var() with no fallback makes the whole declaration invalid, so those elements silently
   inherited their parent's colour instead of stepping back. The colour gate did not catch it
   — it checks that a colour IS a token, not that the token exists. */
/* The chart sits in the house padding like everything else, with a money column wide enough
   for a six-figure label. */
.fin-chart {
    padding: 13px;
    --fin-gut: 36px;
}
/* a gutter on the left for the money axis („36 k"); the plot itself starts after it */
.fin-plot { position: relative; height: 110px; padding-left: var(--fin-gut); }
/* ONE box for everything that is drawn. A percentage `left` resolves against the PADDING box, so
   a bar at left:0 inside .fin-plot landed in the gutter — before the chart, not on it. The bars
   and the rules they stand on share this box instead, which makes 0% the first month and 100%
   the last by construction. The money labels stay outside it, in the gutter. */
.fin-canvas { position: absolute; inset: 0 0 0 var(--fin-gut); }
/* the wealth curve, drawn as an SVG stretched to the box: a dashed line for a FORECAST, the
   money under it as a wash, and hairlines on the round steps */
.fin-canvas svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.fin-area { fill: var(--ink); fill-opacity: 0.10; }
.fin-line { fill: none; stroke: var(--ink); stroke-width: 1.8px; stroke-linecap: round;
    stroke-linejoin: round; stroke-dasharray: 4 3; vector-effect: non-scaling-stroke; }
.fin-grid { fill: none; stroke: var(--line2); stroke-width: 1px; opacity: .6;
    vector-effect: non-scaling-stroke; }
.fin-zero { fill: none; stroke: var(--ink2); stroke-width: 1px; opacity: .8;
    vector-effect: non-scaling-stroke; }
/* NAMES MATTER: .fin-val is the amount on every finance ROW. Reusing it here made the chart's
   `position:absolute` apply to every row amount in the module and shove them off screen. */
/* a point on a curve: a ring of ink on the card (the start, a recorded value) */
.fin-plot-dot { position: absolute; width: 7px; height: 7px; border-radius: 50%; background: var(--card);
    box-shadow: inset 0 0 0 1.8px var(--ink); transform: translate(-50%, -50%); }
.fin-plot-val {
    position: absolute;
    font-size: 16px;
    font-weight: 500;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.fin-plot-val.start { transform: translate(0, calc(-100% - 8px)); }
.fin-plot-val.end { transform: translate(-100%, calc(-100% - 8px)); }
/* the scale's hairlines, and the one that means nothing left */
.fin-rule { position: absolute; left: 0; right: 0; height: 1px; background: var(--line2); opacity: .5; }
.fin-rule.zero { background: var(--ink2); opacity: .8; }
/* ONE column per month, centred on its slot and never fatter than a thumb. The column spans the
   full height so a segment's top/height in percent lands in the same space as the rules. */
.fin-bar { position: absolute; top: 0; bottom: 0; max-width: 22px; transform: translateX(-50%); }
.fin-seg { position: absolute; left: 0; right: 0; display: block; }
/* what the month costs is the quiet mass, what it leaves is the bright head, what it cannot
   cover hangs under the line — the one red thing on this page */
.fin-seg.out { background: var(--ink3); }
.fin-seg.gain { background: var(--ok); }
.fin-seg.short { background: var(--due); border-radius: 0 0 3px 3px; }
.fin-seg.tip { border-radius: 3px 3px 0 0; }
/* the Rückblick: what a month spent is the same quiet mass; the month that is not over yet is
   drawn light, and the average of the months that are over is a dashed line named at its end */
.fin-seg.spend { background: var(--ink3); }
/* a one-off purchase is the hatched head of its month — counted, but not part of the usual */
.fin-seg.once { background: repeating-linear-gradient(135deg, var(--ink3) 0 2px, transparent 2px 5px); }
.fin-seg.partial { opacity: .45; }
/* the month the readout speaks of stands in ink among the quiet ones */
.fin-bar.is-focus .fin-seg.spend { background: var(--ink); }
.fin-bar.is-focus .fin-seg.once { background: repeating-linear-gradient(135deg, var(--ink) 0 2px, transparent 2px 5px); }
.fin-key.focus i { background: var(--ink); }
.fin-key.spend i { background: var(--ink3); }
.fin-key.avg i { background: none; box-shadow: inset 0 0 0 1px var(--ink2); }
.fin-key.once i { background: repeating-linear-gradient(135deg, var(--ink3) 0 2px, transparent 2px 5px); }
.fin-rule.avg { height: 0; background: none; border-top: 1px dashed var(--ink2); opacity: .9; }
/* a Wofür's months that are over, under its look back */
.fin-review-months { margin-top: 8px; }
/* the holdings' month ends: the quiet bars, today's in ink, a month under zero in amber — on the
   holdings' card, its last part: no line over it, its words 4 under the last row, the plot 12
   under them, the months 6 under the plot */
.fin-seg.worth { background: var(--ink3); }
.fin-seg.worth.tip { border-radius: 2px 2px 0 0; }
.fin-seg.worth.neg { background: var(--pend); border-radius: 0 0 2px 2px; }
.fin-bar.is-now .fin-seg.worth:not(.neg) { background: var(--ink); }
.fin-chart.fin-worth-chart { padding: 4px 14px 10px; }
.fin-worth-chart .fin-readout { min-height: 0; margin-bottom: 12px; }
.fin-worth-chart .fin-axis { margin-top: 6px; }
.fin-item + .fin-worth-chart { border-top-left-radius: 0; border-top-right-radius: 0; }
.fin-item:has(+ .fin-worth-chart) { margin-bottom: 0; border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
/* the Wofür list under it: a month more than usual says so in the warning voice; past the eighth
   the rows wait behind „Alle zeigen" */
.fin-review-list .fin-item.is-more .fin-meta { color: var(--due-ink); }
.fin-review-list .fin-item.is-extra { display: none; }
.fin-review-list.is-all .fin-item.is-extra { display: grid; }
.fin-review-more { margin: 2px 0 8px; }
/* the bank-file import: a line per transaction — tick · party and day · amount — and under the
   text what it becomes (its Wofür, the fixed cost it ticks off, or „schon da" — that line quiet:
   its party and amount in the second ink, the amount lighter) */
.fin-import-head { margin: 0 0 6px; }
.fin-import-err { color: var(--due); }
.fin-import-list { display: flex; flex-direction: column; margin: 0 0 12px; }
.fin-import-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 2px 10px; align-items: center;
    padding: 8px 0; border-bottom: 1px solid var(--line); }
.fin-import-row:last-child { border-bottom: 0; }
.fin-import-row.is-dup .fin-title, .fin-import-row.is-dup .fin-val { color: var(--ink2); }
.fin-import-row.is-dup .fin-val { font-weight: 400; }
.fin-import-main { min-width: 0; }
.fin-import-what { grid-column: 2 / -1; display: flex; align-items: center; gap: 6px; min-width: 0;
    font-size: var(--fs-sub); color: var(--ink2); }
.fin-import-what .mg-select { flex: 1 1 auto; min-width: 0; }
/* A percentage `top` resolves against the PADDING box, so top:0 already sits in the gutter —
   the negative margin on top of it pushed every label off the screen. */
.fin-ytick {
    position: absolute;
    width: 30px;   /* "36 k" at 11px; the gutter is 36 */
    text-align: right;
    transform: translateY(-50%);
    font-size: 11px;
    color: var(--ink2);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* The month names sit under the SAME box the bars are drawn in. They used to carry another
   var(--pad) on each side on top of .fin-chart's own, so every name stood a padding to the right
   of the month it names. */
.fin-axis { position: relative; height: 16px; margin: 2px 0 0 var(--fin-gut); }
.fin-axis span {
    position: absolute;
    transform: translateX(-50%);
    font-size: 11px;
    color: var(--ink2);
    white-space: nowrap;
}
/* the curve's axis names its two ENDS (heute … the far month), which sit ON the edges — a
   centred label there hangs half outside the card. The bars name the middle of a column and
   must keep the centring. */
.fin-axis-ends span:first-child { transform: none; }
.fin-axis-ends span:last-child { transform: translateX(-100%); }
/* what the three colours mean, said once, under the months they colour */
.fin-legend { display: flex; flex-wrap: wrap; gap: 2px 14px; margin: 6px 0 0 var(--fin-gut); }
.fin-key { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-label); color: var(--ink2); }
.fin-key i { display: block; width: 10px; height: 10px; border-radius: 3px; flex: none; }
/* the whole bar IS the income — its key is the outline the two parts stand in */
.fin-key.in i { box-shadow: inset 0 0 0 1.5px var(--ink3); }
.fin-key.out i { background: var(--ink3); }
.fin-key.gain i { background: var(--ok); }
.fin-key.short i { background: var(--due); }
.fin-warn {
    margin: 10px var(--pad) 0;
    padding: 10px 14px;
    border-radius: var(--r-ctl);
    background: var(--nav-fill);
    color: var(--due);
    font-size: var(--fs-md);
    font-weight: 600;
}
/* Die Urteilszeile sagt auch, wenn es GUT steht — dann in Tinte, nicht in Rot: „keine Warnung"
   ist keine Antwort auf „läuft es?". */
.fin-warn.is-ok { color: var(--ink); font-weight: 500; }

/* Die zwei Monate, um die ein Haushalt herum plant, als Punkt AUF der Kurve: der tiefste Stand
   gefüllt in Tinte, unter null wie der erste Monat unter null in Amber — einen Tick größer. */
.fin-plot-dot.is-low { background: var(--ink); box-shadow: none; width: 8px; height: 8px; }
.fin-plot-dot.is-low.is-neg, .fin-plot-dot.is-broke { background: var(--pend); box-shadow: none; width: 8px; height: 8px; }

/* what the outlook reckons with every month, at the end of the Übersicht's ⓘ: the explanation
   rows' own voice — word left in --ink2, amount right in ink, 14, a hairline over each — so the
   list reads on as the rows above it */
.fin-flist { display: flex; flex-direction: column; }
.fin-frow { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 8px 0; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; }
.fin-frow > span { color: var(--ink2); min-width: 0; }
.fin-frow > b { font-weight: 400; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* the pill (Alltag) keeps the row as high as the others */
.fin-frow > .mg-pill { margin: -4px 0; }
.fin-frow.is-bad > span, .fin-frow.is-bad > b { color: var(--due-ink); }
/* the verdict closes the list: no line over it */
.fin-frow.is-verdict { display: block; border-top: 0; padding-top: 12px; padding-bottom: 12px;
    font-size: var(--fs-ui); background: none; border-radius: 0; margin: 0; }
/* the outlook's two assumptions under its plot, in its card: the ranges as marks (the one in force
   in ink), under them what everyday life costs as one mark with its › */
.fin-fore-pick { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.fin-pick-row { display: flex; flex-wrap: wrap; gap: 6px; }
.fin-pick { border: 0; font-family: var(--font-family); cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fin-pick.on { background: var(--ink); color: var(--card); }
.fin-pick > i { font-size: 11px; color: var(--ink3); }
/* the chart's head row: its readout, and at the right the switch between the two charts — the
   notes' glyph track, ON in ink */
.fin-readrow { display: flex; align-items: flex-start; gap: 12px; }
.fin-readrow > .fin-readout { flex: 1 1 auto; min-width: 0; }
.fin-viewsw { flex: none; box-sizing: border-box; height: 28px; background: var(--field); border-radius: var(--r-pill); padding: 2px; gap: 0; }
.fin-viewsw .notes-groupsw-opt { width: 30px; height: 24px; border-radius: var(--r-pill); }
.fin-viewsw .notes-groupsw-opt.on { background: var(--ink); color: var(--card); }
/* the chart's readout over its plot: in figures what the drawing only shows — the low point and
   its month, the range's end, a tapped month its own —, the figure and its sentence on one
   baseline, the sentence wrapping under it where the line is too short; the bars' key, which
   carries the figures beside its colours, stands under its range */
.fin-readout { display: flex; flex-flow: row wrap; align-items: baseline; gap: 2px 8px; min-height: 0; margin-bottom: 6px; padding: 0 2px; }
.fin-readout:has(> .fin-keys) { flex-direction: column; align-items: stretch; }
/* a chart stands on a card: the readout and the plot on the card tone, never on the ground */
.fin-chart { background: var(--card); border-radius: var(--r-card); padding: 12px 14px; }
.widget .fin-chart { background: none; border-radius: 0; padding: 0; }
.fin-readout-cap { font-size: var(--fs-label); color: var(--ink2); }
.fin-readout-val { font-size: 16px; font-weight: 500; color: var(--ink); font-variant-numeric: tabular-nums; }
.fin-readout-sub { font-size: var(--fs-label); color: var(--ink2); font-variant-numeric: tabular-nums; }
.fin-readout .is-bad { color: var(--ink); }
.fin-keys { display: flex; flex-wrap: wrap; gap: 2px 14px; }
.fin-keys .fin-key b { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
/* a month's tap target: the full height of its slot, invisible; the tapped month a hairline and
   a dot on the curve, the other bars stepped back */
.fin-hit { position: absolute; top: 0; bottom: 0; margin: 0; padding: 0; border: 0; appearance: none;
    background: transparent; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fin-guide { position: absolute; bottom: 0; width: 1px; background: var(--ink3); }
.fin-plot-dot.is-pick { width: 9px; height: 9px; background: var(--ink); box-shadow: none; }
.fin-canvas.has-pick .fin-bar:not(.is-pick) { opacity: .35; }
/* the finance HERO — one card over every surface, in the greeting's language, its tab strip the
   last row (the health and baby anatomy): Status the word over its number in the display serif,
   the month as a sentence ("+1.427,63 € im Monat") in the warning colour when it takes more than
   it brings; Fixkosten and Alltag the calendar's month head; Split its balance; an opened element
   or circle ‹ its name ✎. The small hero marks say the rest. The content keeps 6px more air than
   the strip, which runs flush with the card's 10px sides. */
.fin-hero.fin-hero-card { flex: none; margin: 8px var(--pad) 8px; padding: 12px 13px 12px; background: var(--card);
    border-radius: var(--r-card); gap: 0; }
.fin-hero-card > .fin-tabs { margin: 12px 0 0; height: 36px; }
.fin-hero-card > .hero-marks + .fin-tabs { margin-top: 12px; }
/* the month / back head: the calendar's title and discs, in one row 32 high — the title keeps its
   own width, so the menu circle stands right behind it; ‹ Heute › at the row's end */
.fin-hero-head { display: flex; align-items: center; gap: 6px; min-height: 32px; }
.fin-hero-head > .cal-title { flex: 0 1 auto; }
.fin-hero-head > .cal-steps { margin-left: auto; }
/* the calendar title's own sizes and inks — the section rule `.fin-hero span` would shrink them */
.fin-hero-head .cal-title-main { font-size: inherit; color: var(--ink); }
.fin-hero-head .cal-title-info { font-size: var(--fs-sub); color: var(--ink2); }
/* a circle's or an element's name, in the month's size; ‹ in ink, ✎ quieter at the row's end */
#app .fin-hero-head > .fin-hero-name { font-size: 28px; }
.fin-hero-head > .fin-back { font-size: 16px; }
.fin-hero-head > .fin-edit { margin-left: auto; font-size: 14px; color: var(--ink2); }
/* the word over the figure, 10 under the head row, its ⓘ right behind it */
.fin-hero-card > .fin-hero-cap { display: flex; align-items: center; gap: 6px; margin-top: 10px; font-size: var(--fs-ui); font-weight: 500; color: var(--ink2); }
.fin-hero-card > .fin-hero-cap > .fin-info { width: auto; height: auto; margin: 0; padding: 0; font-size: 15px; color: var(--ink3); }
.fin-hero-card > .fin-hero-num { line-height: 1.15; margin-top: 2px; }
/* a sentence as the figure („du bekommst 33,21 €"): a step smaller */
#app .fin-hero-card > .fin-hero-num.is-sm { font-size: 28px; }
/* the sentence a page without a figure leads with („Lena schuldet dir 45,21 €, …") */
.fin-hero-card > .fin-hero-lead { margin-top: 6px; font-size: var(--fs-body); line-height: 1.4; color: var(--ink); }
.fin-hero-card > .fin-hero-lead b { font-weight: 500; }
/* the month line of a hero: the calendar's title and discs, the month a line high — the hero's
   figure is the big number (over it on Gemeinsam and Persönlich, under the worth on Übersicht) */
.fin-hero-head.is-step .cal-title-main, .fin-hero-head.is-step .cal-title-info { display: inline; }
.fin-hero-head.is-step .cal-title-info { margin-left: 5px; font-family: var(--font-family); font-size: var(--fs-sub); font-weight: 500; letter-spacing: 0.02em; }
.fin-hero-sub + .fin-hero-head.is-step, .fin-hero-num + .fin-hero-head.is-step { margin: 10px 0 0; }
/* the sentence under the figure („+412,30 € im Monat", „Budget 300,00 € · 88,00 € frei") */
.fin-hero-card > .fin-hero-sub { font-size: var(--fs-sub); color: var(--ink2); margin-top: 2px; }
/* the hero's small sum that adds up — label left, amount right, the total under a line; the same
   sum lists a head's details in the sheet its ⓘ opens */
.fin-hero-sum { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 12px;
    font-size: var(--fs-ui); color: var(--ink); font-variant-numeric: tabular-nums; }
.fin-hero-card > .fin-hero-sum { margin-top: 8px; }
/* in the ⓘ sheet the sum is a list: rows of 14 under hairlines, the word in --ink2, the amount in
   ink; a group's head and the total in ink, the total under an ink rule */
.popup-body > .fin-hero-sum { gap: 0; font-size: 14px; }
.popup-body > .fin-hero-sum > span:nth-child(even) { padding-left: 12px; }
.popup-body > .fin-hero-sum > span { padding: 8px 0; border-top: 1px solid var(--line); line-height: 1.35; }
.popup-body > .fin-hero-sum > span:nth-child(-n+2) { border-top: 0; }
.popup-body > .fin-hero-sum > span:nth-child(odd) { color: var(--ink2); }
.popup-body > .fin-hero-sum > span.is-head, .popup-body > .fin-hero-sum > span.is-total { color: var(--ink); }
.popup-body > .fin-hero-sum > span.is-total { border-top-color: var(--ink); padding-top: 8px; }
.fin-hero-sum > span:nth-child(even) { text-align: right; }
.fin-hero-sum > span.is-total { border-top: 1px solid var(--line); padding-top: 8px; font-weight: 500; }
/* the arrow beside the big number shows and hides the head's extra rows (sum, bar): shut, the
   head is the month, the word and the number, and the page keeps the height */
.fin-hero.fin-hero-card > .fin-hero-off { display: none; }
/* the number's row: the figure, and right behind it the titled pill that opens its sum */
.fin-hero-num.has-fold { display: flex; align-items: center; gap: 10px; }
.fin-hero-num > .fin-head-fold { height: 26px; padding: 0 9px 0 10px; border: 0; border-radius: var(--r-pill);
    display: inline-flex; align-items: center; gap: 3px; flex: none;
    background: var(--field); color: var(--ink2); font-family: var(--font-family); font-size: var(--fs-cap);
    font-weight: 500; letter-spacing: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fin-hero-num > .fin-head-fold i { font-size: 13px; }
.fin-hero-num > .fin-head-fold.is-open i { transform: rotate(180deg); }
/* in an ⓘ sheet a group's head stands bold with air above (none for the first), its items under
   it; open ones in the due voice, the quiet ones in the second ink */
.fin-hero-sum > span.is-head { font-weight: 500; padding-top: 12px; }
.fin-hero-sum > span.is-head:nth-child(-n+2) { padding-top: 0; }
.popup-body > .fin-hero-sum > span.is-head { padding-top: 8px; }
.popup-body > .fin-hero-sum > span.is-warn { color: var(--due-ink); }
.popup-body > .fin-hero-sum > span.is-quiet { color: var(--ink2); }
.popup-body > .fin-info-text { margin-top: 16px; }
/* in the ⓘ sheet the verdict („Es geht sich aus …") stands as a box on the menu-circle tone: the
   good news in the sentence's ink at 400, a warning in the red ink at 500 */
.popup-body > .fin-flist > .fin-frow.is-verdict { margin: 8px 0 0; padding: 10px 12px; border-radius: var(--r-ctl); background: var(--nav-fill); font-size: 14px; line-height: 1.4; font-weight: 500; color: var(--due-ink); }
.popup-body > .fin-flist > .fin-frow.is-verdict.is-ok { font-weight: 400; color: var(--ink); }
/* the section rule .fin-hero span further down would shrink and grey every cell: the sum keeps its own size and ink */
.fin-hero .fin-hero-sum > span { font-size: var(--fs-ui); color: var(--ink); }
.fin-hero .fin-hero-sum > span.is-warn { color: var(--due-ink); }
.fin-hero .fin-hero-sum > span.is-quiet { color: var(--ink2); }

/* Privat: what you have, in one line the eye lands on first */
/* The Status is TWO sections of the SAME build: a head (one big number, the word under it, its
   window pick) and then what that section is about — the wealth curve, or the month's bars with
   the tiles that count them. A hairline is all that tells them apart; looking alike is the point. */
/* no rule between the blocks: they are three answers to one question, not three pages */
.fin-sec + .fin-sec { margin-top: 16px; }
/* a Status section inside a DASHBOARD card: the same section, only the card carries the
   padding the page gets from its feed */
.fin-w-sec { padding: 0 0 4px; }
.fin-w-sec .fin-hero { padding: 4px 14px 10px; }
/* the card's list ("woraus es entsteht") in its fold: its rows on the card itself, on the card's
   inset — no card inside the card, and its first hairline right under the head */
/* the one finance card: its head is the page's (the word over the serif figure, the month's sum
   under it) and a door to the Übersicht; its fold runs on the card's inset like every widget row,
   a hairline over it */
.fin-w-top { cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* the word with its ⓘ, the figure in the serif 30, the month's result as one quiet line */
.fin-w-top > .fin-hero-cap { display: flex; align-items: center; gap: 6px; font-size: var(--fs-ui); font-weight: 500; color: var(--ink2); }
.fin-w-top > .fin-hero-cap > .fin-info { padding: 0; border: 0; background: none; color: var(--ink3); font-size: 15px; display: flex; cursor: pointer; }
.fin-w-top > .fin-hero-num { line-height: 1.15; margin-top: 2px; }
#app .fin-w-top > .fin-w-say { margin-top: 2px; font-size: var(--fs-sub); color: var(--ink2); }
#app .fin-w-sec .fin-w-top > .hero-marks { margin-top: 8px; }
.fin-w-sec > .fin-w-fold { margin: 0; }
/* the outlook in the card: a quiet band — its word, where the range ends, the chevron (˅ shut) */
.fin-w-sec > .fin-w-fold > summary.sec-head { min-height: 0; margin: 0; padding: 8px 14px 2px; font-size: var(--fs-cap); color: var(--ink2); }
/* the card ends 10 px under its last word either way, like the Übersicht and Für dich: shut, the
   Vorausschau head stands with even air (6 + the section's 4 below); open, the range pills keep
   6 above the section's 4 */
.fin-w-sec > .fin-w-fold:not([open]) > summary.sec-head { padding: 10px 14px 6px; }
.fin-w-sec > .fin-w-fold > summary.sec-head > .sec-head-label { color: var(--ink2); }
.fin-w-sec > .fin-w-fold > summary.sec-head .fold-chev { transform: none; }
.fin-w-sec > .fin-w-fold[open] > summary.sec-head .fold-chev { transform: rotate(180deg); }
.fin-w-sec > .fin-w-fold > .sec-fold-body { cursor: pointer; padding-top: 0; }
.fin-w-sec .fin-fore-pick { padding-left: var(--w-inset); padding-right: var(--w-inset); padding-bottom: 6px; }
.widget .fin-chart { padding-left: var(--w-inset); padding-right: var(--w-inset); }
.fin-hero { padding: 14px var(--pad) 4px; display: flex; flex-direction: column; gap: 2px; }
/* the hero's own rows only: a mark, a badge or a bold amount inside a sentence keeps its own voice */
.fin-hero > b { font-size: 26px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--ink); }
.fin-hero > span { font-size: var(--fs-sub); color: var(--ink3); }
.fin-hero-more { font-variant-numeric: tabular-nums; }
/* the breakdown of the big number: quieter than it, because it explains it */
/* what a holding was worth before — a record, so it steps back from the form above it */
/* the head of a holding's sheet: the curve, then the record as a fold — one line per value, a tap
   edits it in place */
.fin-hist { display: flex; flex-direction: column; margin: 0 0 14px; }
.fin-hist-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; width: 100%;
    border: 0; border-bottom: 1px solid var(--line); background: none; padding: 8px 2px; cursor: pointer;
    font-family: inherit; font-size: var(--fs-sub); color: var(--ink2); text-align: left;
    font-variant-numeric: tabular-nums; -webkit-tap-highlight-color: transparent; }
.fin-hist-row:last-child { border-bottom: 0; }
.fin-hist-edit { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--line); }
.fin-hist-edit input { flex: 1 1 0; min-width: 0; }
.fin-hist-edit .fin-hist-del { flex: none; height: 32px; }
/* the record's curve: the Status curve, card-sized, and SOLID — measured values, not a forecast */
.fin-hist .fin-hist-chart { margin: 0 0 6px; }
.fin-hist-chart .fin-plot { height: 124px; }
.fin-hist-chart .fin-line { stroke-dasharray: none; }
/* A price's history (render/prices.js): the step curve in the holdings' chart language — solid
   for what was and is, dashed for what is announced, today a hairline — the prices newest first as
   quiet rows, a rise in the late voice, and the add button as the editor's pill. */
.price-hist { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 14px; }
/* with a history it is a card in the sheet: its head the readout's small line, the steps a strip */
.price-hist.is-card { gap: 4px; padding: 10px 12px 8px; border-radius: var(--r-card); background: var(--card2); }
.price-hist-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
    font-size: var(--fs-cap); font-weight: 400; color: var(--ink2); }
.price-hist-meta { font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); }
.price-hist .fin-chart { padding: 0; background: none; --fin-gut: 30px; }
.price-hist-chart .fin-plot { height: 48px; }
/* its two dates 6 under the strip, one 11px line high */
.price-hist-chart .fin-axis { height: 15px; margin-top: 6px; }
/* the strip is too low for every step of its scale: only its two ends carry a number */
.price-hist-chart .fin-ytick:not(:first-of-type):not(:last-of-type),
.price-hist-chart .fin-plot-val, .price-hist-chart .price-today-label { display: none; }
.price-hist-chart .price-line { stroke-dasharray: none; }
.price-hist-chart .price-line.is-ahead { stroke-dasharray: 4 3; }
.price-today { fill: none; stroke: var(--ink3); stroke-width: 1px; stroke-dasharray: 2 3; vector-effect: non-scaling-stroke; }
.price-today-label { position: absolute; transform: translate(4px, calc(-100% - 2px)); font-size: var(--fs-cap); color: var(--ink3); white-space: nowrap; }
.price-today-label.is-left { transform: translate(calc(-100% - 4px), calc(-100% - 2px)); }
.price-hist-list { display: flex; flex-direction: column; margin-top: 14px; }
.price-hist-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; width: 100%;
    padding: 8px 0; border: 0; border-top: 1px solid var(--line); background: none; color: var(--ink);
    font: inherit; font-size: var(--fs-sub); text-align: left; cursor: pointer; font-variant-numeric: tabular-nums; }
.price-hist-delta { margin-right: 8px; font-size: var(--fs-cap); color: var(--ink2); }
.price-hist-delta.is-up { color: var(--pend-ink); }
.price-hist-add { align-self: flex-start; }
/* a thing's price (alone): the card is its curve, a tap unfolds the head, the prices and the pill */
.price-hist-toggle { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.price-hist-more { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.price-hist-more > .price-hist-list { margin-top: 4px; }
/* „Gilt ab" over a running cost's course: the month and the amount of the price in force as two
   field faces on one line — one button, a tap corrects that price — and the course 8 under it */
.fin-since-faces { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; width: 100%;
    padding: 0; border: 0; background: none; font: inherit; text-align: left; cursor: pointer; }
.fin-since-faces > span { display: block; min-width: 0; height: 44px; padding: 0 13px; box-sizing: border-box;
    border-radius: var(--r-ctl); background: var(--field); font-size: var(--fs-md); line-height: 44px; color: var(--ink);
    font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.popup-body .fin-since + .price-hist { margin-top: -6px; }
/* where a running cost's reminder rings, under its whole line (Am Tag · Erinnerung) at the
   Erinnerung's end — in the column alone its two words took two lines and left the day's empty */
.popup-body .form-pair + .fin-remind-hint { justify-content: flex-end; margin: -6px 0 14px; }
.price-sheet-pair { display: flex; gap: 6px; width: 100%; }
.price-sheet-pair input { flex: 1 1 auto; min-width: 0; }
.price-sheet-pair .mg-select { flex: 0 0 84px; }

/* the Aufteilung rows: who · the typed value · the euro it lands on, right-aligned */
.fin-shares { display: flex; flex-direction: column; gap: 6px; margin: 2px 0 4px; }
.fin-share-row { display: grid; grid-template-columns: 1fr 84px auto; align-items: center; gap: 8px; }
.fin-share-who { font-size: var(--fs-md); color: var(--ink); }
.fin-share-val { width: 100%; text-align: right; font-variant-numeric: tabular-nums; }
.fin-share-out {
    min-width: 76px;
    text-align: right;
    font-size: var(--fs-sub);
    font-variant-numeric: tabular-nums;
    color: var(--ink3);
}
.fin-share-hint.is-bad { color: var(--due); }
/* a builder of lines on the field tone, 42 high: a receipt's parts (its Wofür · its amount · ✕),
   the payers of a bill (badge · who · what they paid · ✕); the first part the Wofür above with what
   is left for it; the last line adds one. A new Wofür's name opens under its part. */
.fin-builder { display: grid; gap: 6px; }
.fin-bl { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 42px; box-sizing: border-box;
    padding: 0 6px 0 10px; border-radius: var(--r-ctl); background: var(--field); }
.fin-bl > i { flex: none; font-size: 18px; color: var(--ink2); }
.fin-bl-txt { flex: 1; min-width: 0; font-size: var(--fs-body); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fin-bl-sum { flex: none; margin-right: 34px; font-size: 14px; font-variant-numeric: tabular-nums; }
.fin-bl > .fin-bl-pick { flex: 1 1 auto; min-width: 0; }
.popup-body .fin-builder .fin-bl > .mg-select.fin-bl-pick > .mg-select-btn { height: 42px; padding: 0 4px; border: 0; background: none; box-shadow: none; }
/* a line's pick reads as its name, without a chevron: the line itself is the door to the list */
.fin-builder .fin-bl-pick .mg-select-chev { display: none; }
.popup-body .fin-builder .fin-bl > input.fin-bl-amt { flex: 0 0 84px; width: 84px; height: 32px; padding: 0 8px; border: 0;
    border-radius: 8px; background: var(--card); text-align: right; font-variant-numeric: tabular-nums; }
.popup-body .fin-builder .fin-bl > input.fin-part-name { flex: 1 0 100%; height: 36px; margin: 0 0 6px; background: var(--card); border: 0; }
.fin-bl-del { flex: none; width: 28px; height: 28px; padding: 0; justify-content: center; border-radius: 50%; }
.fin-bl-badge { display: inline-flex; flex: none; }
.fin-bl-badge > .m { box-sizing: border-box; width: 22px; height: 22px; font-size: 11px; }
.fin-bl.is-add { width: 100%; padding: 0 12px; border: 0; font-family: var(--font-family); font-size: var(--fs-body);
    color: var(--ink2); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.fin-parts-rest, .fin-payers-rest { margin: 6px 0 0; font-variant-numeric: tabular-nums; }
.fin-parts-rest.is-ok, .fin-payers-rest.is-ok { color: var(--ink); font-weight: 500; }
.fin-parts-rest.is-bad { color: var(--due); }
/* a settled entry stays readable but steps back — it is history, not a claim */
.is-settled .fin-title,
.is-settled .fin-val { color: var(--ink2); }
/* the currency beside its amount on the booking's first line: the one thing that can be wrong
   without anybody noticing stands where the number is */
.fin-cur { min-width: 0; }
/* the tick: the app's checkbox, ink when set (same shape the notes lines wear) */
.fin-check {
    appearance: none;
    -webkit-appearance: none;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1.5px solid var(--line2);
    background: transparent;
    position: relative;
    cursor: pointer;
    flex: none;
    margin: 0;
}
.fin-item > .fin-check { grid-row: 1; grid-column: 1; margin: 4px auto 0; }
.fin-item > .fin-body { grid-column: 2; }
.fin-check[class*="pc-"] { border-color: var(--pc); }
.fin-check:checked { background: var(--ink); border-color: var(--ink); }
.fin-check:checked::after {
    content: "";
    position: absolute;
    left: 7px;
    top: 3.5px;
    width: 5px;
    height: 10px;
    border: solid var(--card);
    border-width: 0 1.8px 1.8px 0;
    transform: rotate(43deg);
}
/* a finance sheet's setting row („Das ist eine Schuld"): its word 15/500 in ink left, the app's
   switch right, 48 high; the whole row is the label */
.popup-body .form-row.fin-switch-row { display: flex; align-items: center; justify-content: space-between; gap: 12px;
    min-height: 48px; margin: -6px 0 6px; font-size: var(--fs-body); font-weight: 500; color: var(--ink); cursor: pointer; }
.popup-body input.fin-sw.swT { width: 44px; height: 26px; padding: 0; border: 0; border-radius: var(--r-pill); background: var(--line2); }
.popup-body input.fin-sw.swT:checked { background: var(--ink); }
/* a sheet's small head over a group of its fields („Sparziel") */
.fin-form-sh { margin: 2px 0 8px; font-size: var(--fs-head); font-weight: 500; color: var(--ink2); }
/* what a goal needs a month, under its fields; amber when the savings rate falls short */
.popup-body .fin-goal-hint { margin: -6px 0 14px; }
.popup-body .fin-goal-hint.pendt { color: var(--pend-ink); font-weight: 500; }
/* a pair whose second field left for another line holds the first alone */
.form-pair.is-single { grid-template-columns: minmax(0, 1fr); }
/* a sheet's rail of a few words over what it switches (Lawine | Schneeball, Konten | Wofür …) */
.popup-body .fin-rail { margin: 0 0 10px; }
/* the line under the payoff's rail: 12 below it and 12 above the extra, a hint's 1.45 */
.popup-body .fin-payoff-how { margin: 2px 0 12px; line-height: 1.45; }
/* a sheet's plan as lines: the word left in the second ink, the figure right; the sum under an ink
   rule; the payoff's plan (.fin-payoff-plan) as the sheets' kv lines, 9 14, the first under a
   hairline too (it follows the extra's field) */
.fin-kvs { display: flex; flex-direction: column; margin: 4px 0 12px; }
.fin-kv { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; padding: 9px 0;
    border-top: 1px solid var(--line); font-size: 14px; font-variant-numeric: tabular-nums; }
.fin-payoff-plan > .fin-kv { padding: 9px 14px; }
.fin-kv:first-child { border-top: 0; }
.fin-payoff-plan > .fin-kv:first-child { border-top: 1px solid var(--line); }
.fin-kv > span { min-width: 0; color: var(--ink2); }
.fin-kv > b { font-weight: 500; text-align: right; }
.fin-kv.is-sum { border-top-color: var(--ink); font-weight: 500; }
.fin-kvs.fin-balance { margin-top: 4px; padding: 0; background: none; font-size: 14px; font-weight: 400; }
/* a sheet's rows that open or tick (the manager, the settle-up): glyph · word over its line · › or
   amount and tick; the first under its rail without a line */
#app .fin-set-list > .fin-set:first-child { border-top-color: transparent; }
.fin-set-amt { flex: none; font-size: var(--fs-body); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
#app .fin-set > .fin-check { margin: 0; }
/* a tick in a sheet (the settle-up's rows, the import's): the field rule — width 100% with a
   field's padding, fill and frame — must not reach it, or it turns into a bar */
.popup-body .fin-check { width: 22px; height: 22px; padding: 0; border-radius: 50%; border: 1.5px solid var(--line2); background: transparent; }
.popup-body .fin-check:checked { background: var(--ink); border-color: var(--ink); }
#app .fin-settle-item { cursor: pointer; }
/* the manager's foot adds one of the kind on the rail: the secondary pill with its + */
.popup-footer .save-btn.is-sec { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    background: var(--field); color: var(--ink); }
/* „+ Person" turns into the field a name is typed in, as wide as a chip row allows */
.popup-body .fin-people.fuer-chips > input.fin-person-input { flex: 0 1 160px; width: 160px; height: 32px; padding: 0 12px;
    border-radius: var(--r-pill); }
.fuer-chip.fin-add-person > i { font-size: 13px; }
/* the statement's file, first in the import sheet: the wide button that picks it, then its name
   and how many lines it has over what was read — both 15/500, the glyph 6 before the words */
.fin-import-pick { display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; height: 44px;
    margin: 0 0 12px; border: 0; border-radius: var(--r-ctl); background: var(--field); color: var(--ink);
    font-family: var(--font-family); font-size: var(--fs-body); font-weight: 500; cursor: pointer; }
.fin-import-pick > i { font-size: 18px; }
.fin-import-pick.is-read { cursor: default; }
/* A labelled switch in a sheet: label left, box right. Born in the finance sheet, now also the
   pass's "is this being taken" — same row, same rules, one place to change. */
.popup-body .form-row.fin-check-row,
.popup-body .form-row.form-row-check {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: 44px;
}
.popup-body .form-row.fin-check-row label,
.popup-body .form-row.form-row-check label { margin-bottom: 0; flex: 1; }
/* the one sheet checkbox (the calendar's): 20px, radius 6, a frame of its own. The field rule is
   width:100% plus a field's padding, radius, fill and transparent frame — none of it may reach a
   checkbox, or it turns into a bar or an invisible pill */
.popup-body .form-row.fin-check-row .fin-check,
.popup-body .form-row.form-row-check .form-check { width: 22px; height: 22px; flex: none; padding: 0; border-radius: 50%; border: 1.5px solid var(--line2); background: transparent; }
.popup-body .form-row.fin-check-row .fin-check:checked,
.popup-body .form-row.form-row-check .form-check:checked { background: var(--ink); border-color: var(--ink); }
.popup-body .form-row.fin-check-row .fin-check:checked::after { left: 7px; top: 3.5px; width: 5px; }
.form-hint { font-size: var(--fs-hint); color: var(--ink2); margin: 4px 0 0; }
/* a line that explains a surface or says it is empty (Finanzen _hintEl): the hint voice, never
   the body's — a note under a head is read after the head, not instead of it */
.hintline { font-size: var(--fs-hint); color: var(--ink2); line-height: 1.45; padding: 0 2px 10px; }
.rcp-photo-hint { font-size: var(--fs-hint); color: var(--ink2); }

/* ── Passwörter: the vault ─────────────────────────────────────────────────────
   The module HOLDS, one layer SCROLLS (the travel shell). The hero is the one card language: the
   state in the serif with the menu, the eye and — open — the lock button, one line of marks in
   words, the sub-line; under it the notice cards, the folders as sections on the ground with a
   card each, and the blank card of a shut or a new vault. */
#app .module-passwords { display: flex; flex-direction: column; height: 100%; min-height: 0; position: relative; }
#app .module-passwords .tab-layer { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0 var(--pad) calc(var(--safe-bottom) + 90px); }
#app .pw-hero { background: var(--card); border-radius: var(--r-card); padding: 12px 13px; margin: 8px 0; }
#app .pw-hero > .hero-row { min-height: 32px; }
#app .pw-hero-name { color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .pw-hero .hero-mark.pend { background: var(--pend-soft); color: var(--pend-ink); }
/* the open vault's lock: the 36 disc at the head's end, the open lock in ink */
#app .pw-lock { flex: none; width: 36px; height: 36px; margin-left: auto; padding: 0; border: 0; border-radius: 50%;
    background: var(--nav-fill); color: var(--ink); font-size: 17px; display: grid; place-items: center; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
#app .pw-lock:active { transform: scale(var(--button-click-scale)); }
/* a notice: the dot (ink, amber for what wants a look), the title 14/500 over its sentence 13, the small pill */
#app .pw-notice { display: flex; align-items: flex-start; gap: 10px; box-sizing: border-box; margin: 0 0 8px;
    padding: 12px 10px 12px 14px; background: var(--card); border-radius: var(--r-card); }
#app .pw-notice-dot { flex: none; width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--ink); }
#app .pw-notice-dot.amber { background: var(--pend); }
#app .pw-notice-t { flex: 1; min-width: 0; font-size: var(--fs-sub); line-height: 1.45; color: var(--ink2); }
#app .pw-notice-t b { display: block; font-size: 14px; font-weight: 500; color: var(--ink); }
#app .pw-notice > .pw-pill { align-self: center; }
/* the small pill (a notice's, a bin row's, an emergency row's answers): 28 high, 12/500 */
.action-btn.reusable.pw-pill { flex: none; height: 28px; margin: 0; padding: 0 11px; font-size: var(--fs-cap); font-weight: 500; }
/* the blank card: the glyph tile 46, the title 15/500, the sentence 13; the setup's pill 36, the
   locked vault's ways as buttons 44 across — the primary, the field one, the outlined one */
#app .pw-blank { display: flex; flex-direction: column; align-items: center; text-align: center; box-sizing: border-box;
    margin: 0 0 8px; padding: 28px 20px 24px; background: var(--card); border-radius: var(--r-card); }
#app .pw-blank-mark { width: 46px; height: 46px; margin-bottom: 12px; border-radius: 14px; background: var(--nav-fill);
    color: var(--ink2); font-size: 21px; display: grid; place-items: center; }
#app .pw-blank > b { font-size: var(--fs-body); font-weight: 500; color: var(--ink); }
#app .pw-blank > p { max-width: 250px; margin: 4px 0 0; font-size: var(--fs-hint); line-height: 1.5; color: var(--ink2); }
#app .pw-blank-acts { display: flex; flex-direction: column; align-items: center; gap: 8px; width: 100%; margin-top: 14px; }
#app .pw-blank-acts:empty { display: none; }
#app .pw-blank .pw-pill-go { margin: 0; font-size: var(--fs-ui); }
#app .pw-door { width: 100%; height: 44px; margin: 0; border-radius: var(--r-ctl); display: flex; align-items: center;
    justify-content: center; gap: 6px; }
#app .pw-door.pw-door-line { background: none; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line2); }
/* the list: a card of rows — the kind's tile 30, the name over its line 13, the readers right */
#app .pw-folds > .sec-fold + .sec-fold { margin-top: 8px; }
#app .pw-list { background: var(--card); border-radius: var(--r-card); overflow: hidden; }
#app .pw-list:empty { display: none; }
#app .pw-row { display: flex; width: 100%; box-sizing: border-box; align-items: flex-start; gap: 12px; min-height: 50px; padding: 10px 14px;
    text-align: left; background: none; border: 0; border-top: 1px solid var(--line); font-family: var(--font-family); color: var(--ink); cursor: pointer; }
#app .pw-row:first-child { border-top: 0; }
#app .pw-row-ic { width: 30px; height: 30px; flex: none; border-radius: 10px; display: grid; place-items: center;
    background: var(--nav-fill); color: var(--ink2); font-size: 16px; }
#app .pw-row-mid { flex: 1; min-width: 0; min-height: 30px; display: flex; flex-direction: column; justify-content: center; }
#app .pw-row-t { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .pw-row-m { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the line with its marks behind it: the line shortens first, down to 7em of its own (or all of
   it), the marks keep their width; past that the marks take the next line. Each part opens with a
   " · " 0.8em wide (the line's an empty one), and the box reaches 0.8em past the column's left
   edge, so the " · " that opens a line falls outside the column and is cut off */
#app .pw-row-mid:has(> .pw-row-m > .pw-row-flags) { overflow: hidden; }
#app .pw-row-m:has(> .pw-row-flags) { display: flex; flex-wrap: wrap; margin-left: -0.8em; overflow: visible; }
#app .pw-row-m:has(> .pw-row-flags) > .pw-row-words { flex: 1 1 7em; min-width: 0; max-width: max-content; padding-left: 0.8em;
    overflow: hidden; text-overflow: ellipsis; }
#app .pw-row-flags { flex: 0 1 auto; min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: pre; }
#app .pw-row-flags::before { content: "·"; display: inline-block; width: 0.8em; text-align: center; }
#app .pw-row > .notes-avs { flex: none; margin-left: auto; align-self: center; }
#app .pw-list .pw-empty { padding: 12px 14px; cursor: default; }
#app .pw-waiting { margin-top: 10px; }
/* the state words: red what is wrong (a leak, a plain-http link, run out), amber what wants a look —
   also as a row's line of its own, over the row line's --ink2 */
.pw-late, #app .pw-row-m.pw-late { color: var(--due-ink); font-weight: 500; }
.pw-pend, #app .pw-row-m.pw-pend { color: var(--pend-ink); font-weight: 500; }
/* a folder's ⋮ in its head (14 in --ink2) */
#app .pw-fold-more { flex: none; width: 20px; height: 28px; display: grid; place-items: center; padding: 0; border: 0;
    border-radius: 50%; background: none; color: var(--ink2); font-size: 14px; cursor: pointer; }
#app .pw-fold > summary > .pw-fold-more + .fold-chev { margin-left: 0; }
/* a sub-folder's entries in their top folder's card, no row of their own: stepped in on the tree's
   line — the line at 21 down the rows, an arm of 8 at each row's middle, ending there on a
   sub-folder's last entry; a deeper sub-folder is a branch on the same line. The first entry of a
   branch names its sub-folder over its own name, 12/500 */
#app .pw-row.pw-row-sub { position: relative; padding-left: 32px; }
#app .pw-row-sub::before, #app .pw-row-sub::after { content: ""; position: absolute; left: 21px;
    background: var(--line2); pointer-events: none; }
#app .pw-row-sub::before { top: 0; bottom: 0; width: 1px; }
#app .pw-row-sub.is-end::before { bottom: 50%; }
#app .pw-row-sub::after { top: 50%; width: 8px; height: 1px; }
#app .pw-row-folder { margin-bottom: 1px; font-size: var(--fs-cap); font-weight: 500; line-height: 1.35; color: var(--ink2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .pw-row-path i, .pw-folder-field .mg-select-label i { margin-right: 6px; font-size: 0.9em; }
/* the sheets: a quiet note, a warning in the due voice, a message line, a plain link */
.pw-note { margin: 0 0 14px; }
.pw-warn { margin: -6px 0 14px; color: var(--due-ink); }
.pw-err { font-size: var(--fs-hint); color: var(--ink2); margin: -6px 0 12px; min-height: 1em; }
.pw-link { display: block; margin-top: 10px; padding: 6px 0; border: 0; background: none; color: var(--ink2);
    font-family: var(--font-family); font-size: var(--fs-ui); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.pw-go { margin-top: 2px; }
/* a sheet's own action that is not ready yet (the code not yet confirmed, a check running) */
.pw-sheet .action-btn:disabled, .popup-footer .pw-go:disabled { opacity: 0.45; cursor: default; }
/* the six digits: wide-set and centred, the PIN's own shape */
.popup-body input.pw-pin-input { text-align: center; letter-spacing: 0.5em; font-size: 22px; font-variant-numeric: tabular-nums; }
/* a password field with its eye — and its ↻ for the generator — inside the field's right edge */
.pw-eyewrap { position: relative; }
.popup-body .pw-eyewrap > input { padding-right: 44px; }
.popup-body .pw-eyewrap:has(> .pw-gen) > input { padding-right: 80px; }
.pw-eye, .pw-eyewrap > .pw-gen { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 36px; height: 36px;
    border: 0; background: none; color: var(--ink2); cursor: pointer; }
.pw-eyewrap > .pw-gen { right: 40px; }
/* a sheet's head with the entry's tile: the tile before the title, 6 apart; with the line under the
   title the tile stands over both rows */
.popup-header > .pw-head-ic { width: 30px; height: 30px; flex: none; border-radius: 10px; display: grid; place-items: center;
    background: var(--nav-fill); color: var(--ink2); font-size: 16px; }
.popup-header:has(> .pw-head-ic):has(> .popup-sub) { grid-template-columns: auto minmax(0, 1fr); column-gap: 6px; }
.popup-header:has(> .popup-sub) > .pw-head-ic { grid-column: 1; grid-row: 1 / 3; }
.popup-header:has(> .pw-head-ic) > span, .popup-header:has(> .pw-head-ic) > .popup-sub { grid-column: 2; }
/* the recovery code: its groups as tiles 44, two to a line (the odd last one across), the code's
   own figures 18/500 set apart — read off paper later, selectable whole */
.pw-code { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; margin: 0 0 12px;
    font-family: var(--font-family); font-size: 18px; font-weight: 500; letter-spacing: 0.1em; font-variant-numeric: tabular-nums;
    color: var(--ink); user-select: all; }
.pw-code > span { height: 44px; border-radius: 10px; background: var(--field); display: flex; align-items: center; justify-content: center; }
.pw-code > span:last-child:nth-child(odd) { grid-column: 1 / -1; }
/* a button across the sheet (the code's copy): 44, the field tone, its glyph beside the words */
.action-btn.reusable.pw-wide { width: 100%; height: 44px; margin: 0; border-radius: var(--r-ctl); display: flex;
    align-items: center; justify-content: center; gap: 6px; }
/* the confirmation in its box: the tick and the sentence on the second card tone */
.popup-body label.pw-extra { display: flex; align-items: center; gap: 10px; margin: 12px 0 0; padding: 11px 12px;
    border-radius: 10px; background: var(--card2); font-size: 14px; font-weight: 400; color: var(--ink); cursor: pointer; }
.pw-ack { margin: 14px 0 12px; }
/* a vault sheet's foot: its words beside their glyph („In den Papierkorb“, „Bearbeiten“, „Jetzt prüfen“) */
.popup-body.pw-sheet ~ .popup-footer .action-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
/* an entry's rows: the label 13 over the value 15/500, the buttons (36 discs) on the right, a state
   word under the value; a row without a label says its words in the label's place */
.pw-line { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 12px; align-items: center; align-content: center;
    min-height: 48px; box-sizing: border-box; padding: 4px 0; border-top: 1px solid var(--line); }
.pw-line:first-child { border-top: 0; }
.pw-line-k { grid-column: 1; font-size: var(--fs-sub); font-weight: 400; line-height: 1.35; color: var(--ink2); }
.pw-line-v { grid-column: 1; min-width: 0; font-size: var(--fs-body); font-weight: 500; line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }
.pw-line-v:empty { display: none; }
.pw-line-s { grid-column: 1; font-size: var(--fs-sub); line-height: 1.35; }
.pw-line-acts { grid-column: 2; grid-row: 1 / span 3; display: flex; align-items: center; gap: 12px; }
.pw-line.is-plain .pw-line-k { font-size: var(--fs-body); font-weight: 500; color: var(--ink); }
.pw-line.is-note .pw-line-v { white-space: pre-wrap; }
/* the earlier passwords, shut: a fold head 44 — „Früher" in ink 15/500, how many and the last day
   in --ink2 behind it, the chevron at the right; a tap opens them with the key */
.pw-hist-fold { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; box-sizing: border-box; padding: 8px 0;
    border: 0; border-top: 1px solid var(--line); background: none; font-family: var(--font-family); font-size: var(--fs-body);
    line-height: 1.35; color: var(--ink2); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pw-hist-fold > b { flex: none; color: var(--ink); font-weight: 500; white-space: nowrap; }
.pw-hist-fold > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-hist-fold > i { margin-left: auto; flex: none; font-size: 12px; color: var(--ink3); }
/* dots stand apart; a shown secret and the 2FA code are the code role — 18/500, figures set apart */
.pw-secret { letter-spacing: 0.2em; }
.pw-line.is-shown .pw-line-v, .pw-otp { font-family: var(--font-family); font-size: 18px; font-weight: 500;
    letter-spacing: 0.1em; font-variant-numeric: tabular-nums; }
.pw-act { width: 36px; height: 36px; flex: none; border: 0; border-radius: var(--r-pill); background: var(--nav-fill);
    color: var(--ink); font-size: 17px; display: grid; place-items: center; cursor: pointer; text-decoration: none; }
/* the 2FA code's seconds as a mark, and their ring running out */
.pw-ring { position: relative; flex: none; width: 22px; height: 22px; border-radius: 50%;
    background: conic-gradient(var(--ink) 0 calc(var(--p, 100) * 1%), var(--line2) 0); }
.pw-ring::after { content: ""; position: absolute; inset: 4px; border-radius: 50%; background: var(--card); }
.pw-keyhost:not(:empty) { padding: 4px 0 8px; }
/* the generators: the randomness under the password field, and the generator's sheet — the kind's
   track, the one made in a field with its ↻, the slider under its label with the number at its end,
   the switches as word chips, the randomness in ink; the user name's options under its field */
.pw-bits { margin: -6px 0 10px; }
.seg-toggle.pw-track { height: 36px; }
.seg-toggle.pw-track button { font-weight: 500; }
.pw-gen-sheet .pw-track { margin: 0 0 12px; }
.pw-gen-out { display: flex; align-items: center; gap: 8px; height: 44px; box-sizing: border-box; padding: 0 4px 0 13px;
    border-radius: var(--r-ctl); background: var(--field); color: var(--ink); font-size: 16px; font-weight: 500;
    letter-spacing: 0.06em; font-variant-numeric: tabular-nums; }
.pw-gen-out > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-gen-out > .pw-gen { flex: none; width: 36px; height: 36px; border: 0; background: none; color: var(--ink2); cursor: pointer; }
.pw-gen-range { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 10px;
    margin: 14px 0 0; font-size: var(--fs-ui); font-weight: 500; color: var(--ink2); }
.pw-gen-range output { color: var(--ink); font-variant-numeric: tabular-nums; }
.popup-body .pw-gen-range input[type="range"] { grid-column: 1 / -1; width: 100%; height: 28px; margin: 4px 0 6px; padding: 0;
    border: 0; background: none; accent-color: var(--ink); }
.pw-gen-chips { margin: 4px 0 0; }
.pw-gen-chips + .pw-gen-chips { margin-top: 8px; }
.fuer-chip.pw-gen-chip { padding: 0 11px; }
.pw-gen-bits { margin: 12px 0 0; color: var(--ink); font-weight: 500; }
.pw-gen-panel { display: flex; flex-direction: column; gap: 12px; margin: -6px 0 16px; padding: 12px;
    border: 1px solid var(--line); border-radius: var(--r-ctl); }
.pw-gen-note { margin: 0; }
.pw-gen-note:empty { display: none; }
.pw-gen.pw-user-gen { margin: -6px 0 16px; }
/* the kinds: the editor's rail on top (pills 32, 13/500, sliding under a soft edge), the folder
   and the Für as a pair at its end, and a network's QR code for guests — black on white whatever
   the theme, large enough for a camera across a room */
.pw-kinds { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; margin: 0 -16px 14px; padding: 0 16px;
    -webkit-mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, var(--ink) calc(100% - 28px), transparent); }
.pw-kinds::-webkit-scrollbar { display: none; }
.pw-kinds button { flex: none; height: 32px; padding: 0 12px; border: 0; border-radius: var(--r-pill); background: var(--field);
    font-family: var(--font-family); font-size: var(--fs-ui); font-weight: 500; color: var(--ink2); white-space: nowrap; cursor: pointer; }
.pw-kinds button.active { background: var(--ink); color: var(--card); }
.popup-body .form-pair.pw-pair > .form-row { justify-content: flex-start; }
.pw-qr { width: min(260px, 72vw); aspect-ratio: 1; max-width: 100%; margin: 4px auto 14px; }
.pw-qr svg { display: block; width: 100%; height: 100%; border-radius: var(--r-ctl); }
.pw-qr .qr-bg { fill: var(--qr-light); }
.pw-qr .qr-fg { fill: var(--qr-dark); }
.pw-qr-btn { margin: 10px 0 2px; }
/* a link to share an entry with someone without an account: the entry sheet's button, or in its
   place a row per running link — „Link zum Teilen" over how often and until when (13 --ink2), the
   small quiet pill that ends it — the link sheet's two choices side by side, the made link to copy */
.pw-link-btn { margin: 10px 0 2px; }
.pw-line.pw-link-row { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pw-links > .pw-line.pw-link-row:first-child { border-top: 1px solid var(--line); }
.pw-line.pw-link-row .pw-line-v { font-size: var(--fs-sub); font-weight: 400; color: var(--ink2); }
.pw-link-pick { display: flex; flex-direction: column; gap: 6px; margin: 0 0 14px; }
.popup-body .form-pair > .pw-link-pick { gap: 0; margin: 0; }
.pw-link-url { font-family: var(--font-family); font-variant-numeric: tabular-nums; letter-spacing: 0.1em; font-size: var(--fs-ui); }
.pw-link-acts { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0 4px; }
/* emergency access: the sheet's two sections under their heads (13/500), a row per member — the
   badge 30, the name over its state, the answers as small pills — and the other member's entries */
.pw-em-head { margin: 14px 0 6px; font-size: var(--fs-head); font-weight: 500; color: var(--ink2); }
.pw-em-head:first-child { margin-top: 0; }
.pw-em-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; min-height: 48px; box-sizing: border-box;
    padding: 4px 0; border-top: 1px solid var(--line); }
.pw-em-head + .pw-em-row { border-top: 0; }
.pw-em-row > .m { width: 30px; height: 30px; font-size: 12px; }
/* the answers stay in the row: the name and state take what is left beside them, and wrap there */
.pw-em-t { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.pw-em-name { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; color: var(--ink); }
.pw-em-state { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }
.pw-em-acts { display: flex; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.pw-em-acts:empty { display: none; }
.popup-footer .pw-em-add { display: inline-flex; align-items: center; justify-content: center; gap: 6px; }
.pw-em-list .pw-row + .pw-row { border-top: 1px solid var(--line); }
/* the editor's folder row; the folder sheet: the tree (each level stepped in), then a new folder under a line */
.pw-fpick-list { display: flex; flex-direction: column; margin: 0 0 16px; }
.pw-fpick { display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box; padding: 11px 4px 11px calc(4px + var(--depth, 0) * 22px);
    border: 0; border-top: 1px solid var(--line); background: none; font-family: var(--font-family); font-size: var(--fs-ui);
    color: var(--ink); text-align: left; cursor: pointer; }
.pw-fpick:first-child { border-top: 0; }
.pw-fpick > i { flex: none; color: var(--ink2); }
.pw-fpick > span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-fpick.on { font-weight: 600; }
.pw-fpick > .pw-fpick-tick { color: var(--ink); }
.pw-fnew { border-top: 1px solid var(--line); padding-top: 14px; }
/* the bin (the menu's): a row per entry — its tile, the name over the days it still waits, the
   restore pill and the disc that deletes for good; emptying it is the foot's word */
.pw-trash-item { display: flex; align-items: center; gap: 10px; min-height: 48px; box-sizing: border-box; padding: 4px 0; border-top: 1px solid var(--line); }
.pw-trash-item:first-child { border-top: 0; }
.pw-trash-item > .pw-row-ic { width: 30px; height: 30px; flex: none; border-radius: 10px; display: grid; place-items: center;
    background: var(--nav-fill); color: var(--ink2); font-size: 16px; }
.pw-trash-item > .pw-row-mid { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pw-trash-item .pw-row-t { font-size: var(--fs-body); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pw-trash-item .pw-row-m { font-size: var(--fs-sub); color: var(--ink2); }
.pw-kill { flex: none; width: 32px; height: 32px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--ink);
    font-size: 15px; display: grid; place-items: center; cursor: pointer; }
.pw-open-secret { margin: 2px 0 12px; }
/* sharing: the Für field (chips, "Alle", a line naming who cannot read it yet — under both halves
   of the editor's pair) and its words while the secret is shut; the warning to change a password
   someone who left knew */
.pw-for .fuer-chips { margin-bottom: 8px; }
.pw-for-note { margin: 8px 0 0; }
.form-pair > .pw-for-note { grid-column: 1 / -1; margin: 0; }
.pw-for-now .form-hint { margin: 0; }
.pw-warn.pw-stale { margin: 12px 0 0; }
/* the lock's countdown: its digits keep their width */
.pw-idle-left { font-variant-numeric: tabular-nums; }
/* import & export: one sheet — a row each (the glyph, its name over the formats, the chevron) — and
   the amber word that a file is plaintext; the import's picker and what it found */
.pw-io-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px; box-sizing: border-box; padding: 4px 0;
    border: 0; border-top: 1px solid var(--line); background: none; font-family: var(--font-family); color: var(--ink); text-align: left; cursor: pointer; }
.pw-io-row:first-child { border-top: 0; }
.pw-io-lead { flex: none; font-size: 20px; color: var(--ink2); }
.pw-io-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pw-io-t b { font-size: var(--fs-body); font-weight: 500; }
.pw-io-t small { font-size: var(--fs-sub); color: var(--ink2); }
.pw-io-chev { flex: none; font-size: 13px; color: var(--ink3); }
.pw-verdict { margin: 12px 0 0; padding: 10px 12px; border-radius: var(--r-ctl); background: var(--nav-fill);
    font-size: 14px; line-height: 1.4; color: var(--pend-ink); }
.pw-verdict b { font-weight: 500; }
.pw-verdict.pw-export-warn { margin: 0 0 14px; }
.pw-import-file { display: block; width: 100%; margin: 0 0 12px; font-family: var(--font-family); font-size: var(--fs-ui); color: var(--ink2); }
.pw-import-found .pw-note { margin: 0 0 6px; }
.pw-import-names { margin: 4px 0 12px; font-size: var(--fs-ui); color: var(--ink); overflow-wrap: anywhere; }
.pw-verdict.pw-import-warn { margin: 14px 0 0; }
/* Face ID / the fingerprint: its one button carries the glyph */
.pw-bio-go { display: inline-flex; align-items: center; gap: 8px; }
/* the security check's result: a row per kind found — its tile, its name over the entries' names,
   how many (a leak in red, the 2FA hint quiet) — that opens its entries on the second card tone */
.pw-chk { border-top: 1px solid var(--line); }
.pw-chk:first-of-type { border-top: 0; }
.pw-chk > summary { list-style: none; }
.pw-chk > summary::-webkit-details-marker { display: none; }
#app .pw-chk-row { min-height: 48px; padding: 9px 0; border-top: 0; }
.pw-chk-n { flex: none; align-self: center; margin-left: auto; font-size: var(--fs-body); font-weight: 500; font-variant-numeric: tabular-nums; }
.pw-chk-n.quiet { color: var(--ink2); font-weight: 400; }
.pw-chk-list { margin: 0 0 8px; border-radius: var(--r-ctl); background: var(--card2); overflow: hidden; }

/* ── Module headings: the display serif ────────────────────────────────────────
   The ONLY place a second font appears (design/DESIGN.md §4): the module headings
   (the dashboard greeting, the finance status figure, calendar view title, baby's name, a
   health subject's name, a trip's name) plus two
   sanctioned hero moments — the dashboard empty-state title and the recipe overlay title.
   This selector list IS the authoritative inventory;
   nothing else gets the serif (the header's module name left it on 2026-09-26 — it is a pill
   now). Size/weight/letter-spacing come with it —
   the serif carries 400 and one shared 28px. Deliberately last in the file: several
   of these elements are styled via `#app …` further up, so this rule needs equal
   specificity AND later source order to win. */
#app .dash-hello-greet,
#app .fin-hero-card > .fin-hero-num,
#app .fin-w-top > .fin-hero-num,
#app .cal-title,
#app .baby-hero-name,
#app .hl-hero-name,
#app .hl-consent h3,
#app .hl-vit-v,
#app .baby-vit-v,
#app .ringCtr b,
#app .tv-hero-name,
#app .pw-hero-name,
#app .hero-title,
.lp .wm,
#app .setup-title,
#app .popup-header > span,
#app .cal-up-month,
#app .notif-title,
#app .cal-num,
#app .baby-hero-num,
#app .wm,
#app .access-now > b,
#app .cal-mp-year b,
#app .wx-temp,
#app .cal-wdate > b,
#app .cal-mp-day b,
#app .baby-w-due > b,
#recipe-view-overlay .rv-title,
#app .cook-title,
#recipe-view-overlay .rv-step-n {
    font-family: var(--disp), var(--font-family), serif;
    font-optical-sizing: auto;
    font-weight: 400;
    font-size: 28px;
    letter-spacing: -0.005em;
}
/* the day number of a month cell: the serif at 17, no tracking */
#app .cal-num { font-size: 17px; letter-spacing: 0; }
/* the consent card's title at 26, a health value's last reading at 18 (the value role) */
#app .hl-consent h3 { font-size: 26px; line-height: 1.15; }
#app .hl-vit-v, #app .baby-vit-v { font-size: 18px; line-height: 1.2; letter-spacing: 0; }
/* the Tagesbogen's centre figure at 24 */
#app .ringCtr b { font-size: 24px; letter-spacing: 0; }
#app .wm, .lp .wm { font-size: 40px; letter-spacing: -0.01em; }
/* a title the head cannot hold on one line steps down one size before it ellipsizes */
#app .hero-title.long, #app .cal-title.long, #app .dash-hello-greet.long, #app .tv-hero-name.long { font-size: 26px; }
/* A sheet's title and the month divider a step over the header, the finance figure a step over
   the shared 30px — the members of the list with a size of their own. */
#app .popup-header > span,
#app .cal-up-month,
#app .notif-title,
#app .cal-mp-year b,
#recipe-view-overlay .rv-title,
#app .cook-title { font-size: 22px; }
/* a recipe's step number: the serif at 17, no tracking */
#recipe-view-overlay .rv-step-n { font-size: 17px; letter-spacing: 0; }
#app .fin-hero-card > .fin-hero-num { font-size: 34px; }
/* the dashboard's sizes of it: the finance card's figure and the expected baby's days 30, the
   weather's now 40, the Demnächst day 17, the planner's day 15 */
#app .fin-w-top > .fin-hero-num, #app .baby-w-due > b { font-size: 30px; }
#app .baby-w-due > b { display: block; line-height: 1.15; }
#app .wx-temp { font-size: 40px; letter-spacing: 0; }
#app .cal-wdate > b { font-size: 17px; letter-spacing: 0; }
#app .cal-mp-day b { font-size: 15px; letter-spacing: 0; }
/* a person's name beside the 72 badge (and the vault's name) in the shared 28px, the hero line */
#app .baby-hero-name,
#app .hl-hero-name,
#app .pw-hero-name { font-size: 28px; line-height: 1.1; }

/* A past calendar entry is a record, not a task — see _eventRow, which exempts overdue
   todos and chore turns so they keep their full weight. */
#app .cal-event.cal-past .cal-event-title, #app .cal-event.cal-past .cal-time { color: var(--ink2); }

/* a required field the module refused to save on — flagged when Save is tapped, cleared on
   the next keystroke; red is state, and an empty mandatory field IS the error state */
#app .field-missing {
    border-color: var(--due);
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--due) 22%, transparent);
}

/* Neuigkeiten — the operator's announcement card at the top of the dashboard (newsCard): a
   plain card, the amber dot (something new waits to be read), the title 14/500 and the text
   13 in --ink2 under it on the title's edge. */
#app .news-card {
    position: relative;
    grid-column: 1 / -1;
    background: var(--card);
    border: 0;
    border-radius: var(--r-card);
    padding: 12px 38px 12px 14px;
}
#app .news-head {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    font-weight: 500;
    line-height: 1.45;
    color: var(--ink);
}
#app .news-dot {
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--pend);
}
#app .news-card p {
    margin: 2px 0 0 18px;
    font-size: var(--fs-sub);
    color: var(--ink2);
    line-height: 1.45;
}
#app .news-card p + p {
    margin-top: 9px;
    padding-top: 9px;
    border-top: 1px solid var(--line);
}
/* its ✕: the small close disc (32, glyph 15 in ink) on the title's line */
#app .news-x {
    position: absolute;
    right: 10px;
    top: 8px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    font-size: 15px;
    color: var(--ink);
}

/* Feedback sheet: success is green (the base .fm-status is the error tone); the segmented kind
   picker aligns full-width with the text field under it, which carries no label and asks in
   its placeholder. */
#app .fm-status.ok { color: var(--ok-ink); }
#feedback-popup-overlay .seg-tabs.seg-track { margin: 4px 0 0; }
#feedback-popup-overlay .popup-body .form-row { margin-top: 12px; }
#feedback-popup-overlay .popup-body textarea { min-height: 120px; }

/* Health (P31) — a subject's record across four tabs (Notfall · Protokoll · Vorsorge · Pass),
   built like Baby (hero + subject) on the Finanzen shell (holder + scrolling tab-layer + FAB).
   Red is the STATE of a severe allergy or an overdue thing (tokens.css: red is only for states),
   never a person. Everything else speaks the module's own ink. */
#app .module-health { display: flex; flex-direction: column; height: 100%; position: relative; min-height: 0; }
#app .module-health .tab-layer { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0 var(--pad) 90px; }
/* Eine Seite je Person, waagrecht einrastend — dieselbe Mechanik wie beim Baby-Wischer.
   Die Seite selbst scrollt nicht; das tut die Fläche darin, damit der Tab-Streifen stehen bleibt. */
#app .hl-pager {
    flex: 1;
    min-height: 0;
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
}
#app .hl-pager::-webkit-scrollbar { display: none; }
#app .hl-page {
    flex: 0 0 100%;
    min-width: 0;
    scroll-snap-align: start;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    min-height: 0;
}
/* the hero and its reiter are ONE block: the strip is the hero card's last row, flush with its
   10px sides — the head above the scrolling surface costs one card, not two (a 40px track,
   14/12 air); the baby hero carries its tabs the same way */
#app .hl-hero > .hl-tabs { flex: 1 0 100%; margin: 4px 0 0; height: 36px; }
#app .module-health .hl-consent { margin: 0 var(--pad) 12px; }
/* each subject chip is led by its avatar circle (photo when set, else the initial in the person
   colour) — the badge is a real circle, not a bare letter flush against the name */
/* the hero — subject colour ring, serif name, a sub-line of age · gender · privacy scope */
#app .hl-hero { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 8px var(--pad) 8px; padding: 12px 13px 12px; }
#app .hl-hero-glyph {
    width: 72px; height: 72px; box-sizing: border-box; border-radius: 50%; overflow: hidden;
    box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--pc, var(--line2)); flex: none; display: grid; place-items: center;
    font-size: 28px; font-weight: 500; background: var(--pc-soft, var(--card2)); color: var(--pc-ink, var(--ink2));
}
#app .hl-hero-glyph img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* a pet wears its paw where a person wears the initial — drawn at the size the letter reads at */
#app .hl-hero-glyph > i { font-size: 24px; }
#app .hl-hero-tx { flex: 1; min-width: 0; }
#app .hl-hero-name { color: var(--ink); } /* serif, size and line-height come from the display rules above */
#app .hl-hero-age { font-size: var(--fs-head); line-height: 1.3; color: var(--ink2); margin-top: 0; }
#app .hl-head-edit { margin-left: auto; align-self: flex-start; }
/* a phone value dials from its row; the row's own tap still edits (tapToEdit ignores anchors) */
#app .hl-right { margin-left: auto; flex: none; min-height: 30px; display: flex; align-items: center; }
/* Anrufen and the pass's contact rows dial from the round button (32) at the row's end; the number
   stands under the name */
#app a.hl-call { width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
    background: var(--nav-fill); color: var(--ink); font-size: 15px; text-decoration: none;
    -webkit-tap-highlight-color: transparent; }
/* a row's lead in the 30 slot: the glyph tile (r10, --nav-fill), tinted in the page person's
   colour, the badge of a contact (round, the initial 12/600 on its colour ring), or the 22 tick */
#app .hl-lead { flex: none; width: 30px; height: 30px; box-sizing: border-box; border-radius: 10px;
    display: grid; place-items: center; background: var(--nav-fill); color: var(--ink2); font-size: 16px; }
#app .hl-lead.is-tint { background: var(--pc-soft, var(--nav-fill)); color: var(--pc-ink, var(--ink2)); }
#app .hl-lead.is-badge { border-radius: 50%; font-size: 12px; font-weight: 600;
    background: var(--pc-soft, var(--nav-fill)); color: var(--pc-ink, var(--ink2)); box-shadow: inset 0 0 0 2px var(--pc, var(--line2)); }
#app .hl-lead.hl-tick { width: 22px; height: 22px; margin: 4px; border-radius: 50%; border: 1.5px solid var(--line2);
    background: var(--card); color: transparent; font-size: 13px; }
#app .hl-lead.hl-tick.on { background: var(--ink); border-color: var(--ink); color: var(--card); }
#app .hl-lead.hl-tick.na { border-style: dashed; border-color: var(--line2); }
/* the small pill at a row's end (28, --field): „Eintragen" on an overdue line, „Messen" on a value */
#app .hl-pill { flex: none; height: 28px; padding: 0 11px; border: 0; border-radius: var(--r-pill); background: var(--field);
    color: var(--ink); font-family: var(--font-family); font-size: var(--fs-cap); font-weight: 500; white-space: nowrap;
    cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* the wide button of a card's foot or a form (44, r12, --field, 15/500; the PDF glyph 18), and its
   ink twin for the one yes of the consent card */
#app .hl-btn { display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; min-height: 44px;
    box-sizing: border-box; padding: 0 12px; border: 0; border-radius: var(--r-ctl); background: var(--field); color: var(--ink);
    font-family: var(--font-family); font-size: var(--fs-md); font-weight: 500; line-height: 1.25; white-space: normal;
    text-align: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .hl-btn i { font-size: 18px; }
#app .hl-btn.hl-btn-ink { background: var(--ink); color: var(--card); }
#app .hl-btn:active { transform: scale(var(--button-click-scale)); }
/* the head of a running illness: „Krank seit Sa 3. Okt · 4. Tag" with its name at the right — a
   tap opens it */
#app .hl-ill-head { cursor: pointer; }
/* the emergency card: its head with the blood group as a dark mark above it, the card itself
   rows of label · value on one line (14, the value right in ink), the two PDF buttons side by side */
#app .hl-blood { margin-left: auto; display: inline-flex; align-items: center; height: 26px; padding: 0 10px;
    border-radius: var(--r-pill); background: var(--ink); color: var(--card); font-size: var(--fs-cap); font-weight: 500;
    font-variant-numeric: tabular-nums; white-space: nowrap; }
#app .hl-card { background: var(--card); border-radius: var(--r-card); padding: 0; margin: 0 0 8px; }
#app .hl-card-line, #app .hl-kv { display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
    padding: 9px 14px; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; }
#app .hl-card-line:first-child, #app .hl-kv:first-child { border-top: 0; }
/* the card's label is one of its own short words and stands on one line; a pass label shrinks
   only to its longest word (it wraps between words, never inside one) and takes at most 60 % */
#app .hl-card-k { flex: none; color: var(--ink2); }
#app .hl-kv > span:first-child { flex: 0 1 auto; max-width: 60%; color: var(--ink2); overflow-wrap: break-word; }
#app .hl-card-v, #app .hl-kv > span:last-child { flex: 1 1 0; min-width: 0; text-align: right; color: var(--ink); overflow-wrap: break-word; }
#app .hl-card-line.hl-severe .hl-card-v { color: var(--pend-ink); font-weight: 500; }
/* a value of several medicines puts each on its own line */
#app .hl-card-v { white-space: pre-line; }
#app .hl-card-line.hl-severe .hl-sev-ic { margin-right: 5px; font-size: 14px; vertical-align: -2px; }
#app .hl-card-actions { display: flex; gap: 9px; padding: 8px 14px 12px; }
#app .hl-card > .hl-empty { padding: 14px; }
/* a scalar line inside its section reaches the card's edges, its hairline with it */
#app .hl-section > .hl-kv { margin: 0 -14px; cursor: pointer; }
#app .hl-section { display: flex; flex-direction: column; background: var(--card); border-radius: var(--r-card); padding: 0 14px; }
/* the documents' tiles: 12 inside the card */
#app .hl-section > .ent-files { padding: 12px 0; }
/* a row: the lead in its 30 slot, the title over its meta on the lead's axis (one line centred on
   it, more lines from its top), the right side on the same axis */
#app .hl-item { display: flex; align-items: flex-start; gap: 12px; min-height: 50px; box-sizing: border-box; padding: 10px 0;
    border-bottom: 1px solid var(--line); cursor: pointer; }
#app .hl-item:last-child { border-bottom: 0; }
/* the line under a row runs the card's full width: the rows reach past the section's 14px */
#app .hl-section > .hl-item { margin: 0 -14px; padding-left: 14px; padding-right: 14px; }
#app .hl-body { flex: 1; min-width: 0; min-height: 30px; display: flex; flex-direction: column; justify-content: center; }
#app .hl-title { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; word-break: break-word; }
/* the meta wraps between its facts, never inside one: each short fact („zuletzt 14.05.2019",
   „3 Einträge", a phone number) is a block that moves to the next line whole, its dot staying
   behind it; a long one (.is-prose — a reaction, a note) flows on with the line — nothing is cut */
#app .hl-meta { font-size: var(--fs-sub); color: var(--ink2); line-height: 1.35; margin-top: 1px; overflow-wrap: break-word; }
#app .hl-by { display: inline-block; max-width: 100%; vertical-align: top; }
#app .hl-by.is-prose { display: inline; }
#app .hl-by:not(:last-child)::after { content: "\00a0·"; color: var(--ink2); font-weight: 400; }
/* the fold row of never-recorded lines: its count and the first names on ONE line, cut short */
#app .hl-fold-row .hl-meta { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .hl-fold-row .hl-by { display: inline; }
#app .hl-item.hl-severe .hl-title::after { content: " !"; color: var(--ink); }
#app .hl-empty { color: var(--ink2); font-size: var(--fs-sub); padding: 14px 0; text-align: center; cursor: pointer; }
/* a closed pass section keeps its + only while it is empty — open, or empty, it adds */
#app .hl-pass > .sec-fold:not([open]):not(.is-empty) .sec-head-add { display: none; }
/* „Was eintragen?", „Was nachtragen?": the kinds as tiles, three to a line (the Mehr sheet's) */
#app .hl-tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
/* a sheet of tiles has no foot: the air of one under its last line */
#app .popup-body > .hl-tiles:last-child { margin-bottom: 12px; }
#app .hl-tile-rows { margin-bottom: 10px; }
/* the consent: the 56 badge, the title in the serif, the text and its small print in --ink2,
   the one yes as the wide ink button — always inside the card */
#app .hl-consent { background: var(--card); border-radius: var(--r-card); padding: 20px 18px 18px; }
#app .hl-consent-badge { width: 56px; height: 56px; box-sizing: border-box; border-radius: 50%; overflow: hidden; margin: 2px 0 14px 2px;
    display: grid; place-items: center; font-size: 22px; font-weight: 500;
    background: var(--pc-soft, var(--card2)); color: var(--pc-ink, var(--ink2));
    box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--pc, var(--line2)); }
#app .hl-consent-badge img { width: 100%; height: 100%; object-fit: cover; display: block; }
#app .hl-consent h3 { margin: 0 0 8px; color: var(--ink); } /* the serif 26 comes from the display rules at the end */
#app .hl-consent p { margin: 0 0 10px; font-size: 14px; line-height: 1.45; color: var(--ink2); }
#app .hl-consent p.hl-consent-fine { font-size: var(--fs-cap); margin-bottom: 16px; }
/* ── the dashboard card ─────────────────────────────────────────────────────────────
   Three storeys: the loudest true thing first — a running illness as a row (the tinted tile,
   „Krank seit …“ over its last reading and dose, „Eintragen“), else the next thing due as a HERO —,
   the further signals as rows, and the value series as the page's value rows with their
   sparkline. Every row after the first stands under a hairline. */
#app .hl-w { container-type: inline-size; }
#app .hl-w-hero {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    width: 100%;
    padding: 2px var(--w-inset) 12px;
    border: 0;
    background: transparent;
    color: var(--ink);
    font-family: var(--font-family);
    text-align: left;
    cursor: pointer;
}
#app .hl-w-hero .m { width: 26px; height: 26px; font-size: var(--fs-sub); }
#app .hl-w-hero-main { min-width: 0; }
#app .hl-w-hero .h1 { display: block; font-size: var(--fs-md); font-weight: 600; color: var(--ink); line-height: 1.2; }
#app .hl-w-hero .h2 { display: block; font-size: var(--fs-cap); color: var(--ink2); margin-top: 3px; }
#app .hl-w-hero.is-quiet .h1 { color: var(--ink2); font-weight: 500; }
#app .hl-w .w-row { border-bottom: 0; border-top: 1px solid var(--line); }
/* a running illness: the tinted tile (.hl-w-ki), what and since when over its last reading and dose, „Eintragen“ (.hl-w-log) */
#app .hl-w-ill { flex-wrap: nowrap; align-items: flex-start; gap: 12px; cursor: pointer; }
/* the tile leads the first line: the words and the pill stand on its 30 px axis */
#app .hl-w-ill > .txt { min-height: 30px; display: flex; flex-direction: column; justify-content: center; }
#app .hl-w-ill > .hl-w-log { margin-top: 1px; }
#app .hl-w-row { display: flex; gap: 9px; align-items: center; cursor: pointer; }
#app .hl-w-row .m { box-sizing: border-box; width: 26px; height: 26px; font-size: var(--fs-sub); }
#app .hl-w-what { flex: 1; min-width: 0; }
#app .hl-w-what b { display: block; font-size: var(--fs-body); font-weight: 500; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .hl-w-what i { display: block; font-style: normal; font-size: var(--fs-cap); color: var(--ink3); margin-top: 1px; }
#app .hl-w-tag { flex: none; font-size: var(--fs-cap); font-weight: 600; padding: 3px 8px;
    border-radius: var(--r-pill); white-space: nowrap; }
#app .hl-w-tag.is-late { background: var(--due-soft); color: var(--due-ink); }
#app .hl-w-tag.is-soon { background: var(--pend-soft); color: var(--pend-ink); }
/* a value row on the card: the value card's head (.hl-vit) under a hairline, its sparkline in the
   person's colour and without the page's end dot */
#app .hl-w .hl-vit { border-top: 1px solid var(--line); }
#app .hl-w .hl-area { fill: var(--pc, var(--ink)); fill-opacity: 0.18; }
#app .hl-w .hl-line { stroke: var(--pc, var(--ink)); }
#app .hl-w .hl-dot { display: none; }
/* a plan line's state: due wants a look (amber), overdue is late (red) — the word alone, at 500 */
#app .hl-item.hl-due .hl-meta .hl-by:first-child { color: var(--pend-ink); font-weight: 500; }
#app .hl-item.hl-overdue .hl-meta .hl-by:first-child { color: var(--due-ink); font-weight: 500; }
#app .hl-rec-head { margin-top: 14px; }
#app .hl-rec { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: var(--fs-sub); }
#app .hl-rec:last-child { border-bottom: 0; }
#app .hl-rec-del { margin-left: auto; border: 0; background: none; color: var(--ink3); font-size: 14px; line-height: 1; cursor: pointer; padding: 0 6px; }
#app .hl-rec-from { margin-left: auto; color: var(--ink3); }
/* the plan sheet's rail Impfung | Kontrolle, first in its body */
#app .hl-rail { margin: 0 0 14px; }
/* Stage 3 — the log as timeline rows: the time column (50, 13/500 --ink2) on the left, what
   happened over its kind; a hairline between rows the card's full width. A running illness is its
   card under its head with „Beenden" at its foot; a closed one is a row in „Krankheiten" that
   opens its log in place. */
#app .hl-ev { display: grid; grid-template-columns: 50px minmax(0, 1fr); column-gap: 12px; align-items: start;
    min-height: 50px; box-sizing: border-box; padding: 10px 0; border-top: 1px solid var(--line); cursor: pointer; }
#app .hl-ev:first-child { border-top: 0; }
#app .hl-section > .hl-ev { margin: 0 -14px; padding-left: 14px; padding-right: 14px; }
#app .hl-ev-tm { font-size: var(--fs-sub); font-weight: 500; color: var(--ink2); font-variant-numeric: tabular-nums; white-space: nowrap; }
#app .hl-ev-txt { min-width: 0; }
#app .hl-ev-txt > b { font-size: var(--fs-md); font-weight: 500; line-height: 1.35; color: var(--ink); overflow-wrap: break-word; }
#app .hl-ev-txt > small { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); margin-top: 1px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .hl-section > .hl-ep-foot { padding: 6px 0 12px; }
#app .hl-section > .hl-ev + .hl-ep-foot { border-top: 0; }
#app .hl-ep-foot { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
#app .hl-ep-foot .action-btn { margin: 0; }
#app .hl-ep { margin: 0 0 8px; background: var(--card); border-radius: var(--r-card); }
#app .hl-ep .hl-item { border-bottom: 0; }
#app .hl-ep-body { padding: 0 0 12px; }
#app .hl-ep-body > .hl-ep-foot { padding-top: 6px; }
#app .hl-ep-loose .hl-ep-head { padding: 8px 0 4px; }
/* The past illnesses are rows on ONE card, like every list in the app: a closed illness inside
   its section is a row (no card inside the card, no second indent), a hairline the card's full
   width between them. */
#app .hl-section > .hl-ep { background: none; border-radius: 0; margin: 0 -14px; padding: 0 14px; }
#app .hl-section > .hl-ep + .hl-ep,
#app .hl-section > .hl-ep + .hl-ep-loose { border-top: 1px solid var(--line); }
#app .hl-ep-head { padding: 10px 0; }
/* the empty-log greeting sits like the notes/finances blank, sized for the scrolling layer */
#app .module-health .tab-layer .notes-blank { margin-top: 40px; }
/* Stage 4 — a card per value: its head the name (13/500 --ink2), the last reading in the serif 18
   with its time (12), the sparkline 120 × 44 and the fold's chevron; open, the readings as
   timeline rows with the „n weitere" foot under them. A value never measured reads „—" with
   „noch keine Messung" and the pill „Messen". */
#app .hl-val { background: var(--card); border-radius: var(--r-card); margin: 0 0 8px; }
#app .hl-vit { display: flex; align-items: center; gap: 12px; padding: 10px 14px; cursor: pointer; }
#app .hl-val.is-empty .hl-vit { cursor: default; }
#app .hl-vit-tx { flex: 1; min-width: 0; }
#app .hl-vit-tx > b { display: block; font-size: var(--fs-head); font-weight: 500; color: var(--ink2); }
#app .hl-vit-v { color: var(--ink); font-variant-numeric: tabular-nums; } /* the serif 18 comes from the display rules at the end */
#app .hl-val.is-empty .hl-vit-v { color: var(--ink2); }
#app .hl-vit-tx > small { font-size: var(--fs-cap); color: var(--ink2); white-space: nowrap; }
#app .hl-spark { position: relative; flex: 0 0 120px; height: 44px; }
#app .hl-spark svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; display: block; }
#app .hl-vit > .fold-chev { margin-left: 0; transform: none; }
#app .hl-val.open .hl-vit > .fold-chev { transform: rotate(180deg); }
#app .hl-readings > .hl-ev { padding-left: 14px; padding-right: 14px; }
/* the first reading hangs right under the head, the hairline between them */
#app .hl-readings > .hl-ev:first-child { border-top: 1px solid var(--line); padding-top: 0; }
/* a reading's time is its weekday over its clock („Mo" / „08:00") in the 50 column, the value
   level with the weekday */
#app .hl-readings .hl-ev-tm { white-space: normal; }
#app .hl-readings .hl-ev-txt { justify-content: flex-start; }
/* three readings stand, the rest behind the „n weitere" foot under them */
#app .hl-readings .hl-ev.w-xtra { display: none; }
#app .hl-readings.open .hl-ev.w-xtra { display: grid; }
/* open, the foot is only the turned chevron — „n weitere" would name rows already standing */
#app .hl-readings.open .w-foot i { transform: rotate(180deg); }
#app .hl-readings.open .w-foot .w-more { display: none; }
#app .hl-readings.open .w-foot .w-less { display: inline; }
/* a pet's food log: its meals as rows on one card, ten standing, the rest behind the foot */
#app .hl-food > .w-foot { width: auto; margin: 0 -14px; }
#app .hl-food:not(.open) > .hl-ev.w-xtra { display: none; }
#app .hl-food.open > .w-foot i { transform: rotate(180deg); }
#app .hl-food.open > .w-foot .w-more { display: none; }
#app .hl-food.open > .w-foot .w-less { display: inline; }
/* the value sparkline (_valueSpark) — the app's chart language (see .fin-chart): the wash, the line, the end dot */
#app .hl-area { fill: var(--ink); fill-opacity: 0.10; }
#app .hl-line { fill: none; stroke: var(--ink); stroke-width: 1.8px; stroke-linecap: round;
    stroke-linejoin: round; vector-effect: non-scaling-stroke; }
/* the newest reading's point: 7 on the card with a 1.8 ink ring */
#app .hl-dot { position: absolute; width: 7px; height: 7px; border-radius: 50%;
    background: var(--card); box-shadow: inset 0 0 0 1.8px var(--ink); transform: translate(-50%, -50%); }
/* A switch row is a <label> inside the sheet body — it must NOT read as a field caption
   (the generic .popup-body label is small caps, muted, block): 48 high, the name 15/500 over
   its unit and what it is (13 --ink2). */
#app .popup-body label.hl-opt { display: flex; align-items: center; gap: 12px; min-height: 48px; box-sizing: border-box; padding: 4px 0;
    margin: 0; border-top: 1px solid var(--line); cursor: pointer; text-transform: none; letter-spacing: 0; font-weight: 400;
    font-size: var(--fs-body); color: var(--ink); }
#app .popup-body label.hl-opt:first-child { border-top: 0; }
#app .hl-opt-tx { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
#app .hl-opt-tx > b { font-weight: 500; }
#app .hl-opt-tx > small { font-size: var(--fs-sub); color: var(--ink2); }
/* a unit inside its number field, at its end („°C", „mmHg") */
#app .hl-unit-field { position: relative; display: block; }
#app .hl-unit-field > input { width: 100%; box-sizing: border-box; padding-right: 64px; }
#app .hl-unit { position: absolute; right: 13px; top: 50%; transform: translateY(-50%); font-size: var(--fs-md);
    color: var(--ink2); pointer-events: none; white-space: nowrap; }
/* „Zur Krankheit": the fold under an entry naming the illness it belongs to — a tap opens it; a
   long name wraps onto a second line instead of being cut */
#app .hl-kfold { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 44px; box-sizing: border-box; padding: 8px 0;
    border: 0; border-top: 1px solid var(--line); background: none; font-family: var(--font-family); font-size: var(--fs-md);
    color: var(--ink2); text-align: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }
#app .hl-kfold > b { flex: none; color: var(--ink); font-weight: 500; white-space: nowrap; }
#app .hl-kfold > span { display: flex; min-width: 0; line-height: 1.35; }
/* „Zur Krankheit" in one line: the illness's name gives way, „· seit Sa 3. Okt" stands whole */
#app .hl-kfold-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .hl-kfold-since { flex: 0 100 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#app .hl-kfold > i { margin-left: auto; flex: none; font-size: 12px; color: var(--ink3); }

/* ============================================================================
   Reisen (module 'travel') — two surfaces in one module: the JOURNEY (list, record, legs) and
   the EVERYDAY board (stops, departures, the way home). They share the card language of the
   rest of the app; what is specific to travel is the state chip (LIVE/PLAN/STILL) and the
   departure row, whose numbers are tabular so a countdown does not jump while it ticks.
   ========================================================================== */
/* The shell: the module HOLDS, one layer SCROLLS — the segmented-track idiom of Finanzen,
   Notizen and Gesundheit. Two tabs, because the module answers two kinds of question. */
#app .module-travel { display: flex; flex-direction: column; height: 100%; min-height: 0; position: relative; }
#app .module-travel .tab-layer { overflow-y: auto; -webkit-overflow-scrolling: touch;
    padding: 0 var(--pad) calc(var(--safe-bottom) + 90px); }

/* a trip card — the picture 88 × 70, the name over two clipped lines, and at the right the pill
   over the badges: 88 / 1fr / auto, so nothing at the right ever runs into the text */
#app .tv-card { display: grid; grid-template-columns: 88px minmax(0, 1fr) auto; align-items: start; gap: 12px;
    width: 100%; box-sizing: border-box; margin-bottom: 8px; padding: 12px 14px;
    background: var(--card); border: 0; border-radius: var(--r-card); text-align: left;
    cursor: pointer; font-family: var(--font-family); color: var(--ink); }
/* DAS BILD der Reise — in der Liste als Kachel vor dem Namen, auf der Reise selbst als Band
   ÜBER dem Kopf. Nie hinter dem Text: Schrift auf einem fremden Foto ist eine Wette auf dessen
   Helligkeit, und die verliert man bei jedem zweiten Urlaubsbild. Ohne Foto steht das Zeichen
   der Szene auf dem Feld-Ton. */
#app .tv-card-shot { width: 88px; height: 70px; border-radius: 10px; overflow: hidden; background: var(--field);
    display: grid; place-items: center; color: var(--ink2); }
#app .tv-card-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
#app .tv-card-shot > .tv-scene-glyph { font-size: 30px; }
#app .tv-card-main { min-width: 0; display: flex; flex-direction: column; font-size: var(--fs-sub); line-height: 1.4; color: var(--ink2); }
#app .tv-card-title { font-size: var(--fs-body); font-weight: 500; line-height: 1.4; color: var(--ink); }
#app .tv-card-sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* a trip that is over says so in the quiet ink, never by fading */
#app .tv-card-past .tv-card-title { color: var(--ink2); }
#app .tv-card-rt { display: grid; gap: 8px; justify-items: end; align-content: start; }
/* the „+n" of a Für capsule, tucked under its last badge like the badges under each other */
#app .tv-more { height: 22px; display: inline-flex; align-items: center; margin-left: -6px; padding: 0 8px;
    border-radius: var(--r-pill); background: var(--field); box-shadow: 0 0 0 2px var(--card);
    font-size: var(--fs-cap); font-weight: 500; color: var(--ink2); }

/* the scene of a trip without a photo, in its sheet: one tile per glyph with its word, the
   chosen one in ink */
#app .tv-scenes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
#app .tv-scene { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
    min-height: 64px; padding: 8px 4px; border: 0; border-radius: var(--r-ctl);
    background: var(--field); color: var(--ink2); font-family: var(--font-family); font-size: 11px; font-weight: 500;
    cursor: pointer; transition: transform var(--transition-fast); -webkit-tap-highlight-color: transparent; }
#app .tv-scene > .tv-scene-glyph { font-size: 22px; }
#app .tv-scene:active { transform: scale(var(--button-click-scale)); }
#app .tv-scene.on { background: var(--ink); color: var(--card); }
#app .tv-cover {
    display: block;
    position: relative;
    /* Die Reise-Fläche ist eine FLEX-SPALTE: ohne `flex: none` schrumpft ein Kind mit fester
       Höhe auf null, sobald die Spalte überläuft — das Band war gesetzt, gemessen 0 px hoch. */
    flex: none;
    width: 100%;
    padding: 0;
    border: 0;
    margin: 8px 0 10px;
    height: 120px;
    border-radius: var(--r-card);
    overflow: hidden;
    background: var(--nav-fill);
    cursor: pointer;
}
#app .tv-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* without a photo the band is a light wash with the scene's glyph at its bottom right */
#app .tv-cover-scene { background: linear-gradient(160deg, var(--wx-snow-soft), var(--wx-rain-soft) 60%, var(--p4-soft)); }
#app .tv-cover-scene > .tv-scene-glyph { position: absolute; right: 14px; bottom: 10px; font-size: 44px; color: var(--wx-rain); }

/* the record's hero — an opened Split circle's head under the trip's picture: ‹ name ✎ in one
   row, the sentence and the marks 6px further in, the card on the finance hero's 14/10/12 */
#app .tv-hero { display: flex; flex-direction: column; gap: 6px; padding: 12px 13px 12px; }
#app .tv-hero:first-child { margin-top: 8px; }
#app .tv-hero-head { display: flex; align-items: center; gap: 6px; }
#app .tv-hero-name { flex: 1; min-width: 0; margin: 0; line-height: 1.1;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .tv-hero-sub { margin: 0; font-size: var(--fs-head); line-height: 1.4; color: var(--ink2); }
#app .tv-hero > .hero-marks { margin: 10px 0 0; align-items: center; }
/* the trip's cover and its hero are one card: the picture is the card's top */
#app .tv-cover:has(+ .tv-hero) { margin-bottom: 0; border-radius: var(--r-card) var(--r-card) 0 0; }
#app .tv-cover + .tv-hero { border-radius: 0 0 var(--r-card) var(--r-card); }

/* the destination's weather — its own card under the hero: the dashboard card's head and its
   week row for the trip's days; the head's ˅ folds the row away and turns while it is shut */
#app .tv-wx { flex: none; margin-top: 8px; background: var(--card); border-radius: var(--r-card); overflow: hidden; }
#app .tv-wx.shut > .wx-week { display: none; }
#app .tv-wx.shut > .w-head { padding-bottom: 12px; }
#app .tv-wx.shut .wx-chev { transform: rotate(-90deg); }
/* the first fold stands the page's 8 under the hero card, or under the weather card */
#app .tv-hero + .sec-fold, #app .tv-wx + .sec-fold { margin-top: 8px; }

/* rows (legs, bookings, rounds): the tile, the text, the right side — 30 / 1fr / auto */
#app .tv-rows { background: var(--card); border-radius: var(--r-card); overflow: hidden; }
#app .tv-row { display: grid; grid-template-columns: 30px minmax(0, 1fr) auto; align-items: start; gap: 2px 12px;
    width: 100%; box-sizing: border-box; min-height: 50px; padding: 10px 14px;
    border: 0; border-top: 1px solid var(--line); background: var(--card); color: var(--ink);
    font-family: var(--font-family); text-align: left; cursor: pointer; }
#app .tv-rows > .tv-row:first-child { border-top: 0; }
#app .tv-row-mid { min-width: 0; }
#app .tv-row-t { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; color: var(--ink); }
#app .tv-row-m { margin-top: 1px; font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* a sub line of facts (travel `facts`: rounds, the pot question) breaks between its facts — their
   no-break spaces hold each one whole — so nothing is cut */
#app .tv-row-m.tv-facts, #app .tv-chs .new-tx .tv-facts { white-space: normal; }
#app .tv-amt { font-size: var(--fs-body); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
#app .tv-row > .ppl { min-height: 30px; }
/* a card's foot with its one action as a small pill („+ Kosten eintragen") */
#app .tv-rows-foot { display: flex; padding: 6px 14px 8px; }
#app .tv-empty-row { display: block; width: 100%; padding: 13px 14px; border: 0;
    border-radius: var(--r-card); background: var(--card); color: var(--ink2);
    font-family: var(--font-family); font-size: var(--fs-hint); text-align: left; cursor: pointer; }
/* one line saying there is nothing (yet) — „Niemand unterwegs.", „Noch nichts eingetragen." */
#app .tv-emptyline { padding: 14px; border-radius: var(--r-card); background: var(--card);
    font-size: var(--fs-hint); color: var(--ink2); text-align: center; }
/* a sentence under a card's rows, inside the card („niemand daheim wird an sie erinnert") */
#app .tv-rows-line { padding: 8px 14px 12px; font-size: var(--fs-hint); color: var(--ink2); text-align: left; }
#app .tv-hint { font-size: var(--fs-hint); color: var(--ink2); padding: 8px 4px 0; line-height: 1.45; }
#app .tv-note { margin-top: 14px; padding: 12px 14px; background: var(--card2); border-radius: var(--r-card);
    font-size: var(--fs-hint); color: var(--ink2); white-space: pre-wrap; }
#app .tv-docs { background: var(--card); border-radius: var(--r-card); padding: 12px; }
/* the packing list on the trip: the notes' own lines, no hairline over them — the fold's head is
   the list's head; a line's own badge stands on its text's axis */
#app .tv-pack { background: var(--card); border-radius: var(--r-card); padding: 4px 14px; }
#app .tv-pack > .nc-lines { margin-top: 0; padding-top: 0; border-top: 0; }
#app .tv-pack .nc-line > .ppl { margin-top: 4px; }
/* the ✎ in a fold head, where its count would stand */
#app .tv-head-pen { flex: none; display: grid; place-items: center; width: 28px; height: 28px; margin: -4px 0 -4px auto;
    padding: 0; border: 0; background: transparent; color: var(--ink2); font-size: 13px; cursor: pointer;
    -webkit-tap-highlight-color: transparent; }
#app .tv-head-pen + .fold-chev { margin-left: 0; }
/* „Wohin gehört das Geld?" — the pot as chooser rows in a card: tile · title over its sub · the
   selection tick at the right, centred on the tile's 30 and in ink while it holds */
#app .tv-chs { margin-bottom: 8px; padding: 4px 14px 0; background: var(--card); border-radius: var(--r-card); }
#app .tv-chs-q { display: flex; align-items: center; min-height: 30px; font-size: var(--fs-head); font-weight: 500; color: var(--ink2); }
#app .tv-chs > .new-row { padding: 9px 0; border-bottom: 0; border-top: 1px solid var(--line); align-items: flex-start; }
#app .tv-chs > .new-row > .new-tx { min-height: 30px; justify-content: center; }
#app .tv-chs .new-tick { margin: 4px 0; }
#app .tv-chs .new-row[aria-checked="true"] .new-tick { background: var(--ink); border-color: var(--ink); color: var(--card); }

/* the pills of a card: „läuft" in ink, „2 offen" in the amber, an action on the field tone */
#app .tv-pill { flex: none; display: inline-flex; align-items: center; gap: 6px; box-sizing: border-box; height: 28px; padding: 0 11px;
    border: 0; border-radius: var(--r-pill); font-family: var(--font-family); font-size: var(--fs-cap); font-weight: 500; white-space: nowrap; }
#app .tv-pill-pend { background: var(--pend-soft); color: var(--pend-ink); }
/* a trip under way — the house's voice for ON is ink, not a colour */
#app .tv-pill-live { background: var(--ink); color: var(--card); }
#app .tv-pill-add { background: var(--field); color: var(--ink); cursor: pointer; }
#app .tv-pill-add > i { font-size: 14px; }

/* editors */
#app .tv-place { position: relative; }
/* the picked destination stands where the search field stood, as a field of its own */
#app .tv-place-chosen { display: flex; align-items: center; gap: 8px; min-height: 44px; box-sizing: border-box; padding: 0 6px 0 13px;
    border-radius: var(--r-ctl); background: var(--field); }
#app .tv-place-name { flex: 1; min-width: 0; font-size: var(--fs-md); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .tv-place-clear { flex: none; border: 0; background: transparent; color: var(--ink3); cursor: pointer; }
#app .tv-place-list { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
#app .tv-place-list:empty { display: none; }
/* destination and zone line up at their labels: the place's hits open under its own field */
#app .popup-body .form-pair.tv-where > .form-row { justify-content: flex-start; }
#app .tv-place-hit { text-align: left; padding: 9px 11px; border: 0; border-radius: var(--r-ctl);
    background: var(--card2); color: var(--ink); font-family: var(--font-family); font-size: var(--fs-md); cursor: pointer; }
#app .tv-place-none { padding: 8px 11px; font-size: var(--fs-cap); color: var(--ink3); }
/* the leg's „Fahrt | Aufenthalt" rail on top of its sheet, and under its times how long it takes */
#app .popup-body .tv-rail { margin: 0 0 14px; }
#app .popup-body .tv-dur { display: flex; align-items: center; gap: 6px; margin: -6px 0 14px;
    font-size: var(--fs-hint); line-height: 1.45; color: var(--ink2); }
#app .popup-body .tv-dur > i { flex: none; font-size: 13px; }
#app .tv-flight-block { display: contents; }
/* the FAB — one per surface, its target follows the view */

/* dashboard cards: the trip — its picture 88 × 70 beside its name and two lines, whom it is for
   at the top right; a photo's brightness is nobody's to bet on, so the picture never stands
   behind the words */
#app .tv-w-body { display: grid; grid-template-columns: 88px minmax(0, 1fr) auto; align-items: start; gap: 12px; width: 100%;
    box-sizing: border-box; padding: 12px 14px; border: 0; text-align: left;
    background: transparent; color: var(--ink); font-family: var(--font-family); cursor: pointer; }
#app .tv-w-name { display: block; font-size: var(--fs-body); font-weight: 500; color: var(--ink); }
#app .tv-w-meta { display: block; font-size: var(--fs-sub); line-height: 1.4; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#app .tv-w-shot { width: 88px; height: 70px; border-radius: 10px; overflow: hidden; background: var(--field);
    display: grid; place-items: center; color: var(--ink2); }
#app .tv-w-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
#app .tv-w-shot > .tv-scene-glyph { font-size: 30px; }
#app .tv-w-main { min-width: 0; }
#app .tv-w-body > .who { margin-left: 0; }

/* ── das Bild einer Sache ────────────────────────────────────────────────────────────
   EINE Fläche für jedes Portrait: Mitglied, Person, Sache, Reise. Vorschau links, darunter
   dieselben drei Knöpfe in derselben Reihenfolge — hochladen, vorhandenes wählen, entfernen. */
#app .av-pick { display: flex; flex-direction: column; gap: 10px; padding: 4px 0 12px; }
#app .av-pick-shot {
    width: 84px;
    height: 84px;
    border-radius: var(--r-card);
    background: var(--card2);
    border: 1px solid var(--line);
    overflow: hidden;
    display: grid;
    place-items: center;
    color: var(--ink3);
    font-size: 24px;
}
#app .av-pick-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
#app .av-pick-btns { display: flex; flex-wrap: wrap; gap: 8px; }
#app .av-pick-status { font-size: var(--fs-hint); color: var(--ink2); }

/* the page behind a shared vault link (link.html, passwords/linkPage.js), outside the app: the
   body scrolls like a page (app.css pins it for the shell) on the app's ground; one card in the
   middle — the word mark with its dot, the line under it, the entry's rows like the entry sheet's
   (the kind's tile with the name, each label over its value, the buttons right), the closing word */
body.link-page { position: static; overflow: auto; height: auto; min-height: 100vh; background: var(--line); }
[data-theme="dark"] body.link-page { background: var(--bg); }
.lp { box-sizing: border-box; max-width: 520px; min-height: 100vh; margin: 0 auto; display: flex; flex-direction: column; justify-content: center;
    padding: calc(28px + var(--safe-top)) var(--pad) calc(40px + var(--safe-bottom)); }
.lp-card { background: var(--card); border-radius: var(--r-card); padding: 18px 16px 16px; color: var(--ink); }
.lp-hdr { display: flex; align-items: center; margin-bottom: 16px; }
.lp .wm { line-height: 1; color: var(--ink); display: inline-flex; align-items: center; gap: 8px; }
.lp .wm .wm-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--wm-dot); margin: 0 0 20px -6px; }
.lp-sub { margin: -10px 0 14px; font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); }
.lp-text { margin: 0 0 12px; font-size: var(--fs-body); line-height: 1.5; color: var(--ink); }
.lp-quiet { font-size: var(--fs-hint); color: var(--ink2); }
.lp-err { color: var(--due-ink); }
.lp-go { margin: 6px 0 12px; }
.lp-line { display: flex; align-items: center; gap: 12px; min-height: 48px; box-sizing: border-box; padding: 4px 0; border-top: 1px solid var(--line); }
.lp-line:first-child { border-top: 0; }
.lp-ki { width: 30px; height: 30px; flex: none; border-radius: 10px; display: grid; place-items: center;
    background: var(--nav-fill); color: var(--ink2); font-size: 16px; }
.lp-t { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.lp-k { font-size: var(--fs-sub); line-height: 1.35; color: var(--ink2); overflow-wrap: anywhere; }
.lp-v { font-size: var(--fs-body); font-weight: 500; line-height: 1.35; color: var(--ink); overflow-wrap: anywhere; }
.lp-line.is-note .lp-v { white-space: pre-wrap; }
.lp-line.is-masked .lp-v { letter-spacing: 0.2em; }
.lp-line.is-shown .lp-v { font-family: var(--font-family); font-size: 18px; font-variant-numeric: tabular-nums; letter-spacing: 0.1em; }
.lp-acts { display: flex; gap: 12px; flex: none; }
.lp-act { width: 36px; height: 36px; border: 0; border-radius: var(--r-pill); background: var(--nav-fill);
    color: var(--ink); font-size: 17px; display: grid; place-items: center; cursor: pointer; }
.lp-after { margin: 8px 0 0; line-height: 1.45; text-align: center; }
.lp-status { margin: 8px 0 0; text-align: center; }
.lp-status:empty { display: none; }

/* reduced motion: nothing travels — every way in is a fade in the fast duration */
@media (prefers-reduced-motion: reduce) {
    .popup-modal.sheet, .head-menu, .popup-overlay, .write-error-toast, .menu-veil { animation: fadeIn var(--transition-fast) both; }
    #app .profile-drawer { transition-duration: 0ms; }
}

/* a phone's keyboard stands where the footer stood: while the head's field has the focus the
   footer, the + and the dock step aside (the head stays; a sheet's foot rides over the keys) */
@media (max-width: 999px) {
    #app:has(header .tb-input:focus) footer,
    #app:has(header .tb-input:focus) .cal-fab, #app:has(header .tb-input:focus) .notes-fab,
    #app:has(header .tb-input:focus) .fin-fab, #app:has(header .tb-input:focus) .dash-fab,
    #app:has(header .tb-input:focus) .baby-fab, #app:has(header .tb-input:focus) .hl-fab,
    #app:has(header .tb-input:focus) .tv-fab, #app:has(header .tb-input:focus) .pw-fab,
    #app:has(header .tb-input:focus) .fin-dock-group { display: none; }
}

/* ====================== THE DESKTOP (from 1000px) ======================
   The head grows to 60, the page stands centred at 1280 and 24 from the window (the panel's 8
   and the module's own 16, var(--pad)) — the list modules in one column of 720 —, the dashboard
   holds three columns, finances (Status) and the calendar (month) two — hero and main on the
   left, the folds / the day list in a 360 column on the right from the top —, a sheet is a
   centred card of 560 (a confirmation 480), the footer is 60 with every module in the middle.
   Between 600 and 999 the phone layout stays, with its 16px gutter. */
@media (min-width: 1000px) {
    #app header { padding: calc(var(--safe-top) + 8px) 24px 8px; gap: 12px; }
    #app .tb-input::placeholder { font-size: 14px; }
    #app .tb-chip.tb-view:not(.min) .tb-chip-k { display: inline; }
    #app main > div[data-module] { padding: 0 max(8px, calc(50% - 656px)); box-sizing: border-box; }
    #app main > div[data-module="notes"], #app main > div[data-module="household"],
    #app main > div[data-module="health"], #app main > div[data-module="baby"],
    #app main > div[data-module="travel"], #app main > div[data-module="passwords"] {
        padding: 0 max(8px, calc(50% - 376px));
    }
    #app .hero-lean, .cal-hero, .fin-hero.fin-hero-card, #app .baby-hero, #app .hl-hero, #app .tv-hero, #app .pw-hero { padding-left: 18px; padding-right: 18px; }
    #app .hero-title, #app .cal-title, #app .dash-hello-greet, #app .baby-hero-name, #app .hl-hero-name, #app .tv-hero-name, #app .pw-hero-name { font-size: 32px; }
    #app .fin-hero-card > .fin-hero-num { font-size: 40px; }
    .fin-feed { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 12px; align-items: start; }
    /* finances (Status) and the calendar (month): the module is the grid — the hero and the main
       part (the Vorausschau and „Was kostet …“, the month grid) on the left, the folds / the day's
       list in 360 on the right from the hero's top, 16 apart; the layer, the feed and the month's
       columns step aside (display: contents), so the page scrolls as one in the panel and the +
       sticks to the bottom corner of the right column */
    .module-finances:has(.fin-fore), .module-calendar:has(> .tab-layer > .cal-cols) {
        display: grid; grid-template-columns: minmax(0, 1fr) 360px; grid-template-rows: auto auto 1fr;
        column-gap: 16px; align-items: start; align-content: start;
        flex: none; height: auto; min-height: 100%; padding: 0 var(--pad) 16px; box-sizing: border-box; }
    .module-finances:has(.fin-fore) > .tab-layer, .module-finances:has(.fin-fore) > .tab-layer > div,
    .module-finances:has(.fin-fore) .fin-feed,
    .module-calendar:has(> .tab-layer > .cal-cols) > .tab-layer, .module-calendar > .tab-layer > .cal-cols { display: contents; }
    .module-finances:has(.fin-fore) > .fin-hero-card,
    .module-calendar:has(> .tab-layer > .cal-cols) > .cal-hero { grid-column: 1; grid-row: 1; margin: 8px 0 0; }
    .module-finances .fin-feed > .fin-sec.fin-fore, .module-calendar .cal-cols > .cal-grid { grid-column: 1; grid-row: 2; margin: 12px 0 0; }
    .module-calendar .cal-cols > .cal-grid { margin-top: 8px; } /* the grid card 8 under the hero */
    .module-finances .fin-feed > .fin-sec.fin-carriers { grid-column: 1; grid-row: 3; margin-top: 12px; }
    .module-finances .fin-feed > .fin-sec.fin-values { grid-column: 2; grid-row: 1 / -1; margin-top: 8px; padding-bottom: 80px; }
    .module-calendar .cal-cols > .cal-agenda { grid-column: 2; grid-row: 1 / -1; margin-top: 8px; }
    .module-finances:has(.fin-fore) > .fin-fab, .module-calendar:has(> .tab-layer > .cal-cols) > .cal-fab {
        position: sticky; grid-column: 2; grid-row: 1 / -1; align-self: end; justify-self: end; bottom: 16px;
        margin-right: calc(8px - max(8px, 50vw - 656px)); }
    /* the + stands 24 from the window however far the page is centred in: the module's 16 and the
       panel's 8, less what the panel pads beyond its 8 (the list column's centring too) */
    .cal-fab, .notes-fab, .fin-fab, .dash-fab, #app .baby-fab, #app .hl-fab, #app .tv-fab, #app .pw-fab { right: calc(var(--pad) + 8px - max(8px, 50vw - 656px)); }
    #app main > div:is([data-module="notes"], [data-module="household"], [data-module="health"], [data-module="baby"], [data-module="travel"], [data-module="passwords"])
        :is(.notes-fab, .dash-fab, .baby-fab, .hl-fab, .tv-fab, .pw-fab) { right: calc(var(--pad) + 8px - max(8px, 50vw - 376px)); }
    .fin-dock-group { max-width: 640px; }
    /* sheets: a centred card, no grip, 90vh at most; a confirmation narrower */
    .popup-overlay.sheet { align-items: center; }
    .popup-modal.sheet { max-width: 560px; max-height: 90vh; border-radius: 22px; border-bottom: 0; }
    .popup-modal.sheet::before { display: none; }
    .popup-modal.sheet .popup-header { padding-top: 10px; }
    .popup-modal.sheet.confirm-sheet { max-width: 480px; }
    .popup-modal.sheet .popup-footer { padding-bottom: 16px; }
    .popup-modal.sheet .popup-body:last-child { padding-bottom: 20px; }
    /* the footer: 60 high, every module in the middle, the same pill */
    #app footer { justify-content: center; gap: 28px; padding: 5px 4px calc(var(--safe-bottom) + 5px); }
    #app footer > div, #app footer > .nav-more { flex: 0 0 66px; }
}
/* hover, only where there is a pointer: rows and entries on the inset tone, circles, pills and
   chips a step darker, the primary a step lighter, links underlined — nothing lifts */
@media (hover: hover) {
    .notes-item:hover, .fin-item:hover, .hh-row:hover, .cal-event:not(.cal-static):hover, .head-menu-item:hover,
    #app .search-result:hover, .new-row:hover, #app .set-row:hover, #app .profile-drawer-menu button:hover { background: var(--card2); }
    #app .hero-menu:hover, .cal-nav:hover, .head-edit:hover, .sec-head-add:hover, #app .w-add:hover,
    #app .tb-chip:not(.on):hover, .hero-mark.hero-mark-btn:hover, #app .tb-group:not(.on):hover,
    #app footer > div:not(.active):hover i, #app footer > .nav-more:not(.active):hover i { background: color-mix(in srgb, var(--ink) 12%, transparent); }
    .action-btn.reusable:not(.cancel-btn):not(.delete-btn):hover, .cal-fab:hover, .notes-fab:hover, .fin-fab:hover, .dash-fab:hover,
    #app .baby-fab:hover, #app .hl-fab:hover, #app .tv-fab:hover, #app .pw-fab:hover { background: color-mix(in srgb, var(--ink) 88%, transparent); }
    #app .hero-act:hover, .notes-title > a.notes-link:hover { text-decoration: underline; text-decoration-color: var(--ink2); }
    .notes-item, .fin-item, .hh-row, .cal-event:not(.cal-static), .head-menu-item, #app .search-result, .new-row { cursor: pointer; }
}
