/* ui.css — InviteFromMe's ONE design (David, 2026-09-26: "keep a common design and make sure anything that gets
   added uses that design"). Every page loads it first (src/worker.js shell, src/portal/shell.js, src/admin/shell.js).
   Modelled on StaySearch: small pieces that expand for more; three clear levels on a card (the name and its key fact;
   one small grey facts line; pills); each card its own surface with space between.

   The HTML comes from the helpers in public/ui.js (backLink, pill, pills, facts, info, cardHead, …): build pages
   from them, never by hand. tests/design.test.mjs fails when a converted page sets its own font sizes or colours,
   builds its own card or back link, or a page doesn't load this file.

   Sizes only from the type scale below (rem, so the text-size control scales them); colours only from the tokens.
   Light and dark: [data-theme] on <html> (worker.js HEAD_SCRIPT).

   CONSISTENCY RULES (David, 2026-09-27: "we need to be consistent in all places, we use the same nomenclature, same
   UI styles"). New or odd screens follow the rest of the product; where screens disagree, the pattern most screens
   already use wins (counted, not guessed: the 2026-09-27 audit, ~/Downloads/invitefromme-consistency/report.md).
   David's four decisions (2026-09-27: "good, your recommendations") are written into rules 1, 5 and 9.
   1. Everything is a page ("yes, everything should be page"). Nothing opens over the page: no <dialog>, sheet,
      lightbox, panel, or native confirm()/alert()/prompt(). Something that needs its own screen gets its own address
      and a back link (Tables and seating is the model). Toasts are fine. Small menus are controls,
      not screens, and stay menus: the Aa display menu, the vendor's avatar menu, the admin's phone drawer, the date
      pickers, the map's pin pop-ups — closing with the word "Close", never ✕. The guest's answer is a page
      (/r/<token>/answer, "‹ Back to the invitation", Send pinned at the foot).
   2. The return control: one per page, the first thing under the top bar, top-left, above the title:
      backLink() "‹ Back to <where>", naming where it goes even when opened fresh (never a bare "‹ Back"). Never a
      second copy at the foot, never inside a notice, never "Exit". A host step has no ‹ (David, 2026-09-30): the logo
      goes to Your invitations, and the party's name goes to the page for where the party stands (public/phase.js). A
      page below a step has no party on the header. Top-level pages (home, Your invitations, a guest's invitation, a
      portal or admin section or tab, sign in, join) have none.
   3. Closing: "Close" closes what was opened in place (toggle(): the opener's words turn into Close, with its
      chevron). "Cancel" leaves a form without saving (secondary, left of Save). No ✕, "Dismiss" or "Exit" for either;
      ✕ only takes one thing out of a list (a name chip).
   4. Opening in place: ⓘ (info()) for one line with the rest on demand; ui-open for a part that opens; an expandable
      card is details.ui-card with its chevron. Never the browser's ▶ triangle.
   5. A flow in steps: the steps as dots on .ui-track under the page head; one pinned bar (.ui-actbar): Back
      (secondary, left, no ‹, not on the first step) and the primary on the right; the last step's primary says what it
      does (Print, Send, Send for review). Forward: "Next: <the next step's name>" ("Next: Guests"), in every flow.
   6. A page's head: ui-pagehead: the back link, the title (.ui-h1, sans), its count or pill beside it, at most one
      main action, one lead line. Sections: .ui-h2. Serif is the brand's name only. On a host step the party's name
      is in the pill and the step's heading is .ui-h2.
   7. Buttons: .btn is the one main action of an area; .btn.secondary the rest; .btn.danger (or secondary.danger) for
      what removes; a button that reads as a link is .ui-link. The main action sits right of Cancel/Back. Words:
      Save (not "Save the note"); Remove (Delete only for "for good": a party, a photo); Change for changing a thing
      (proposed: no clear pattern yet). A printout's Print is a .btn too.
   8. Cards .ui-card; pills .ui-pill with its tones; empty .ui-empty (what fills it, the next step); a result on the
      page .ui-msg / a notice .ui-banner; a toast is .ui-toast (errors stay until Close). Nothing from app.css's old
      looks (.card, .pill, .linkish, .hint, .muted, .eyebrow, .toast).
   9. Destructive actions ask first, in place: the row or card opens to say what happens, with Cancel and the red
      button. No dialog. The biggest ("Delete this party", "Close my account") get their own confirm page.
   9b. Changes not saved yet (David, 2026-09-29: "If people make edits and dont hit save we need a warning"): every form
      with a Save button is marked changed as the host types; leaving it (another step, a link, back) first asks, in
      place, "Save your changes?" with Don't save and Save (public/ui.js unsaved, askHere); closing the tab gets the
      browser's own question. A form's Cancel (data-nosave) never asks. Server-drawn forms: <form data-unsaved>.
   10. Pages open in the same tab. Only the printouts (guest list, QR card, name tags and table cards) and the TV
      screen open in a new tab (they carry <meta name="ifm-trail" content="off">), from every place that links them.
   11. Every field has a visible label (ui-field, label for=); a placeholder is only an example. (The Details card,
      typed right on the invitation, is the one exception.)
   12. Languages (David, 2026-09-27: "want to make sure we are thinking about i18n and l12n"; "yes spanish and portuguese
       first"). Every word a person reads comes from the one word list, never typed into a page's code; a sentence is
       written whole (no gluing fragments: other languages reorder words and count plurals differently); dates, times,
       numbers and money are formatted for the reader's language (Intl, never a fixed "en-US"); a party has its own
       time zone (never a fixed Eastern offset); no words baked into pictures; <html lang> says the page's language.
       English first; Spanish and Portuguese next, starting with the guest's pages (the invitation, the answer, the
       photos), chosen from the guest's browser with a switch to change it. The host's own words on an invitation are
       theirs and aren't machine-translated. How languages flow (David, 2026-09-27: "if a host selects spanish can they
       select which language invite to send out, then when the recipient clicks the RSVP the language auto selects to the
       type they got. If they got the wrong kind they should be able to switch to a different language"): the host
       chooses their own language for the host app, and chooses the language each invitation goes out in; the guest's
       link carries that language, so the guest's pages open in it; a switch on every guest page changes it, and the
       guest's choice sticks for that guest. The party has a language and each guest can be set differently ("they
       select a language for the party, but each guest can be overridden"). The host's own words are never translated
       by us; the host can add their own version in another language ("we don't try to translate hosts words, but they
       can provide other language equivalents"); our words — labels like Date, Where, the buttons — are translated per
       language ("For normal vocabulary we will do the translation per language"). Dates and times on a
       guest's page are written that language's way, read from what the host typed (David, 2026-09-27: "yes we need to be
       i18n ready (dates, etc)"). A guest's own choice of language wins over a later change by the host ("yes"). The vendor portal and the operator pages stay English only (David, 2026-09-27: "I am ok with only english in vendor portal and for sure for admin"); their words still live in word lists, but no Spanish or Portuguese is planned for them. Legal pages (Terms, Privacy, the vendor terms) stay in English only, so a translation can never misstate them (David, 2026-09-28: "all legal pages kept in english only"); a reader in another language gets one line in their language saying the English version applies, and the "you agree" notices elsewhere stay in the reader's language. Right-to-left languages (Arabic, Hebrew) are not planned (David, 2026-09-27: "we can skip arabic and hebrew for now"); the next language added is Haitian Creole, as the test of adding one. Built for the guest's pages (fix group
       5): the words are shared/words.js (English, Spanish, Portuguese as spoken in Brazil: pt-BR); a guest's page opens
       in the guest's language (guests.lang), else the party's (extras.lang), else the browser's, else English (a party
       with no language never falls back to English before the browser). The language choice is in the Aa display menu
       (David, 2026-09-27: "for the language selector that should be in the Aa setting"): "Language" beside Theme and
       Text size, on every page that has one (a guest's pages, a party's photo pages, the group link and its "tap your
       name" page), each language named in its own words (English · Español · Português). There the Aa button shows the
       page's language as its two-letter code, which reads the same in every language ("Aa · EN", "Aa · ES",
       "Aa · PT"), and says the name in full ("Display and language: Español"); elsewhere it's just "Aa". It saves on the guest on a guest's own
       link, and in a cookie kept to /p/<id> on a party's pages (the group link is shared, so it never changes a guest).
       Built for the host (languages part 2): the party's language in Details, each guest's on the guest list; a guest's
       own choice wins over a later change by the host (David: "yes"), and the list says so ("Chose Español
       themselves"); the messages the host sends go out in each guest's language (our words translated, theirs as they
       wrote them). Built next (languages part 2, build 2): the host can add their own Spanish or Portuguese version
       of their words (/h/<key>/words/<lang>; never machine-translated), which that language's guests see; our
       suggested questions, choices and sign-offs show in each reader's language until the host changes them
       (recognized by every English wording we've ever used: OUR_WORDINGS in shared/words.js); and a built-in card is
       drawn once per language the guests use, each guest getting theirs (David: "draw one card per language the
       party's guests actually use"). The Aa menu's footer says the theme and size stay on this device and the language
       with the invitation. The host app's own words (the host-words build, 2026-09-27): public/host-words.js, one file
       served to the browser (the host app, /my, /start, Tables and seating) and read by the server's host pages, in
       whole sentences, in English, Spanish and Portuguese (the host-languages build); its helpers format dates, times,
       numbers and money through Intl, times where the party is. The host picks their own language in the Aa menu on
       their pages (this browser; the browser's language to start); it never changes what guests get. Each language's
       words are their own files (shared/words/<code>.js, public/host-words/<code>.js), listed once in
       public/languages.js. Adding a language: docs/adding-a-language.md, step by step.
       tests/design.test.mjs fails when a host script types English into its code. */

