/* walkmap design system: tokens, base elements, app shell, shared components, auth screens.
   Values are measured from the prototype docs/design/walkmap.dc.html. Feature pages add their
   own css/<page>.css and reuse these classes instead of redefining them. Dynamic colours come
   in through style="--c:#hex". */

/* Golos Text, self-hosted (OFL, see ../fonts/OFL.txt). */
@font-face{font-family:'Golos Text';font-style:normal;font-weight:400;font-display:swap;src:url(../fonts/golos-text-cyrillic-400-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Golos Text';font-style:normal;font-weight:400;font-display:swap;src:url(../fonts/golos-text-latin-400-normal.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:'Golos Text';font-style:normal;font-weight:500;font-display:swap;src:url(../fonts/golos-text-cyrillic-500-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Golos Text';font-style:normal;font-weight:500;font-display:swap;src:url(../fonts/golos-text-latin-500-normal.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:'Golos Text';font-style:normal;font-weight:600;font-display:swap;src:url(../fonts/golos-text-cyrillic-600-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Golos Text';font-style:normal;font-weight:600;font-display:swap;src:url(../fonts/golos-text-latin-600-normal.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:'Golos Text';font-style:normal;font-weight:700;font-display:swap;src:url(../fonts/golos-text-cyrillic-700-normal.woff2) format('woff2');unicode-range:U+0301,U+0400-045F,U+0490-0491,U+04B0-04B1,U+2116}
@font-face{font-family:'Golos Text';font-style:normal;font-weight:700;font-display:swap;src:url(../fonts/golos-text-latin-700-normal.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}

/* Text colours keep 4.5:1 (WCAG 1.4.3) on the surfaces they sit on: --faint on --surface and
   --bg and --muted on --seg (audit 2026-10-07, finding 3). Text on a colour
   that comes from data (an avatar, a tag) takes --on, which views.TextOn / WM.textOn pick. */
:root{
  --bg:#f4f2ee; --surface:#fff; --surface-2:#faf9f6; --surface-3:#f7f5f1; --map-bg:#e9e6e0;
  --ink:#1d1c1a; --ink-2:#3d3b37; --muted:#6b6862; --muted-2:#5f5c56; --faint:#716c64;
  --line:#e6e2db; --line-2:#eeeae4; --line-3:#f1eee9; --field:#d9d4cb; --chip-line:#e0dcd4;
  --seg:#efece6;
  --danger:#b91c1c; --danger-bg:#fbeaea; --danger-ink:#7f1d1d; --danger-line:#e3b4b4;
  --ok:#166534; --ok-bg:#e3f4e8; --dup:#92400e; --dup-bg:#fdf1d6; --warn:#b45309; --warn-bg:#fef3c7;
  --heat-1:#ffd166; --heat-2:#f8961e; --heat-3:#e85d04; --heat-4:#9d0208; --mosaic-0:#ece8e1;
  --heat-3-deep:#c2410c; /* --heat-3 dark enough for white text (5.2:1): the filter count */
  --tag-bg:#fdecdc; --tag-ink:#7c2d12; /* the tag «глава семьи» (8.9:1) */
  --none:#a8a297;
  --font:'Golos Text',system-ui,sans-serif; --mono:ui-monospace,Menlo,monospace;
  --shadow-pop:0 6px 24px rgba(0,0,0,.16);
  --disabled:#bdb7ad;
  /* The UI redesign (2026-10-17): a tap target, the radius of a card and of a sheet, the scrim. */
  --tap:44px; --r-card:16px; --r-sheet:22px; --scrim:rgba(20,19,18,.38);
}

/* ---------- base */
*{box-sizing:border-box}
[hidden]{display:none!important}
html,body{height:100%}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--font);-webkit-font-smoothing:antialiased}
a{color:var(--ink);text-underline-offset:2px}
a:hover{color:var(--muted)}
button,input,textarea,select{font-family:inherit;color:inherit}
h1,h2,h3,p{margin:0}
@keyframes wmspin{to{transform:rotate(360deg)}}

/* ---------- app shell */
.app{height:100vh;height:100dvh;display:flex;flex-direction:column;overflow:hidden;background:var(--bg);position:relative}
.topbar{height:52px;flex:none;display:flex;align-items:center;gap:10px;padding:0 6px 0 12px;background:var(--surface);border-bottom:1px solid var(--line);position:relative;z-index:30}
.brand,.brand:hover{display:flex;align-items:center;gap:12px;flex:none;color:var(--ink);text-decoration:none}
.brand-mark{display:grid;grid-template-columns:repeat(2,8px);gap:2px}
.brand-mark i{height:8px;border-radius:2px;background:var(--heat-1)}
.brand-mark i:nth-child(2){background:var(--heat-2)}
.brand-mark i:nth-child(3){background:var(--heat-3)}
.brand-mark i:nth-child(4){background:var(--heat-4)}
.brand-word{font-weight:700;font-size:18px;letter-spacing:-0.03em}
/* The header (UI redesign, phase 1): on a phone the brand's mark, its name only on the map (the
   home page, .topbar--home), and the page's title; a page opened from somewhere has a back link
   and the title as its heading (.topbar--back). */
.topbar:not(.topbar--home) .brand-word{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
.topbar-title{flex:1;min-width:0;font-size:16px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Two families (redesign 2026-10-29, item 6): the family the person acts in, under the title, a
   button that opens the avatar menu. The block lets the line's 44 px hit area (the coarse ::after
   below) out: .topbar-title's overflow:hidden cut it to 30 px. Its two lines cut their own text. */
.topbar-title--family{display:flex;flex-direction:column;justify-content:center;line-height:1.2;overflow:visible}
.topbar-title-text{min-width:0;margin:0;font:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar-family{display:inline-flex;align-items:center;gap:2px;align-self:flex-start;max-width:100%;padding:0;border:0;background:none;color:var(--muted);font:inherit;font-size:13px;font-weight:400;cursor:pointer}
.topbar-family-name{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topbar-family .ic{width:14px;height:14px;transform:rotate(90deg)}
.topbar .topbar-back{margin-left:-6px;background:none}
/* A page opened from somewhere (phase 3): on a phone its header is the back link, a colour dot
   (the walk's), the title and the page's actions, without the brand; from 1024 px the brand and
   the sections, as on any page, and the back bar at the top of the content has the back link and
   the title (one heading shows at a time). */
.topbar--back .brand{display:none}
.topbar-dot{width:10px;height:10px;flex:none;margin:0 4px 0 2px;border-radius:50%;background:var(--c,var(--none))}
.topbar-actions{flex:none;display:flex;align-items:center;gap:2px}
.topbar-actions .ic-btn{background:none}
.backbar{display:none}
.topnav{display:none}
.avatar{display:inline-flex;align-items:center;gap:8px;height:var(--tap);min-width:var(--tap);flex:none;padding:0 4px;border:0;border-radius:22px;background:none;color:var(--ink);font:inherit;cursor:pointer}
.avatar-face{width:36px;height:36px;flex:none;display:flex;align-items:center;justify-content:center;border-radius:50%;background:var(--c,var(--none));color:var(--on,#fff);font-weight:700;font-size:15px}
.avatar-family{display:none;max-width:220px;font-size:14px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* The map's bar (UI redesign, phase 2): on a phone the map has no fixed header; the header
   floats over it, 8 px from the edges and below the safe area, with the brand's mark, the map's
   tools (#map-tools: «Вид карты» and the filters, map.js) and the avatar. From 1024 px it is the
   page's header, and the tools sit in the map's side panel. */
.topbar-tools{flex:1;min-width:0;display:flex;align-items:center;gap:8px}
@media (max-width:1023.98px){
  .topbar--map{position:absolute;top:calc(8px + env(safe-area-inset-top));left:8px;right:8px;height:56px;gap:8px;padding:6px 6px 6px 12px;border:0;border-radius:18px;box-shadow:0 4px 16px rgba(0,0,0,.12)}
  .topbar--map .topbar-title{display:none}
  .topbar--map .brand-word{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap}
}
/* The avatar menu (UI redesign, phase 1; by meaning, redesign 2026-10-29): a sheet from the bottom
   of a phone (.sheet), a 360 px dropdown under the avatar from 1024 px. Its head names the person
   and closes it; then come the family with the person's role, the account and settings, signing
   out, the documents. */
.menu-head{display:flex;align-items:center;gap:12px;padding:2px 2px 10px 8px;border-bottom:1px solid var(--line-2);margin-bottom:6px;min-width:0}
.menu-head .avatar-face{width:44px;height:44px;font-size:18px}
.menu-who{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.menu-name{font-weight:600;font-size:16px}
.menu-email{font-size:13px;color:var(--muted)}
.menu-name,.menu-email{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.menu-item{display:flex;align-items:center;gap:12px;width:100%;height:var(--tap);padding:0 10px;border:0;border-radius:10px;background:none;color:var(--ink);font-size:15px;text-align:left;text-decoration:none;cursor:pointer}
/* Before .menu-lang:hover, which takes the hover back off the language row. */
.menu-item:hover{background:var(--bg);color:var(--ink)}
.menu-item .ic{color:var(--muted-2)}
.menu-item>.ic:last-child:not(:first-child){width:18px;height:18px;margin-left:auto}
/* A row of two lines, a family's name and the person's role there: it grows from 44 px. */
.menu-item--two{height:auto;min-height:var(--tap);padding-top:6px;padding-bottom:6px}
.menu-family,.menu-group{display:flex;flex-direction:column;padding-bottom:6px;border-bottom:1px solid var(--line-2);margin-bottom:6px;min-width:0}
.menu-family-label{padding:4px 10px;font-size:12px;font-weight:600;color:var(--faint)}
.menu-lang{cursor:default}
.menu-lang:hover{background:none}
.menu-lang-label{flex:1}
.menu-lang-opts{display:flex;gap:2px;padding:3px;border-radius:10px;background:var(--seg)}
.menu-lang-opt{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:30px;padding:0 10px;border:0;border-radius:8px;background:none;font:inherit;font-size:13px;font-weight:600;color:var(--muted);cursor:pointer}
.menu-lang-opt--on{background:var(--surface);color:var(--ink);box-shadow:0 1px 3px rgba(0,0,0,.12);cursor:default}
.menu-foot{display:flex;align-items:center;gap:2px;padding-top:2px}
@media (min-width:1024px){
  .menu.sheet{position:absolute;top:52px;right:12px;left:auto;bottom:auto;width:360px;max-height:calc(100vh - 72px);max-height:calc(100dvh - 72px);padding:8px;border:1px solid var(--line);border-radius:14px;box-shadow:0 10px 30px rgba(0,0,0,.14)}
  .menu.sheet::before,.menu .menu-close{display:none}
}
/* The family (N3b-2a): under the person, a row of its name with the person's role there, and with
   two or more families the switcher, the active one marked, each with the role. A long name wraps
   in the row of one family; in the switcher it is cut short. */
.menu-family-name{font-weight:600;overflow-wrap:anywhere}
.menu-item--on,.menu-item--on:hover{font-weight:600;background:none;cursor:default}
.menu-family-mark{width:20px;flex:none}
.menu-family-text{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* The foot of the menu (N3b-1): the privacy policy and the terms of use, quieter than the items. */
.menu-foot-link{display:inline-flex;align-items:center;min-height:44px;padding:0 10px;border-radius:10px;font-size:13px;color:var(--muted);text-decoration:none}
.menu-foot-link:hover{background:var(--bg);color:var(--ink)}
.menu-foot-sep{color:var(--field)}
.content{flex:1;min-height:0;position:relative;overflow-x:hidden;overflow-y:auto}
.content--bleed{overflow:hidden}
.tabbar{flex:none;display:flex;background:var(--surface);border-top:1px solid var(--line);padding-bottom:env(safe-area-inset-bottom);z-index:20}
/* The tab bar: an icon above each section's name (views.Icon); a long name is cut short. */
.tab{flex:1;min-width:0;height:56px;padding:0 4px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;font-size:11px;font-weight:500;color:var(--faint);text-decoration:none;cursor:pointer}
.tab-label{max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tab:hover{color:var(--ink-2)}
.tab--on,.tab--on:hover{font-weight:600;color:var(--ink)}
/* From 1024 px the sections move into the header and the tab bar goes; the brand shows its name,
   and the avatar the family the person acts in. The title of a section page goes too (the link of
   its section is marked). A page opened from somewhere shows the brand and the sections too; its
   back link and its title move into the back bar. */
@media (min-width:1024px){
  .tabbar{display:none}
  .topbar-tools{display:none}
  .topbar{gap:18px;padding:0 16px 0 20px}
  .topbar:not(.topbar--home) .brand-word{position:static;width:auto;height:auto;overflow:visible;clip:auto;white-space:normal}
  .topbar-title{display:none}
  .topnav{display:flex;align-self:stretch;flex:1;min-width:0;gap:2px}
  .topbar--back .brand{display:flex}
  .topbar--back .topbar-back,.topbar--back .topbar-dot,.topbar--back .topbar-actions{display:none}
  .backbar{display:flex;align-items:center;gap:10px;width:100%;max-width:var(--page-w,640px);margin:0 auto;padding:16px 16px 0}
  .backbar-link{display:inline-flex;align-items:center;gap:4px;min-height:var(--tap);margin-left:-6px;padding:0 10px 0 4px;border-radius:12px;color:var(--muted-2);font-size:14px;font-weight:500;text-decoration:none}
  .backbar-link .ic{width:20px;height:20px}
  .backbar-link:hover{background:var(--surface-2);color:var(--ink)}
  .backbar-title{min-width:0;margin:0;font-size:22px;font-weight:700;letter-spacing:-0.01em;overflow-wrap:anywhere}
  .topnav-link{display:flex;align-items:center;padding:0 12px;border-bottom:2px solid transparent;font-size:14px;font-weight:500;color:var(--muted-2);text-decoration:none}
  .topnav-link:hover{color:var(--ink)}
  .topnav-link--on,.topnav-link--on:hover{border-bottom-color:var(--ink);font-weight:600;color:var(--ink)}
  /* The sections push the avatar to the right; without them (a person without a family, redesign
     2026-10-29) it keeps there by itself. */
  .avatar{margin-left:auto;padding:0 12px 0 4px}
  .avatar:hover{background:var(--surface-2)}
  .avatar-family{display:block}
}
/* The toast (WM.toast) is a manual popover where the browser has the Popover API: its rule undoes
   the popover's own styles (inset 0, auto margins, a border, fit-content, overflow auto) so the bar
   looks as it does elsewhere. It takes the width its text needs, up to the screen's less 32 px and
   560 px at most: from left 50% an auto width stops at half the screen, where a long message stood
   in five short lines on a phone, and on a wide screen a longer line is hard to read. A message of
   more than one line has lines of about one length (text-wrap, where the browser has it). It stands
   84 px above the safe area at the bottom, which the tab bar takes too (.tabbar padding-bottom), so
   on a phone with a home indicator it no longer covers the bar's top. Over a modal dialog it sits
   at the top of the screen, inside the safe area, above the tour's sheet at the bottom (.toast--top;
   on a short screen tour.css keeps a band free for it). The bar takes no taps (pointer-events:none):
   a long one stays up to 10 s (app.js toastDuration) and at its place above the tab bar covers the
   map's add-a-pin button (map.css .mp-add), whose taps would land on it. Only the button of a toast
   that can be undone (WM.undoable: «Метка удалена · Вернуть», 6 s) takes them (.toast-act),
   underlined and bold in the toast's text, 44 px to a finger; app.js lifts such a toast 12 px above
   «+ Метка» where its usual place would cover the button or come closer than that (a phone's). */
.toast{position:fixed;inset:auto auto calc(84px + env(safe-area-inset-bottom)) 50%;width:max-content;height:auto;margin:0;border:0;transform:translateX(-50%);background:var(--ink);color:#fff;padding:11px 16px;border-radius:12px;font-size:14px;box-shadow:0 8px 24px rgba(0,0,0,.25);z-index:60;max-width:min(100% - 32px,560px);overflow:visible;text-align:center;overflow-wrap:anywhere;text-wrap:balance;pointer-events:none}
.toast--top{top:calc(12px + env(safe-area-inset-top));bottom:auto}
.toast-act{position:relative;padding:0;border:0;background:none;color:#fff;font:inherit;font-weight:600;text-decoration:underline;cursor:pointer;pointer-events:auto}
.toast-act:focus-visible{outline:2px solid #fff;outline-offset:2px}
/* A toast that can be undone holds its 6 s while the pointer is over it (app.js holdUndo; the
   owner's decision of 2026-10-30). Where a pointer can hover (a mouse, a trackpad) its whole bar
   takes the pointer, so that resting on its words holds it too; it stands clear of «+ Метка»
   (app.js keepClear). On a touch screen it lets taps through as every toast does, and a finger on
   «Вернуть» holds it until the tap. */
@media (hover:hover){.toast--undo{pointer-events:auto}}

/* ---------- pages */
.page{max-width:640px;margin:0 auto;padding:22px 16px 40px;display:flex;flex-direction:column;gap:16px}
.page--walk{max-width:720px;padding-top:14px;gap:14px}
.page--wide{max-width:760px;gap:14px}
.page-head{display:flex;flex-direction:column;gap:6px}
.page-head h1{font-size:26px;font-weight:700;letter-spacing:-0.02em}
.page-sub{font-size:15px;color:var(--muted);line-height:1.45;overflow-wrap:anywhere}

/* ---------- cards and rows */
.card{background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:14px;display:flex;flex-direction:column;gap:12px}
.card--flush{padding:0;gap:0;overflow:hidden}
.card--lg{border-radius:16px;padding:16px}
.row-item{padding:12px 14px;border-bottom:1px solid var(--line-3)}

/* ---------- empty states (N2): a family without walks or dogs is told what comes next, in a
   card of the page (.card, the map's .mp-card) with the buttons that lead there */
.empty-title{font-size:17px;font-weight:700;line-height:1.3}
.empty-text{font-size:15px;color:var(--muted);line-height:1.45}
.empty-actions{display:flex;gap:8px}
.empty-actions>.btn{flex:1;min-width:0;padding:0 8px}
/* The greyhound above the words of a page with no data yet and of an error page (views.dogArt):
   decoration in the ink colour with the brand's orange collar, as tall as four lines of text. */
.empty-art{display:block;align-self:flex-start;width:auto;height:88px}
.page-head>.empty-art{margin-bottom:6px}
.stats-empty>.empty-art{height:76px} /* asleep, it lies wide */

/* ---------- buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;height:44px;padding:0 16px;border:1px solid var(--field);border-radius:12px;background:var(--surface);color:var(--ink);font-size:15px;font-weight:600;text-align:center;text-decoration:none;cursor:pointer}
.btn:hover{background:var(--btn-hover,var(--surface-2));color:var(--btn-hover-ink,var(--ink))}
.btn--primary{--btn-hover:var(--ink-2);--btn-hover-ink:#fff;border:0;background:var(--ink);color:#fff}
.btn--danger-soft{--btn-hover:var(--danger-bg);--btn-hover-ink:var(--danger);border:0;background:var(--danger-bg);color:var(--danger)}
.btn--danger{--btn-hover:var(--danger);--btn-hover-ink:#fff;border:0;background:var(--danger);color:#fff}
.btn--lg{height:52px;border-radius:14px;font-size:16px}
.btn--sm{height:34px;padding:0 11px;border-radius:9px;font-size:13px;font-weight:400}
.btn--block{display:flex;width:100%}
.btn--round{--btn-hover:var(--seg);width:32px;height:32px;flex:none;padding:0;border:0;border-radius:50%;background:var(--bg);font-size:16px;font-weight:400}
.btn:disabled,.btn:disabled:hover{cursor:default}
.btn--primary:disabled,.btn--primary:disabled:hover{background:var(--disabled)}
.link-btn{padding:0;border:0;background:none;font:inherit;font-size:13px;color:var(--ink);text-decoration:underline;cursor:pointer}
.spinner{width:18px;height:18px;flex:none;border-radius:50%;border:2px solid rgba(255,255,255,.35);border-top-color:#fff;animation:wmspin .8s linear infinite}

/* ---------- chips and segments */
.chip{position:relative;display:inline-flex;align-items:center;gap:7px;height:36px;padding:0 13px;border:1px solid var(--chip-line);border-radius:18px;background:var(--surface);color:var(--ink-2);font-size:14px;cursor:pointer}
/* A chip can also be a <label> around a checkbox or radio: the input is hidden and its state drives the look. */
.chip--on,.chip:has(>input:checked){background:var(--ink);border-color:var(--ink);color:#fff}
.chip>input{position:absolute;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
.chip:has(>input:focus-visible){outline:2px solid var(--ink);outline-offset:2px}
.chip--sm{height:32px;padding:0 12px;border-radius:16px;font-size:13px}
.chip--lg{height:38px;padding:0 14px;border-radius:19px}
.chip-dot{width:10px;height:10px;flex:none;border-radius:50%;background:var(--c,transparent)}
.chip--sm .chip-dot{width:9px;height:9px}
.chip-check{width:14px;height:14px;flex:none;border-radius:4px;border:1.5px solid currentColor;display:flex;align-items:center;justify-content:center;font-size:12px;line-height:1}
.chip--on .chip-check::after,.chip:has(>input:checked) .chip-check::after{content:"✓"}
.seg{display:flex;background:var(--seg);border-radius:10px;padding:3px;gap:2px}
.seg-btn{display:inline-flex;align-items:center;justify-content:center;height:36px;padding:0 12px;border:0;border-radius:8px;background:transparent;color:var(--muted);font-size:15px;font-weight:500;white-space:nowrap;cursor:pointer}
.seg-btn--on{background:var(--surface);color:var(--ink);font-weight:600;box-shadow:0 1px 3px rgba(0,0,0,.12)}
.seg--fill{flex:1}
.seg--fill .seg-btn{flex:1}
.seg--sm{border-radius:9px;padding:2px}
.seg--sm .seg-btn{height:30px;padding:0 10px;border-radius:7px;font-size:13px}

/* ---------- form controls */
.field{display:block;width:100%;height:44px;padding:0 12px;border:1px solid var(--field);border-radius:10px;background:var(--surface);font-size:16px;outline:none}
.textarea{display:block;width:100%;padding:10px 12px;border:1px solid var(--field);border-radius:10px;background:var(--surface);font-size:16px;resize:none;outline:none}
.field:focus,.textarea:focus{border-color:var(--ink)}
.field:focus-visible,.textarea:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.field--error,.field--error:focus{border-color:var(--danger)}
.label{font-size:13px;font-weight:600;color:var(--muted);overflow-wrap:anywhere}
.err-text{font-size:13px;color:var(--danger)}

/* ---------- badges, tags, swatches */
.badge{display:inline-block;padding:4px 8px;border-radius:6px;background:var(--seg);color:var(--muted);font-size:12px;font-weight:600}
.badge--ok{background:var(--ok-bg);color:var(--ok)}
.badge--dup{background:var(--dup-bg);color:var(--dup)}
.badge--err{background:var(--danger-bg);color:var(--danger)}
.badge--muted{background:var(--seg);color:var(--muted)}
.tag{display:inline-flex;align-items:center;height:24px;padding:0 9px;border-radius:12px;background:var(--c,var(--none));color:var(--on,#fff);font-size:12px;font-weight:600}
.swatches{display:flex;flex-wrap:wrap;gap:8px}
.swatch{position:relative;display:inline-block;width:34px;height:34px;flex:none;padding:0;border:3px solid #fff;border-radius:50%;background:var(--c,var(--none));cursor:pointer}
.swatch--sm{width:28px;height:28px}
.swatch--on,.swatch:has(>input:checked){border-color:var(--ink)}
.swatch>input{position:absolute;width:1px;height:1px;margin:0;opacity:0;pointer-events:none}
.swatch:has(>input:focus-visible){outline:2px solid var(--ink);outline-offset:2px}

/* ---------- text utilities */
.muted{color:var(--muted)}
.ellipsis{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stack{display:flex;flex-direction:column;gap:8px}
.row{display:flex;align-items:center;gap:8px}
.wrap{display:flex;flex-wrap:wrap;gap:6px}
.spacer{flex:1}

/* ---------- auth screens (AuthLayout: denied, invite, invalid invite, dev login…; the landing
   page, /login too, has its own css/landing.css) */
/* The «EN · RU» switch (N1) sits above the mosaic, at the right; its 44 px buttons overlap the
   gap below it instead of pushing the content down. It stands over the mosaic (z-index): the
   mosaic comes later, and its first row took the lowest 2 px of each button (44 × 42 to a hit
   test, the touch check of 2026-10-29). */
.auth-lang{position:relative;z-index:1;display:flex;align-items:center;justify-content:flex-end;margin:-14px -10px -30px 0;font-size:13px;font-weight:600;letter-spacing:.04em;color:var(--faint)}
.auth-lang-opt{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:44px;padding:0 8px;border:0;background:none;font:inherit;letter-spacing:inherit;color:var(--faint);cursor:pointer}
.auth-lang-opt:hover{color:var(--ink-2)}
.auth-lang-opt[aria-current]{color:var(--ink);cursor:default}
.auth-lang-sep{color:var(--field)}
.auth{flex:1;overflow:auto;display:flex;padding:32px 20px}
.auth-inner{width:100%;max-width:380px;margin:auto;display:flex;flex-direction:column;gap:28px}
.mosaic{display:grid;grid-template-columns:repeat(12,1fr);gap:3px}
.mosaic i{aspect-ratio:1;border-radius:2px;background:var(--c,var(--mosaic-0))}
.auth-brand{display:flex;flex-direction:column;gap:8px}
.auth-title{font-size:44px;font-weight:700;letter-spacing:-0.04em;line-height:1}
.auth-tagline{font-size:17px;color:var(--muted);line-height:1.4;text-wrap:pretty}
/* A notice above the landing page's sign-in button: «Your account was deleted» (N3c-3), a flash
   the landing uses up (css/landing.css places it). */
.auth-notice{padding:12px 14px;border-radius:12px;background:var(--ok-bg);color:var(--ok);font-size:15px;line-height:1.45;text-align:center;overflow-wrap:anywhere}
.auth-google{gap:12px}
.g-icon{width:24px;height:24px;flex:none;border:2px solid currentColor;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700}
.auth-card{display:flex;flex-direction:column;gap:12px;padding:20px;background:var(--surface);border:1px solid var(--line);border-radius:16px}
.auth-card--invite{gap:14px}
.err-code{font-size:13px;color:var(--faint);font-family:var(--mono)}
.auth-card-title{font-size:20px;font-weight:700;overflow-wrap:anywhere}
.auth-card-title--invite{line-height:1.25}
.auth-card-text{font-size:15px;color:var(--muted);line-height:1.45;overflow-wrap:anywhere}
.auth-card-text--plain{line-height:normal}
.auth-facts{display:grid;grid-template-columns:auto minmax(0,1fr);gap:4px 12px;margin:0;font-size:15px;line-height:1.45}
.auth-facts dt{color:var(--muted)}
.auth-facts dd{margin:0;color:var(--ink);font-weight:600;overflow-wrap:anywhere}
/* The invite page of a person in two families already (spec 2026-10-28 §2.2): the message, then a
   row a family, its name beside its 44 px «Leave the family». The name takes what the button
   leaves and breaks anywhere, so 60 letters without a space wrap inside the row on a 360 px
   phone, and nothing scrolls sideways. */
.auth-full-title{font-size:16px;font-weight:700;line-height:1.3;overflow-wrap:anywhere}
.auth-families{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}
.auth-family{display:flex;align-items:center;gap:12px;min-width:0}
.auth-family-name{flex:1 1 auto;min-width:0;font-size:15px;font-weight:600;line-height:1.45;color:var(--ink);overflow-wrap:anywhere}
.auth-family-leave{flex:none}
/* Under the invite page's sign-in button, the line that accepts the terms (N3b-1; the landing
   page, which has its own css/landing.css, sets it under its button too). Every signed-out page
   ends with the links to the documents and the contact (.public-foot, also the foot of the
   documents themselves and of the landing page). */
.auth-legal{font-size:13px;color:var(--muted);line-height:1.45;text-align:center;text-wrap:pretty}
.auth-legal a{color:inherit}
.public-foot{display:flex;flex-wrap:wrap;justify-content:center;column-gap:4px;font-size:13px}
.public-foot a{display:inline-flex;align-items:center;min-height:44px;padding:0 8px;color:var(--muted);overflow-wrap:anywhere}
.public-foot a:hover{color:var(--ink)}
.public-foot a[aria-current]{color:var(--ink);text-decoration:none}
.accounts{display:flex;flex-direction:column;gap:6px}
.acct{display:flex;align-items:center;gap:12px;width:100%;padding:10px 8px;border:0;border-radius:12px;background:none;color:var(--ink);text-align:left;cursor:pointer}
.acct:hover{background:var(--bg)}
.acct-avatar{width:38px;height:38px;flex:none;border-radius:50%;background:var(--c,var(--faint));color:var(--on,#fff);display:flex;align-items:center;justify-content:center;font-weight:700}
.acct-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}
.acct-name{font-size:15px;font-weight:600}
.acct-email{font-size:13px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acct-note{font-size:12px;color:var(--faint)}

/* ---------- the redesign's components (2026-10-17, phase 1): an icon (views.Icon) in the
   colour of its text, an icon button as large as a tap, a visually hidden text, a list of rows
   in a card, and a sheet: a panel from the bottom of a phone over a scrim that dims the page
   (from 1024 px each user of .sheet places it, and the scrim goes). */
.ic{width:22px;height:22px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.ic-btn{display:inline-flex;align-items:center;justify-content:center;width:var(--tap);height:var(--tap);flex:none;padding:0;border:0;border-radius:50%;background:var(--line-3);color:var(--ink);text-decoration:none;cursor:pointer}
.ic-btn:hover{background:var(--seg);color:var(--ink)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.list{background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-card);overflow:hidden}
.list>*+*{border-top:1px solid var(--line-3)}
.list-label{margin:0 0 6px 4px;font-size:12px;font-weight:600;color:var(--muted)}
.list-row{display:flex;align-items:center;gap:12px;width:100%;min-height:56px;padding:8px 14px;border:0;background:none;color:var(--ink);font:inherit;font-size:15px;font-weight:500;text-align:left;text-decoration:none;cursor:pointer}
.list-row:hover{background:var(--surface-2);color:var(--ink)}
/* The card clips its rows (its rounded corners), so a row's focus ring is drawn inside it. */
.list-row:focus-visible{outline:2px solid var(--ink);outline-offset:-2px}
.list-row .ic{color:var(--muted-2)}
.list-text{display:flex;flex-direction:column;gap:1px;flex:1;min-width:0}
.list-sub{font-size:13px;font-weight:400;color:var(--muted);overflow-wrap:anywhere}
.list-row--danger,.list-row--danger:hover,.list-row--danger .ic{color:var(--danger)}
/* .list-row takes every border off, so two link rows in a row get the list's line back. */
.list>.list-row+.list-row{border-top:1px solid var(--line-3)}
.account-profile .avatar-face{width:44px;height:44px;font-size:18px}
.sheet{position:fixed;left:0;right:0;bottom:0;z-index:61;max-height:calc(100vh - 48px);max-height:calc(100dvh - 48px);overflow-y:auto;display:flex;flex-direction:column;background:var(--surface);border-radius:var(--r-sheet) var(--r-sheet) 0 0;padding:6px 8px calc(10px + env(safe-area-inset-bottom));box-shadow:0 -8px 30px rgba(0,0,0,.18)}
.sheet::before{content:"";flex:none;width:36px;height:4px;margin:4px auto 6px;border-radius:2px;background:var(--field)}
.sheet>*{flex:none}
.sheet-scrim{position:fixed;inset:0;z-index:60;background:var(--scrim)}
@media (min-width:1024px){
  .sheet-scrim{display:none}
}

/* ---------- dialog sheets (UI redesign, phases 2–3; WM.sheet): a <dialog> from the bottom of a
   phone over the scrim, in the middle from 1024 px. An inner box (.dlg-in) fills its content box,
   so a click on the dialog itself is a click on the scrim; its body scrolls, its head and its
   foot stay. Only an open dialog gets a display: a closed one keeps the browser's display:none. */
.dlg{max-width:none;max-height:none;padding:0;border:0;background:transparent;color:var(--ink);overflow:visible}
.dlg::backdrop{background:var(--scrim)}
.dlg[open]{position:fixed;inset:auto 0 0;margin:0;width:100%;display:flex}
.dlg-in{flex:1;min-width:0;max-height:calc(100dvh - 48px);display:flex;flex-direction:column;padding-bottom:env(safe-area-inset-bottom);border-radius:var(--r-sheet) var(--r-sheet) 0 0;background:var(--surface);box-shadow:0 -8px 30px rgba(0,0,0,.18)}
.dlg-in::before{content:"";flex:none;width:36px;height:4px;margin:8px auto 2px;border-radius:2px;background:var(--field)}
.dlg-head{flex:none;display:flex;align-items:center;gap:4px;padding:4px 8px 6px 16px}
.dlg-title{flex:1;min-width:0;margin:0;font-size:18px;font-weight:700}
.dlg-body{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;display:flex;flex-direction:column;gap:18px;padding:4px 16px 16px}
.dlg-foot{flex:none;display:flex;gap:8px;padding:10px 16px 12px;border-top:1px solid var(--line-3)}
@media (min-width:1024px){
  .dlg[open]{inset:0;margin:auto;width:min(440px,calc(100% - 32px))}
  .dlg-in{max-height:calc(100dvh - 64px);padding-bottom:0;border-radius:var(--r-card);box-shadow:var(--shadow-pop)}
  .dlg-in::before{display:none}
}

/* ---------- details sheets (UI redesign, phase 3; WM.details): the sheets that hold the
   server's forms (a person's actions, the family's name) are <details data-dsheet>, so the page
   works without JavaScript. On a phone the panel is a sheet at the bottom over a scrim, which is
   the summary's ::before: a tap on it toggles the disclosure as a tap on the summary does. From
   1024 px the panel is a popover under its summary. */
.dsheet{position:relative}
.dsheet>summary{list-style:none;cursor:pointer}
.dsheet>summary::-webkit-details-marker{display:none}
.dsheet-panel{display:flex;flex-direction:column;gap:14px;padding:0 16px 16px;background:var(--surface);color:var(--ink);text-align:left;cursor:auto}
.dsheet-head{display:flex;align-items:center;gap:12px}
.dsheet-title{flex:1;min-width:0;margin:0;font-size:17px;font-weight:700}
@media (max-width:1023.98px){
  .dsheet[open]>summary::before{content:"";position:fixed;inset:0;z-index:60;background:var(--scrim);cursor:default}
  .dsheet[open]>.dsheet-panel{position:fixed;left:0;right:0;bottom:0;z-index:61;max-height:calc(100dvh - 48px);overflow-y:auto;overscroll-behavior:contain;padding-bottom:calc(16px + env(safe-area-inset-bottom));border-radius:var(--r-sheet) var(--r-sheet) 0 0;box-shadow:0 -8px 30px rgba(0,0,0,.18)}
  .dsheet[open]>.dsheet-panel::before{content:"";flex:none;align-self:center;width:36px;height:4px;margin-top:8px;border-radius:2px;background:var(--field)}
}
@media (min-width:1024px){
  .dsheet[open]>.dsheet-panel{position:absolute;top:calc(100% + 6px);right:0;z-index:40;width:360px;max-width:calc(100vw - 32px);padding-top:14px;border:1px solid var(--line-2);border-radius:var(--r-card);box-shadow:var(--shadow-pop)}
}

/* ---------- touch: 44 px hit areas (WCAG 2.5.5; audit 2026-10-07, finding 11). With a coarse
   pointer the small controls keep the size they are drawn at, and an invisible ::after makes
   what a finger hits at least 44 px each way, centred on the control; the gaps between them
   grow so that no two hit areas overlap. Page stylesheets add their own controls the same way. */
@media (pointer:coarse){
  .chip,.seg-btn,.btn--sm,.btn--round,.swatch,.avatar,.brand,.menu-lang-opt,.toast-act,.topbar-family{position:relative}
  .chip::after,.seg-btn::after,.btn--sm::after,.btn--round::after,.swatch::after,.avatar::after,.brand::after,.menu-lang-opt::after,.toast-act::after,.topbar-family::after{content:"";position:absolute;top:calc(50% - 22px);bottom:calc(50% - 22px);left:min(0px,calc(50% - 22px));right:min(0px,calc(50% - 22px))}
  .chip--sm{height:36px}
  .seg--sm .seg-btn{min-width:44px}
  .wrap{gap:8px}
  /* Each swatch sits in a 44 px cell, its hit area: two rows of four on a phone, where eight
     cells take more than the line, one row where they fit. */
  .swatches{display:grid;grid-template-columns:repeat(4,44px);grid-auto-rows:44px;gap:0}
  .swatch{justify-self:center;align-self:center}
  /* A link button stands in a line of text: it takes the height itself, its text at the end and
     at the bottom, on the line of the text beside it. */
  .link-btn{display:inline-flex;align-items:flex-end;justify-content:flex-end;min-width:44px;min-height:44px}
}
@media (pointer:coarse) and (min-width:480px){
  .swatches{grid-template-columns:repeat(8,44px)}
}