/* ---------- colours (light, then dark) ---------- */
:root,:root[data-theme="light"]{--bg:#eee6d9;--card:#fff;--ink:#2b2118;--head:#6b3f18;--muted:#5f5144;--accent:#a8581a;--accent-ink:#fff;--accent-bg:#fdf0e2;--line:#e4d8c8;--ok:#2e7d32;--ok-bg:#e8f5e9;--warn:#9a5b00;--warn-bg:#fff4e0;--bad:#b3261e;--focus:#1f6fb0;--shadow:rgba(60,40,20,.08);color-scheme:light}
:root[data-theme="dark"]{--bg:#0e0c0a;--card:#2a241e;--ink:#f3eadf;--head:#f2c996;--muted:#c9b8a5;--accent:#f0a35a;--accent-ink:#1d1409;--accent-bg:#33271c;--line:#3b3129;--ok:#8fd694;--ok-bg:#1f3322;--warn:#f5c26b;--warn-bg:#3a2d17;--bad:#ff9b8a;--focus:#6cb6f0;--shadow:rgba(0,0,0,.35);color-scheme:dark}
:root,:root[data-theme="light"]{--info:#1f5f99;--info-bg:#e6f0fa;--bad-bg:#fdecea}
:root[data-theme="dark"]{--info:#8cc4f5;--info-bg:#1a2733;--bad-bg:#3a1f1b}
/* Depth (David, 2026-09-26: "the UI is too flat… provide some depth"): three levels. The page (--bg, a step deeper
   than a card); what sits on it (cards, tables, the search, chips: --e1); what's lifted or floats (a card opened or
   under the pointer, pop-ups, dialogs: --e2, --e3). In dark, shadows barely show, so a raised surface is also lighter
   (--card-hi) with a faint light rim on its top edge. */
:root,:root[data-theme="light"]{--e1:0 1px 2px rgba(60,40,20,.09),0 4px 14px rgba(60,40,20,.11);--e2:0 2px 5px rgba(60,40,20,.1),0 14px 32px rgba(60,40,20,.18);--e3:0 16px 40px rgba(40,25,10,.24);--card-hi:#fff;--rim:0 0 #0000}
:root[data-theme="dark"]{--e1:0 1px 2px rgba(0,0,0,.5),0 4px 12px rgba(0,0,0,.35);--e2:0 2px 6px rgba(0,0,0,.55),0 16px 34px rgba(0,0,0,.5);--e3:0 18px 44px rgba(0,0,0,.65);--card-hi:#352d25;--rim:inset 0 1px 0 rgba(255,255,255,.08)}
:root{
  /* the type scale: the only font sizes a page uses */
  --fs-xs:.78rem;   /* pills */
  --fs-s:.875rem;   /* the facts line, notes, the back link */
  --fs-m:1rem;      /* text inside cards */
  --fs-l:1.125rem;  /* names on cards; body text */
  --fs-xl:1.35rem;  /* the key fact; a section's heading */
  --fs-2xl:1.9rem;  /* the page title */
  --sans:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,"PingFang SC","Hiragino Sans GB","Noto Sans CJK SC","Noto Sans SC","Source Han Sans SC","Microsoft YaHei","PingFang TC","Noto Sans CJK TC","Noto Sans TC","Source Han Sans TC","Microsoft JhengHei",sans-serif;
  --r-s:.5rem;--r-m:.8rem;--r-l:1rem;
  /* a quiet surface one step off the card (the control zone, an opened panel), in every theme */
  --zone:color-mix(in oklab,var(--card) 94%,var(--ink) 6%);
  --line-strong:color-mix(in oklab,var(--line) 70%,var(--ink) 30%);
}

/* ---------- the back link: every one on the site is this, and public/nav.js takes it where you came from ---------- */
.ui-back{display:inline-flex;align-items:center;min-height:2.75rem;font:600 var(--fs-s)/1.2 var(--sans);color:var(--focus);text-decoration:none}
.ui-back:hover{text-decoration:underline}
.ui-back:focus-visible{outline:3px solid var(--focus);outline-offset:2px;border-radius:.3rem}

/* ---------- busy: a button waiting on the server (public/busy.js; David, 2026-09-30: "spinners to any function that
   will take more than 2 seconds"). After 500 ms: the label gives way to a spinner, the button keeps its width; after 3 s,
   a short line after it. With reduced motion, a still ring. ---------- */
.ui-busy{position:relative;min-width:var(--busy-w);color:transparent!important;cursor:progress}
.ui-busy>:not(.ui-spin):not(.ui-busy-note){visibility:hidden}
.ui-spin{position:absolute;inset:0;margin:auto;width:1.1em;height:1.1em;box-sizing:border-box;border-radius:50%;border:2px solid var(--busy-c,var(--accent));border-right-color:transparent;animation:ui-spin .8s linear infinite}
@keyframes ui-spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.ui-spin{animation:none;border-style:dotted;border-right-color:var(--busy-c,var(--accent))}}
/* the line after 3 s: under the button (above it in a bar pinned to the foot), nothing around it moves */
.ui-busy-note{position:absolute;left:50%;top:calc(100% + .3rem);transform:translateX(-50%);z-index:2;white-space:nowrap;pointer-events:none;padding:.1rem .5rem;border-radius:var(--r-s);background:var(--card);font:600 var(--fs-xs)/1.3 var(--sans);color:var(--muted);box-shadow:var(--e1)}
.ui-actbar .ui-busy-note{top:auto;bottom:calc(100% + .4rem)}

/* ---------- text ---------- */
.ui-h2{font:700 var(--fs-xl)/1.25 var(--sans);color:var(--ink);letter-spacing:-.01em;margin:1.6rem 0 .6rem}
.ui-label{font:700 var(--fs-xs)/1.3 var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--muted);margin:1.3rem 0 .5rem}
.ui-title,.ui-card .ui-title{font:700 var(--fs-l)/1.3 var(--sans);color:var(--ink);margin:0;overflow-wrap:anywhere}
.ui-key{font:800 var(--fs-xl)/1.1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.ui-facts{display:block;font:400 var(--fs-s)/1.4 var(--sans);color:var(--muted);font-variant-numeric:tabular-nums;margin:0;overflow-wrap:anywhere}
.ui-text{font-size:var(--fs-m);color:var(--ink);margin:.5rem 0;overflow-wrap:anywhere}   /* a long email address wraps, never runs out of its card */
.ui-note{font-size:var(--fs-s);color:var(--muted);margin:.5rem 0}
.ui-strong{font-weight:700;color:var(--ink)}
.ui-msg{font:600 var(--fs-m)/1.4 var(--sans);border-left:3px solid;padding:.5rem .8rem;border-radius:0 var(--r-s) var(--r-s) 0;margin:.6rem 0;background:var(--zone)}
.ui-msg.ok{border-color:var(--ok);color:var(--ok)}.ui-msg.err{border-color:var(--bad);color:var(--bad)}

/* ---------- pills: small bordered words (Ad, an offer, Takes vouchers, a badge, where a request stands) ---------- */
.ui-pills{display:flex;flex-wrap:wrap;gap:.3rem;margin:.35rem 0 0}
.ui-pill{display:inline-flex;align-items:center;font:600 var(--fs-xs)/1.35 var(--sans);border:1px solid var(--line-strong);border-radius:999px;padding:.08rem .55rem;background:var(--card);color:var(--ink);white-space:nowrap}
.ui-pill.ad{background:var(--ink);border-color:var(--ink);color:var(--card);font-weight:800;letter-spacing:.03em}
.ui-pill.accent{background:var(--accent-bg);border-color:var(--accent);color:var(--head)}
.ui-pill.ok{background:var(--ok-bg);border-color:color-mix(in oklab,var(--ok) 55%,var(--line));color:var(--ok)}
.ui-pill.warn{background:var(--warn-bg);border-color:color-mix(in oklab,var(--warn) 55%,var(--line));color:var(--warn)}
.ui-pill.quiet{background:transparent;border-style:dashed;color:var(--muted);font-weight:500}
.ui-pill.info{background:var(--info-bg);border-color:color-mix(in oklab,var(--info) 55%,var(--line));color:var(--info)}
.ui-pill.bad{background:var(--bad-bg);border-color:color-mix(in oklab,var(--bad) 55%,var(--line));color:var(--bad)}
.ui-pill[hidden]{display:none}

/* ---------- ⓘ: one line, and the rest when you want it ---------- */
.ui-info{margin:.6rem 0;font-size:var(--fs-s);color:var(--muted)}
.ui-info>summary{list-style:none;cursor:pointer;display:inline;color:inherit;font-weight:400}
.ui-info>summary::-webkit-details-marker{display:none}
.ui-info>summary:focus-visible{outline:3px solid var(--focus);outline-offset:2px;border-radius:.3rem}
.ui-i{display:inline-block;margin-left:.3rem;color:var(--focus);font-weight:700;font-style:normal}
.ui-info[open] .ui-i{color:var(--ink)}
.ui-info-body{margin:.5rem 0 0;padding:.5rem .8rem;border-left:2px solid var(--line-strong);color:var(--muted);font-size:var(--fs-s)}
.ui-info-body p{margin:0 0 .5rem}.ui-info-body p:last-child{margin-bottom:0}

/* ---------- long text on a card: the legal pages, Help, How ranking works (fix group 6). Sections are .ui-h2; a list
   of points with a tick is .ui-ticks ---------- */
.ui-prose{font-size:var(--fs-m);line-height:1.55;color:var(--ink)}
.ui-prose p{margin:.65rem 0}
.ui-prose ul,.ui-prose ol{margin:.6rem 0;padding-left:1.25rem}.ui-prose li{margin:.4rem 0}
.ui-prose a{color:var(--focus)}
.ui-prose .ui-h2{font-size:var(--fs-l);margin:1.5rem 0 .4rem}
.ui-prose>:first-child{margin-top:0}.ui-prose>:last-child{margin-bottom:0}   /* after .ui-h2, which would win otherwise */
.ui-ticks{list-style:none;padding-left:0!important}
.ui-ticks li{position:relative;padding-left:1.5rem}
.ui-ticks li::before{content:"✓";position:absolute;left:0;top:0;font-weight:800;color:var(--ok)}
/* /start (from an AI assistant): what each file added (each line says ✓ or ✗ itself), its picture, its wide buttons */
.ui-filenotes{list-style:none;padding:0;margin:.4rem 0 .8rem}.ui-filenotes li{padding:.25rem 0;font-size:var(--fs-m)}
.ui-startpic{display:block;max-width:100%;border-radius:var(--r-l);margin:0 auto 1rem;box-shadow:var(--rim),var(--e2)}
.btn.ui-wide{display:block;width:100%;font-size:var(--fs-l);padding-top:.8rem;padding-bottom:.8rem}
/* a vendor's second step of sign-in (/vendors/verify, public/vendor.js): the authenticator app's QR code and key, and the
   backup codes, shown once */
.ui-totp{margin-top:.8rem}.ui-qr{width:12rem;max-width:70%;background:#fff;padding:.5rem;border-radius:var(--r-s)}.ui-qr svg{width:100%;height:auto;display:block}
.ui-codes{columns:2;list-style:none;padding:0;margin:0}.ui-codes li{padding:.25rem 0}
.ui-codes code,code.ui-key{font:600 var(--fs-l)/1.3 ui-monospace,Menlo,monospace;letter-spacing:.05em}   /* the authenticator key only (it was every .ui-key: a price on a vendor card came out monospace) */
/* ---------- cards: each its own surface, space between ---------- */
.ui-card{background:var(--card);border:1px solid var(--line);border-radius:var(--r-l);box-shadow:var(--rim),var(--e1);margin:0 0 .75rem;transition:box-shadow .15s ease,transform .15s ease,background-color .15s ease}
details.ui-card:not([open]):hover{box-shadow:var(--rim),var(--e2);transform:translateY(-1px)}
details.ui-card[open]{box-shadow:var(--rim),var(--e2);background:var(--card-hi)}
@media (prefers-reduced-motion:reduce){.ui-card{transition:none}details.ui-card:not([open]):hover{transform:none}}
.ui-card.pad{padding:1rem 1.1rem}
.ui-card.quiet{border-style:dashed;box-shadow:var(--rim),0 1px 3px var(--shadow)}
/* An expandable card: the summary row (a photo, the three levels, a chevron); tapped open, the rest below a line. */
details.ui-card{overflow:hidden}
.ui-sum{color:var(--ink);font-weight:400;display:flex;align-items:flex-start;gap:.8rem;padding:.8rem 1rem;cursor:pointer;list-style:none;min-height:44px}
.ui-sum::-webkit-details-marker{display:none}
.ui-sum:focus-visible{outline:3px solid var(--focus);outline-offset:-3px}
details.ui-card:hover{border-color:var(--line-strong)}
.ui-thumb{width:3.75rem;height:3.75rem;flex:none;object-fit:cover;border-radius:var(--r-s);background:var(--zone)}
.ui-main{flex:1;min-width:0;display:flex;flex-direction:column;gap:.15rem}
.ui-head{display:flex;align-items:baseline;justify-content:space-between;gap:.3rem .8rem;flex-wrap:wrap}
.ui-chev{flex:none;width:.55rem;height:.55rem;border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);transform:rotate(45deg);margin:.55rem .2rem 0}
details[open]>.ui-sum .ui-chev{transform:rotate(-135deg);margin-top:.8rem}
.ui-body{padding:.2rem 1rem 1rem;border-top:1px solid var(--line);font-size:var(--fs-m)}
.ui-body>:first-child{margin-top:.8rem}
.ui-photos{display:grid;grid-template-columns:repeat(3,1fr);gap:.4rem}
.ui-photos img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-s)}
.ui-list{list-style:none;padding:0;margin:.5rem 0}
.ui-list>li{padding:.6rem 0;border-bottom:1px solid var(--line)}.ui-list>li:last-child{border-bottom:0}
.ui-bullets{margin:.3rem 0 .6rem;padding-left:1.1rem}.ui-bullets li{margin:.25rem 0}
.ui-callout{background:var(--accent-bg);border:1px solid var(--accent);border-radius:var(--r-s);padding:.5rem .75rem;margin:.6rem 0;font-size:var(--fs-m)}
.ui-callout[hidden]{display:none}
/* "More (6)": the rest of a list, one tap away */
.ui-more>summary{list-style:none;cursor:pointer;display:inline-flex;align-items:center;min-height:44px;margin:.1rem 0 .6rem;font:600 var(--fs-s)/1 var(--sans);color:var(--focus)}
.ui-more>summary::-webkit-details-marker{display:none}
.ui-more>summary::after{content:"";width:.4rem;height:.4rem;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);margin:-.2rem 0 0 .5rem}
.ui-more[open]>summary::after{transform:rotate(-135deg);margin-top:.2rem}
/* A button (or link) that opens something says so, and says how to close it: toggle() in public/ui.js gives it both
   labels; an arrow flips with it. */
details:not([open])>summary .ui-opened,details[open]>summary .ui-shut{display:none}
[aria-expanded="false"]>.ui-opened,[aria-expanded="true"]>.ui-shut{display:none}   /* the same for a button that opens something below it (Your invitations: + New invitation) */
details>summary.btn{list-style:none;display:inline-flex;align-items:center;gap:.5rem}
details>summary.btn::-webkit-details-marker{display:none}
details>summary.btn::after{content:"";width:.45rem;height:.45rem;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);margin-top:-.25rem}
details[open]>summary.btn::after{transform:rotate(-135deg);margin-top:.25rem}

/* ---------- choosing: a segmented pair (Best match / Nearest), chips (browse by kind) ---------- */
.ui-seg{display:inline-flex;border:1px solid var(--line-strong);border-radius:999px;overflow:hidden;margin:.2rem 0 .4rem;background:var(--card);box-shadow:0 1px 3px var(--shadow)}
.ui-seg a{font:600 var(--fs-s)/1 var(--sans);color:var(--muted);text-decoration:none;padding:.55rem .95rem;min-height:2.4rem;display:inline-flex;align-items:center}
.ui-seg a[aria-current="true"],.ui-seg a[aria-current="page"]{background:var(--ink);color:var(--card)}
.ui-chips{display:flex;flex-wrap:wrap;gap:.4rem;margin:.4rem 0}
.ui-chip{font:600 var(--fs-s)/1 var(--sans);color:var(--ink);background:var(--card);border:1px solid var(--line-strong);border-radius:999px;padding:.55rem .9rem;text-decoration:none;display:inline-flex;align-items:center;box-shadow:0 1px 2px var(--shadow)}
.ui-chip[aria-current="true"]{border-color:var(--accent);background:var(--accent-bg)}
.ui-chip-n{font-weight:700;color:var(--muted);margin-left:.3rem}
.ui-chip[aria-current="true"] .ui-chip-n{color:var(--ink)}
/* A search: one line, Enter searches; a small button at its end for a mouse. */
.ui-search{display:flex;align-items:center;background:var(--card);border:1px solid var(--line-strong);border-radius:999px;padding:0 .3rem 0 1rem;margin:0 0 .6rem;min-height:2.9rem;box-shadow:var(--rim),var(--e1)}
.ui-search:focus-within{outline:3px solid var(--focus);outline-offset:2px}
.ui-search input{flex:1;min-width:0;border:0;background:transparent;font:400 var(--fs-m)/1.3 var(--sans);color:var(--ink);padding:.6rem 0;outline:0}
.ui-search button{flex:none;display:grid;place-items:center;width:2.4rem;height:2.4rem;border:0;border-radius:999px;background:transparent;color:var(--muted);cursor:pointer}
.ui-search button svg{width:1.25rem;height:1.25rem}
/* A map (the host's vendor map: public/vendor-map.js, Leaflet): pins are towns, numbered; the party is a star. */
.ui-map{height:22rem;border:1px solid var(--line);border-radius:var(--r-l);margin:.6rem 0 .3rem;z-index:0;background:var(--zone);box-shadow:var(--e1)}
.ui-map .leaflet-popup-content-wrapper,.ui-map .leaflet-popup-tip{background:var(--card-hi);color:var(--ink);box-shadow:var(--e3)}
.ui-map-pin span,.ui-map-party span{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;border:2px solid #fff;box-shadow:0 1px 4px rgba(0,0,0,.35);font:700 13px/1 var(--sans)}
.ui-map-pin span{background:var(--accent);color:var(--accent-ink)}
.ui-map-party span{width:26px;height:26px;background:var(--ink);color:var(--bg);font-size:14px}
.ui-map-list{margin:.4rem 0 0;padding-left:1.1rem}.ui-map-list li{margin:.2rem 0}
.ui-search button:hover{background:var(--zone);color:var(--ink)}
.ui-bar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.4rem .8rem}

/* ---------- buttons ---------- */
.btn{display:inline-block;background:var(--accent);color:var(--accent-ink);border:2px solid var(--accent);border-radius:var(--r-m);padding:.75rem 1.2rem;font:600 1.05rem var(--sans);text-decoration:none;cursor:pointer;min-height:3rem;text-align:center}
.btn:not(.secondary){box-shadow:inset 0 1px 0 rgba(255,255,255,.22),0 2px 6px color-mix(in oklab,var(--accent) 35%,transparent)}
.btn.secondary{box-shadow:0 1px 2px var(--shadow)}
.btn.secondary{background:var(--card);color:var(--accent)}.btn.big{display:block;width:100%;font-size:1.15rem;padding:1rem}
.btn[disabled],.btn.off{opacity:.45;pointer-events:none}
.btn+.btn{margin-left:.4rem}
.btn.sm{font-size:.85rem;padding:.25rem .7rem;min-height:0;margin-left:.5rem}
.ui-btns{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;margin:.6rem 0}.ui-btns .btn+.btn{margin-left:0}
.btn.danger{background:var(--bad);border-color:var(--bad);color:var(--card)}
.btn.secondary.danger{background:transparent;color:var(--bad)}
/* a button that reads as a link (Sign out, Finish later, Remove in a list) */
.ui-link{display:inline-flex;align-items:center;min-height:2.75rem;padding:0;border:0;background:none;font:600 var(--fs-s)/1.2 var(--sans);color:var(--focus);text-decoration:underline;text-underline-offset:.15em;cursor:pointer}
.ui-link:disabled{opacity:.45;cursor:default}

/* ---------- a vendor's offers, inside their card (src/offers.js): one short row each; a row opens in place ---------- */
.ui-offers{list-style:none;margin:.8rem 0;padding:0;display:grid;grid-template-columns:minmax(0,1fr);gap:.5rem}
.ui-offer{position:relative;min-width:0;background:var(--accent-bg);border:1px solid var(--accent);border-radius:var(--r-m)}
.ui-offer-d>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:.6rem;min-height:44px;padding:.35rem 4.6rem .35rem 2rem;position:relative}
.ui-offer-d>summary>*{min-width:0}
.ui-offer-d>summary::-webkit-details-marker{display:none}
.ui-offer-d>summary::before{content:"";position:absolute;left:.85rem;top:calc(50% - .3rem);width:.45rem;height:.45rem;border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);transform:rotate(-45deg)}
.ui-offer-d[open]>summary::before{transform:rotate(45deg);top:calc(50% - .4rem)}
.ui-offer-d>summary:focus-visible{outline:3px solid var(--focus);outline-offset:-3px;border-radius:var(--r-m)}
.ui-offer-h{font:800 var(--fs-m)/1.3 var(--sans);color:var(--ink);flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-offer-d[open]>summary .ui-offer-h{white-space:normal}
.ui-offer-w{font-size:var(--fs-xs);color:var(--muted);flex:none;white-space:nowrap}
.ui-offer-w code{font-weight:800;letter-spacing:.04em;color:var(--ink)}
.ui-offer-use{display:inline-flex;align-items:center;justify-content:center;min-height:2.75rem;padding:.35rem .9rem;margin:0;font-size:var(--fs-m);border-radius:var(--r-m);white-space:nowrap}
.ui-offers .ui-offer .btn.ui-offer-use-row{position:absolute;top:calc(22px - 1.1rem);right:.5rem;min-height:2.2rem;padding:.2rem .8rem;font-size:var(--fs-s)}
.ui-offer-d[open]+.ui-offer-use-row{display:none}
span.ui-offer-use{cursor:default}
.ui-offer-b{padding:.1rem .9rem .8rem;border-top:1px dashed var(--accent)}
.ui-offer-done .ui-offer-d>summary{padding-right:.9rem}
.ui-offer-kv{margin:.5rem 0 .7rem}.ui-offer-kv>div{display:grid;grid-template-columns:6.5rem minmax(0,1fr);gap:.6rem;padding:.2rem 0}
.ui-offer-kv dt{color:var(--muted);font-size:var(--fs-s);padding-top:.1rem}.ui-offer-kv dd{margin:0;overflow-wrap:anywhere}
.ui-offer-code{display:inline-block;font-weight:800;letter-spacing:.06em;border:2px dashed var(--accent);border-radius:var(--r-s);padding:.05rem .5rem}
@media (max-width:30rem){.ui-offer-kv>div{grid-template-columns:5.5rem minmax(0,1fr);gap:.5rem}}

/* ======================================================================================================================
   The app pieces: the vendor portal and the operator's (src/portal/ui.js builds them; src/portal/shell.js and
   src/admin/shell.js the frame). Same tokens, same type scale, same card; one piece per job, used everywhere.
   ====================================================================================================================== */

/* ---------- the site's name (every page's top bar) ---------- */
.brand{font:700 1.2rem/1 Georgia,"Times New Roman",serif;color:var(--head);text-decoration:none;letter-spacing:-.01em}.brand span{color:var(--accent);font-style:italic;font-weight:600}
.ui-legal{text-align:center;font-size:var(--fs-xs);color:var(--muted);margin:2.5rem 0 0}.ui-legal a{color:var(--muted)}

/* ---------- the logo and its Preview badge (every page; src/preview.js) ----------
   David, 2026-09-29: "add a small preview badge under InviteFromMe which can be clicked to see text". The badge sits
   under the name (under the envelope where the name shrinks to it) and opens What Preview means (/preview). */
.ui-logo{display:inline-flex;flex-direction:column;align-items:flex-start;gap:.15rem;flex:none}
.ui-logo .brand{display:inline-flex;align-items:center}
.ui-logo-ic{display:none;width:2.5rem;height:2.5rem;border-radius:.6rem}
.ui-preview-b{display:inline-block;padding:.05rem .45rem;border:1px solid color-mix(in oklab,var(--accent) 45%,var(--line));border-radius:999px;background:var(--accent-bg);color:var(--accent);font:700 var(--fs-xs)/1.35 var(--sans);letter-spacing:.02em;text-decoration:none;white-space:nowrap}
.ui-preview-b:hover{border-color:var(--accent)}
.ui-preview-b:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-brand+.ui-preview-b,.ui-logo .ui-brand{min-height:0}

/* ---------- the one-line header (a party's host pages: the app, Party needs, the wallet) ----------
   David, 2026-09-28, option A of docs/tracks/header-mockup.png: one line: the logo · the party's name (its facts line
   under it) · the steps, smaller and closer (labels under) · Vouchers · Aa. David, 2026-09-30: no ‹ and no eye; the logo
   goes to Your invitations; the name goes to the page for where the party stands (public/phase.js: the guest's page while
   designing, Party needs once invitations are out, Replies in the last week, Party day).
   On a narrower laptop the logo becomes the app's envelope (public/icon.png) and only the step you're on keeps its
   label (the others name themselves when pointed at). On a phone the steps take their own line. The big party bar
   and its large eye are gone. src/worker.js displayControl draws it (.topbar.ui-hdr-p); public/app.js fills its slot. */
.topbar.ui-hdr-p{flex-wrap:wrap;align-items:center;column-gap:.9rem;row-gap:.35rem;max-width:78.2rem;padding-bottom:.35rem}
.ui-hdr-party,.ui-hdr-party .ui-apptop{display:contents}
.ui-hdr-p .ui-logo{order:1}.ui-hdr-p .ui-phead{order:2}.ui-hdr-p .ui-hdr-steps{order:3}.ui-hdr-p .disp{order:4}
body:has(#app.booting) .ui-hdr-party{visibility:hidden}
.ui-phead{flex:1 1 12rem;min-width:0;display:flex;align-items:center;gap:.35rem}
.ui-phead-q{flex:0 1 auto;min-width:0;display:flex;flex-direction:column}
/* the name and its facts: one link to the page for where the party stands (public/phase.js; David, 2026-09-30); it looks
   like the name, and says where it goes when pointed at or focused (its tooltip; underlined) */
a.ui-phead-go{color:inherit;text-decoration:none;border-radius:var(--r-s);padding:.1rem .3rem;margin:-.1rem 0 -.1rem -.3rem}
a.ui-phead-go[href]{cursor:pointer}
a.ui-phead-go[href]:hover .ui-phead-t,a.ui-phead-go[href]:focus-visible .ui-phead-t{text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:.18em}
a.ui-phead-go[href]:hover{background:var(--zone)}
a.ui-phead-go:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-phead-t,h1.ui-phead-t{margin:0;font:800 var(--fs-l)/1.2 var(--sans);color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-phead-facts{font:400 var(--fs-s)/1.3 var(--sans);color:var(--muted);overflow-wrap:break-word}   /* wraps, never cut: it holds counts (docs/adding-a-language.md) */
.ui-phead-f{display:inline-block;max-width:100%}   /* one part of the facts line: the line breaks between parts, not inside one */
.ui-hdr-steps{flex:none;min-width:0}
/* .ui-hdr-word: "Vouchers" in "Vouchers $20" (its space inside it); on a phone only the amount shows */
/* the steps on the header: smaller and closer */
.ui-hdr-p .ui-steprail{margin:0;padding:.1rem 0 .15rem}
.ui-hdr-p .ui-steprail li{flex:0 0 auto;min-width:3.6rem}
.ui-hdr-p .ui-steprail li+li::before{top:1.3rem}
.ui-hdr-p .ui-steprail-ic{width:2.1rem;height:2.1rem}
.ui-hdr-p .ui-steprail-ic svg{width:1.05rem;height:1.05rem}
.ui-hdr-p .ui-steprail a,.ui-hdr-p .ui-steprail button{gap:.15rem;padding:.2rem .05rem .2rem}
.ui-hdr-p .ui-steprail .ui-steprail-more{width:3rem;margin-left:.15rem}
.ui-hdr-p .disp{flex:none}
/* a laptop: the header stays in sight as the page scrolls. The line is spread out (David, 2026-09-29: "Can we spread
   out the header row a little"): the party keeps only the room its name needs, the steps take the space between it and
   the buttons, spaced out and centered in it, and a clear gap stays before Vouchers · Aa. When the line is short, the
   party's name gives way first ("…", the facts wrap), never the steps. */
@media (min-width:44rem){
  .topbar.ui-hdr-p{position:sticky;top:0;flex-wrap:nowrap;background:linear-gradient(var(--bg) 85%,transparent);padding-top:.5rem}
  .ui-hdr-p .ui-phead{flex:0 1 auto}
  .ui-hdr-p .ui-hdr-steps{flex:1 1 0;min-width:max-content;display:flex;justify-content:center}
  .ui-hdr-p .ui-steprail{flex:0 1 26rem;min-width:max-content;justify-content:center}
  .ui-hdr-p .ui-steprail ol{flex:1 1 auto}
  .ui-hdr-p .ui-steprail li{flex:1 0 auto}
}
@media (min-width:74rem){
  .ui-hdr-p .ui-steprail{flex-basis:40rem}
  .ui-hdr-p .ui-hdr-steps{padding:0 .75rem}
  .ui-hdr-p .ui-steprail li{min-width:4.4rem}
  .ui-hdr-p .disp{margin-left:1.5rem}
}
/* a narrower laptop: the envelope for the logo, the label only on the step you're on */
@media (min-width:44rem) and (max-width:74rem){
  .ui-hdr-p .brand{font-size:0;letter-spacing:0}
  .ui-hdr-p .ui-logo{align-items:center}
  .ui-hdr-p .ui-logo-ic{display:block}
  .ui-hdr-p .ui-steprail li{min-width:2.9rem}
  .ui-hdr-p .ui-steprail li.cur{min-width:5.2rem}
  .ui-hdr-p .ui-steprail li:not(.cur) .ui-steprail-l,.ui-hdr-p .ui-steprail li:not(.cur) .ui-steprail-n,.ui-hdr-p .ui-steprail-more .ui-steprail-l{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .ui-hdr-p .ui-steprail .ui-steprail-more{width:2.9rem}
}
/* a phone: the envelope, the party and its eye, the wallet's amount and Aa on the first line; the steps on their own */
@media (max-width:43.99rem){
  .topbar.ui-hdr-p{column-gap:.5rem;padding-left:.9rem;padding-right:.9rem}
  .ui-hdr-p .brand{font-size:0;letter-spacing:0}
  .ui-hdr-p .ui-logo{align-items:center}
  .ui-hdr-p .ui-logo-ic{display:block;width:2.3rem;height:2.3rem}
  .ui-hdr-p .ui-preview-b{font-size:.62rem;padding:0 .3rem}
  .ui-hdr-p .ui-hdr-steps{order:5;flex:1 1 100%}
  .ui-hdr-p .ui-steprail{margin:0 -.9rem;padding:.1rem .9rem .2rem}
  .ui-hdr-p .ui-steprail li{flex:1 0 auto;min-width:3.4rem}
  /* the counts' short forms ("11", not "11 accepted"; the full count stays for screen readers and the tooltip), so no
     language needs the steps' row to scroll to reach More (the coordinator, 2026-09-30) */
  .ui-hdr-p .ui-steprail-nf{position:absolute;width:1px;height:1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .ui-hdr-p .ui-steprail-ns{display:inline}
  /* the steps share the row by what they hold, none narrower than its longest word; a label of two words may take two
     lines ("Party / needs"), never split inside a word */
  .ui-hdr-p .ui-steprail li{flex:1 1 auto;min-width:min-content}
  .ui-hdr-p .ui-steprail-l{white-space:normal;line-height:1.1;padding:0}
  .ui-hdr-p .ui-steprail .ui-steprail-more{width:2.8rem;margin-left:.1rem}
  .ui-hdr-p .ui-phead{flex:1 1 0}   /* the party takes what's left of the first line; the rest never drops to a second */
  .ui-hdr-p .ui-phead-t{font-size:var(--fs-m)}
  .ui-hdr-p .ui-phead-facts{font-size:var(--fs-xs)}
  .ui-hdr-p .ui-hdr-word{display:none}
  .ui-hdr-p .ui-spill-chip{padding:0 .6rem}
  .ui-hdr-p .disp{gap:.35rem}
  .ui-hdr-p .disp-btn{min-width:0;padding:.45rem .55rem;white-space:nowrap}
  .ui-hdr-p .disp-lang{letter-spacing:-.03em;word-spacing:-.2em}   /* "Aa·EN": the language stays on the button (what it's for), compact */
}

/* a phone: any header's Vouchers chip shows only the amount (Your invitations too) */
@media (max-width:43.99rem){.topbar .ui-hdr-word{display:none}}
/* a small phone (360): the steps' row keeps a narrower margin at its sides, so the longest labels (Haitian Creole) fit */
@media (max-width:24rem){
  .ui-hdr-p .ui-steprail{margin:0 -.9rem;padding:.1rem .45rem .2rem}
}

/* ---------- a host's notes: the Preview banner and the Home Screen tip (each once; public/display.js) ---------- */
.ui-banner.ui-hostnote{margin:.6rem 0 1rem;flex-wrap:nowrap;justify-content:flex-start;align-items:flex-start}
.ui-hostnote[hidden]{display:none}
.ui-hostnote p{margin:.2rem 0}
.ui-hostnote-ic{flex:none;display:grid;place-items:center;width:2.2rem;height:2.2rem;color:var(--info)}
.ui-hostnote-ic svg{width:1.5rem;height:1.5rem}
.ui-hometip-steps{display:flex;align-items:center;gap:.5rem;margin:.35rem 0;color:var(--info)}
.ui-hometip-steps>span:not(.ui-hometip-arrow){display:grid;place-items:center;width:2.2rem;height:2.2rem;border:1.5px solid currentColor;border-radius:.6rem}
.ui-hometip-steps svg{width:1.3rem;height:1.3rem}
.ui-hometip-arrow{font-weight:700}
.ui-hometip-sent{margin-top:1rem}
@media (max-width:767px){.ui-hostnote .ui-hostnote-more{display:none}}   /* a phone: the Preview banner in one line, the card first */

/* ---------- the frame: top bar, the sections (a drawer on phones), the main column ---------- */
body.portal{min-height:100vh}
.portal .btn{display:inline-flex;align-items:center;justify-content:center;gap:.25rem;font-size:var(--fs-m);padding:.55rem 1.1rem;min-height:2.75rem;border-radius:var(--r-m);line-height:1.3}
.portal .btn.sm{position:relative;font-size:var(--fs-s);padding:.3rem .85rem;min-height:2.25rem;margin-left:0;border-width:1.5px}
.portal .btn.sm::after{content:"";position:absolute;inset:-.25rem}   /* a 44px touch target around a small button */
.portal .btn+.btn{margin-left:0}
.portal input[type=checkbox],.portal input[type=radio]{width:1.25rem;height:1.25rem;flex:none;margin:.1rem 0 0;accent-color:var(--accent)}
.portal input,.portal textarea,.portal select{font-size:var(--fs-m)}
.ui-skip{position:absolute;left:-999rem;top:.5rem;z-index:100;background:var(--card);color:var(--focus);padding:.5rem 1rem;border-radius:var(--r-s);border:1px solid var(--line)}.ui-skip:focus{left:1rem}
.ui-top{position:sticky;top:0;z-index:30;display:flex;align-items:center;gap:.75rem;min-height:3.5rem;padding:.25rem 1rem;background:var(--card);border-bottom:1px solid var(--line);box-shadow:var(--e1)}
.ui-top.admin{border-bottom:2px solid var(--accent)}
.ui-brand{display:inline-flex;align-items:center;flex-wrap:wrap;column-gap:.4rem;min-height:2.75rem;text-decoration:none}
.ui-brand .brand{font-size:var(--fs-l)}
.ui-brand-for{font:600 var(--fs-s)/1.2 var(--sans);color:var(--muted)}
.admin .ui-brand-for{color:var(--head);text-transform:uppercase;letter-spacing:.08em;font-size:var(--fs-xs)}
.ui-top-r{margin-left:auto;display:flex;align-items:center;gap:.75rem;min-width:0}
.ui-who{font:600 var(--fs-s)/1.2 var(--sans);color:var(--ink);max-width:16rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ui-top .disp-btn{min-height:2.75rem}
.ui-signin{display:inline-flex;align-items:center;min-height:2.75rem;font:600 var(--fs-s)/1.2 var(--sans);text-decoration:none}
.ui-top .btn.sm{min-height:2.75rem}.ui-top .btn.sm::after{content:none}
.ui-menu,.ui-side-x{display:none;align-items:center;justify-content:center;width:2.75rem;height:2.75rem;border:0;border-radius:var(--r-s);background:transparent;color:var(--ink);cursor:pointer}
.ui-side-x{width:auto;min-width:2.75rem;padding:0 .6rem;font:600 var(--fs-s)/1 var(--sans);color:var(--focus)}   /* the phone menu's "Close" (rule 3: the word, never ✕; the menu itself stays a menu, D4) */
.ui-menu{margin-left:-.5rem}.ui-menu:hover{background:var(--accent-bg)}
.ui-frame{display:flex;align-items:stretch;min-height:calc(100vh - 3.5rem)}
.ui-side{flex:none;width:15rem;background:var(--card);border-right:1px solid var(--line);padding:1rem .75rem;position:sticky;top:3.5rem;height:calc(100vh - 3.5rem);overflow-y:auto;box-shadow:4px 0 16px -8px var(--shadow)}
.ui-side ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.25rem}
.ui-side a{display:flex;align-items:center;gap:.75rem;min-height:2.75rem;padding:.5rem .75rem;border-left:3px solid transparent;border-radius:0 var(--r-s) var(--r-s) 0;color:var(--ink);text-decoration:none;font:600 var(--fs-m)/1.3 var(--sans)}
.ui-side a:hover{background:var(--accent-bg)}
.ui-side a[aria-current]{background:var(--accent-bg);border-left-color:var(--accent);color:var(--head)}
.ui-side a:focus-visible{outline-offset:-.15rem}
.ui-ico{flex:none;width:1.25rem;height:1.25rem}
.ui-nl{min-width:0}
.ui-count{margin-left:auto;min-width:1.5rem;padding:.05rem .45rem;border-radius:999px;background:var(--accent);color:var(--accent-ink);font:700 var(--fs-xs)/1.4 var(--sans);text-align:center}
.ui-side-top{display:none;align-items:center;justify-content:space-between;gap:.5rem;padding:0 0 .75rem .5rem;margin:0 0 .5rem;border-bottom:1px solid var(--line)}
.ui-side-top .ui-who{font-weight:700}
.ui-side-out{display:none;margin-top:1rem;padding:.75rem .75rem 0;border-top:1px solid var(--line)}
.ui-top-out{margin:0}
.ui-scrim{position:fixed;inset:0;z-index:35;background:rgba(0,0,0,.45)}.ui-scrim[hidden]{display:none}
.ui-page{flex:1;min-width:0;padding:1.75rem 2rem 3rem}.ui-page:focus{outline:none}
.ui-col{max-width:62rem;margin:0 auto}
.ui-col.wide{max-width:76rem}   /* a page with two columns (the vendor portal's Home, Requests, Your listing) */
.ui-site{max-width:44rem;margin:0 auto;padding:1.5rem 1rem 3rem}.ui-site:focus{outline:none}
.ui-site.wide{max-width:70rem}
html:not(.p-js) [data-js-only]{display:none!important}
@media (max-width:47.99rem){
  .ui-menu,.ui-side-x{display:inline-flex}
  .ui-top .ui-who,.ui-top-out{display:none}
  .ui-top{gap:.5rem;padding:.25rem .75rem}
  .ui-side{position:fixed;top:0;left:0;bottom:0;height:auto;width:min(18rem,85vw);z-index:40;transform:translateX(-105%);visibility:hidden;transition:transform .2s ease,visibility 0s linear .2s;box-shadow:0 0 2.5rem rgba(0,0,0,.3)}
  .p-drawer-open .ui-side{transform:none;visibility:visible;transition:transform .2s ease}
  .ui-side-top{display:flex}
  .ui-side-out{display:block}
  .ui-page{padding:1.1rem 1rem 2.5rem}
  html:not(.p-js) .ui-frame{flex-direction:column}
  html:not(.p-js) .ui-side{position:static;transform:none;visibility:visible;width:auto;height:auto;padding:.5rem;border-right:0;border-bottom:1px solid var(--line);box-shadow:none}
  html:not(.p-js) .ui-side ul{flex-direction:row;overflow-x:auto}
  html:not(.p-js) .ui-side a{white-space:nowrap}
}
@media (max-width:30rem){.ui-brand{flex-direction:column;align-items:flex-start;justify-content:center;gap:0}.ui-brand .brand{font-size:var(--fs-m)}.ui-brand-for{font-size:var(--fs-xs)}.ui-top-r{gap:.5rem}}
@media (prefers-reduced-motion:reduce){.ui-side,.p-drawer-open .ui-side{transition:none}.ui-toast{animation:none}}

/* ---------- a page's head: the back link, the title and its count, at most one main action ---------- */
.ui-pagehead{margin-bottom:1.25rem}
.ui-pagehead .ui-back{margin:-.6rem 0 .1rem}
.ui-pagehead-row{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:.6rem 1rem}
.ui-h1{font:800 var(--fs-2xl)/1.15 var(--sans);color:var(--ink);letter-spacing:-.015em;margin:0;overflow-wrap:anywhere}
.ui-h1 .ui-facts{display:inline;margin-left:.5rem;letter-spacing:0;white-space:nowrap}
.ui-h1 .ui-pill{vertical-align:middle;margin-left:.4rem;letter-spacing:0}
.ui-lead{font-size:var(--fs-m);color:var(--muted);margin:-.6rem 0 1.25rem;max-width:40rem}
@media (max-width:47.99rem){.ui-h1{font-size:var(--fs-xl)}}

/* ---------- a card with a head: its name on the left, a count / pill / Edit on the right ---------- */
.ui-card-top{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.4rem .8rem;margin:0 0 .6rem}
.ui-card-r{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap}
.ui-card>:last-child{margin-bottom:0}
.ui-card.warn{border-left:4px solid var(--warn)}.ui-card.bad{border-left:4px solid var(--bad)}.ui-card.ok{border-left:4px solid var(--ok)}
.ui-card.info{border-left:4px solid var(--info)}.ui-card.accent{border-left:4px solid var(--accent)}
.ui-card.is-editing{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}
.ui-grid2{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(18rem,100%),1fr));gap:0 1rem;align-items:start}
.ui-cards{list-style:none;padding:0;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(15rem,100%),1fr));gap:.75rem;margin:.5rem 0 .75rem}
.ui-cards>.ui-card{margin:0}
.ui-sub{font:700 var(--fs-m)/1.3 var(--sans);color:var(--ink);margin:1rem 0 .35rem}

/* ---------- facts as label / value ---------- */
.ui-kv{margin:0}
.ui-kv>div{display:grid;grid-template-columns:minmax(7rem,12rem) minmax(0,1fr);gap:.1rem 1rem;padding:.45rem 0;border-bottom:1px solid var(--line)}
.ui-kv>div:first-child{padding-top:0}.ui-kv>div:last-child{border-bottom:0;padding-bottom:0}
.ui-kv dt{color:var(--muted);font-size:var(--fs-s);padding-top:.1rem}
.ui-kv dd{margin:0;min-width:0;overflow-wrap:anywhere;font-size:var(--fs-m)}
.ui-dash{color:var(--muted)}
@media (max-width:30rem){.ui-kv>div{grid-template-columns:minmax(0,1fr);gap:0}}

/* ---------- a list of rows: each its own surface, the three levels; the whole row a link ---------- */
.ui-rows{list-style:none;margin:0 0 1rem;padding:0;display:grid;gap:.5rem}
.ui-row{display:flex;align-items:center;gap:.8rem;min-height:2.75rem;padding:.7rem 1rem;margin:0;color:var(--ink);text-decoration:none}
a.ui-row:hover{border-color:var(--line-strong)}
a.ui-row:focus-visible{outline:3px solid var(--focus);outline-offset:-3px}
a.ui-row[aria-current]{border-color:var(--accent)}
.ui-row .ui-main{flex:1;min-width:0}
.ui-row .ui-title{font-size:var(--fs-m)}
.ui-row .ui-key{font-size:var(--fs-l)}
.ui-go{flex:none;width:.5rem;height:.5rem;border-right:2px solid var(--muted);border-top:2px solid var(--muted);transform:rotate(45deg);margin-right:.2rem}
.ui-row-act{flex:none;display:flex;gap:.4rem;align-items:center}
.ui-row-ico{flex:none;display:inline-flex;align-items:center;justify-content:center;width:2.25rem;height:2.25rem;border-radius:50%;background:var(--accent-bg);color:var(--head)}
.ui-row-pic{flex:none;display:inline-flex;align-items:center;justify-content:center;width:3.4rem;height:4.25rem;border-radius:var(--r-s);object-fit:cover;background:var(--accent-bg);color:var(--head);font:800 var(--fs-xl)/1 var(--sans)}   /* a party's picture on its row (Your invitations), or its first letter */
.ui-row .ui-btns{margin:.5rem 0 0}
@media (max-width:30rem){.ui-row{flex-wrap:wrap}.ui-row .ui-main{flex-basis:12rem}}

/* ---------- a table of many columns (the operator's lists): a header row, then rows; stacked on phones ---------- */
.ui-table{background:var(--card);border:1px solid var(--line);border-radius:var(--r-l);margin:0 0 1rem;overflow:hidden;box-shadow:var(--rim),var(--e1)}
.ui-table table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}
.ui-table thead th{background:var(--zone);border-bottom:1px solid var(--line);font:700 var(--fs-xs)/1.3 var(--sans);letter-spacing:.08em;text-transform:uppercase;color:var(--muted);text-align:left;padding:.5rem .75rem}
.ui-table th:first-child,.ui-table td:first-child{padding-left:1rem}
.ui-trow{position:relative}
.ui-trow+.ui-trow{border-top:1px solid var(--line)}
.ui-trow.link:hover,.ui-trow[aria-current]{background:var(--accent-bg)}
.ui-cell{padding:.6rem .75rem;vertical-align:middle;min-width:0;overflow-wrap:anywhere;font-size:var(--fs-s);color:var(--ink)}
.ui-cell.first{font-weight:700;font-size:var(--fs-m)}
.ui-trow-a{color:var(--ink);text-decoration:none}.ui-trow-a::after{content:"";position:absolute;inset:0}
.ui-trow-a:focus-visible{outline:none}.ui-trow-a:focus-visible::after{outline:3px solid var(--focus);outline-offset:-3px}
.ui-go-c{width:1.5rem;padding-right:1rem}
.ui-cl{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.ui-num{text-align:right;font-variant-numeric:tabular-nums}
.why-join .ui-cell.first{overflow-wrap:break-word}   /* the "why join" table's row names break between words only ("Vouchers", not "Vouche rs") */
@media (min-width:48rem){.ui-table .ui-num{white-space:nowrap}}   /* an amount (or "Maya $5") never breaks inside a wide table */
@media (max-width:47.99rem){
  .ui-table thead{display:none}
  .ui-table table,.ui-table tbody{display:block}
  .ui-trow{display:grid;grid-template-columns:minmax(0,1fr) auto;padding:.6rem 1rem}
  .ui-cell,.ui-table td:first-child{grid-column:1;padding:0;color:var(--muted)}.ui-cell.first{color:var(--ink)}.ui-cell.ui-num{text-align:left}
  .ui-go-c{grid-column:2;grid-row:1/span 12;align-self:center;padding:0}
  .ui-cl{position:static;width:auto;height:auto;clip:auto;overflow:visible}
}

/* ---------- status in words: the pill, one line, the next step ---------- */
.ui-status{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem .9rem;padding:.75rem 1rem;margin:0 0 1rem}
.ui-status>.ui-pill{font-size:var(--fs-s)}
.ui-status-t{flex:1 1 16rem;margin:0;font-size:var(--fs-m);color:var(--ink)}
.ui-status-t .ui-info{margin:0;font-size:var(--fs-m);color:var(--ink)}
.ui-status-a{display:flex;flex-wrap:wrap;gap:.5rem}

/* ---------- a notice at the top of a page or card, with its fix ---------- */
.ui-banner{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.6rem 1rem;padding:.7rem 1rem;margin:0 0 1rem;background:var(--info-bg);border:1px solid var(--line);border-left:4px solid var(--info);border-radius:var(--r-m);color:var(--ink)}
.ui-banner.ok{border-left-color:var(--ok);background:var(--ok-bg)}.ui-banner.warn{border-left-color:var(--warn);background:var(--warn-bg)}
.ui-banner.bad{border-left-color:var(--bad);background:var(--bad-bg)}
.ui-banner[hidden]{display:none}
.ui-banner>div:first-child{flex:1 1 16rem;min-width:0}
.ui-banner p{margin:0;font-size:var(--fs-m)}.ui-banner p+p{margin-top:.2rem;font-size:var(--fs-s)}
.ui-banner-t{font-weight:700}
.ui-banner-a{display:flex;flex-wrap:wrap;gap:.5rem}
.ui-banner-a form{margin:0}

/* ---------- empty: what fills it, and the next step ---------- */
.ui-empty{margin:0 0 1rem;padding:1.5rem 1rem;text-align:center;color:var(--muted);border:1px dashed var(--line-strong);border-radius:var(--r-l)}
.ui-card .ui-empty{border:0;padding:.25rem 0;margin:0;text-align:left}
.ui-empty p{margin:0 auto;max-width:34rem;font-size:var(--fs-s)}
.ui-card .ui-empty p{margin:0}
.ui-empty .ui-empty-t{font:700 var(--fs-m)/1.3 var(--sans);color:var(--ink);margin-bottom:.3rem}
.ui-empty .ui-empty-a{margin-top:.8rem;display:flex;flex-wrap:wrap;gap:.5rem;justify-content:center}
.ui-card .ui-empty .ui-empty-a{justify-content:flex-start}

/* ---------- a few numbers: the key fact big, its name small ---------- */
.ui-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(9rem,100%),1fr));gap:.6rem;margin:0 0 1rem}
.ui-stats.three{grid-template-columns:repeat(3,minmax(0,1fr))}
.ui-stat{display:flex;flex-direction:column;gap:.15rem;padding:.8rem 1rem;margin:0;min-width:0}
.ui-stat .ui-key{white-space:normal;overflow-wrap:anywhere}
@media (max-width:30rem){.ui-stat{padding:.65rem .75rem}.ui-stat .ui-key{font-size:var(--fs-l)}}

/* ---------- to do: each item a row that goes where it's fixed ---------- */
.ui-todo{list-style:none;margin:0 0 1rem;padding:0;display:grid;gap:.5rem}
.ui-todo a{display:flex;align-items:center;justify-content:space-between;gap:1rem;min-height:2.75rem;padding:.65rem 1rem;margin:0;border-left:4px solid var(--accent);color:var(--ink);text-decoration:none;font-size:var(--fs-m)}
.ui-todo a:hover{border-color:var(--accent)}
.ui-todo-a{flex:none;color:var(--head);font:700 var(--fs-s)/1.2 var(--sans);white-space:nowrap}

/* ---------- a checklist: done ✓ / the next one / to come (Home's setup, Join's review and status) ---------- */
.ui-checklist{list-style:none;margin:0;padding:0;display:grid;gap:.2rem}
.ui-checklist>li>a,.ui-checklist>li>span{display:flex;align-items:center;gap:.75rem;min-height:2.75rem;padding:.35rem .5rem;border-radius:var(--r-s);color:var(--ink);text-decoration:none}
.ui-checklist>li>a:hover{background:var(--accent-bg)}
.ui-cn{flex:none;display:inline-flex;align-items:center;justify-content:center;width:1.7rem;height:1.7rem;border-radius:50%;background:var(--card);border:1.5px solid var(--line-strong);font:700 var(--fs-s)/1 var(--sans);color:var(--muted)}
.ui-cl-t{flex:1;min-width:0;overflow-wrap:anywhere}
.ui-cl-t .ui-facts{display:block}
.ui-checklist .done .ui-cn{background:var(--ok-bg);border-color:var(--ok);color:var(--ok)}
.ui-checklist .done>span>.ui-cl-t{color:var(--muted)}
.ui-checklist .cur .ui-cn{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.ui-checklist .cur .ui-cl-t{font-weight:700}
.ui-checklist .cur>a{background:var(--accent-bg)}

/* ---------- steps (Join): done ✓ / current / to come ---------- */

/* ---------- Build › Guests (the simpler Guests step, 2026-09-28): an invitation that can't be sent yet (amber, with the
   field on it), and the one same-last-name question, in the list ---------- */
.ui-card.need{background:var(--warn-bg);border-color:color-mix(in oklab,var(--warn) 45%,var(--line))}
.ui-need-t{font:600 var(--fs-s)/1.4 var(--sans);color:var(--warn);margin:.25rem 0 0}
.ui-card.ask{background:var(--accent-bg);border:1.5px dashed var(--accent)}

/* ---------- forms: a field, a group of boxes, the actions ---------- */
.ui-field{margin:0 0 .9rem;min-width:0}
.ui-field>label,.ui-checks>legend{display:block;margin:0 0 .3rem;font:700 var(--fs-s)/1.3 var(--sans);color:var(--ink)}
.ui-hint{font-size:var(--fs-s);color:var(--muted);margin:.3rem 0 0}
.ui-check>label,.ui-checks-grid>label{display:flex;gap:.6rem;align-items:flex-start;font:400 var(--fs-m)/1.4 var(--sans);color:var(--ink);margin:0;min-height:2.75rem;padding:.35rem 0;cursor:pointer}
.ui-checks{border:0;padding:0;min-width:0}.ui-checks>legend{padding:0}
.ui-checks-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(13rem,100%),1fr));gap:0 1rem}
.ui-group{border:1px solid var(--line);border-radius:var(--r-m);padding:.4rem 1rem 1rem;margin:1rem 0 0;min-width:0}
.ui-group>legend{font:700 var(--fs-m)/1.3 var(--sans);color:var(--ink);padding:0 .35rem}
.ui-form-actions{display:flex;justify-content:flex-end;flex-wrap:wrap;align-items:center;gap:.5rem;border-top:1px solid var(--line);padding-top:.9rem;margin-top:.5rem}
.ui-form-err{color:var(--bad);font-weight:700;font-size:var(--fs-s);margin:0 0 .75rem}.ui-form-err[hidden]{display:none}
.ui-dirty{display:none}[data-dirty] .ui-dirty{display:inline}
.ui-sub-form{border:1px solid var(--line);border-radius:var(--r-m);padding:1rem;background:var(--zone)}
/* one choice of a few, as buttons (sale / no sale / still in progress; stars) */
.ui-choices{display:flex;flex-wrap:wrap;gap:.5rem}
.ui-choice{position:relative;display:inline-flex;align-items:center;gap:.5rem;min-height:2.75rem;padding:.4rem 1rem;border:1px solid var(--line-strong);border-radius:var(--r-m);background:var(--card);cursor:pointer;font:600 var(--fs-m)/1.3 var(--sans);color:var(--ink);margin:0}
/* its radio or tick box keeps its own size: the host app's stylesheet gives every input the full width, which pushed
   the words out past the box (David, 2026-09-28: the "Report a problem" types) */
.ui-choice input[type=radio],.ui-choice input[type=checkbox]{width:auto;flex:none;margin:0;padding:0;accent-color:var(--accent)}
.ui-choice:hover{border-color:var(--accent)}
.ui-choice:has(input:checked){border-color:var(--accent);background:var(--accent-bg);color:var(--head)}
.ui-choice:has(input:focus-visible){outline:3px solid var(--focus);outline-offset:2px}
.ui-choice.stars{letter-spacing:.1em;font-weight:400;color:var(--head)}
/* the words hosts read, with the few values that change as blanks (New offer) */
.ui-sentence{font:700 var(--fs-xl)/1.9 var(--sans);color:var(--ink);margin:0 0 1rem}.ui-sentence[hidden]{display:none}
.portal .ui-blank{font:inherit;font-size:var(--fs-l);width:5.5rem;min-height:2.75rem;padding:.2rem .5rem;margin:0 .15rem;border:2px solid var(--accent);border-radius:var(--r-s);background:var(--accent-bg);color:var(--ink);vertical-align:baseline}
.portal .ui-blank.wide{width:min(16rem,100%)}.portal .ui-blank[type=date]{width:auto;font-size:var(--fs-m)}
@media (max-width:30rem){.ui-sentence{font-size:var(--fs-l)}.portal .ui-blank{font-size:var(--fs-m);width:4.5rem}}
/* a part of a form or card that opens (More options, Change the wording, Add a product) */
.ui-open{margin:0 0 1rem;border-top:1px solid var(--line);padding-top:.4rem}
.ui-open>summary{list-style:none;cursor:pointer;min-height:2.75rem;display:inline-flex;align-items:center;font:600 var(--fs-s)/1.2 var(--sans);color:var(--focus)}
.ui-open>summary::-webkit-details-marker{display:none}
.ui-open>summary::after{content:"";width:.4rem;height:.4rem;border-right:2px solid currentColor;border-bottom:2px solid currentColor;transform:rotate(45deg);margin:-.2rem 0 0 .5rem}
.ui-open[open]>summary::after{transform:rotate(-135deg);margin-top:.2rem}
.ui-open.bare{border-top:0;padding-top:0;margin:.5rem 0 0}

/* ---------- words someone wrote (a host's note, a review), codes, keys ---------- */
.ui-quote{margin:0;padding:.4rem 0 .4rem .9rem;border-left:3px solid var(--accent);font-size:var(--fs-m);white-space:pre-line;overflow-wrap:anywhere;color:var(--ink)}
.ui-codes{list-style:none;margin:0 0 1rem;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(8rem,1fr));gap:.5rem}
.ui-codes code{display:block;padding:.45rem .7rem;border:1px solid var(--line);border-radius:var(--r-s);background:var(--bg);font-size:var(--fs-m);text-align:center;letter-spacing:.05em}
.ui-qr{flex:none;width:11rem;max-width:60vw;border-radius:var(--r-s);overflow:hidden;border:1px solid var(--line)}.ui-qr svg{display:block;width:100%;height:auto}
.ui-keytext{font-size:var(--fs-m);letter-spacing:.05em;overflow-wrap:anywhere}
.ui-side-by{display:flex;flex-wrap:wrap;gap:1rem 1.5rem;align-items:flex-start;margin:0 0 1rem}.ui-side-by>div{flex:1 1 16rem;min-width:0}
.ui-panel{margin:1rem 0;padding:1rem;border:1px solid var(--accent);border-radius:var(--r-m);background:var(--card)}.ui-panel[hidden]{display:none}
.ui-zone{padding:.75rem .9rem;border-radius:var(--r-m);background:var(--zone);border:1px solid var(--line);margin:0 0 1rem}
.ui-zone.warn{background:var(--warn-bg);border-color:var(--warn)}
.ui-zone>:last-child{margin-bottom:0}

/* ---------- photos a vendor manages; photos to pick ---------- */
.ui-gallery{list-style:none;margin:0 0 .75rem;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(min(8.5rem,45%),1fr));gap:.75rem}
.ui-gallery li{position:relative;display:flex;flex-direction:column;gap:.35rem;align-items:flex-start}
.ui-gallery img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-s);border:1px solid var(--line);background:var(--zone)}
.ui-gallery .ui-pill{position:absolute;top:.4rem;left:.4rem}
.ui-pick{display:grid;grid-template-columns:repeat(auto-fill,minmax(7rem,1fr));gap:.5rem;margin:0 0 1rem}
.ui-pick label{position:relative;display:block;cursor:pointer;margin:0}
.ui-pick input{position:absolute;top:.4rem;left:.4rem}
.ui-pick img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-s);border:2px solid var(--line)}
.ui-pick input:checked+img{border-color:var(--accent)}
.ui-pick input:focus-visible+img{outline:3px solid var(--focus);outline-offset:2px}

/* ---------- the card as hosts see it, shown to the vendor: side by side, each on the host page's background ---------- */
.ui-previews{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(19rem,100%),1fr));gap:1rem 1.25rem;align-items:start;margin:.5rem 0 0}
.ui-preview{min-width:0}.ui-preview>.ui-label{margin:0 0 .4rem}
.ui-stage{padding:.75rem;background:var(--bg);border:1px dashed var(--line-strong);border-radius:var(--r-m)}
.ui-stage .ui-card:last-child{margin-bottom:0}

/* ---------- a bar that shows how many (Home's this month) ---------- */
.ui-meter{display:block;width:100%;height:.45rem;margin:.3rem 0 0;border:0;border-radius:999px;background:var(--zone);overflow:hidden;-webkit-appearance:none;appearance:none}
.ui-meter::-webkit-progress-bar{background:var(--zone);border-radius:999px}
.ui-meter::-webkit-progress-value{background:var(--accent);border-radius:999px}
.ui-meter::-moz-progress-bar{background:var(--accent);border-radius:999px}

/* ---------- a section's own tabs (Finances, Catalog): one line of words, the current one underlined ---------- */
.ui-tabs{display:flex;flex-wrap:wrap;gap:0 1.25rem;margin:-.5rem 0 1.25rem;border-bottom:1px solid var(--line)}
.ui-tabs a{display:inline-flex;align-items:center;gap:.35rem;min-height:2.75rem;margin-bottom:-1px;border-bottom:3px solid transparent;font:600 var(--fs-s)/1.2 var(--sans);color:var(--muted);text-decoration:none}
.ui-tabs a:hover{color:var(--ink)}
.ui-tabs a[aria-current]{color:var(--ink);border-bottom-color:var(--accent)}
.ui-tabs .ui-count{margin-left:0}

/* ---------- one thing in a list that has its own facts and actions (a claim, a payout, a step): a card of its own ---------- */
.ui-entry>.ui-head+.ui-facts,.ui-entry>.ui-head+.ui-pills{margin-top:.2rem}
.ui-entry>.ui-kv,.ui-entry>.ui-table{margin-top:.75rem}
.ui-entry>.ui-note,.ui-entry>.ui-text{margin:.6rem 0 0}
.ui-entry form{margin-top:.75rem}

/* ---------- machine words: a code, a command, what a program printed ---------- */
.ui-code{font:600 var(--fs-s)/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;background:var(--zone);border:1px solid var(--line);border-radius:.3rem;padding:.05rem .3rem;overflow-wrap:anywhere}
.ui-pre{font:400 var(--fs-xs)/1.45 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--ink);background:var(--zone);border:1px solid var(--line);border-radius:var(--r-s);padding:.5rem .75rem;margin:.6rem 0;max-height:12rem;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere}

/* ---------- choices stacked, one a line, with the key that picks each (Catalog › Review) ---------- */
.ui-choices.stack{display:grid;gap:.5rem}
.ui-choices.stack .ui-choice{display:flex;font-weight:500}
.ui-choice kbd{flex:none;font:600 var(--fs-xs)/1 var(--sans);color:var(--muted);border:1px solid var(--line-strong);border-radius:.3rem;padding:.25rem .45rem}
@media (max-width:47.99rem){.ui-choice kbd{display:none}}

/* ---------- dialogs and toasts (public/portal/portal.js) ---------- */
.ui-toasts{position:fixed;left:50%;bottom:1rem;z-index:60;transform:translateX(-50%);width:max-content;max-width:calc(100vw - 2rem);pointer-events:none}
.ui-toasts-s,.ui-toasts-e{display:flex;flex-direction:column;align-items:center;gap:.5rem}
.ui-toasts-e:not(:empty){margin-top:.5rem}
.ui-toast{pointer-events:auto;display:flex;align-items:center;gap:1rem;padding:.7rem 1.1rem;border-radius:var(--r-m);background:var(--ink);color:var(--bg);font:600 var(--fs-s)/1.3 var(--sans);box-shadow:0 .5rem 1.5rem rgba(0,0,0,.25);animation:ui-in .2s ease}
.ui-toast.err{background:var(--bad-bg);color:var(--ink);border:1px solid var(--bad);border-left-width:4px}
.ui-toast.out{opacity:0;transition:opacity .25s}
.ui-toast-x{all:unset;cursor:pointer;display:inline-flex;align-items:center;min-height:2.75rem;color:var(--focus);text-decoration:underline;font-weight:600}
.ui-toast-x:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
@keyframes ui-in{from{opacity:0;transform:translateY(.5rem)}to{opacity:1;transform:none}}
@media print{.ui-top,.ui-side,.ui-legal,[data-no-print]{display:none!important}}

/* ---------- a finder page: search pill, category rail, picture-first cards, the list as a sheet over a map ----------
   (David, 2026-09-26: "true changes… use examples from other industry products". Patterns from Airbnb (floating search
   pill, category rail, map with the list as a sheet over it, photo-first cards with the badge on the picture, one
   floating List/Map button), The Knot and Thumbtack (price as the key fact, clear actions on every card). Depth comes
   from things sitting on other things: the pill over the page, the sheet over the map, badges over pictures. */
.ui-spill-bar{position:sticky;top:0;z-index:25;margin:0 -1rem;padding:.6rem 1rem .5rem;background:linear-gradient(var(--bg) 72%,transparent)}
.ui-spill{display:flex;align-items:center;gap:.6rem;background:var(--card);border-radius:999px;padding:.45rem .45rem .45rem 1.1rem;box-shadow:var(--rim),var(--e2)}
.ui-spill:focus-within{outline:3px solid var(--focus);outline-offset:2px}
.ui-spill-q{flex:1;min-width:0;display:flex;flex-direction:column}
.ui-spill input{border:0;background:transparent;padding:.15rem 0;font:700 var(--fs-m)/1.25 var(--sans);color:var(--ink);outline:0;min-width:0}
.ui-spill input::placeholder{color:var(--ink);opacity:.85}
.ui-spill input:focus::placeholder{color:var(--muted);opacity:1;font-weight:500}   /* in the box: the example reads as a hint, not a title */
.ui-spill:has(#vq){cursor:text}
.ui-spill input:focus-visible{outline:0}   /* one ring, the pill's (:focus-within), not a second inside it (David: "Is this how you are expecting this control to behave") */
.ui-spill-facts{font:400 var(--fs-xs)/1.3 var(--sans);color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-spill button{flex:none;display:grid;place-items:center;width:2.6rem;height:2.6rem;border:0;border-radius:50%;background:var(--accent);color:var(--accent-ink);cursor:pointer;box-shadow:0 3px 8px color-mix(in oklab,var(--accent) 45%,transparent)}
.ui-spill button svg{width:1.2rem;height:1.2rem}
.ui-rail{display:flex;gap:.35rem;overflow-x:auto;margin:.3rem -1rem .2rem;padding:.2rem 1rem .5rem;scrollbar-width:none;scroll-snap-type:x proximity}
.ui-rail::-webkit-scrollbar{display:none}
.ui-rail a{flex:none;scroll-snap-align:start;display:flex;flex-direction:column;align-items:center;gap:.2rem;min-width:4.9rem;padding:.55rem .4rem .6rem;border-radius:var(--r-l);color:var(--muted);font:600 var(--fs-xs)/1.15 var(--sans);text-align:center;text-decoration:none}
.ui-rail a:hover{background:color-mix(in oklab,var(--card) 60%,transparent)}
.ui-rail .ic{font-size:1.65rem;line-height:1}
.ui-rail .n{font-weight:800;color:var(--ink);background:var(--card);border-radius:999px;padding:.05rem .45rem;box-shadow:0 1px 3px var(--shadow)}
.ui-rail a[aria-current="true"]{color:var(--ink);background:var(--card);box-shadow:var(--rim),var(--e1)}
.ui-rail a[aria-current="true"] .n{background:var(--accent);color:var(--accent-ink)}
.ui-rail a:focus-visible{outline:3px solid var(--focus);outline-offset:-3px}
/* the list as a sheet: over the map (Airbnb), with a grab line; alone, the same surface */
.ui-sheet{position:relative;z-index:5;margin:0 -1rem;padding:.4rem 1rem 5.5rem;background:var(--bg);border-radius:1.5rem 1.5rem 0 0}
.ui-map+.ui-sheet,.ui-mapwrap+.ui-sheet{margin-top:-1.6rem;box-shadow:0 -10px 30px var(--shadow),var(--rim)}
@media (max-width:55.99rem){.ui-finder>.ui-map{margin:0 -1rem;height:16rem;border:0;border-radius:0;box-shadow:none}}
.ui-sheet::before{content:"";display:block;width:2.5rem;height:.3rem;border-radius:.2rem;background:var(--line-strong);margin:.2rem auto .7rem}
.ui-sheet-h{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.3rem .8rem;margin:0 0 .4rem}
.ui-sheet-h .ui-title{font-size:var(--fs-l)}
/* one floating button: "List" over the map, "Map" over the list */
.ui-float{position:fixed;left:50%;bottom:1.1rem;transform:translateX(-50%);z-index:30;display:inline-flex;align-items:center;gap:.45rem;padding:.8rem 1.2rem;border-radius:999px;background:var(--ink);color:var(--bg);font:700 var(--fs-s)/1 var(--sans);text-decoration:none;box-shadow:var(--e3)}
.ui-float:focus-visible{outline:3px solid var(--focus);outline-offset:3px}
/* picture-first cards (a details: tap to open; the picture band, the name and key fact, the facts line, the actions) */
.ui-tile{padding:0;overflow:hidden;border-radius:1.15rem}
.ui-tile>summary{display:block;list-style:none;cursor:pointer}
.ui-tile>summary::-webkit-details-marker{display:none}
.ui-tile>summary:focus-visible{outline:3px solid var(--focus);outline-offset:-3px;border-radius:1.15rem}
.ui-media{position:relative;display:grid;place-items:center;height:9.5rem;overflow:hidden;background:linear-gradient(135deg,var(--g1,#f3e3b5),var(--g2,#e9b98c));font-size:3.6rem;line-height:1}
.ui-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.ui-media-s{height:5.75rem;font-size:2.6rem}
.ui-media-badge{position:absolute;left:.7rem;top:.7rem;z-index:1;font:700 var(--fs-xs)/1 var(--sans);padding:.4rem .65rem;border-radius:999px;background:var(--card);color:var(--ink);box-shadow:var(--e1)}
.ui-media-badge.ad{background:var(--ink);color:var(--card);letter-spacing:.03em}
.ui-tile-body{display:block;padding:.75rem 1rem 1rem}
.ui-tile .ui-key{color:var(--accent);font-size:var(--fs-l)}
/* Party needs: a member stands out from a business listed from public info (David, 2026-10-01: "we can not make free
   equal to signed up vendor"; the mock-up he said yes to, docs/tracks/party-needs-3). A member: a wide card, their
   photo beside the facts, ✓ On InviteFromMe (.ui-mark), Request and Details below. Listed: compact, two lines, no
   picture, their phone or website on the right. */
/* Compare (party-needs-3): a member's row raised a step, ✓ On InviteFromMe; a listed row plain, its name not a link color */
.vcmp tr.vcmp-mem:not(.top) td{background:color-mix(in oklab,var(--card-hi) 70%,var(--card))}
.vcmp tr.vcmp-cat td{padding-top:.5rem;padding-bottom:.5rem}
.vcmp tr.vcmp-cat .vcmp-nm,.vcmp-rows li.vcmp-cat .vcmp-nm{color:var(--ink);text-decoration:none;font-weight:600}
.vcmp-rows li.vcmp-mem{border-color:color-mix(in oklab,var(--accent) 45%,var(--line));box-shadow:var(--rim),var(--e2)}
.vcmp-rows li.vcmp-cat{background:transparent;box-shadow:none}
.vcmp-morep{margin:.2rem 0 1rem}   /* Compare: Show more (N), the next rows in place (party-needs-4) */
/* Party needs: filters to check off (party-needs-5): a panel under the search (a sheet from the bottom on a phone), the
   kinds, the kind's filters and How you get it with their counts; the checked ones as chips under the search. */
.ui-spill-bar{position:relative}
.vfp{--vfp-edge:color-mix(in oklab,var(--line) 40%,var(--ink) 60%);position:absolute;z-index:30;left:0;right:0;top:calc(100% + .5rem);max-height:min(70vh,40rem);overflow:auto;padding:1rem 1.15rem .9rem;border:1px solid var(--line-strong);border-radius:var(--r-l);background:var(--card);box-shadow:var(--rim),var(--e2),0 0 0 100vmax rgba(0,0,0,.4)}
.vfp[hidden]{display:none}
.vfp-in{position:relative}
.vfp-x{position:absolute;top:-.45rem;right:-.5rem;display:grid;place-items:center;width:2.6rem;height:2.6rem;padding:0;border:1px solid var(--vfp-edge);border-radius:50%;background:var(--card-hi);color:var(--ink);font:700 1rem/1 var(--sans);cursor:pointer}
.vfp-x:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.vfp-in>.vfp-h:first-of-type{padding-right:3rem}
html.vfp-on .rp-float,html.vfp-on .vview{display:none}   /* "Something look wrong?" and the map's List button not over the panel, at every width */
.vfp-h{margin:0 0 .5rem;font:700 var(--fs-xs)/1.25 var(--sans);text-transform:uppercase;letter-spacing:.06em;color:var(--muted)}
.vfp-kinds{display:flex;gap:.4rem;flex-wrap:wrap;margin:0 0 1rem}
.vfp-k{display:inline-flex;align-items:center;min-height:2.3rem;padding:.4rem .8rem;border:1px solid var(--vfp-edge);background:var(--card-hi);border-radius:999px;font:600 var(--fs-s)/1 var(--sans);color:var(--ink);text-decoration:none}
.vfp-k[aria-current="true"]{background:var(--ink);color:var(--card);border-color:var(--ink)}
/* the tiles wrap to the panel at every width and text size: never wider than it, a long label wraps (David saw them cut at ~1000px) */
.vfp-f{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,11rem),1fr));gap:.4rem .6rem;margin:0 0 1rem}
.vfp-l{min-width:0;overflow-wrap:anywhere}
/* each tile, kind and How choice outlined clearly on a lighter fill: at least 3:1 against the panel (WCAG non-text), dark and light */
label.vfp-c{display:flex;align-items:center;gap:.55rem;min-width:0;min-height:2.6rem;margin:0;padding:.45rem .65rem;border:1px solid var(--vfp-edge);background:var(--card-hi);border-radius:var(--r-m);font:600 var(--fs-s)/1.2 var(--sans);color:var(--ink);cursor:pointer}
.vfp-c input{width:1.15rem;height:1.15rem;margin:0;flex:none;accent-color:var(--accent)}
.vfp-c.on{border-color:var(--accent);background:var(--accent-bg);box-shadow:inset 0 0 0 1px var(--accent)}
.vfp-c.zero:not(.on){opacity:.55}   /* none would match with it too */
.vfp-n{margin-left:auto;color:var(--muted);font-variant-numeric:tabular-nums}
.vfp-foot{display:flex;justify-content:space-between;align-items:center;gap:.8rem;border-top:1px solid var(--line);padding-top:.8rem;position:sticky;bottom:-.9rem;background:var(--card)}
.vfp-foot .ui-note{margin:0}.vfp-foot .btn{margin:0;flex:none}
/* What a search was read as (party-needs-7): on/off chips under the search; a kind squarer, a fact plain; ▾ opens a
   tag's variants. Outlines as the filter panel's (3:1 in dark and light). */
.vread{--vr-edge:color-mix(in oklab,var(--line) 40%,var(--ink) 60%);display:flex;flex-wrap:wrap;gap:.45rem;align-items:center;margin:.7rem 0 .1rem;position:relative}
.vread-l{font:700 var(--fs-xs)/1.2 var(--sans);text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-right:.15rem}
.vrd{position:relative;display:inline-flex;align-items:center;min-height:2.4rem;border-radius:999px;border:1px solid var(--vr-edge);background:var(--card-hi);color:var(--muted)}
.vrd.kind{border-radius:.7rem}
.vrd.on{border-color:var(--accent);background:var(--accent-bg);box-shadow:inset 0 0 0 1px var(--accent);color:var(--ink)}
.vrd-t{display:inline-flex;align-items:center;gap:.45rem;min-height:2.4rem;padding:.3rem .75rem;font:600 var(--fs-s)/1.1 var(--sans);color:inherit;text-decoration:none;border-radius:inherit}
.vrd-ck{display:grid;place-items:center;flex:none;width:1.15rem;height:1.15rem;border-radius:.3rem;border:2px solid var(--muted);font-size:.72rem;line-height:1}
.vrd.on .vrd-ck{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.vrd-v{position:static}
.vrd-v>summary{list-style:none;cursor:pointer;display:grid;place-items:center;min-width:2.2rem;min-height:2.4rem;margin-left:-.35rem;padding-right:.35rem;color:var(--muted)}
.vrd-v>summary::-webkit-details-marker{display:none}
.vrd-pop{position:absolute;z-index:25;left:0;top:calc(100% + .35rem);min-width:min(17rem,calc(100vw - 2rem));padding:.35rem;border:1px solid var(--vr-edge);border-radius:var(--r-m);background:var(--card);box-shadow:var(--rim),var(--e2)}
.vrd-o{display:flex;align-items:center;gap:.55rem;min-height:2.6rem;padding:.4rem .6rem;border-radius:var(--r-s);font:600 var(--fs-s)/1.2 var(--sans);color:var(--ink);text-decoration:none}
.vrd-o.cur{background:var(--accent-bg)}
.vrd-r{flex:none;width:1rem;height:1rem;border-radius:50%;border:2px solid var(--muted)}
.vrd-o.cur .vrd-r{border-color:var(--accent);background:radial-gradient(var(--accent) 45%,transparent 50%)}
.vrd-n{margin-left:auto;color:var(--muted);font-weight:500}
.vfclear{font:600 var(--fs-s)/1 var(--sans);color:var(--focus)}
@media (max-width:40rem){
  .vfp{position:fixed;left:0;right:0;top:auto;bottom:0;max-height:85vh;border-radius:1.2rem 1.2rem 0 0;padding:.9rem 1rem calc(1rem + env(safe-area-inset-bottom))}
  .vfp::before{content:"";display:block;width:2.6rem;height:.3rem;border-radius:999px;background:var(--line-strong);margin:-.2rem auto .8rem}
  .vfp-kinds{flex-wrap:nowrap;overflow-x:auto;margin-right:-1rem;padding-right:1rem;scrollbar-width:none}.vfp-k{flex:none}
  .vfp-f{grid-template-columns:1fr 1fr}
  .vfp-foot{flex-direction:column;align-items:stretch;bottom:-1rem;padding-bottom:.4rem}.vfp-foot .btn{width:100%}
}
.vcmp-match{display:block;margin-top:.15rem;color:var(--ink);font-weight:600}   /* Compare: "Matches 2 of 3: …" under the name (party-needs-5) */
/* Party needs: where the list is looking from (party-needs-6), the line that opens "Look somewhere else" */
.vnear-row{display:flex;flex-wrap:wrap;align-items:baseline;gap:.2rem 1rem;margin:0 0 .8rem}
.vnear-d{flex:1 1 auto;min-width:0;margin:0}
.vnear-d>summary{display:flex;flex-wrap:wrap;align-items:baseline;gap:.15rem .6rem;color:var(--ink);font-weight:400}
.vnear-at{font:400 var(--fs-m)/1.35 var(--sans);color:var(--ink)}.vnear-at b{font-weight:700}
.vnear-ch{font:600 var(--fs-s)/1.2 var(--sans);color:var(--focus)}
.vnear-back{font:600 var(--fs-s)/1.2 var(--sans);color:var(--focus);white-space:nowrap}
.ui-mark{display:block;margin:.1rem 0;font:700 var(--fs-xs)/1.3 var(--sans);color:var(--ok);letter-spacing:.02em}
.vcard-mem{grid-column:1 / -1;border-color:color-mix(in oklab,var(--accent) 45%,var(--line));box-shadow:var(--rim),var(--e2)}
.vcard-mem>.vcard-sum{display:grid;grid-template-columns:minmax(0,15rem) 1fr;grid-template-rows:1fr auto}
.vcard-mem>.vcard-sum>.ui-media{grid-row:1 / span 2;height:auto;min-height:12.5rem}
.vcard-mem>.vcard-sum>.vcard-acts{grid-column:2;margin:0;padding:0 1rem 1rem}
.vcard-cat{grid-column:1 / -1;border-radius:var(--r-m);background:transparent;box-shadow:none}
.vcat-row{display:flex;align-items:center;justify-content:space-between;gap:.8rem;padding:.6rem .9rem}
.vcat-row .ui-main{min-width:0}.vcat-row .ui-title{font-size:var(--fs-m)}.vcat-row .ui-facts{margin-top:.1rem}
.vcat-acts{display:flex;align-items:center;gap:.6rem;flex:none}.vcat-acts .btn{margin:0}
.vcat-more{font:600 var(--fs-s)/1.2 var(--sans);color:var(--focus)}
.ui-tiles:has(> .vcard-cat){gap:.45rem}
@media (max-width:40rem){
  .vcard-mem>.vcard-sum{grid-template-columns:6.5rem 1fr;grid-template-rows:auto auto}
  .vcard-mem>.vcard-sum>.ui-media{grid-row:1;height:6.5rem;min-height:0;margin:.9rem 0 0 .9rem;border-radius:var(--r-m);font-size:2.4rem}
  .vcard-mem>.vcard-sum>.vcard-acts{grid-column:1 / -1;padding:0 .9rem .9rem}.vcard-mem .vcard-acts .btn{flex:1}
  .vcat-row{padding:.55rem .75rem}.vcat-more{display:none}
}
.ui-rate{display:block;margin:.05rem 0 .2rem;font:600 var(--fs-s)/1.3 var(--sans);color:var(--ink)}   /* a member's rating, right under the name */
.vcard .ui-key{font:600 var(--fs-m)/1.3 var(--sans);color:var(--ink);white-space:normal}   /* a member's price beside their name, in the card's own type */
.ui-tile-acts{display:flex;gap:.5rem;margin-top:.8rem}
.ui-tile-acts>*{flex:1;text-align:center;margin:0}
.ui-tile-acts .btn{display:inline-flex;align-items:center;justify-content:center;gap:.4rem;padding:.65rem .8rem;font-size:var(--fs-m)}
.ui-tile[open] .ui-tile-acts .ui-opens{display:none}
.ui-tile .ui-body{border-top:1px solid var(--line)}
/* a kind's picture when there's no photo: its colours and its sign */
.k-cake{--g1:#f7c9a6;--g2:#eb9fb4}.k-rentals{--g1:#c9e3d3;--g2:#9cc9b6}.k-catering{--g1:#f3e3b5;--g2:#e9b98c}.k-bar{--g1:#cfe0f5;--g2:#a9c1ea}
.k-flowers{--g1:#f6cfe0;--g2:#d8b6ec}.k-music{--g1:#d9d2f0;--g2:#b8c6ee}.k-photobooth{--g1:#ffe0b3;--g2:#f5b98e}.k-decor{--g1:#ffd6d6;--g2:#f7b0c8}
.k-entertain{--g1:#d7f0c8;--g2:#b5dea1}.k-favors{--g1:#fde7c4;--g2:#f3c7a6}.k-gifts{--g1:#f9d4c6;--g2:#eab0b8}.k-kits{--g1:#dff0f2;--g2:#b9dbe4}
.k-toppers{--g1:#fbe2ea;--g2:#e8c1d8}.k-printables{--g1:#e6e2da;--g2:#cfc6b6}
:root[data-theme="dark"] .ui-media{background:linear-gradient(135deg,color-mix(in oklab,var(--g1,#f3e3b5) 38%,#1a1410),color-mix(in oklab,var(--g2,#e9b98c) 38%,#1a1410))}
/* Party needs: Cards | Compare (David, 2026-09-30: "having a list view will be good to compare"). Compare is the same
   vendors side by side: a table on a laptop (its headings sort), two-line rows with one Sort by on a phone (no table
   that scrolls sideways); on a laptop the map becomes a short strip above the table. The top spot is first, tinted. */
.vlayout a{white-space:nowrap}
/* Party needs: how far to look, "Within 10 · 15 · 25 · 50 miles" (a form: each number saves it on the party) */
.vwithin{display:flex;flex-wrap:wrap;align-items:center;gap:.2rem .6rem;margin:0 0 .5rem}.vwithin .ui-seg{margin:0}.vwithin .ui-seg button{padding:.55rem .8rem;font-variant-numeric:tabular-nums}
.ui-map-reach{stroke:var(--accent);stroke-width:2;stroke-dasharray:6 6;fill:var(--accent);fill-opacity:.06}
/* Party needs › Contact: "Share with {business}: ☑ email ☑ phone · Change" (what we know, shared with permission) */
.vshare{border:0;margin:.4rem 0 .7rem;padding:0;min-width:0}
.vshare>legend{padding:0;margin:0 0 .35rem;font:600 var(--fs-s)/1.3 var(--sans);color:var(--ink)}
label.vshare-o{display:inline-flex;align-items:center;gap:.45rem;margin:0 1rem .35rem 0;font-weight:400;cursor:pointer;overflow-wrap:anywhere}
label.vshare-o[hidden]{display:none}
.vshare-o>input{width:1.2rem;height:1.2rem;margin:0;flex:none;accent-color:var(--accent)}
.vshare-ch{border-top:0;padding-top:0;margin:0}
.vshare-f{display:grid;gap:.4rem;margin:.2rem 0 .4rem}
.vwithin-l{font:600 var(--fs-s)/1.2 var(--sans);color:var(--muted)}
.vcmp-wrap{display:none;overflow:hidden;overflow-x:auto;border:1px solid var(--line);border-radius:var(--r-m);background:var(--card);box-shadow:var(--rim),var(--e1);margin:0 0 1rem}
.vcmp{width:100%;border-collapse:collapse;font:400 var(--fs-s)/1.35 var(--sans);color:var(--ink)}
.vcmp th{text-align:left;padding:.7rem .8rem;background:var(--card-hi);color:var(--muted);font:700 var(--fs-xs)/1.2 var(--sans);text-transform:uppercase;letter-spacing:.06em;border-bottom:1px solid var(--line);white-space:nowrap}
.vcmp th a{color:inherit;text-decoration:none}.vcmp th a:hover{text-decoration:underline}.vcmp th[aria-sort]{color:var(--ink)}
.vcmp-ar{display:inline-block;min-width:1em;color:var(--accent)}
.vcmp td{padding:.7rem .8rem;border-bottom:1px solid var(--line);vertical-align:top}
.vcmp tr:last-child td{border-bottom:0}
.vcmp tr.top td,.vcmp-rows li.top{background:color-mix(in oklab,var(--accent-bg) 75%,var(--card))}
.vcmp-n{font-variant-numeric:tabular-nums;white-space:nowrap}
.vcmp-nm{font-weight:700}
.vcmp-dim{color:var(--muted)}
.vcmp .ui-pill{margin-top:.25rem;white-space:normal;text-align:left}   /* a long offer wraps in its cell, so the table fits its box (the Contact column was cut off) */
.vcmp-act{text-align:right;white-space:nowrap}
.vcmp-rows{list-style:none;margin:0 0 1rem;padding:0}
.vcmp-l1{display:flex;justify-content:space-between;align-items:baseline;gap:.6rem;margin:0}
.vcmp-pr{font:700 var(--fs-s)/1.3 var(--sans);white-space:nowrap}
.vcmp-rows .ui-facts{margin-top:.2rem}
.vcmp-sortby{display:flex;align-items:center;gap:.5rem;margin:.2rem 0 .8rem;font:600 var(--fs-s)/1 var(--sans)}
.vcmp-sortby select{flex:1;min-width:0;min-height:2.75rem}
@media (max-width:55.99rem){.vcompare .vsort{display:none}}
@media (min-width:56rem){
  .vcmp-wrap{display:block}.vcmp-rows,.vcmp-sortby{display:none}
  .ui-finder.vcompare{display:block}
  .ui-finder.vcompare>.ui-map{position:relative;top:auto;height:15rem;margin:0 0 1.2rem}
}
@media (min-width:56rem){
  .ui-finder{display:grid;grid-template-columns:minmax(0,1fr) 42%;gap:1.5rem;align-items:start}
  .ui-finder .ui-sheet{order:1;margin:0;padding:0 0 3rem;background:transparent;border-radius:0;box-shadow:none!important}
  .ui-finder .ui-sheet::before{display:none}
  /* wider than the page's reading column: the list and the map side by side */
  .ui-finder,.ui-wide{width:min(76rem,100vw - 3rem);margin-left:calc(50% - min(38rem,50vw - 1.5rem))}
  .ui-wide .ui-spill-bar{margin:0;padding-left:0;padding-right:0}.ui-wide .ui-spill{max-width:46rem}
  .ui-wide .ui-rail{margin-left:0;margin-right:0;padding-left:0}
  .ui-finder>.ui-map,.ui-finder>.ui-mapwrap{order:2;position:sticky;top:5rem;height:calc(100vh - 6rem);margin:0}
  .ui-tiles{display:grid;grid-template-columns:1fr 1fr;gap:1rem;align-items:start}.ui-tiles>.ui-card{margin:0}
  .ui-float{display:none}
}

/* ---------- a guest's invitation (src/worker.js rsvpPage, inviteTop): the picture first, the answer always in reach ----------
   (David, 2026-09-26, the guest-page mockup: "yes… start with the guest page". Patterns from Partiful (the picture on a
   blurred copy of itself, one floating answer pill, big choices, the answer as a sheet), Apple Invites (faces and badges
   laid on the picture, a row of round actions), Luma (date and place as icon tiles; two columns on desktop), Evite (the
   answer pinned as "Change"). The answer is a page of its own now (rule 1; /r/<token>/answer): the big choices, the
   pill and "Change" are links to it. html.ui-js: the page's script runs. */
:root{--serif:Georgia,"Times New Roman","Songti SC","Noto Serif CJK SC","Noto Serif SC","Source Han Serif SC",STSong,SimSun,"Songti TC","Noto Serif CJK TC","Noto Serif TC","Source Han Serif TC",PMingLiU,MingLiU,serif}
/* A Traditional Chinese page (lang="zh-Hant") names the Traditional faces first, so a character both scripts share is drawn
   the Taiwan way. */
:root:lang(zh-Hant){--sans:-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,"PingFang TC","Noto Sans CJK TC","Noto Sans TC","Source Han Sans TC","Microsoft JhengHei","PingFang SC","Hiragino Sans GB","Noto Sans CJK SC","Noto Sans SC","Source Han Sans SC","Microsoft YaHei",sans-serif;--serif:Georgia,"Times New Roman","Songti TC","Noto Serif CJK TC","Noto Serif TC","Source Han Serif TC",PMingLiU,MingLiU,"Songti SC","Noto Serif CJK SC","Noto Serif SC","Source Han Serif SC",STSong,SimSun,serif}
html:not(.ui-js) [data-ui-js]{display:none!important}
/* the top of a guest's page: the back link, when there is one (the language choice is in the Aa menu: rule 12) */
.ui-guesttop{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:.3rem .8rem;margin:0 0 .4rem}
.ui-guesttop+.ui-pagehead{margin-top:.5rem}
/* the language in the Aa menu (rule 12; David, 2026-09-27: "the language selector that should be in the Aa setting"):
   the button shows its code ("Aa · ES"), the menu's first choice is Language, each in its own words */
.disp-btn .disp-lang{white-space:pre;font:700 var(--fs-xs)/1 var(--sans)}
/* The languages: English, and a list of all the others beside it, so more languages never change the layout (David,
   2026-09-28). The list's own Go button only shows where scripts don't run. */
.disp-panel .seg.langs{margin:0;display:grid;grid-template-columns:auto minmax(0,1fr)}
.disp-panel .seg.langs button{padding:.5rem .8rem;font-size:var(--fs-s);line-height:1.2}
.disp-panel .lang-other{display:flex;min-width:0}
.disp-panel .lang-other select{flex:1;min-width:0;min-height:2.6rem;padding:.4rem .5rem;border:1px solid var(--line);border-radius:.5rem;background:var(--bg);color:var(--ink);font:600 var(--fs-s)/1.2 var(--sans)}
.disp-panel .lang-other.on select{border:2px solid var(--accent);background:var(--accent-bg);color:var(--accent)}
.disp-panel .lang-other .lang-go{flex:none;margin-left:.3rem}
/* Theme: Auto across the top, Light and Dark side by side below it, so a longer word ("Automático") always fits. */
.disp-panel .seg:not(.sizes):not(.langs){display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
.disp-panel .seg:not(.sizes):not(.langs) button{padding:.55rem .4rem;font-size:var(--fs-s)}
.disp-panel .seg:not(.sizes):not(.langs) button:first-child{grid-column:1 / -1}
/* faces: initials in a coloured circle (never a photo) */
.ui-av{display:inline-grid;place-items:center;flex:none;width:2.4rem;height:2.4rem;border-radius:50%;font:800 .78rem/1 var(--sans);color:#fff;border:2px solid var(--card);background:var(--c,#a8581a);letter-spacing:0}
.ui-c1{--c:#c05a2b}.ui-c2{--c:#3f7d5c}.ui-c3{--c:#6a5acd}.ui-c4{--c:#b0476e}.ui-c5{--c:#2f6f9f}.ui-c6{--c:#8a6d1f}.ui-c7{--c:#5b6b7a}
.ui-av-han{font-size:.74em;letter-spacing:-.06em}   /* two Chinese characters are wider than two capitals */
.ui-ico-tile.faces .ui-av:has(.ui-av-han)+.ui-av,.ui-stack .ui-av:has(.ui-av-han)+.ui-av,.ui-faces .ui-av:has(.ui-av-han){margin-left:-.15rem}   /* and aren't hidden under the next face */
.ui-stack{display:flex;align-items:center;margin:.6rem 0 .3rem}.ui-stack .ui-av+.ui-av{margin-left:-.45rem}
.ui-stack .ui-more-n{background:var(--zone);color:var(--ink);border-color:var(--card)}
/* the host's picture, on a blurred copy of itself that fades into the page; badges and faces laid on it */
.ui-poster{position:relative;isolation:isolate;margin:0 0 .4rem}
.ui-above{position:relative;z-index:2}   /* a notice above the picture: over its blurred copy, not under it */
.ui-poster::before{content:"";position:absolute;inset:-4.5rem -1.1rem -4rem;z-index:-1;background:var(--pic) center/cover no-repeat;filter:blur(38px) saturate(1.15);opacity:.55;-webkit-mask:linear-gradient(#000 55%,transparent);mask:linear-gradient(#000 55%,transparent);pointer-events:none}
:root[data-theme="dark"] .ui-poster::before{opacity:.38}
.ui-poster-in{position:relative;width:fit-content;max-width:100%;margin:0 auto;border-radius:1.25rem;overflow:hidden;box-shadow:var(--e2),var(--rim);background:var(--card)}
.ui-poster-in img{display:block;max-width:100%;max-height:62vh;width:auto;height:auto}
.ui-poster.short .ui-poster-in{width:100%}.ui-poster.short .ui-poster-in img{width:100%;height:13.5rem;max-height:none;object-fit:cover;object-position:center 35%}
.ui-onpic{position:absolute;z-index:2;display:inline-flex;align-items:center;gap:.4rem;max-width:calc(100% - 1.4rem);font:700 var(--fs-xs)/1.2 var(--sans);padding:.3rem .65rem;border-radius:999px;background:var(--card);color:var(--ink);box-shadow:var(--e1)}
.ui-onpic.tl{left:.7rem;top:.7rem}.ui-onpic.tr{right:.7rem;top:.7rem}
.ui-onpic:has(.ui-av){padding-left:.3rem}
.ui-onpic .ui-av{width:1.5rem;height:1.5rem;font-size:.6rem;border-width:0}
.ui-onpic.ok{background:var(--ok);color:#fff}:root[data-theme="dark"] .ui-onpic.ok{color:#10240f}
/* your own picture, and the party's name, date, time or place changed since (David, 2026-09-29): a warning, in its tone */
.ui-onpic.warn{background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn)}
.ui-faces{position:absolute;right:.7rem;bottom:.7rem;z-index:2;display:flex;align-items:center;padding:.25rem .6rem .25rem .3rem;border-radius:999px;background:color-mix(in oklab,var(--card) 88%,transparent);backdrop-filter:blur(8px);box-shadow:var(--e1);font:700 var(--fs-xs)/1 var(--sans);color:var(--ink)}
.ui-faces .ui-av{width:1.6rem;height:1.6rem;font-size:.55rem;margin-right:-.3rem}.ui-faces b{margin-left:.7rem}
/* the title, the greeting */
.ui-invite-title{font:700 var(--fs-2xl)/1.12 var(--serif);color:var(--head);letter-spacing:-.015em;margin:1.1rem 0 .2rem;text-wrap:balance;overflow-wrap:anywhere}
.ui-invite-lead{margin:0 0 .9rem;color:var(--muted);font-size:var(--fs-m)}
/* when, where, who: icon tiles, each with its one action at the end */
.ui-plan{list-style:none;margin:0 0 1rem;padding:0;display:flex;flex-direction:column;gap:.15rem}
.ui-plan-i{display:flex;align-items:center;gap:.8rem;padding:.45rem 0}
.ui-ico-tile{flex:none;display:grid;place-items:center;width:2.9rem;height:2.9rem;border-radius:.75rem;background:var(--card);box-shadow:var(--rim),var(--e1);color:var(--accent)}
.ui-ico-tile svg{width:1.3rem;height:1.3rem}
.ui-ico-tile.cal{display:flex;flex-direction:column;overflow:hidden}
.ui-ico-tile.cal i{display:block;width:100%;text-align:center;font:800 .6rem/1.5 var(--sans);letter-spacing:.08em;background:var(--accent);color:var(--accent-ink);font-style:normal}
.ui-ico-tile.cal b{flex:1;display:grid;place-items:center;font:800 1.05rem/1 var(--sans);color:var(--ink)}
.ui-ico-tile.faces{background:none;box-shadow:none}.ui-ico-tile.faces .ui-av{width:1.9rem;height:1.9rem;font-size:.62rem}.ui-ico-tile.faces .ui-av+.ui-av{margin-left:-.6rem}
.ui-ico-tile.faces{display:flex;align-items:center;justify-content:center}
.ui-plan-t{flex:1;min-width:0;overflow-wrap:anywhere}.ui-plan-t b{display:block;font-weight:700;font-size:var(--fs-m);color:var(--ink)}.ui-plan-t span{display:block;color:var(--muted);font-size:var(--fs-s);line-height:1.35}
.ui-mini{flex:none;display:inline-flex;align-items:center;gap:.3rem;min-height:2.5rem;padding:0 .85rem;border-radius:999px;border:1px solid var(--line-strong);background:var(--card);color:var(--ink);font:700 var(--fs-s)/1 var(--sans);text-decoration:none;box-shadow:0 1px 2px var(--shadow);cursor:pointer;white-space:nowrap}
.ui-mini:hover{border-color:var(--accent)}
/* the answer box: its own raised card with a head strip, three big choices */
.ui-answer-card{overflow:hidden;box-shadow:var(--rim),var(--e2);border-color:color-mix(in oklab,var(--accent) 35%,var(--line))}
.ui-answer-strip{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.2rem .5rem;padding:.55rem 1.1rem;background:var(--accent-bg);color:var(--head);font:700 var(--fs-s)/1.3 var(--sans);border-bottom:1px solid var(--line)}
.ui-answer-strip span{font-weight:600;color:var(--muted)}
.ui-answer-in{padding:1rem 1.1rem 1.1rem}
.ui-answer-h{font:700 var(--fs-xl)/1.2 var(--serif);color:var(--head);margin:0 0 .8rem}
.ui-answer-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.5rem}
.ui-big-choice{text-decoration:none}
.ui-big-choice,.choice.ui-answer label{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35rem;min-height:5.2rem;padding:.6rem .3rem;margin:0;border:1.5px solid var(--line-strong);border-radius:1rem;background:var(--card);color:var(--ink);font:700 var(--fs-m)/1.1 var(--sans);text-align:center;cursor:pointer;box-shadow:0 1px 2px var(--shadow)}
.ui-big-choice:hover,.choice.ui-answer label:hover{border-color:var(--accent)}
.choice.ui-answer{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.5rem;margin:.2rem 0 .4rem}
.choice.ui-answer label{min-width:0;min-height:4.6rem}
.choice.ui-answer label:has(input:checked){border-color:var(--accent);background:var(--accent-bg);color:var(--head);box-shadow:0 0 0 3px color-mix(in oklab,var(--accent) 25%,transparent)}
.ui-e{font-size:1.9rem;line-height:1}
/* who's going: faces, the numbers, then the names */
.ui-counts{display:flex;flex-wrap:wrap;gap:.4rem;margin:.4rem 0 .2rem}
.ui-people{list-style:none;margin:.4rem 0 0;padding:0}
.ui-people li{display:flex;align-items:center;gap:.7rem;padding:.5rem 0;border-top:1px solid var(--line)}
.ui-people li:first-child{border-top:0}
.ui-people .ui-av{width:2.1rem;height:2.1rem;font-size:.66rem}
.ui-people-n{flex:1;min-width:0;font-weight:600;overflow-wrap:anywhere}.ui-people-n span{display:block;font-weight:400;color:var(--muted);font-size:var(--fs-s)}
.ui-people li.ui-me{background:var(--accent-bg);margin:0 -1.1rem;padding:.5rem 1.1rem;border-top-color:transparent}
.ui-people+.ui-more>summary{margin-bottom:0}
/* items to bring: each a row with how full it is */
.ui-items{list-style:none;margin:.5rem 0 0;padding:0;display:flex;flex-direction:column;gap:.75rem}
.ui-items-h{display:flex;justify-content:space-between;align-items:baseline;gap:.5rem;font-weight:700;color:var(--ink)}
.ui-items-h span{font-weight:600;font-size:var(--fs-s);color:var(--muted);white-space:nowrap}
.ui-items-h span.done{color:var(--ok)}
.ui-items-who{font-size:var(--fs-s);color:var(--muted);margin:.25rem 0 0;overflow-wrap:anywhere}.ui-items-who b{color:var(--head)}
.ui-items .ui-meter{margin-top:.35rem}
.ui-meter.full::-webkit-progress-value{background:var(--ok)}.ui-meter.full::-moz-progress-bar{background:var(--ok)}
.ui-foot{text-align:center;font-size:var(--fs-xs);color:var(--muted);margin:1.4rem 0 0;line-height:1.6}
/* one floating pill: the answer, always in sight (phones) */
.ui-dock{position:fixed;left:1rem;right:1rem;bottom:max(1rem,env(safe-area-inset-bottom));z-index:30;display:flex;align-items:center;gap:.1rem;max-width:26rem;margin:0 auto;padding:.3rem;border-radius:999px;background:var(--ink);color:var(--bg);box-shadow:var(--e3)}
.ui-dock a{text-decoration:none}
.ui-dock button,.ui-dock a{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:.35rem;min-height:2.9rem;min-width:0;padding:0 .5rem;border:0;border-radius:999px;background:transparent;color:inherit;font:700 var(--fs-m)/1 var(--sans);cursor:pointer;white-space:nowrap}
.ui-dock button:hover,.ui-dock a:hover{background:color-mix(in oklab,var(--bg) 14%,transparent)}
.ui-dock button:focus-visible,.ui-dock a:focus-visible{outline:3px solid var(--focus);outline-offset:1px}
.ui-dock .ui-e{font-size:1.25rem}
.ui-dock-sep{flex:none;width:1px;align-self:stretch;margin:.6rem 0;background:color-mix(in oklab,var(--bg) 30%,transparent)}
.ui-dock.status{padding:.35rem .35rem .35rem 1rem;gap:.7rem}
.ui-dock-st{flex:1;min-width:0;display:flex;align-items:center;gap:.5rem;font:700 var(--fs-m)/1.15 var(--sans)}
.ui-dock-st>span:last-child{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ui-dock-st small{display:block;font:500 var(--fs-xs)/1.25 var(--sans);opacity:.8;overflow:hidden;text-overflow:ellipsis}
.ui-dock .ui-dock-chg{flex:none;padding:0 1.1rem;min-height:2.6rem;background:var(--accent);color:var(--accent-ink);font-size:var(--fs-s)}
.ui-dock .ui-dock-chg:hover{background:var(--accent)}
.ui-dock a.ui-dock-chg{display:inline-flex;align-items:center}
.ui-dot{flex:none;display:grid;place-items:center;width:1.6rem;height:1.6rem;border-radius:50%;background:var(--ok);color:#fff;font-size:.9rem}
:root[data-theme="dark"] .ui-dot{color:#10240f}
.ui-dot.maybe{background:var(--warn)}.ui-dot.no{background:var(--muted)}
main:has(>.ui-dock){padding-bottom:6.5rem}
/* A bar pinned to the bottom (Next, the dock, the tab bar) never covers the page's last lines or the footer links. */
main:has(.ui-actbar:not([hidden]),.ui-pinbar:not([hidden]),.ui-tabbar,.ui-dock)>.legal{margin-bottom:calc(8.5rem + env(safe-area-inset-bottom,0px))}
/* the answer page (/r/<token>/answer): the questions in one card, Send pinned at the foot (.ui-actbar, its line
   beside Send says the answer so far) */
.ui-answer-form{margin:0}
.ui-answer-set{border:0;margin:0;padding:0;min-width:0}
.ui-answer-form .ui-actbar-say{white-space:normal;overflow:visible}
.ui-answer-form .ui-actbar-say b{white-space:normal}
body.embed .ui-answer-form>.ui-card{border:0;box-shadow:none;padding:0;background:transparent}
.ui-q{display:block;font:700 var(--fs-m)/1.3 var(--sans);color:var(--ink);margin:1.1rem 0 .15rem}
.ui-q+.hint,.ui-q+.ui-hint{margin:0 0 .5rem}
/* how many: − n + */
.ui-steps-list{display:flex;flex-direction:column;gap:.5rem;margin:.4rem 0 0}
.ui-stepper{display:flex;align-items:center;justify-content:space-between;gap:.5rem;background:var(--card);border:1px solid var(--line);border-radius:var(--r-m);padding:.4rem .5rem .4rem 1rem;box-shadow:var(--rim),0 1px 2px var(--shadow)}
.ui-stepper .ui-stepper-l{flex:1;min-width:0;margin:0;font:700 var(--fs-m)/1.25 var(--sans);color:var(--ink)}
.ui-stepper-c{flex:none;display:flex;align-items:center;gap:.2rem}
.ui-stepper .ui-stepper-c input{width:2.8rem;min-height:2.75rem;padding:0;margin:0;border:0;background:transparent;text-align:center;font:800 var(--fs-l)/1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums;-moz-appearance:textfield;appearance:textfield}
.ui-stepper input::-webkit-inner-spin-button,.ui-stepper input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
html:not(.ui-js) .ui-stepper input{border:1px solid var(--line-strong);border-radius:var(--r-s);background:var(--bg);width:4.5rem}
.ui-step-b{display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;border:1.5px solid var(--line-strong);background:var(--card);color:var(--ink);font:600 1.3rem/1 var(--sans);cursor:pointer}
.ui-step-b.plus{border-color:var(--accent);color:var(--accent)}
html:not(.ui-js) .ui-step-b{display:none}
/* people you answer for: tap-to-add chips */
.ui-togs{display:flex;flex-wrap:wrap;gap:.4rem;margin:.3rem 0 0}
.ui-tog{position:relative;display:inline-flex;align-items:center;gap:.5rem;min-height:2.75rem;margin:0;padding:.2rem .9rem .2rem .3rem;border-radius:999px;border:1.5px solid var(--line-strong);background:var(--card);color:var(--ink);font:700 var(--fs-m)/1.2 var(--sans);cursor:pointer}
.ui-tog input{position:absolute;inset:0;width:100%;height:100%;margin:0;padding:0;opacity:0;cursor:pointer}
.ui-tog .ui-av{width:2rem;height:2rem;font-size:.62rem;border-width:0}
.ui-tog-ck{color:var(--accent);visibility:hidden}
.ui-tog:has(input:checked){border-color:var(--accent);background:var(--accent-bg);color:var(--head)}
.ui-tog:has(input:checked) .ui-tog-ck{visibility:visible}
.ui-tog:has(input:focus-visible),.ui-claim:has(>label input:focus-visible){outline:3px solid var(--focus);outline-offset:2px}
/* items to bring, to pick: each a row with how full it is */
.ui-claims{display:flex;flex-direction:column;gap:.5rem;margin:.4rem 0 0}
.ui-claims>div.ui-claim{position:relative;border:1.5px solid var(--line);border-radius:var(--r-m);background:var(--card);padding:.7rem .9rem;box-shadow:0 1px 2px var(--shadow)}
.ui-claim>label{position:relative;display:block;margin:0;cursor:pointer;font-weight:400}
.ui-claim>label>input{position:absolute;inset:-.7rem -.9rem;width:calc(100% + 1.8rem);height:calc(100% + 1.4rem);margin:0;opacity:0;cursor:pointer}
.ui-claim-h{display:flex;justify-content:space-between;align-items:baseline;gap:.5rem;font-weight:700;color:var(--ink)}
.ui-claim-h span{font-weight:600;font-size:var(--fs-s);color:var(--muted);white-space:nowrap}
.ui-claim-who{display:block;font-size:var(--fs-s);color:var(--muted);margin-top:.25rem}
.ui-claim:has(>label input:checked){border-color:var(--accent);background:var(--accent-bg);box-shadow:0 0 0 3px color-mix(in oklab,var(--accent) 22%,transparent)}
.ui-claim:has(>label input:checked) .ui-claim-h span{color:var(--head)}
.ui-claim:has(>label input:disabled){opacity:.6;box-shadow:none;background:transparent;border-style:dashed}
.ui-claim:has(>label input:disabled)>label{cursor:default}
.ui-claim .ask-detail{position:relative;z-index:1;display:block;width:100%;margin:.6rem 0 0}
.ui-claim .ask-detail[hidden]{display:none}
/* after answering: a status card laid over the picture, with round actions */
.ui-ticket{position:relative;z-index:3;padding:1.1rem 1.1rem 1rem;box-shadow:var(--rim),var(--e3);border-color:color-mix(in oklab,var(--ok) 35%,var(--line));text-align:center}
.ui-ticket.lift{margin:-3.2rem .6rem .9rem}
.ui-ticket-ok{display:grid;place-items:center;width:3.2rem;height:3.2rem;margin:-2.7rem auto .5rem;border-radius:50%;background:var(--ok);color:#fff;font-size:1.5rem;box-shadow:0 0 0 5px var(--card),var(--e1)}
:root[data-theme="dark"] .ui-ticket-ok{color:#10240f}
.ui-ticket-ok.maybe{background:var(--warn)}.ui-ticket-ok.no{background:var(--muted)}
.ui-ticket:not(.lift) .ui-ticket-ok{margin-top:0}
.ui-ticket-h{font:700 var(--fs-2xl)/1.1 var(--serif);color:var(--head);margin:0 0 .35rem}
.ui-ticket p{margin:0;color:var(--muted)}
.ui-ticket .ui-pills{justify-content:center;margin:.75rem 0 0}
.ui-acts{display:flex;justify-content:center;gap:.4rem;margin:1rem 0 .1rem}
.ui-act{flex:0 1 7rem;display:flex;flex-direction:column;align-items:center;gap:.4rem;padding:0;border:0;background:none;color:var(--ink);font:600 var(--fs-s)/1.15 var(--sans);text-align:center;text-decoration:none;cursor:pointer}
.ui-act-r{display:grid;place-items:center;width:3.25rem;height:3.25rem;border-radius:50%;background:var(--accent-bg);color:var(--accent);box-shadow:var(--rim),var(--e1)}
.ui-act-r svg{width:1.35rem;height:1.35rem}
.ui-act:hover .ui-act-r{box-shadow:var(--rim),var(--e2)}
/* the link to the photo page, on the invitation */
.ui-afterlink{display:block;text-decoration:none;color:var(--ink);border:2px solid var(--accent);background:var(--accent-bg)}
.ui-afterlink b{display:block;font:700 var(--fs-l)/1.3 var(--sans);color:var(--head)}
.ui-afterlink span{display:block;font-size:var(--fs-s);color:var(--muted)}
.ui-keep{display:flex;gap:.8rem;align-items:flex-start}.ui-keep .ui-ico-tile{color:var(--focus)}
.ui-keep-t{flex:1;min-width:0}.ui-keep-t b{display:block;color:var(--ink)}.ui-keep-t>span{font-size:var(--fs-s);color:var(--muted)}
.ui-linkbox{display:flex;gap:.5rem;margin-top:.7rem}
.ui-linkbox code{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:500 var(--fs-s)/2.75 ui-monospace,Menlo,monospace;background:var(--zone);border-radius:var(--r-s);padding:0 .7rem;color:var(--muted)}
.ui-linkbox .ui-mini{border-radius:var(--r-m)}
/* desktop: two columns, the picture sticky on the left; the sheet a window in the middle */
@media (min-width:56rem){
  .ui-invite{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0 2.75rem;align-items:start}
  .ui-invite-pic{position:sticky;top:1rem}
  .ui-invite-pic .ui-poster-in{width:100%}
  .ui-invite-pic .ui-poster-in img,.ui-poster.short .ui-poster-in img{width:100%;height:auto;max-height:calc(100vh - 6rem);object-fit:contain;background:var(--card)}
  .ui-poster::before{inset:-6rem -100vw -6rem -40vw}
  .ui-invite-pic{z-index:0}.ui-invite-main{position:relative}   /* the column over the picture's blurred copy */
  .ui-invite-main .ui-invite-title{font-size:2.5rem;margin-top:.2rem}
  .ui-invite-main>.ui-ticket.lift{margin:1.6rem 0 .9rem}
  .ui-dock{display:none}
  main:has(>.ui-dock){padding-bottom:4rem}
}

/* ---------- the photo pages (src/worker.js afterPage, photoPage; public/after.js): after the party, the guests' photos and
   notes. A card each; the photos a grid of squares, each a link to its own page (rule 1: no lightbox); that page: the
   photo whole, Previous and Next, and its actions, each asked first in place (rule 9) ---------- */
.ui-photos{display:grid;grid-template-columns:repeat(auto-fill,minmax(8.5rem,1fr));gap:.5rem;margin:.3rem 0 0}
.ui-photo-t{display:block;aspect-ratio:1/1;border-radius:var(--r-m);overflow:hidden;background:var(--zone)}
.ui-photo-t img{display:block;width:100%;height:100%;object-fit:cover}
.ui-photo-t:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-photo{margin:0 0 .75rem;border-radius:var(--r-l);overflow:hidden;background:var(--card);box-shadow:var(--rim),var(--e1);text-align:center}
.ui-photo img{display:block;max-width:100%;max-height:72vh;width:auto;height:auto;margin:0 auto}
.ui-photonav{display:flex;justify-content:space-between;gap:.5rem;margin:0 0 .75rem}
.ui-photonav .btn{margin:0}
.ui-photoacts .ui-btns{margin:0}
.ui-mine{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.5rem}.ui-mine[hidden]{display:none}
.ui-mine img{width:4rem;height:4rem;object-fit:cover;border-radius:var(--r-s)}.ui-mine img.wait{opacity:.55}
.ui-camonly[hidden]{display:none}
.ui-asks{list-style:none;margin:0;padding:0}
.ui-askq{display:flex;gap:.8rem;align-items:flex-start;padding:.6rem 0;border-top:1px solid var(--line)}
.ui-askq:first-child{border-top:0}
.ui-askq img{flex:none;width:4.5rem;height:4.5rem;object-fit:cover;border-radius:var(--r-s)}
.ui-askq>div{flex:1;min-width:0}.ui-askq .ui-text{margin-top:0}
.ui-wallpost{border-top:1px solid var(--line);padding:.6rem 0}
.ui-wallpost .ui-text,.ui-wallpost .ui-note{margin:.1rem 0}
.ui-names{display:grid;grid-template-columns:repeat(auto-fill,minmax(9rem,1fr));gap:.5rem;margin:.7rem 0}
.ui-name{display:block;text-align:center;font:600 var(--fs-m)/1.3 var(--sans);text-decoration:none;color:var(--ink);background:var(--bg);border:2px solid var(--line);border-radius:var(--r-m);padding:.75rem .5rem;min-height:3rem}
.ui-name:hover,.ui-name:focus-visible{border-color:var(--accent);outline:none;background:var(--accent-bg)}

/* ---------- the host app (public/app.js): the party pill, the rail, steps as dots, one floating bar ----------
   (David, 2026-09-26, the host-app mockup: "guest page, then host app…". The vendors page's pieces, holding the party:
   the search pill becomes the party pill (Airbnb), the category rail the party's areas with their counts; Evite's editor
   steps as dots on a track; Partiful's floating Preview / Save bar as one bar of actions that never scrolls away; the
   invitation lifted on its own colours (Partiful, Apple Invites); ways to send as picture cards (Paperless Post);
   replies over the picture with a counts card (Apple Invites, Evite); a check-in list for the door (Paperless Post,
   Partiful).) */
:root{--imsg:#2f7cf6}
.ui-hostapp{padding-bottom:6rem}
/* The host's wallet on the header (vouchers v2): the amount, or "Claim $3" filled when there's some to claim. */
.ui-spill-chip{flex:none;display:inline-flex;align-items:center;min-height:2.4rem;padding:0 .85rem;border:1.5px solid var(--accent);border-radius:999px;color:var(--accent);font:700 var(--fs-s)/1 var(--sans);text-decoration:none;white-space:nowrap}
.ui-spill-chip.claim{background:var(--accent);color:var(--accent-ink)}
.ui-spill-chip[hidden]{display:none}
/* the party's steps: one-colour line icons joined by a thin track, the state as a small badge (David, 2026-09-26: not
   emoji, so they never look like the vendors page's colourful category rail under them) */
.ui-steprail{display:flex;align-items:flex-start;margin:.3rem -1rem .1rem;padding:.15rem 1rem .35rem;overflow-x:auto;scrollbar-width:none}
.ui-steprail::-webkit-scrollbar{display:none}
.ui-steprail ol{list-style:none;display:flex;flex:1 0 auto;margin:0;padding:0}
.ui-steprail li{position:relative;flex:1 0 auto;min-width:4.1rem}   /* a longer word (Spanish, Portuguese) widens its step; the rail scrolls */
.ui-steprail li+li::before{content:"";position:absolute;z-index:0;top:1.5rem;left:-50%;right:50%;height:1.5px;background:var(--line-strong)}
.ui-steprail li.done+li::before{background:var(--accent)}
.ui-steprail a,.ui-steprail button{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;gap:.22rem;width:100%;padding:.25rem .1rem .3rem;border:0;border-radius:var(--r-m);background:none;color:var(--muted);font:600 var(--fs-xs)/1.15 var(--sans);text-align:center;text-decoration:none;cursor:pointer}
.ui-steprail a:focus-visible,.ui-steprail button:focus-visible{outline:3px solid var(--focus);outline-offset:-2px}
.ui-steprail-ic{display:grid;place-items:center;width:2.5rem;height:2.5rem;border-radius:50%;background:var(--bg);border:1.5px solid var(--line-strong);color:var(--muted)}
.ui-steprail-ic svg{width:1.25rem;height:1.25rem}
.ui-steprail .done .ui-steprail-ic{border-color:var(--accent);color:var(--accent)}
.ui-steprail [aria-current] .ui-steprail-ic,.ui-steprail [aria-expanded="true"] .ui-steprail-ic{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);box-shadow:0 0 0 4px color-mix(in oklab,var(--accent) 20%,transparent)}
.ui-steprail [aria-current],.ui-steprail [aria-expanded="true"]{color:var(--ink)}
.ui-steprail a:hover .ui-steprail-ic,.ui-steprail button:hover .ui-steprail-ic{border-color:var(--accent)}
.ui-steprail-l{white-space:nowrap;padding:0 .2rem}
.ui-steprail-n{white-space:nowrap;padding:.02rem .42rem;border-radius:999px;background:var(--card);box-shadow:0 1px 3px var(--shadow);color:var(--ink);font:800 .7rem/1.3 var(--sans)}
.ui-steprail-n.ok{background:var(--ok-bg);color:var(--ok)}
.ui-steprail-ns{display:none}   /* a count's short form ("11"), shown on a phone only (public/ui.js stepRail short) */
.ui-steprail [aria-current] .ui-steprail-n{background:var(--accent);color:var(--accent-ink)}
.ui-steprail .ui-steprail-more{flex:none;width:3.3rem;margin-left:.2rem;border-left:1px dashed var(--line-strong);border-radius:0}
/* steps as dots joined by a track: done ✓, the current one ringed, the rest to come */
.ui-track{list-style:none;display:flex;align-items:flex-start;margin:.35rem 0 .2rem;padding:0}
.ui-track li{position:relative;flex:1 1 0;min-width:0}
.ui-track li+li::before{content:"";position:absolute;z-index:0;top:1.2rem;left:-50%;right:50%;height:2px;background:var(--line-strong)}
.ui-track li.done+li::before{background:var(--accent)}
/* a step: a button (the host app's flows), or a link back to a done step and a plain item (Join, drawn on the server) */
.ui-track :is(button,a,.ui-track-i){position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;gap:.3rem;width:100%;min-height:2.75rem;padding:.35rem .1rem;border:0;background:none;color:var(--muted);font:600 var(--fs-xs)/1.2 var(--sans);text-align:center;text-decoration:none;cursor:pointer}
.ui-track .ui-track-i,.ui-track button:disabled{cursor:default}
.ui-track a:hover{color:var(--ink)}
.ui-track :is(button,a):focus-visible{outline:3px solid var(--focus);outline-offset:-3px;border-radius:var(--r-s)}
.ui-track small{display:block;font-weight:500;font-size:.7rem}
.ui-track-n{display:grid;place-items:center;width:1.7rem;height:1.7rem;border-radius:50%;background:var(--card);border:2px solid var(--line-strong);font:800 var(--fs-xs)/1 var(--sans);color:var(--muted)}
.ui-track .done .ui-track-n{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.ui-track .cur :is(button,.ui-track-i){color:var(--ink)}
.ui-track .cur .ui-track-n{border-color:var(--accent);color:var(--accent);box-shadow:0 0 0 4px color-mix(in oklab,var(--accent) 22%,transparent)}
/* seven steps or more (Join) on a phone: a little wider and smaller, so each name fits under its dot */
/* A track of 7 or more on a phone (Join): only the current step's name shows under the dots; the others keep theirs
   for screen readers (font-size 0 hides the words, not the name). David, 2026-09-27, "ok" — the seven names were 10.5px. */
@media (max-width:30rem){.ui-track:has(>li:nth-child(7)){margin-left:-.5rem;margin-right:-.5rem}.ui-track:has(>li:nth-child(7)) :is(button,a,.ui-track-i){padding-left:0;padding-right:0}.ui-track:has(>li:nth-child(7)) li:not(.cur) :is(button,a,.ui-track-i){font-size:0;gap:0}.ui-track:has(>li:nth-child(7)) li.cur :is(button,a,.ui-track-i){white-space:nowrap}}
/* one floating bar of actions, always in sight (the vendors page's floating button, grown into a bar) */
.ui-actbar{position:fixed;left:1rem;right:1rem;bottom:max(.9rem,env(safe-area-inset-bottom));z-index:30;display:flex;align-items:center;gap:.5rem;max-width:30rem;margin:0 auto;padding:.4rem;background:var(--card-hi);border:1px solid var(--line);border-radius:999px;box-shadow:var(--rim),var(--e3)}
.ui-actbar[hidden]{display:none}
.ui-actbar .btn,.ui-actbar a.btn{flex:1 1 0;display:inline-flex;align-items:center;justify-content:center;min-width:0;min-height:2.9rem;margin:0;padding:.45rem .9rem;border-radius:999px;font-size:var(--fs-m);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-actbar .btn.secondary{flex:0 1 auto}
.ui-actbar .btn[hidden]{display:none}
.ui-actbar-say~.btn{flex:0 1 auto;padding-left:.85rem;padding-right:.85rem}
.ui-actbar-say{flex:1 1 0;min-width:0;padding-left:.7rem;font:500 var(--fs-xs)/1.25 var(--sans);color:var(--muted);overflow:hidden}
/* too little room beside the buttons (a long line, larger text): the words take their own line above them, instead of
   four squeezed lines or "Phot…" (the phone pass, 2026-09-26) */
.ui-actbar:has(>.ui-actbar-say){flex-wrap:wrap;justify-content:flex-end;border-radius:1.6rem}
.ui-actbar>.ui-actbar-say{flex:1 1 9rem}
.ui-actbar>.ui-actbar-say~.btn{flex:0 0 auto}   /* buttons keep their words whole; the bar wraps instead of clipping "Preview" */
.ui-actbar-say b{display:block;font-size:var(--fs-m);color:var(--ink)}   /* a longer line (Spanish) wraps, never cut off */
.ui-actbar-say .ok{color:var(--ok);font-weight:700}
.ui-actbar-say .warn{color:var(--warn);font-weight:700}
/* the switch kind (Door · Photos · Print): dark, like the vendors page's List / Map button */
.ui-actbar.switch{left:50%;right:auto;transform:translateX(-50%);width:max-content;max-width:calc(100vw - 2rem);gap:0;padding:0;overflow:hidden;background:var(--ink);border-color:var(--ink)}
.ui-actbar.switch>*{display:inline-flex;align-items:center;gap:.4rem;min-height:3rem;padding:0 1.15rem;border:0;background:transparent;color:var(--bg);font:700 var(--fs-s)/1 var(--sans);text-decoration:none;cursor:pointer;white-space:nowrap}
.ui-actbar.switch>*+*{border-left:1px solid color-mix(in oklab,var(--bg) 25%,transparent)}
.ui-actbar.switch>[aria-pressed="true"]{background:color-mix(in oklab,var(--bg) 18%,transparent)}
.ui-actbar.switch>*:focus-visible{outline:3px solid var(--focus);outline-offset:-3px}
/* the invitation lifted on its own colours: a blurred copy of the picture behind it (--pic), else a warm wash */
.ui-lift{position:relative;isolation:isolate;overflow:hidden;margin:.7rem -1rem 0;padding:2.9rem 1.1rem 3rem;background:linear-gradient(160deg,var(--accent-bg),color-mix(in oklab,var(--accent) 22%,var(--bg)))}
.ui-lift::before{content:"";position:absolute;inset:-3rem;z-index:-1;background:var(--pic,none) center/cover no-repeat;filter:blur(34px) saturate(1.25);opacity:.8}
.ui-lift::after{content:"";position:absolute;inset:auto 0 0 0;z-index:-1;height:2.4rem;background:linear-gradient(transparent,var(--bg))}
:root[data-theme="dark"] .ui-lift::before{opacity:.42}
.ui-lift>.invcard{position:relative;margin:0 auto;box-shadow:var(--e3)}
.ui-lift-pic{display:block;max-width:min(100%,21rem);max-height:60vh;margin:0 auto;border-radius:1.1rem;box-shadow:var(--e3);background:var(--card)}
.ui-lift-empty{max-width:21rem;margin:0 auto;padding:2.5rem 1.2rem;border-radius:1.1rem;border:2px dashed var(--line-strong);background:color-mix(in oklab,var(--card) 75%,transparent);text-align:center;color:var(--muted);font-size:var(--fs-s)}
.ui-lift-empty b{display:block;color:var(--ink);font-size:var(--fs-l);margin-bottom:.2rem}
.ui-onpic.br{right:.9rem;bottom:1.4rem}.ui-onpic.bl{left:.9rem;bottom:1.4rem}
.ui-onpic.ink{background:var(--ink);color:var(--card)}
button.ui-onpic,a.ui-onpic{border:0;cursor:pointer;text-decoration:none;min-height:2rem}
/* pictures in a row to pick from (designs), each with its badge on the picture */
.ui-strip{display:flex;gap:.7rem;overflow-x:auto;margin:.2rem -1rem 0;padding:.4rem 1rem .8rem;scrollbar-width:none;scroll-snap-type:x proximity;scroll-padding-inline:1rem}
.ui-strip::-webkit-scrollbar{display:none}
.ui-ptile{flex:none;scroll-snap-align:start;width:7.4rem;padding:0;border:0;background:none;color:var(--ink);font:700 var(--fs-s)/1.25 var(--sans);text-align:center;cursor:pointer}
.ui-ptile small{display:block;font-weight:500;color:var(--muted);font-size:var(--fs-xs)}
.ui-ptile-pic{position:relative;display:grid;place-items:center;height:9.2rem;margin-bottom:.35rem;overflow:hidden;border-radius:.9rem;border:3px solid transparent;background:var(--zone);box-shadow:var(--e1)}
.ui-ptile-pic canvas,.ui-ptile-pic img{display:block;width:100%;height:100%;object-fit:cover}
.ui-ptile .ui-media-badge{left:.3rem;top:.3rem;padding:.28rem .45rem;font-size:.66rem}
.ui-ptile-ck{position:absolute;right:.35rem;bottom:.35rem;display:none;place-items:center;width:1.55rem;height:1.55rem;border-radius:50%;background:var(--accent);color:var(--accent-ink);font:900 .8rem/1 var(--sans);box-shadow:var(--e1)}
.ui-ptile[aria-pressed="true"] .ui-ptile-pic{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in oklab,var(--accent) 25%,transparent),var(--e2)}
.ui-ptile[aria-pressed="true"] .ui-ptile-ck{display:grid}
.ui-ptile.own .ui-ptile-pic{border:2px dashed var(--line-strong);background:var(--card);box-shadow:none;color:var(--accent);font:400 2rem/1 var(--sans)}
.ui-ptile.own[aria-pressed="true"] .ui-ptile-pic{border-style:solid;border-color:var(--accent)}
.ui-ptile:focus-visible{outline:none}.ui-ptile:focus-visible .ui-ptile-pic{outline:3px solid var(--focus);outline-offset:2px}
/* a screen in two columns on a wide screen (the list beside what it's about); one column on a phone */
.ui-narrow,.ui-hostapp .ui-narrow{max-width:44rem;margin-left:auto;margin-right:auto}
/* who it goes to, once chosen: one line with faces */
.ui-wholine{display:flex;align-items:center;gap:.8rem;padding:.7rem .9rem;margin:.8rem 0 0}
.ui-wholine .ui-stack{margin:0;flex:none}.ui-wholine .ui-stack .ui-av{width:2rem;height:2rem;font-size:.66rem}
.ui-wholine-t{flex:1;min-width:0;font-size:var(--fs-s);color:var(--muted)}.ui-wholine-t b{display:block;color:var(--ink);font-size:var(--fs-m)}
.ui-wholine .ui-link{flex:none}
/* ways to send: each a card with a picture band and its badge; the chosen one ringed */
.ui-ways{display:grid;gap:.7rem;margin:.5rem 0 1rem}
.ui-way{position:relative;display:flex;align-items:stretch;overflow:hidden;margin:0;border:1px solid var(--line);border-radius:1.1rem;background:var(--card);box-shadow:var(--rim),var(--e1);cursor:pointer}
.ui-way>input{position:absolute;opacity:0;pointer-events:none}
.ui-media.band{flex:none;width:5.2rem;height:auto;min-height:5.5rem;font-size:2rem}
.ui-way-b{flex:1;min-width:0;padding:.75rem 2.8rem .8rem .9rem}
.ui-way-b b{display:block;font-size:var(--fs-l);color:var(--ink)}
.ui-way-b>span{display:block;font-size:var(--fs-s);color:var(--muted)}
.ui-way-b .ui-pill{margin-top:.4rem}
.ui-way-ck{position:absolute;right:.75rem;top:.75rem;display:grid;place-items:center;width:1.6rem;height:1.6rem;border-radius:50%;border:2px solid var(--line-strong);background:var(--card);color:transparent;font:900 .85rem/1 var(--sans)}
.ui-way:has(input:checked){border:2px solid var(--accent);box-shadow:0 0 0 3px color-mix(in oklab,var(--accent) 20%,transparent),var(--e2)}
.ui-way:has(input:checked) .ui-way-ck{background:var(--accent);border-color:var(--accent);color:var(--accent-ink)}
.ui-way:has(input:focus-visible){outline:3px solid var(--focus);outline-offset:2px}
/* what a guest gets, drawn as a message thread */
.ui-thread{margin:.4rem 0 1rem;padding:.9rem .9rem 1rem;border-radius:1.2rem;background:var(--zone);border:1px solid var(--line)}
.ui-thread-h{margin:0 0 .6rem;text-align:center;font-size:var(--fs-xs);color:var(--muted)}
.ui-bubble{max-width:18rem;margin:.45rem 0 0 auto;padding:.55rem .85rem;border-radius:1.1rem 1.1rem .3rem 1.1rem;background:var(--imsg);color:#fff;font-size:var(--fs-s);line-height:1.4;white-space:pre-line;overflow-wrap:anywhere}
.ui-linkcard{display:block;max-width:18rem;margin:.45rem 0 0 auto;overflow:hidden;border-radius:1.1rem 1.1rem .3rem 1.1rem;background:var(--card);box-shadow:var(--e1)}
.ui-linkcard img{display:block;width:100%;height:8rem;object-fit:cover;object-position:center 30%}
.ui-linkcard span{display:block;padding:.5rem .8rem .65rem;font-size:var(--fs-s);color:var(--muted)}.ui-linkcard b{display:block;color:var(--ink);font-size:var(--fs-m)}
/* the party's picture across the top, its name on it; the counts on a card laid over it */
.ui-hero{position:relative;isolation:isolate;height:14rem;margin:.5rem -1rem 0;overflow:hidden;background:linear-gradient(160deg,var(--accent-bg),color-mix(in oklab,var(--accent) 30%,var(--bg)))}
.ui-hero>img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center top;z-index:-2}
.ui-hero::after{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(transparent 30%,rgba(30,18,8,.62))}
.ui-hero-t{position:absolute;left:1rem;right:1rem;bottom:2.9rem;color:#fff;text-shadow:0 1px 8px rgba(0,0,0,.4)}
.ui-hero-t h2,.ui-hero .ui-hero-t h2{margin:0;font:700 var(--fs-2xl)/1.05 var(--serif);color:#fff;overflow-wrap:anywhere}
.ui-hero-t p{margin:.25rem 0 0;font:600 var(--fs-s)/1.3 var(--sans)}
.ui-tally{position:relative;z-index:2;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin:-2.1rem .2rem 0;padding:.75rem .5rem .7rem;border:1px solid var(--line);border-radius:1.1rem;background:var(--card-hi);box-shadow:var(--rim),var(--e2);text-align:center}
.ui-tally>button{display:flex;flex-direction:column;align-items:center;min-width:0;padding:.1rem .2rem;border:0;border-left:1px solid var(--line);background:none;color:var(--muted);font:600 var(--fs-xs)/1.2 var(--sans);cursor:pointer}
.ui-tally>button:first-child{border-left:0}
.ui-tally>button b{font:800 1.55rem/1.1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}
.ui-tally>button.yes b{color:var(--ok)}
.ui-tally>button[aria-pressed="true"]{color:var(--ink);text-decoration:underline;text-underline-offset:.2em}
.ui-tally>button:focus-visible{outline:3px solid var(--focus);outline-offset:1px;border-radius:var(--r-s)}
.ui-split{grid-column:1/-1;display:flex;height:.42rem;margin:.7rem .4rem 0;overflow:hidden;border-radius:999px;background:var(--zone)}
.ui-split i{display:block;min-width:0}.ui-split .yes{background:var(--ok)}.ui-split .maybe{background:var(--warn)}.ui-split .no{background:var(--muted)}.ui-split .wait{background:var(--line-strong)}
/* inside the counts card, under the bar: when the last answer came, and when the page last checked (↻ checks now) */
.ui-tally-note{grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:0 .3rem;margin:.45rem .3rem 0;font:500 var(--fs-xs)/1.3 var(--sans);color:var(--muted);font-variant-numeric:tabular-nums}
.ui-tally-note button{display:inline-grid;place-items:center;width:1.9rem;height:1.9rem;margin:-.3rem 0;padding:0;border:0;border-radius:50%;background:none;color:var(--focus);font:700 1rem/1 var(--sans);cursor:pointer}
.ui-tally-note button:hover{background:var(--zone)}
.ui-tally-note button:focus-visible{outline:3px solid var(--focus);outline-offset:1px}
.ui-tally-note button:disabled{opacity:.45;cursor:default}
/* The Shortcuts permission prompt, drawn small (public/app.js promptPic, the setup page): a dialog with its three
   buttons, Always Allow marked, beside one line saying to choose it. Decorative (the line says it). */
.ui-osask{display:flex;align-items:center;gap:1rem;margin:.6rem 0 .3rem}
.ui-osask>p{margin:0;font-size:var(--fs-s);color:var(--ink)}
.ui-osask-pic{flex:none;display:grid;grid-template-columns:2rem 1fr;gap:.35rem .6rem;align-items:center;width:17rem;max-width:58%;padding:.7rem .75rem;border:1px solid var(--line-strong);border-radius:.8rem;background:var(--zone);box-shadow:0 4px 14px var(--shadow)}
.ui-osask-ic{grid-row:span 2;width:2rem;height:2rem;border-radius:.5rem;background:linear-gradient(135deg,#ef6aa0,#7b6cf6 55%,#3fb6f2)}
.ui-osask-l{height:.42rem;border-radius:.2rem;background:var(--line-strong)}.ui-osask-l.s{width:60%}
.ui-osask-b{grid-column:1/-1;display:flex;gap:.3rem;margin-top:.25rem}
.ui-osask-b i,.ui-osask-b b{flex:1;padding:.25rem .2rem;border-radius:.35rem;font:600 .68rem/1.2 var(--sans);font-style:normal;text-align:center;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-osask-b i{background:var(--card);color:var(--muted)}
.ui-osask-b b{flex:none;padding:.25rem .45rem;background:var(--accent);color:var(--accent-ink);outline:2.5px solid var(--focus);outline-offset:2px}   /* never cut short: it's the word to find */
.ui-osask-more{margin:.2rem 0 .4rem}.ui-osask-more summary{font-size:var(--fs-s)}.ui-osask-more .ui-bullets{font-size:var(--fs-s)}
@media (max-width:520px){.ui-osask{flex-direction:column;align-items:flex-start;gap:.5rem}.ui-osask-pic{width:100%;max-width:19rem;padding:.6rem .65rem}}
/* The welcome overview (public/app.js openOverview; docs/tracks/welcome-overview/): one panel over the host app the first
   time a host opens a party. A centered panel on a wide screen; on a phone a sheet from the bottom that scrolls under
   its pinned button. The steps use the rail's own icons (.ui-steprail-ic); the header's chips are copied in (.ui-ov-chip). */
.ui-ov-open{overflow:hidden}
.ui-ov-open .rp-float{display:none}   /* "Something look wrong?" floats over everything: not over the panel's own button */
.ui-ov-scrim{position:fixed;inset:0;z-index:60;display:grid;place-items:center;padding:1.2rem;background:rgba(0,0,0,.62)}
.ui-ov{position:relative;width:min(100%,50rem);max-height:calc(100dvh - 2.4rem);overflow:auto;overscroll-behavior:contain;padding:1.6rem 1.8rem 1.5rem;background:var(--card);color:var(--ink);border:1px solid var(--line-strong);border-radius:1.4rem;box-shadow:0 24px 60px rgba(0,0,0,.45);animation:ui-ov-in .2s ease-out}
.ui-ov:focus{outline:0}
@keyframes ui-ov-in{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.ui-ov h2{margin:0 2.8rem .6rem 0;font:700 var(--fs-xl,1.55rem)/1.2 var(--serif,var(--sans));color:var(--head)}
.ui-ov-x{position:absolute;top:1rem;right:1rem;display:grid;place-items:center;width:2.75rem;height:2.75rem;padding:0;border:0;border-radius:50%;background:none;color:var(--muted);font:700 1.1rem/1 var(--sans);cursor:pointer}
.ui-ov-x:hover{background:var(--zone);color:var(--ink)}
.ui-ov-x:focus-visible{outline:3px solid var(--focus);outline-offset:1px}
.ui-ov-first{display:flex;align-items:center;gap:1.1rem;margin:0 0 1.1rem;padding:.9rem 1rem;border:1.5px solid var(--accent);border-radius:1rem;background:var(--accent-bg)}
.ui-ov-first p{margin:0}
.ui-ov-big{font:700 1.45rem/1.3 var(--sans);color:var(--ink)}
.ui-ov-first .ui-ov-sub{margin-top:.3rem;font-size:var(--fs-m);color:var(--muted)}
/* a small copy of the host's own card (Build › Details): drawn at a card's width, then scaled down to fit */
.ui-ov-card{flex:none;width:14rem;overflow:hidden;border-radius:.6rem;box-shadow:0 6px 18px var(--shadow);pointer-events:none}
.ui-ov-card>div{width:34rem;transform-origin:0 0}
.ui-ov-lede{margin:0 0 1.2rem;font-size:var(--fs-m);color:var(--muted)}
.ui-ov-steps{position:relative;display:grid;grid-template-columns:repeat(auto-fit,minmax(0,1fr));gap:.8rem;margin:0 0 1.2rem;padding:0;list-style:none}
.ui-ov-steps::before{content:"";position:absolute;top:1.25rem;left:10%;right:10%;height:2px;background:var(--line-strong)}
.ui-ov-steps li{position:relative;display:flex;flex-direction:column;align-items:center;gap:.3rem;text-align:center}
.ui-ov-steps .ui-steprail-ic{color:var(--accent);border-color:var(--accent);background:var(--card)}
.ui-ov-steps b{font-size:var(--fs-m)}
.ui-ov-steps .ui-ov-t{font-size:var(--fs-s);line-height:1.35;color:var(--muted)}
.ui-ov-own{display:flex;gap:.8rem;align-items:flex-start;margin:0 0 .4rem;padding:.8rem 1rem;border:1px solid var(--line);border-left:4px solid var(--accent);border-radius:var(--r-m);background:var(--accent-bg)}
.ui-ov-own svg{flex:none;width:1.4rem;height:1.4rem;margin-top:.1rem;color:var(--accent)}
.ui-ov-own p{margin:0;font-size:var(--fs-m);line-height:1.4}
.ui-ov-where{display:grid;grid-template-columns:repeat(auto-fit,minmax(9rem,1fr));gap:.7rem;margin:0 0 1.4rem;padding:0;list-style:none}
.ui-ov-where li{display:flex;flex-direction:column;align-items:flex-start;gap:.4rem;font-size:var(--fs-s);line-height:1.35;color:var(--muted)}
.ui-ov-chip{position:static!important;inset:auto!important;transform:none!important;margin:0!important;box-shadow:none!important;max-width:100%;pointer-events:none}
.ui-ov-more{display:inline-flex;align-items:center;gap:.4rem;font-weight:600;color:var(--ink)}
.ui-ov-go{display:flex;justify-content:flex-end}
.ui-ov-go .btn{min-width:14rem}
@media (max-width:700px){
  .ui-ov-scrim{place-items:end stretch;padding:0}
  .ui-ov{width:100%;max-height:92dvh;padding:1.3rem 1.1rem 1.1rem;border-bottom:0;border-radius:1.4rem 1.4rem 0 0}
  .ui-ov h2{font-size:1.35rem}
  .ui-ov-first{gap:.8rem;margin-bottom:.8rem;padding:.7rem .75rem}
  .ui-ov-card{width:5.6rem}
  .ui-ov-big{font-size:1.08rem}.ui-ov-first .ui-ov-sub{font-size:var(--fs-s)}
  .ui-ov-lede{margin-bottom:.9rem}
  .ui-ov-steps{grid-template-columns:1fr;gap:.5rem;margin-bottom:1rem}
  .ui-ov-steps::before{top:1.1rem;bottom:1.1rem;left:1.1rem;right:auto;width:2px;height:auto}
  .ui-ov-steps li{display:grid;grid-template-columns:2.2rem 1fr;column-gap:.75rem;row-gap:0;align-items:center;text-align:left}
  .ui-ov-steps .ui-steprail-ic{width:2.2rem;height:2.2rem}.ui-ov-steps .ui-steprail-ic svg{width:1.1rem;height:1.1rem}
  .ui-ov-steps li>.ui-steprail-ic{grid-row:span 2}
  .ui-ov-steps b{align-self:end;line-height:1.2}.ui-ov-steps .ui-ov-t{align-self:start;line-height:1.3}
  .ui-ov-own{padding:.65rem .8rem}
  .ui-ov-where{grid-template-columns:1fr 1fr;gap:.8rem .7rem}
  .ui-ov-go{position:sticky;z-index:1;bottom:-1.1rem;margin:0 -1.1rem -1.1rem;padding:.8rem 1.1rem 1.1rem;background:var(--card);border-top:1px solid var(--line)}
  .ui-ov-go .btn{width:100%}
}
@media (prefers-reduced-motion:reduce){.ui-ov{animation:none}}
/* under the counts card: Coming and Maybe as two lines of a small table (the answer, the groups, the total); the cells
   wrap on a phone, the page never scrolls sideways */
.ui-hc{width:100%;margin:.9rem 0 .7rem;border-collapse:collapse;font:400 var(--fs-s)/1.35 var(--sans);font-variant-numeric:tabular-nums;color:var(--muted)}
.ui-hc th,.ui-hc td{padding:.15rem .9rem .15rem 0;text-align:left;vertical-align:baseline}
.ui-hc th{font-weight:700;color:var(--ink);white-space:nowrap}
.ui-hc td:last-child{padding-right:0;text-align:right;white-space:nowrap;color:var(--ink);font-weight:600}
.ui-hc td[colspan]{text-align:left}
/* what guests were asked, added up: small cards */
.ui-told{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(7rem,100%),1fr));gap:.5rem;margin:.2rem 0 .6rem}
.ui-told>button{display:flex;flex-direction:column;align-items:flex-start;gap:.1rem;margin:0;padding:.65rem .75rem;border:1px solid var(--line);border-radius:.9rem;background:var(--card);box-shadow:var(--rim),var(--e1);color:var(--muted);font:600 var(--fs-xs)/1.25 var(--sans);text-align:left;cursor:pointer}
.ui-told>button b{font:800 var(--fs-l)/1.2 var(--sans);color:var(--ink)}
.ui-told>button small{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-weight:500;font-size:var(--fs-xs)}
.ui-told>button[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-bg)}
/* chips that carry counts, in one row that scrolls */
.ui-chiprow{flex-wrap:nowrap;overflow-x:auto;margin:.3rem -1rem .4rem;padding:.2rem 1rem .4rem;scrollbar-width:none}
.ui-chiprow::-webkit-scrollbar{display:none}
button.ui-chip{flex:none;cursor:pointer;min-height:2.6rem}
.ui-chip[aria-pressed="true"]{background:var(--ink);border-color:var(--ink);color:var(--card)}
.ui-chip[aria-pressed="true"] .ui-chip-n{color:var(--card)}
/* a tab line (tabs or chips) with an optional search at its end: a field on a wide screen; on a phone a round
   button that opens the field across the line (the tabs hide under it), ✕ closes and clears */
.ui-tabline{position:relative;display:flex;align-items:center;gap:.5rem;margin:.3rem 0 .4rem}
.ui-tabline>:first-child{flex:1;min-width:0}
.ui-tabline>.ui-chiprow{margin:0 0 0 -1rem;padding-right:.2rem}
.ui-tabline-find{flex:none;display:flex;align-items:center}
.ui-tabline-open{display:grid;place-items:center;width:2.6rem;height:2.6rem;padding:0;border:1px solid var(--line-strong);border-radius:50%;background:var(--card);color:var(--ink);box-shadow:0 1px 2px var(--shadow);cursor:pointer}
.ui-tabline-open svg,.ui-tabline-field>svg{width:1.1rem;height:1.1rem;flex:none}
.ui-tabline-field{display:none;align-items:center;gap:.45rem;min-height:2.6rem;padding:0 .3rem 0 .85rem;border:1px solid var(--line);border-radius:999px;background:var(--card-hi);color:var(--muted);box-shadow:var(--rim),var(--e1)}
.ui-tabline-field:focus-within{outline:3px solid var(--focus);outline-offset:2px}
.ui-tabline .ui-tabline-field input{flex:1;min-width:0;width:100%;margin:0;padding:.45rem 0;border:0;border-radius:0;background:transparent;font:400 var(--fs-m)/1.3 var(--sans);color:var(--ink);outline:0;box-shadow:none;-webkit-appearance:none;appearance:none}
.ui-tabline .ui-tabline-field input::placeholder{color:var(--muted);opacity:1}
.ui-tabline-field input::-webkit-search-cancel-button{display:none}
.ui-tabline-x{display:none;place-items:center;width:2.1rem;height:2.1rem;padding:0;border:0;border-radius:50%;background:none;color:var(--muted);font:700 .95rem/1 var(--sans);cursor:pointer}
.ui-tabline-x:hover{background:var(--zone);color:var(--ink)}
.ui-tabline-open:focus-visible,.ui-tabline-x:focus-visible{outline:3px solid var(--focus);outline-offset:1px}
.ui-tabline.open>:first-child{visibility:hidden}
.ui-tabline.open .ui-tabline-open{display:none}
.ui-tabline.open .ui-tabline-field{display:flex;position:absolute;inset:0;z-index:2}
.ui-tabline.open .ui-tabline-x{display:grid}
@media (min-width:36rem){
  .ui-tabline-open{display:none}
  .ui-tabline-field{display:flex;width:13rem}
  .ui-tabline.open>:first-child{visibility:visible}
  .ui-tabline.open .ui-tabline-field{position:static}
  .ui-tabline-field:has(input:not(:placeholder-shown)) .ui-tabline-x{display:grid}
  .ui-tabline.open .ui-tabline-x{display:none}
  .ui-tabline.open .ui-tabline-field:has(input:not(:placeholder-shown)) .ui-tabline-x{display:grid}
}
/* a guest (or a family): a face with their answer as a badge on it, their note as a speech bubble */
.ui-gcards{list-style:none;margin:.4rem 0 0;padding:0;display:flex;flex-direction:column;gap:.55rem}
.ui-gcard{margin:0;overflow:hidden}
.ui-gcard.wait{border-style:dashed;box-shadow:var(--rim),0 1px 3px var(--shadow)}
.ui-gcard-h{display:flex;align-items:flex-start;gap:.75rem;width:100%;padding:.75rem .85rem;border:0;background:none;color:var(--ink);font:inherit;text-align:left;cursor:pointer}
.ui-gcard-h:focus-visible{outline:3px solid var(--focus);outline-offset:-3px;border-radius:var(--r-l)}
.ui-gcard .ui-av,.ui-dcard .ui-av{position:relative;width:2.9rem;height:2.9rem;font-size:.85rem;border:0;box-shadow:var(--e1)}
.ui-av-st{position:absolute;right:-.25rem;bottom:-.25rem;display:grid;place-items:center;width:1.3rem;height:1.3rem;border-radius:50%;border:2px solid var(--card);background:var(--card);color:var(--muted);font:900 .62rem/1 var(--sans)}
.ui-av-st.yes{background:var(--ok);color:#fff}.ui-av-st.maybe{background:var(--warn);color:#fff}.ui-av-st.no{background:var(--muted);color:var(--card)}.ui-av-st.wait{border-color:var(--line-strong)}
:root[data-theme="dark"] .ui-av-st.yes,:root[data-theme="dark"] .ui-av-st.maybe{color:#10240f}
.ui-gcard .ui-head{flex-wrap:nowrap}.ui-gcard .ui-title{font-size:var(--fs-l)}
.ui-gcard .ui-key{font-size:var(--fs-l)}
.ui-say{display:inline-block;max-width:100%;margin:.35rem 0 0;padding:.35rem .65rem;border-radius:.2rem .85rem .85rem .85rem;background:var(--zone);color:var(--ink);font-size:var(--fs-s);overflow-wrap:anywhere}
.ui-gcard-top{display:flex;align-items:flex-start}
.ui-gcard-top>.ui-gcard-h{flex:1;min-width:0}
.ui-gcard-top>.btn{flex:none;margin:.8rem .85rem 0 0}
.ui-gcard-b{padding:.2rem .9rem .9rem;border-top:1px solid var(--line)}
/* the door: how many are here, as a ring; each family's people ticked one by one */
.ui-here{display:flex;align-items:center;gap:.9rem;margin:.6rem 0 .8rem;padding:.8rem 1rem;border-radius:1.2rem;background:var(--ink);color:var(--bg);box-shadow:var(--e2)}
.ui-ring{--p:0;flex:none;display:grid;place-items:center;width:3.6rem;height:3.6rem;border-radius:50%;background:conic-gradient(var(--accent) calc(var(--p) * 1%),color-mix(in oklab,var(--bg) 22%,transparent) 0)}
.ui-ring span{display:grid;place-items:center;width:2.8rem;height:2.8rem;border-radius:50%;background:var(--ink);font:800 var(--fs-s)/1 var(--sans)}
.ui-here-t{flex:1;min-width:0}.ui-here-t b{display:block;font:800 var(--fs-xl)/1.1 var(--sans)}.ui-here-t span{font-size:var(--fs-s);opacity:.85}
.ui-door{list-style:none;margin:.3rem 0 0;padding:0;display:flex;flex-direction:column;gap:.55rem}
.ui-dcard{display:flex;align-items:flex-start;gap:.8rem;margin:0;padding:.75rem .85rem}
.ui-dcard.in{background:var(--zone);box-shadow:none}
.ui-dcard.in .ui-title{color:var(--muted)}
.ui-tick{flex:none;display:grid;place-items:center;width:3rem;height:3rem;border-radius:50%;border:2.5px solid var(--line-strong);background:var(--card);color:transparent;font:900 1.15rem/1 var(--sans);cursor:pointer}
.ui-tick.part{border-color:var(--accent);color:var(--accent);font-size:var(--fs-s);background:conic-gradient(var(--accent-bg) calc(var(--p,50) * 1%),var(--card) 0)}
.ui-tick[aria-pressed="true"]{background:var(--ok);border-color:var(--ok);color:#fff}
:root[data-theme="dark"] .ui-tick[aria-pressed="true"]{color:#10240f}
.ui-tick:focus-visible,.ui-hd:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-heads{display:flex;flex-wrap:wrap;gap:.3rem;margin:.45rem 0 0}
.ui-hd{display:inline-flex;align-items:center;gap:.3rem;min-height:2.4rem;padding:.3rem .7rem;border:1.5px solid var(--line-strong);border-radius:999px;background:var(--card);color:var(--ink);font:700 var(--fs-s)/1.2 var(--sans);cursor:pointer}
.ui-hd[aria-pressed="true"]{background:var(--ok-bg);border-color:color-mix(in oklab,var(--ok) 60%,var(--line));color:var(--ok)}
.ui-dcard .ui-pills{margin-top:.45rem}
@media (min-width:56rem){
  .ui-two{display:grid;grid-template-columns:minmax(0,1fr) 25rem;gap:2rem;align-items:start}
  .ui-two.flip{grid-template-columns:27rem minmax(0,1fr)}
  .ui-two-side{position:sticky;top:5.5rem}
  .ui-lift{margin:.8rem 0 0;padding:2.4rem 2rem 2.6rem;border-radius:1.4rem;box-shadow:var(--rim),var(--e1)}
  .ui-lift::after{display:none}
  .ui-strip{flex-wrap:wrap;overflow:visible;margin:.2rem 0 0;padding:.4rem 0 .8rem}
  .ui-hero{margin:.8rem 0 0;border-radius:1.4rem}
  .ui-tally{margin:-2.1rem .9rem 0}
  .ui-chiprow{margin-left:0;margin-right:0;padding-left:0}
  .ui-gcards,.ui-door{display:grid;grid-template-columns:1fr 1fr;gap:.7rem;align-items:start}
}
.ui-onpic[hidden]{display:none}
.ui-bubble.mail{margin-left:0;max-width:none;background:var(--card);color:var(--ink);border-radius:.9rem;box-shadow:var(--e1)}
@media (min-width:56rem){.ui-track{max-width:42rem;margin-left:auto;margin-right:auto}}   /* the steps sit centred over the card, like the card and the bar (David, 2026-09-28) */

/* ---------- getting ready: a head card on the picture's colours with a ring, then a checklist of jobs ----------
   (David, 2026-09-26, Party day before the party: "To much text, too many options, not clear what to do"). Each job:
   a line icon on a tinted tile, its name, one short grey line, one button; done, a green ✓ tile, a dashed edge and a
   quieter button. */
.ui-readyhead{position:relative;isolation:isolate;overflow:hidden;display:flex;align-items:center;gap:1rem;margin:.6rem 0 1rem;padding:1.2rem 1.1rem 1.2rem 1.3rem;border-radius:1.4rem;background:linear-gradient(135deg,var(--accent-bg),color-mix(in oklab,var(--accent) 30%,var(--bg)));box-shadow:var(--rim),var(--e2)}
.ui-readyhead::before{content:"";position:absolute;inset:-2.5rem;z-index:-1;background:var(--pic,none) center/cover no-repeat;filter:blur(40px) saturate(1.6);opacity:.5}
:root[data-theme="dark"] .ui-readyhead::before{opacity:.35}
.ui-readyhead-t{flex:1;min-width:0}
.ui-readyhead-t h2,.ui-readyhead .ui-readyhead-t h2{margin:0 0 .3rem;font:800 var(--fs-2xl)/1.1 var(--sans);color:var(--ink);letter-spacing:-.01em}
.ui-readyhead .ui-info{margin:0;font-size:var(--fs-m);color:var(--ink)}
.ui-readyhead .ui-ring{width:4.4rem;height:4.4rem;background:conic-gradient(var(--ink) calc(var(--p) * 1%),color-mix(in oklab,var(--card) 55%,transparent) 0)}
.ui-readyhead .ui-ring span{width:3.3rem;height:3.3rem;background:color-mix(in oklab,var(--card) 70%,transparent);color:var(--ink);font-size:var(--fs-s);letter-spacing:-.02em;white-space:nowrap}   /* "23/29" fits inside the ring (was --fs-l and spilled over it) */
.ui-tasks{list-style:none;margin:.3rem 0 0;padding:0;display:flex;flex-direction:column;gap:.6rem}
.ui-task{display:flex;align-items:center;gap:.85rem;margin:0;padding:.8rem .8rem .8rem .9rem;border:1px solid var(--line);border-radius:1.1rem;background:var(--card);box-shadow:var(--rim),var(--e1)}
.ui-task-ic{flex:none;display:grid;place-items:center;width:3rem;height:3rem;border-radius:.9rem;background:var(--accent-bg);color:var(--accent)}
.ui-task-ic svg{width:1.4rem;height:1.4rem}
.ui-task-t{flex:1;min-width:0}
.ui-task-t b{display:block;font:700 var(--fs-l)/1.25 var(--sans);color:var(--ink);overflow-wrap:anywhere}
.ui-task-t>span{display:block;margin-top:.15rem;font-size:var(--fs-s);line-height:1.4;color:var(--muted);overflow-wrap:anywhere}
.ui-task-t>span.quote{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ui-task-t .ui-info{margin:0;font-size:var(--fs-s)}
.ui-task-t .ui-link{min-height:0;font-size:inherit}
.ui-task-end{flex:none;display:flex;flex-wrap:wrap;gap:.3rem;justify-content:flex-end}
.ui-tasks+.ui-label,.ui-tasks+.ui-tasks{margin-top:1.2rem}
.ui-task .ui-task-go{flex:none;display:inline-flex;align-items:center;justify-content:center;min-width:4.6rem;min-height:2.75rem;margin:0;padding:.4rem 1rem;font-size:var(--fs-m);border-radius:var(--r-m)}
.ui-task.done{background:transparent;border-style:dashed;border-color:var(--line-strong);box-shadow:none}
.ui-task.done .ui-task-ic{background:var(--ok-bg);color:var(--ok)}
.ui-task.done .ui-task-t b{color:var(--muted);text-decoration:line-through;text-decoration-thickness:1.5px}
.ui-task.done .ui-task-go{border-color:var(--line-strong);background:var(--card);color:var(--ink);box-shadow:none}
.ui-sheet-note{width:100%;min-height:7rem;margin:.4rem 0 0}

/* a picture card's band holding a drawing (a sheet of labels) instead of an emoji */
.ui-media.band svg{width:2.9rem;height:auto;color:var(--head)}
/* names to print: each a chip with ✕ to leave it out; one left out stays, struck through, with ↺ to put it back */
.ui-namechips{list-style:none;display:flex;flex-wrap:wrap;gap:.35rem;margin:.4rem 0 .5rem;padding:0}
.ui-namechip{display:inline-flex;align-items:center;min-height:2.6rem;margin:0;padding:0 .15rem 0 .85rem;border:1.5px solid var(--line-strong);border-radius:999px;background:var(--card);color:var(--ink);font:700 var(--fs-s)/1.2 var(--sans);box-shadow:0 1px 2px var(--shadow)}
.ui-namechip.added{border-color:color-mix(in oklab,var(--accent) 55%,var(--line))}
.ui-namechip.out{background:transparent;border-style:dashed;color:var(--muted);box-shadow:none}
.ui-namechip.out>span{text-decoration:line-through}
.ui-namechip button{display:grid;place-items:center;width:2.3rem;height:2.3rem;margin-left:.1rem;padding:0;border:0;border-radius:50%;background:none;color:var(--muted);font:700 .9rem/1 var(--sans);cursor:pointer}
.ui-namechip button:hover{background:var(--zone);color:var(--ink)}
.ui-namechip button:focus-visible{outline:3px solid var(--focus);outline-offset:1px}
/* the name tags sheet in three steps (Type · Style · Icons; David, 2026-09-26, the place-cards mockup): the steps as dots
   on a track, a live preview of one card at the top, Back / Next pinned at the foot with Print on the last */
.ui-ntstep[hidden]{display:none}
.ui-cardpv{display:grid;place-items:center;margin:.3rem 0 .4rem;padding:1rem .75rem;border-radius:var(--r-l);background:linear-gradient(135deg,color-mix(in oklab,var(--bg) 70%,var(--accent-bg)),var(--zone));box-shadow:var(--rim),var(--e1)}
.ui-cardpv-card{position:relative;overflow:hidden;background:var(--paper);border-radius:3px;box-shadow:0 8px 18px rgba(0,0,0,.18)}
.ui-cardpv .ui-lbl{left:0;top:0;outline:0;border-radius:0;transform-origin:0 0}
.ui-cardpv .ui-lbl.tent::after{display:none}
.ui-cardpv .ui-lbl.tent .ui-lbl-face{height:100%}
.ui-cardpv-say{margin:.45rem 0 0;font-size:var(--fs-xs);color:var(--muted);text-align:center}
/* text styles: each a tile with the guest's own name in it */
.ui-fonttiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.5rem;margin:.4rem 0 .2rem}
.ui-fonttile{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.25rem;min-height:5rem;margin:0;padding:.55rem .3rem;border:1.5px solid var(--line);border-radius:var(--r-m);background:var(--card);color:var(--ink);box-shadow:var(--rim),var(--e1);cursor:pointer;text-align:center}
.ui-fonttile>input{position:absolute;opacity:0;pointer-events:none}
.ui-fonttile b{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:var(--lw) 1.45rem/var(--lh) var(--lf);letter-spacing:var(--ls)}
.ui-fonttile>span{font-size:var(--fs-xs);color:var(--muted)}
.ui-fonttile:has(input:checked){border-color:var(--accent);background:var(--accent-bg);box-shadow:0 0 0 3px color-mix(in oklab,var(--accent) 20%,transparent)}
.ui-fonttile:has(input:focus-visible){outline:3px solid var(--focus);outline-offset:2px}
/* icons: an answer's options each with its icon and how many; a picker over the whole library, by category */
.ui-iconopts{display:grid;grid-template-columns:repeat(auto-fill,minmax(6.4rem,1fr));gap:.5rem;margin:.5rem 0 .2rem}
.ui-iconopt{display:flex;flex-direction:column;align-items:center;gap:.3rem;min-height:4.6rem;padding:.55rem .3rem;border:1.5px solid var(--line);border-radius:var(--r-m);background:var(--card);color:var(--ink);font:600 var(--fs-s)/1.2 var(--sans);box-shadow:var(--rim),var(--e1);cursor:pointer;text-align:center;overflow-wrap:anywhere}
.ui-iconopt svg,.ui-iconopt .ui-iconnone{width:1.9rem;height:1.9rem}
.ui-iconnone{display:grid;place-items:center;border:1.5px dashed var(--line-strong);border-radius:50%;color:var(--muted);font-size:var(--fs-xs)}
.ui-iconopt[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-bg)}
.ui-iconopt:focus-visible,.ui-iconbtn:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-iconpick{margin:.5rem 0 .3rem;padding:.6rem;border-radius:var(--r-m);background:var(--zone)}
.ui-iconpick .ui-chiprow{margin:0 -.6rem .4rem;padding:.1rem .6rem .4rem}
.ui-icongrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(3rem,1fr));gap:.4rem}
.ui-iconbtn{display:grid;place-items:center;aspect-ratio:1;min-height:2.9rem;padding:.35rem;border:1.5px solid var(--line);border-radius:var(--r-m);background:var(--card);color:var(--muted);font:600 var(--fs-xs)/1.1 var(--sans);box-shadow:0 1px 2px var(--shadow);cursor:pointer}
.ui-iconbtn svg{width:100%;height:100%}
.ui-iconbtn[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-bg);box-shadow:0 0 0 3px color-mix(in oklab,var(--accent) 20%,transparent)}
.ui-search button.word{width:auto;padding:0 .95rem;font:700 var(--fs-s)/1 var(--sans);color:var(--accent)}
.ui-search[hidden]{display:none}
.ui-search input:focus-visible{outline:0}   /* the field's own ring is the search's (:focus-within), not a second one inside it */
.ui-link[hidden]{display:none}

/* ---------- fonts for name tags and place cards (their text styles: public/labels.js STYLES, LabelKeeper's list). On
   this site (the CSP allows fonts only from 'self'): the latin files from the @fontsource packages, one weight each, in
   public/fonts/ with their SIL Open Font License. A browser fetches one only when something is drawn in it. ---------- */
@font-face{font-family:"DM Sans";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/dm-sans-latin-700-normal.woff2) format("woff2")}
@font-face{font-family:"Merriweather";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/merriweather-latin-700-normal.woff2) format("woff2")}
@font-face{font-family:"Playfair Display";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/playfair-display-latin-600-normal.woff2) format("woff2")}
@font-face{font-family:"Cormorant Garamond";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/cormorant-garamond-latin-600-normal.woff2) format("woff2")}
@font-face{font-family:"Dancing Script";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/dancing-script-latin-700-normal.woff2) format("woff2")}
@font-face{font-family:"Caveat";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/caveat-latin-700-normal.woff2) format("woff2")}
@font-face{font-family:"Oswald";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/oswald-latin-600-normal.woff2) format("woff2")}
@font-face{font-family:"Pacifico";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/pacifico-latin-400-normal.woff2) format("woff2")}
@font-face{font-family:"Lobster";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/lobster-latin-400-normal.woff2) format("woff2")}
/* each style as a class: the font, its weight, (Chinese: the system's own Chinese font, named after the Latin one so
   a printout picks a Chinese face, Simplified then Traditional (TC); the script styles use Kaiti, the brush-like one) the line height and spacing it needs (script fonts reach further up and
   down). Used by the printed name, the sheet's preview and its style tiles. */
.ui-lf-modern{--lf:"DM Sans",var(--sans);--lw:700;--lh:1.1;--ls:-.01em}
.ui-lf-serif{--lf:"Merriweather",Georgia,"Songti SC","Noto Serif CJK SC","Noto Serif SC","Source Han Serif SC",STSong,SimSun,"Songti TC","Noto Serif CJK TC","Noto Serif TC","Source Han Serif TC",PMingLiU,MingLiU,serif;--lw:700;--lh:1.2;--ls:0}
.ui-lf-elegant{--lf:"Playfair Display",Georgia,"Songti SC","Noto Serif CJK SC","Noto Serif SC","Source Han Serif SC",STSong,SimSun,"Songti TC","Noto Serif CJK TC","Noto Serif TC","Source Han Serif TC",PMingLiU,MingLiU,serif;--lw:600;--lh:1.2;--ls:.01em}
.ui-lf-formal{--lf:"Cormorant Garamond",Georgia,"Songti SC","Noto Serif CJK SC","Noto Serif SC","Source Han Serif SC",STSong,SimSun,"Songti TC","Noto Serif CJK TC","Noto Serif TC","Source Han Serif TC",PMingLiU,MingLiU,serif;--lw:600;--lh:1.15;--ls:.01em}
.ui-lf-script{--lf:"Dancing Script","Kaiti SC",STKaiti,KaiTi,"Kaiti TC",DFKai-SB,BiauKai,"PingFang SC","Hiragino Sans GB","Noto Sans CJK SC","Noto Sans SC","Source Han Sans SC","Microsoft YaHei","PingFang TC","Noto Sans CJK TC","Noto Sans TC","Source Han Sans TC","Microsoft JhengHei",cursive;--lw:700;--lh:1.25;--ls:0}
.ui-lf-handwritten{--lf:"Caveat","Kaiti SC",STKaiti,KaiTi,"Kaiti TC",DFKai-SB,BiauKai,"PingFang SC","Hiragino Sans GB","Noto Sans CJK SC","Noto Sans SC","Source Han Sans SC","Microsoft YaHei","PingFang TC","Noto Sans CJK TC","Noto Sans TC","Source Han Sans TC","Microsoft JhengHei",cursive;--lw:700;--lh:1.1;--ls:0}
.ui-lf-display{--lf:"Oswald",var(--sans);--lw:600;--lh:1.2;--ls:.02em}
.ui-lf-fun{--lf:"Pacifico","Kaiti SC",STKaiti,KaiTi,"Kaiti TC",DFKai-SB,BiauKai,"PingFang SC","Hiragino Sans GB","Noto Sans CJK SC","Noto Sans SC","Source Han Sans SC","Microsoft YaHei","PingFang TC","Noto Sans CJK TC","Noto Sans TC","Source Han Sans TC","Microsoft JhengHei",cursive;--lw:400;--lh:1.4;--ls:0}
.ui-lf-bold{--lf:"Lobster","Kaiti SC",STKaiti,KaiTi,"Kaiti TC",DFKai-SB,BiauKai,"PingFang SC","Hiragino Sans GB","Noto Sans CJK SC","Noto Sans SC","Source Han Sans SC","Microsoft YaHei","PingFang TC","Noto Sans CJK TC","Noto Sans TC","Source Han Sans TC","Microsoft JhengHei",cursive;--lw:400;--lh:1.25;--ls:0}

/* ---------- printed sheets of labels (name tags, table tent cards: public/labels.js, src/worker.js namesPrintPage).
   Paper is paper in every theme. Each label is placed on its slot in inches (its left/top/width/height come from
   public/labels.js); the page sets @page { size: letter; margin: 0 } itself. On screen the sheets show their slots
   as dashed outlines and shrink to fit a phone; printed, only the names. ---------- */
:root{--paper:#fff;--paper-ink:#111;--paper-muted:#555;--paper-line:#c4bab0}
.ui-printpage{margin:0;padding:1rem 0 1px;background:var(--bg);color:var(--ink);font:400 var(--fs-m)/1.5 var(--sans)}
.ui-printbar{max-width:44rem;margin:0 auto 1.2rem;padding:0 1rem}
.ui-printbar .ui-text{font-weight:600}
.ui-printbar .btn{margin:.3rem 0 0}
.ui-lsheets{margin:0 auto 2rem;width:8.5in}
.ui-lsheet{position:relative;width:8.5in;height:11in;margin:0 0 1.5rem;overflow:hidden;background:var(--paper);color:var(--paper-ink);box-shadow:var(--e2)}
.ui-lbl{position:absolute;box-sizing:border-box;outline:1px dashed var(--paper-line);outline-offset:-1px;border-radius:.12in}
.ui-lbl.tent{border-radius:0}
.ui-lbl-face{--py:.16in;--px:.2in;position:relative;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;height:100%;padding:var(--py) var(--px);text-align:center;overflow:hidden}
.ui-lbl.tent .ui-lbl-face{--py:.2in;--px:.25in;height:50%}
.ui-lbl.tent .ui-lbl-face.top{transform:rotate(180deg)}
.ui-lbl.tent::after{content:"";position:absolute;left:0;right:0;top:50%;border-top:1px dotted var(--paper-line)}
.ui-lbl-name{display:block;max-width:100%;font:var(--lw,800) 28px/var(--lh,1.1) var(--lf,var(--sans));color:var(--paper-ink);letter-spacing:var(--ls,-.01em);overflow-wrap:anywhere}
.ui-lbl-name.one{white-space:nowrap;overflow-wrap:normal}
.ui-lbl-name.two>span{display:block;white-space:nowrap}
.ui-lbl-name.two.long>span,.ui-lbl-name.long{white-space:normal;overflow-wrap:anywhere}
.ui-lbl.formal .ui-lbl-party{font:italic 400 11px/1.2 Georgia,"Times New Roman","Songti SC","Noto Serif CJK SC","Noto Serif SC","Source Han Serif SC",STSong,SimSun,"Songti TC","Noto Serif CJK TC","Noto Serif TC","Source Han Serif TC",PMingLiU,MingLiU,serif}
.ui-lbl.formal .ui-lbl-face{--py:.14in;--px:.22in}
.ui-lbl-party{display:block;max-width:100%;margin-top:.08in;font:600 13px/1.2 var(--sans);color:var(--paper-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* a decoration BESIDE the name, left or right (every label, blanks too; David, 2026-09-27, LabelKeeper's Left/Right
   graphic slots): about 70% of the face's height (the face with its padding: a tent card's half), centred top to bottom;
   the words centred in the rest. The icon for a person's answer small in a bottom corner, on the words' side (on a tent
   card's top half it's turned with the half, so each face has its own) */
.ui-lbl-face.side{flex-direction:row;gap:.1in}
.ui-lbl-face.side.right{flex-direction:row-reverse}
.ui-lbl-deco{flex:none;display:block;height:calc((100% + 2 * var(--py)) * .7);aspect-ratio:1}
/* flat name tags (5395, the one product that isn't a tent card): about 50%, so the name has more room (David, 2026-09-27: "go") */
.ui-lbl:not(.tent) .ui-lbl-deco{height:calc((100% + 2 * var(--py)) * .5)}
.ui-lbl-text{flex:1 1 0;min-width:0;align-self:stretch;display:flex;flex-direction:column;align-items:center;justify-content:center}
.ui-lbl-deco svg,.ui-lbl-ic svg{display:block;width:100%;height:100%}
.ui-lbl-ic{position:absolute;right:.1in;bottom:.08in;width:.26in;height:.26in}
/* where they sit (Tables and seating), under the name; a table-number card: the number big, its name under it */
.ui-lbl-table{display:block;max-width:100%;margin-top:.06in;font:700 14px/1.2 var(--sans);color:var(--paper-ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-lbl.formal .ui-lbl-table{font-size:12px}
.ui-lbl-face:not(:has(.ui-lbl-name)) .ui-lbl-table{font-size:20px}
.ui-lbl-num{display:block;font:800 1.15in/1 var(--sans);color:var(--paper-ink);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.ui-lbl-numface .ui-lbl-party{font-size:18px;margin-top:.1in;color:var(--paper-ink)}
.ui-lbl:not(.tent) .ui-lbl-ic{right:.14in;bottom:.12in;width:.32in;height:.32in}
.ui-lbl-face.side.right .ui-lbl-ic{right:auto;left:.1in}
.ui-lbl:not(.tent) .ui-lbl-face.side.right .ui-lbl-ic{left:.14in}
@media print{
  .ui-printpage{background:var(--paper);padding:0}
  .ui-printbar{display:none}
  .ui-lsheets{margin:0;width:8.5in;zoom:1!important}
  .ui-lsheet{margin:0;box-shadow:none;break-after:page;page-break-after:always}
  .ui-lsheet:last-child{break-after:auto;page-break-after:auto}
  .ui-lbl{outline:0}
  .ui-lbl.tent::after{display:none}
  .ui-lbl-name,.ui-lbl-party,.ui-lbl-deco,.ui-lbl-ic,.ui-lbl-table,.ui-lbl-num{-webkit-print-color-adjust:exact;print-color-adjust:exact}
}
/* ---------- printed lists (Tables and seating: the seating list A to Z, the tables for the venue). Paper in every
   theme; large type; the list in two columns on a sheet. ---------- */
.ui-plist{max-width:8.5in;margin:0 auto 2rem;padding:.5in;background:var(--paper);color:var(--paper-ink);box-shadow:var(--e2);box-sizing:border-box}
.ui-plist h1{font:800 24px/1.2 var(--sans);margin:0 0 .05in}
.ui-plist-sub{font:500 14px/1.4 var(--sans);color:var(--paper-muted);margin:0 0 .25in}
.ui-az{list-style:none;margin:0;padding:0;columns:2;column-gap:.5in}
.ui-az li{display:flex;justify-content:space-between;gap:.2in;break-inside:avoid;padding:.06in 0;border-bottom:1px solid var(--paper-line);font:600 20px/1.3 var(--sans)}
.ui-az b{font-weight:800;white-space:nowrap;font-variant-numeric:tabular-nums}
.ui-vt{break-inside:avoid;margin:0 0 .3in}
.ui-vt h2{font:800 20px/1.25 var(--sans);margin:0 0 .04in}
.ui-vt table{width:100%;border-collapse:collapse;font:500 15px/1.35 var(--sans)}
.ui-vt td{padding:.04in .06in;border-bottom:1px solid var(--paper-line);vertical-align:top}
.ui-vt td:last-child{text-align:right;color:var(--paper-muted)}
.ui-vt-meals{font:700 14px/1.4 var(--sans);margin:.06in 0 0}
.ui-vt-none{font:500 14px/1.4 var(--sans);color:var(--paper-muted)}
@media (max-width:40rem){.ui-plist{padding:1rem}.ui-az{columns:1}}
@media print{.ui-plist{box-shadow:none;margin:0;padding:0;max-width:none}.ui-plist *{-webkit-print-color-adjust:exact;print-color-adjust:exact}}

/* ---------- the vendor portal: a tab bar, today's requests as picture cards, an inbox, the answer pinned, the listing
   as rows ----------
   (David, 2026-09-26, the vendor-portal mockup: "yes, start the vendor portal with the tab bar". Patterns from Airbnb's
   host app (Today first; the sections as a tab bar at the foot of a phone and as tabs in the top bar on a computer;
   Accept / Decline pinned at the foot of a request; the inbox with the request opened beside it; the listing editor's
   rows that show their value), Thumbtack Pro (the job first; where it stands as a track), Etsy (today's top tasks) and
   Shopify (one numbers card). Depth: the tab bar and the tabs float, badges sit on pictures, the card sits on a sheet
   over a map, the answer bar sits over the page.) */
/* the top bar on the page's own colour: the brand, (computer) the sections, the display control, the avatar */
.ui-top.app{background:linear-gradient(var(--bg) 78%,transparent);border-bottom:0;box-shadow:none;padding-top:.5rem;padding-bottom:.5rem}
.ui-top.app .ui-top-r{margin-left:auto}
/* the sections: a floating tab bar at the foot of a phone; pill tabs in the top bar on a computer */
.ui-tabbar{position:fixed;left:.75rem;right:.75rem;bottom:max(.75rem,env(safe-area-inset-bottom));z-index:30;max-width:30rem;margin:0 auto}
.ui-tabbar ul{list-style:none;display:flex;justify-content:space-around;margin:0;padding:.35rem .25rem;background:var(--card-hi);border:1px solid var(--line);border-radius:1.4rem;box-shadow:var(--rim),var(--e3)}
.ui-tabbar li{flex:1 1 0;min-width:0}
.ui-tabbar a{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.15rem;min-height:3.1rem;padding:0 .1rem;border-radius:1rem;color:var(--muted);font:600 var(--fs-xs)/1.1 var(--sans);text-decoration:none;text-align:center}
.ui-tabbar a[aria-current]{color:var(--accent)}
.ui-tabbar a:focus-visible{outline:3px solid var(--focus);outline-offset:-3px}
.ui-tabbar .ui-ico{width:1.4rem;height:1.4rem}
.ui-tabbar .ui-nl{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the labels grow with Aa only so far: five across can't fit "Payments" at the largest size (it showed "Payme…"; the
   phone pass, 2026-09-26). iOS's own tab bars keep their labels fixed for the same reason; the icons still grow. */
.ui-tabbar a{font-size:min(var(--fs-xs),13px)}
@media (max-width:359px){.ui-tabbar a{font-size:11.5px}.ui-tabbar ul{padding-inline:.1rem}}   /* 320px phones (the first iPhone SE) */
.ui-tabbar .ui-count{position:absolute;top:.1rem;left:calc(50% + .3rem);margin:0;min-width:1.2rem;padding:0 .3rem;border:2px solid var(--card-hi);background:var(--bad);color:#fff;font:800 .7rem/1.05rem var(--sans)}
:root[data-theme="dark"] .ui-tabbar .ui-count{color:#1d1409}
.ui-tabbed .ui-page{padding-bottom:calc(6.75rem + env(safe-area-inset-bottom))}   /* the tab bar never covers the last thing */
/* the avatar: the vendor's initials (a dot when live); tapped, their name, Account and Sign out */
.ui-me{position:relative}
.ui-me>summary{list-style:none;position:relative;display:grid;place-items:center;width:2.75rem;height:2.75rem;border-radius:50%;background:linear-gradient(135deg,#f7c9a6,#eb9fb4);color:#3b2412;font:800 var(--fs-s)/1 var(--sans);box-shadow:var(--e1);cursor:pointer}
.ui-me>summary::-webkit-details-marker{display:none}
.ui-me>summary:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
:root[data-theme="dark"] .ui-me>summary{background:linear-gradient(135deg,#7a5a45,#7a4a5a);color:#fff}
.ui-me.cur>summary,.ui-me[open]>summary{box-shadow:0 0 0 3px var(--accent),var(--e1)}
.ui-me-dot{position:absolute;right:-1px;bottom:-1px;width:.8rem;height:.8rem;border-radius:50%;background:var(--ok);border:2px solid var(--bg)}
.ui-me-dot.warn{background:var(--warn)}
.ui-me-menu{position:absolute;right:0;top:calc(100% + .5rem);z-index:45;width:max-content;min-width:14rem;max-width:calc(100vw - 2rem);padding:.4rem;background:var(--card-hi);border:1px solid var(--line);border-radius:var(--r-l);box-shadow:var(--rim),var(--e3)}
.ui-top .ui-me-menu .ui-who{display:block;max-width:18rem;margin:0 0 .3rem;padding:.55rem .6rem .6rem;border-bottom:1px solid var(--line);white-space:normal;overflow-wrap:anywhere}
.ui-me-menu a,.ui-me-menu .ui-link{display:flex;align-items:center;gap:.6rem;width:100%;min-height:2.75rem;padding:0 .6rem;border-radius:var(--r-s);color:var(--ink);text-decoration:none;font:600 var(--fs-m)/1.2 var(--sans)}
.ui-me-menu a:hover,.ui-me-menu .ui-link:hover,.ui-me-menu a[aria-current]{background:var(--accent-bg);color:var(--head)}
.ui-me-menu form{margin:0}
/* a small line over a page's title (the day, the business) */
.ui-hello{margin:.2rem 0 .2rem;font:600 var(--fs-s)/1.35 var(--sans);color:var(--muted)}
.ui-headline{font-size:var(--fs-2xl);text-wrap:balance}
/* picture cards in a row that scrolls (the next one peeks in) on a phone; a grid on a computer */
.ui-deck{display:flex;gap:.75rem;overflow-x:auto;margin:0 -1rem;padding:.2rem 1rem 1rem;scroll-snap-type:x mandatory;scroll-padding-inline:1rem;scrollbar-width:none}
.ui-deck::-webkit-scrollbar{display:none}
.ui-deck>.ui-card{flex:none;display:flex;flex-direction:column;width:min(82%,21rem);margin:0;scroll-snap-align:start}
.ui-deck>.ui-card:only-child{width:100%}
.ui-deck .ui-tile-body{flex:1;display:flex;flex-direction:column}
.ui-deck .ui-tile-acts{margin-top:auto;padding-top:.8rem}
.ui-deck .ui-title{font-size:var(--fs-xl);line-height:1.15;letter-spacing:-.01em}
.ui-deck .ui-media{padding-top:1.6rem}
.ui-deck .ui-tile-acts .btn{padding-left:.6rem;padding-right:.6rem;white-space:nowrap}
.ui-deck .ui-tile-acts>.secondary{flex:.6 1 0}
.ui-deck a.ui-tile-link{color:inherit;text-decoration:none}
.ui-deck a.ui-tile-link:focus-visible{outline:3px solid var(--focus);outline-offset:2px;border-radius:var(--r-s)}
.ui-clamp{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ui-media-badge.due{display:inline-flex;align-items:center;gap:.35rem}
.ui-media-badge.due::before{content:"";flex:none;width:.5rem;height:.5rem;border-radius:50%;background:var(--warn)}
.ui-media-badge.due.late::before{background:var(--bad)}
.ui-media-badge.past{background:var(--ink);color:var(--card)}
/* who it's from: a small face and the grey line */
.ui-by{display:flex;align-items:center;gap:.5rem;margin-top:.5rem}
.ui-by .ui-av{width:1.7rem;height:1.7rem;font-size:.6rem;border:0}
.ui-by .ui-facts{flex:1;min-width:0}
/* one numbers card: saw you › got in touch › sales, then the money */
.ui-funnel{display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr) auto minmax(0,1fr);align-items:start;gap:.25rem;margin:.2rem 0 0;text-align:center}
.ui-funnel b{display:block;font:800 var(--fs-2xl)/1 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
.ui-funnel span{display:block;margin-top:.3rem;font-size:var(--fs-xs);line-height:1.25;color:var(--muted)}
.ui-funnel i{align-self:center;padding-bottom:1.2rem;font:400 var(--fs-xl)/1 var(--sans);font-style:normal;color:var(--line-strong)}
.ui-sums{display:flex;justify-content:space-between;gap:1rem;margin:1rem 0 0;padding-top:.9rem;border-top:1px solid var(--line);font-size:var(--fs-s);color:var(--muted)}
.ui-sums b{display:block;font:800 var(--fs-l)/1.3 var(--sans);color:var(--ink);font-variant-numeric:tabular-nums}
.ui-sums>:last-child{text-align:right}
/* a group's heading with its count on the right */
.ui-grp{display:flex;justify-content:space-between;align-items:baseline;gap:.5rem}
.ui-grp span{text-transform:none;letter-spacing:0;font-weight:600;color:var(--warn)}
.ui-h2 .ui-facts{display:inline;margin-left:.45rem;font-weight:400;letter-spacing:0}
/* an inbox: rows on one card, each starting with the party's date as a calendar tile */
.ui-inbox{list-style:none;margin:0 0 .75rem;padding:0;overflow:hidden;border-radius:1.15rem}
.ui-inbox>li+li{border-top:1px solid var(--line)}
.ui-irow{display:flex;align-items:flex-start;gap:.8rem;padding:.85rem 1rem;color:var(--ink);text-decoration:none}
a.ui-irow:hover{background:color-mix(in oklab,var(--accent-bg) 55%,var(--card))}
a.ui-irow[aria-current]{background:var(--accent-bg)}
a.ui-irow:focus-visible{outline:3px solid var(--focus);outline-offset:-3px}
.ui-irow .ui-main{flex:1;min-width:0;gap:.05rem}
.ui-irow .ui-title{font-size:var(--fs-m)}
.ui-irow.new .ui-title::after{content:"";display:inline-block;width:.5rem;height:.5rem;margin-left:.4rem;border-radius:50%;background:var(--accent);vertical-align:middle}
.ui-snip{display:block;font-size:var(--fs-s);color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ui-irow-side{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:.35rem;font-size:var(--fs-xs);color:var(--muted);text-align:right}
.ui-ico-tile.cal:has(small){width:3.3rem;height:auto}
.ui-ico-tile.cal small{display:block;padding:0 0 .25rem;text-align:center;font:600 .7rem/1.2 var(--sans);color:var(--muted)}
.ui-ico-tile.cal.past i{background:var(--muted);color:var(--card)}
.ui-ico-tile.cal b{padding-top:.15rem}
/* shown only on a computer (the list beside a request), or only on a phone */
@media (max-width:55.99rem){.ui-wide-only{display:none!important}}
@media (min-width:56rem){.ui-narrow-only{display:none!important}}
/* the host's words, as a message */
.ui-msgrow{display:flex;align-items:flex-end;gap:.6rem;margin:1rem 0}
.ui-msgrow .ui-av{width:2.2rem;height:2.2rem;font-size:.7rem;border:0}
.ui-bubble.in{flex:1;min-width:0;max-width:none;margin:0;padding:.7rem .95rem;border:1px solid var(--line);border-radius:1.1rem 1.1rem 1.1rem .3rem;background:var(--card);color:var(--ink);font-size:var(--fs-m);box-shadow:var(--rim),var(--e1)}
.ui-bubble small{display:block;margin-top:.35rem;font-size:var(--fs-xs);color:var(--muted);white-space:normal}
/* where it stands: a track, top to bottom (done ●, now ◉, to come ○) */
.ui-timeline{list-style:none;margin:.2rem 0 1rem;padding:0}
.ui-timeline li{position:relative;padding:0 0 .9rem 1.9rem;font-size:var(--fs-s);color:var(--muted)}
.ui-timeline li::before{content:"";position:absolute;left:.3rem;top:.2rem;width:.75rem;height:.75rem;border-radius:50%;border:2px solid var(--line-strong);background:var(--card)}
.ui-timeline li::after{content:"";position:absolute;left:.64rem;top:1.15rem;bottom:.1rem;width:2px;background:var(--line)}
.ui-timeline li:last-child{padding-bottom:0}.ui-timeline li:last-child::after{display:none}
.ui-timeline li.done::before{background:var(--ok);border-color:var(--ok)}
.ui-timeline li.done::after{background:color-mix(in oklab,var(--ok) 45%,var(--line))}
.ui-timeline li.cur::before{background:var(--accent);border-color:var(--accent);box-shadow:0 0 0 4px var(--accent-bg)}
.ui-timeline li.no::before{background:var(--muted);border-color:var(--muted)}
.ui-timeline b{font-weight:700;color:var(--ink)}
/* the answer, always in sight: pinned to the foot of a phone; at the top of the request beside the list on a computer */
.ui-pinbar{position:fixed;left:0;right:0;bottom:0;z-index:30;padding:.75rem 1rem max(1rem,env(safe-area-inset-bottom));background:var(--card-hi);border-top:1px solid var(--line);border-radius:1.4rem 1.4rem 0 0;box-shadow:var(--rim),0 -10px 30px var(--shadow),var(--e2)}
.ui-pinbar-t{display:flex;align-items:center;gap:.45rem;margin:0 0 .6rem;font:600 var(--fs-s)/1.3 var(--sans);color:var(--warn)}
.ui-pinbar-t::before{content:"";flex:none;width:.55rem;height:.55rem;border-radius:50%;background:currentColor}
.ui-pinbar-t.late{color:var(--bad)}
.ui-pinbar-a{display:flex;gap:.5rem;max-width:34rem}
.ui-pinbar-a>.btn{flex:1 1 0;margin:0;min-width:0}
.ui-pinbar-a>.btn.secondary{flex:.8 1 0}
.ui-pinned .ui-page{padding-bottom:calc(9.5rem + env(safe-area-inset-bottom))}
@media (max-width:55.99rem){.ui-pinned .ui-tabbar{display:none}}
/* a request beside the list (a computer): its own raised pane */
.ui-pane-grid>*{min-width:0}
/* the card as hosts see it, on a slice of their page: the map behind, the sheet over it, the card on the sheet */
.ui-slice{position:relative;overflow:hidden;margin:0 0 1rem;border-radius:1.3rem;box-shadow:var(--rim),var(--e1);background:radial-gradient(circle at 25% 35%,#cfe0ee 0 10%,transparent 11%),radial-gradient(circle at 80% 20%,#d8e8cf 0 13%,transparent 14%),repeating-linear-gradient(32deg,transparent 0 34px,rgba(255,255,255,.55) 34px 37px),repeating-linear-gradient(-58deg,transparent 0 52px,rgba(230,160,120,.45) 52px 55px),#e8eadf}
:root[data-theme="dark"] .ui-slice{background:radial-gradient(circle at 25% 35%,#1d2a36 0 10%,transparent 11%),radial-gradient(circle at 80% 20%,#1f2b1d 0 13%,transparent 14%),repeating-linear-gradient(32deg,transparent 0 34px,rgba(255,255,255,.06) 34px 37px),repeating-linear-gradient(-58deg,transparent 0 52px,rgba(240,163,90,.18) 52px 55px),#1a1d19}
.ui-slice-pin{position:absolute;display:grid;place-items:center;width:1.9rem;height:1.9rem;border-radius:50%;border:2px solid #fff;background:var(--accent);color:var(--accent-ink);font:800 var(--fs-xs)/1 var(--sans);box-shadow:var(--e2)}
.ui-slice-pin.a{left:30%;top:.9rem}.ui-slice-pin.b{left:8%;top:2rem;background:var(--ink);color:var(--bg)}
/* A language choice (the party's, a guest's): English and any lead choice as buttons, every other language in a list
   beside them, so adding languages never changes the layout (David, 2026-09-28). */
.ui-langpick{display:flex;flex-wrap:wrap;gap:.4rem;margin:.3rem 0 .5rem}
.ui-langpick-b{min-height:2.6rem;padding:.45rem .9rem;border:1px solid var(--line-strong);border-radius:999px;background:var(--card);color:var(--ink);font:600 var(--fs-s)/1.2 var(--sans);cursor:pointer}
.ui-langpick-b[aria-pressed="true"],.ui-langpick .ui-langpick-s.on,.gpanel .ui-langpick .ui-langpick-s.on{border:2px solid var(--accent);background-color:var(--accent-bg);color:var(--head)}
.ui-langpick .ui-langpick-s,.gpanel .ui-langpick .ui-langpick-s,.ui-wordsin .ui-langpick-s{flex:1 1 9rem;width:auto;min-width:0;max-width:100%;min-height:2.6rem;padding:.4rem .7rem;border:1px solid var(--line-strong);border-radius:999px;background:var(--card);color:var(--ink);font:600 var(--fs-s)/1.2 var(--sans)}
.ui-langpick-b:disabled,.ui-langpick-s:disabled{opacity:.55;cursor:not-allowed}
.ui-wordsin{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin:.4rem 0 0}.ui-wordsin .btn{margin:0}   /* your own versions, then the list of the rest */
/* The language lists draw their own box and arrow: Safari otherwise keeps a list at its own small size, ignoring the
   padding (the arrow is two CSS triangles, so no picture is needed). */
.ui-langpick .ui-langpick-s,.gpanel .ui-langpick .ui-langpick-s,.ui-wordsin .ui-langpick-s,.disp-panel .lang-other select{-webkit-appearance:none;appearance:none;padding-right:2rem!important;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 1.05rem) 55%,calc(100% - .7rem) 55%;background-size:.35rem .35rem,.35rem .35rem;background-repeat:no-repeat}
.ui-slice>.ui-seg{position:absolute;right:.7rem;top:.7rem;z-index:2;margin:0;box-shadow:var(--e2)}
.ui-slice-sheet{position:relative;margin-top:4.2rem;padding:.4rem .8rem .9rem;background:var(--bg);border-radius:1.3rem 1.3rem 0 0;box-shadow:0 -10px 30px var(--shadow)}
.ui-slice-sheet::before{content:"";display:block;width:2.5rem;height:.3rem;margin:.2rem auto .6rem;border-radius:.2rem;background:var(--line-strong)}
.ui-slice-sheet .ui-card:last-child{margin-bottom:0}
.ui-slice-sheet>*+*{margin-top:.75rem}
.p-js .ui-slice[data-show="closed"] .ui-slice-open,.p-js .ui-slice[data-show="open"] .ui-slice-closed{display:none}
.ui-seg button{display:inline-flex;align-items:center;min-height:2.4rem;padding:.55rem .95rem;border:0;background:none;color:var(--muted);font:600 var(--fs-s)/1 var(--sans);cursor:pointer}
.ui-seg button[aria-pressed="true"],.ui-seg button[aria-current="true"]{background:var(--ink);color:var(--card)}
.ui-seg button:focus-visible,.ui-seg a:focus-visible{outline:3px solid var(--focus);outline-offset:-3px}
/* a choice with more than fits on a phone (a guest's language on the guest list): its buttons wrap to a second line */
.ui-seg.wrap{flex-wrap:wrap;border-radius:1.2rem}
.ui-seg b{margin-left:.35rem;font-weight:800}
/* photos in a strip: the first one bigger ("Hosts see this first"), then a tile to add more */
.ui-shots{list-style:none;display:flex;gap:.6rem;overflow-x:auto;margin:0 -1rem;padding:.2rem 1rem 1rem;scrollbar-width:none}
.ui-shots::-webkit-scrollbar{display:none}
.ui-shots>li{flex:none}
.ui-shot{position:relative;display:block;width:8.5rem;height:8.5rem;overflow:hidden;border-radius:1rem;background:var(--zone);box-shadow:var(--rim),var(--e1)}
.ui-shot.first{width:12rem}
.ui-shot img{display:block;width:100%;height:100%;object-fit:cover}
.ui-shot .ui-media-badge{font-size:.7rem}
.ui-shot .ui-onpic{left:auto;right:.45rem;bottom:.45rem;top:auto}
.ui-shot.add{display:grid;place-items:center;align-content:center;gap:.15rem;padding:0;border:2px dashed var(--line-strong);background:var(--card);box-shadow:none;color:var(--accent);font:700 var(--fs-s)/1.2 var(--sans);text-align:center;cursor:pointer}
.ui-shot.add b{font-size:1.8rem;line-height:1}
.ui-shot.add:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
/* the parts of a listing as rows that show their value; tapped, the part opens to change it */
.ui-rowgroup>.ui-card{margin-bottom:.5rem}
.ui-rowgroup .ui-sum{align-items:center;min-height:4rem}
.ui-rowgroup .ui-sum .ui-chev{margin-top:0}
.ui-rowgroup details[open]>.ui-sum .ui-chev{margin-top:.3rem}
.ui-rowgroup .ui-row-ico{border-radius:.75rem;width:2.5rem;height:2.5rem}
@media (min-width:56rem){
  .ui-tabbar{position:static;flex:0 1 auto;max-width:none;margin:0 auto;left:auto;right:auto;bottom:auto}
  .ui-tabbar ul{display:inline-flex;gap:.2rem;padding:.3rem;border-radius:999px;box-shadow:var(--rim),var(--e2)}
  .ui-tabbar li{flex:none}
  .ui-tabbar a{flex-direction:row;gap:.4rem;min-height:2.6rem;padding:.5rem 1rem;border-radius:999px;font-size:var(--fs-s)}
  .ui-tabbar a:hover{color:var(--ink)}
  .ui-tabbar a[aria-current]{background:var(--ink);color:var(--card)}
  .ui-tabbar .ui-ico{display:none}
  .ui-tabbar .ui-count{position:static;border:0;line-height:1.2rem}
  .ui-top.app{padding:.8rem 1.5rem;gap:1.5rem}
  .ui-top.app .ui-top-r{margin-left:0}
  .ui-tabbed .ui-page{padding-bottom:3rem}
  .ui-deck{display:grid;grid-template-columns:repeat(auto-fill,minmax(15rem,1fr));overflow:visible;margin:0;padding:.2rem 0 1rem}
  .ui-deck>.ui-card,.ui-deck>.ui-card:only-child{width:auto}
  .ui-pinbar{position:static;display:flex;flex-wrap:wrap;align-items:center;gap:.6rem 1rem;padding:1rem 1.25rem;border:0;border-bottom:1px solid var(--line);border-radius:0;box-shadow:none;background:transparent}
  .ui-pinbar-t{flex:1 1 12rem;margin:0}
  .ui-pinbar-a>.btn,.ui-pinbar-a>.btn.secondary{flex:none;white-space:nowrap}
  .ui-pinned .ui-page{padding-bottom:3rem}
  .ui-pane{background:var(--card);border:1px solid var(--line);border-radius:1.3rem;box-shadow:var(--rim),var(--e2);overflow:hidden}
  .ui-pane-in{padding:1.1rem 1.25rem 1.25rem}
  .ui-shots{flex-wrap:wrap;overflow:visible;margin:0;padding:.2rem 0 1rem}
}
@media (min-width:72rem){.ui-pane-grid{display:grid;grid-template-columns:minmax(0,1fr) 16rem;gap:0 1.25rem;align-items:start}}

/* ---------- tables and seating (src/worker.js hostSeatingPage, public/seating-page.js; David, 2026-09-27): its own page,
   not a pop-up ("Name tags is pop-up, no other screen acts that way"). Add a table by its picture (Zola's shapes and
   sizes); each table a card: its number big, its name, how full (a bar that turns orange when full), Edit that says
   Close while open; how many tables and seats in the floating bar. ---------- */
.ui-seatpage{padding-bottom:max(7rem,var(--actbar-room,0px))}
.ui-seatpage>.ui-h2{margin:.9rem 0 .2rem}
.ui-tablepick{display:grid;grid-template-columns:repeat(auto-fill,minmax(6.2rem,1fr));gap:.6rem;margin:.4rem 0 1rem}
.ui-tablepick button{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.35rem;min-height:6.6rem;padding:.6rem .4rem .55rem;border:1px solid var(--line);border-radius:1rem;background:var(--card);color:var(--accent);box-shadow:var(--rim),var(--e1);font:700 var(--fs-s)/1.2 var(--sans);cursor:pointer;transition:box-shadow .15s ease,transform .15s ease}
.ui-tablepick button>span{color:var(--ink)}
.ui-tablepick button:hover{box-shadow:var(--rim),var(--e2);transform:translateY(-1px)}
.ui-tablepick button[aria-expanded="true"]{border:2px solid var(--accent);background:var(--accent-bg)}
.ui-tablepick button:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-tablepick svg{width:3.4rem;height:3.4rem}
.ui-stables{list-style:none;margin:.4rem 0 0;padding:0;display:grid;grid-template-columns:minmax(0,1fr);gap:.75rem;align-items:start}
@media (min-width:48rem){.ui-stables{grid-template-columns:repeat(2,minmax(0,1fr))}}
.ui-stable{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:.4rem .9rem;margin:0;padding:.85rem .9rem .85rem 1rem}
.ui-stable-n{display:grid;place-items:center;min-width:3.2rem;height:3.2rem;padding:0 .3rem;border-radius:.9rem;background:var(--accent-bg);color:var(--head);font:800 var(--fs-2xl)/1 var(--sans);font-variant-numeric:tabular-nums}
.ui-stable-fill{display:flex;align-items:center;gap:.5rem;margin-top:.35rem;font:600 var(--fs-s)/1.2 var(--sans);color:var(--muted);white-space:nowrap}
.ui-stable-fill .ui-meter{margin:0;flex:1;min-width:3rem}
.ui-stable .ui-meter.full::-webkit-progress-value{background:var(--warn)}.ui-stable .ui-meter.full::-moz-progress-bar{background:var(--warn)}
.ui-stable>.btn{margin:0}
.ui-stable-form{grid-column:1/-1;margin-top:.3rem;padding-top:.8rem;border-top:1px solid var(--line)}
.ui-stable-form .ui-stepper,.ui-stable-other .ui-stepper{margin:0 0 .9rem}
.ui-stable-other{margin:0 0 1rem}
body:has(.ui-seatpage) .ui-toasts{bottom:6.5rem}
/* the host app's pages below a step (public/app.js page mode: More, name tags, delete): the page head and the page,
   with room above the pinned bar; the party pill, the rail and the steps aren't there (rule 2: a page below a step
   has no party pill) */
body:has(.ui-pagemode) .ui-apptop,.ui-pagemode #subnav,.ui-pagemode #navBack,.ui-pagemode #purgeNote,.ui-pagemode section.page,.ui-pagemode #pager{display:none!important}
.ui-subpage{padding-bottom:max(8rem,calc(var(--actbar-room,0px) + 1rem))}
.ui-subpage .ui-actbar .ui-actbar-say{white-space:normal;overflow:visible;text-overflow:clip}
.ui-subpage .ui-actbar .ui-actbar-say b{white-space:normal}
body:has(.ui-subpage .ui-actbar) .ui-toasts{bottom:6.5rem}
html:has(.ui-subpage){scroll-padding-bottom:max(7rem,var(--actbar-room,0px))}   /* the same, below a step and on a guest's answer page (public/app.js, src/worker.js) */
/* asking first, in place (rule 9): what happens, then Cancel and the red button, right where it was asked */
.ui-askfirst{margin:.6rem 0;flex:1 0 100%;box-sizing:border-box}.ui-askfirst .ui-btns{margin:0}
.ui-askfirst p{margin:0}
/* the host app: above its floating bar (a step bar, or Back / Next) */
body:has(.ui-hostapp .page:not([hidden]) .ui-actbar,.ui-hostapp #pager:not([hidden])) .ui-toasts{bottom:6rem}
.ui-seatpage .ui-choice>input{flex:none;width:1.15rem;height:1.15rem;margin:0;padding:0;accent-color:var(--accent)}
html:has(.ui-seatpage){scroll-padding-bottom:max(7rem,var(--actbar-room,0px))}   /* what's brought into view (an opened Edit, a focused field) stops above the pinned bar, however tall (ui.js keepBarRoom sets --actbar-room) */
/* Seat people (step 2): each family a card (its people as chips, Seat/Move opening the tables in place); a table picker
   in the card, a full table or one the family won't fit greyed out; By table: each table's people (✕ takes one off) and
   its meals, "+ Add people" opening a tick list; on a wide screen families on the left and tables on the right. */
.ui-seatpage:has(.ui-seatwide){max-width:none}
.ui-sfams{list-style:none;margin:.4rem 0 0;padding:0;display:grid;gap:.6rem}
.ui-sfam{margin:0;padding:.8rem .9rem}
.ui-sfam.picking{box-shadow:var(--rim),var(--e2);border-color:var(--accent)}
.ui-sfam-h{display:flex;align-items:flex-start;gap:.6rem}
.ui-sfam-h .ui-main{flex:1;min-width:0}
.ui-sfam-h>.btn{flex:none;margin:0}
.ui-sn{display:inline-grid;place-items:center;min-width:1.4rem;height:1.4rem;padding:0 .3rem;border-radius:999px;background:var(--accent-bg);color:var(--head);font:800 var(--fs-xs)/1 var(--sans)}
.ui-hd[aria-expanded="true"]{border-color:var(--accent);background:var(--accent-bg)}
.ui-spick{margin:.7rem 0 0;padding:.7rem 0 0;border-top:1px solid var(--line)}
.ui-spick .ui-q{margin:0 0 .4rem}
.ui-spick-list{list-style:none;margin:0 0 .4rem;padding:0;display:grid;gap:.4rem}
.ui-spick-t{display:flex;align-items:center;gap:.7rem;width:100%;min-height:3rem;padding:.4rem .8rem .4rem .45rem;border:1px solid var(--line-strong);border-radius:var(--r-m);background:var(--card);color:var(--ink);font:600 var(--fs-m)/1.25 var(--sans);text-align:left;cursor:pointer}
.ui-spick-t:hover:not(:disabled){border-color:var(--accent)}
.ui-spick-t:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-spick-t:disabled{cursor:default;opacity:.5;background:var(--zone)}
.ui-spick-t[aria-current="true"]{opacity:1;border-color:var(--accent);background:var(--accent-bg)}
.ui-spick-n{flex:none;display:grid;place-items:center;width:2.2rem;height:2.2rem;border-radius:.6rem;background:var(--accent-bg);color:var(--head);font:800 var(--fs-l)/1 var(--sans)}
.ui-spick-l{flex:1;min-width:0;overflow-wrap:anywhere}
.ui-spick-s{flex:none;font:600 var(--fs-s)/1.2 var(--sans);color:var(--muted);text-align:right}
.ui-stable-p{align-items:start}
.ui-smeals{color:var(--ink);font-weight:600}
.ui-stable-p>.btn{margin:0}
.ui-stable-people{grid-column:1/-1}
.ui-stable-people .ui-namechips{margin:.2rem 0 .3rem}
.ui-sticks{margin:.3rem 0 0;padding:.5rem .8rem;border:1px solid var(--line);border-radius:var(--r-m);background:var(--zone)}
.ui-sticks .ui-pill{margin-left:.3rem}
.ui-sadd{margin:0 0 1rem}
.ui-snotice{align-items:flex-start}
.ui-snotice>span{display:flex;flex-direction:column;gap:.2rem;min-width:0}
.ui-snotice-l{display:block;font-size:var(--fs-s)}
.ui-sprints{list-style:none;margin:.6rem 0;padding:0;display:grid;gap:.6rem}
.ui-sprint{display:flex;align-items:center;gap:.8rem;margin:0}
.ui-sprint .ui-main{flex:1;min-width:0}
.ui-sprint>.btn{flex:none;margin:0}
@media (min-width:64rem){
  .ui-sgrid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:1.5rem;align-items:start}
  .ui-sgrid>section>.ui-h2{margin-top:.6rem}
  .ui-sgrid .ui-stables-p{grid-template-columns:minmax(0,1fr)}
}
.ui-seatpage .ui-check input[type=checkbox]{flex:none;width:1.25rem;height:1.25rem;margin:.15rem 0 0;padding:0;accent-color:var(--accent)}

/* "Report a problem" (src/reports.js, public/report.js): the form opens in place under the footer (rule 1); on a review
   link the "Something look wrong?" button stays at the bottom corner, a control like the Aa menu, never over the form. */
.rp{padding:1rem 1.1rem;margin:1rem 0 0;text-align:left}
.rp .ui-h2{margin-top:0}
.rp .ui-choices{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}   /* the four types, two to a row */
.rp-hp{position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden}
.rp-foot{margin-top:1.5rem}
.rp-float{position:fixed;right:1rem;bottom:calc(1rem + env(safe-area-inset-bottom,0px));z-index:40;min-height:2.75rem;padding:.55rem 1rem;font-size:var(--fs-s);box-shadow:var(--e2)}
body:has(.rp form) .rp-float{display:none}   /* the form is open: the floating button would cover its Cancel and Send */
@media print{.rp,.rp-float,.rp-link,.rp-foot{display:none!important}}

/* Chinese has no italic: slanted characters look broken (the native-speaker reviews, 2026-09-28). A Chinese page, or a
   Chinese name inside another page's italic line, stays upright. */
:lang(zh) :is(em,i,cite,.ui-lbl-party,.ci-for,.so-menu li),:lang(zh) .ui-lbl.formal .ui-lbl-party{font-style:normal}
/* Look: the cards the host tried, small, one tap to put one back (David, 2026-09-28) */
/* Look's row (+ From a file · Paste picture · your own pictures · Default look · the cards tried): one line that scrolls
   sideways at every width, however many pictures the host adds (David, 2026-09-29: "shown in the row the way the cards
   tried scroll"); the designs below still wrap on a wide screen. */
.ui-strip.ui-lookrow{flex-wrap:nowrap;overflow-x:auto;scroll-snap-type:x proximity}
/* A row that scrolls sideways, with its arrows and fades (ui.js stripArrows): the arrows sit on the pictures' middle */
.ui-stripwrap{position:relative}
.ui-strip-arrow{position:absolute;z-index:3;top:5rem;transform:translateY(-50%);display:grid;place-items:center;width:2.6rem;height:2.6rem;padding:0;border:1px solid var(--line);border-radius:50%;background:var(--card-hi);color:var(--ink);box-shadow:var(--e2);cursor:pointer}
.ui-strip-arrow.prev{left:-.3rem}.ui-strip-arrow.next{right:-.3rem}
.ui-strip-arrow[hidden]{display:none}
.ui-strip-arrow:hover{color:var(--accent)}
.ui-strip-arrow:focus-visible{outline:3px solid var(--focus);outline-offset:2px}
.ui-stripwrap::before,.ui-stripwrap::after{content:"";position:absolute;z-index:2;top:0;bottom:1.6rem;width:3rem;pointer-events:none;opacity:0;transition:opacity .2s}
.ui-stripwrap::before{left:-1rem;background:linear-gradient(to right,var(--bg),transparent)}
.ui-stripwrap::after{right:-1rem;background:linear-gradient(to left,var(--bg),transparent)}
.ui-stripwrap.more-l::before,.ui-stripwrap.more-r::after{opacity:1}
@media (min-width:60rem){.ui-stripwrap::before{left:0}.ui-stripwrap::after{right:0}}
.ui-stripwrap.mid .ui-strip-arrow{top:50%}.ui-stripwrap.mid::before,.ui-stripwrap.mid::after{bottom:0}   /* a slim row: Party needs' kinds (party-needs-4) */
/* A step in two columns, on a laptop (ui.js pinColumns; David, 2026-09-29): each column (data-pin) stays once its
   bottom is in view (--pin-top: below the header when it fits, above the pinned bar when it's taller). The step's rail
   scrolls away with the page (David, 2026-09-30: "That should scroll up to give screen more real estate"). So the shorter column (Look's picture, the page being built on Ask guests) stays in
   sight while the longer one (the designs, the list of questions) scrolls to its end. Phones stay one column. */
@media (min-width:56rem){
  [data-pin]{position:sticky;top:var(--pin-top,6rem);align-self:start}
}
/* A question asked from the pinned bar (ui.js askHere): room under it for the bar, so the bar never covers its words */
.ui-askfirst.ui-askbar{margin-bottom:var(--actbar-room,7rem)}
.ui-tried .ui-ptile.sm{width:4.4rem;min-width:4.4rem}
.ui-tried .ui-ptile.sm .ui-ptile-pic{aspect-ratio:4/5}
.ui-tried .ui-ptile.sm canvas{width:100%;height:100%}
/* A line put back after Reload that the host hasn't saved yet (app.js putBackUnsaved): "Your unsaved change". */
.ui-unsaved{outline:2px dashed var(--warn);outline-offset:2px;border-radius:4px}
.ui-unsaved-tag{display:block;margin:.1rem 0 .3rem;font-size:var(--fs-s);font-weight:600;color:var(--warn);font-style:normal}
