/* Event Engine 2.0 — one stylesheet, no build step.
   --brand is injected per install from the settings table (base.html), so this
   file never hardcodes an organisation's colour.

   Always light, deliberately. The OS-following dark theme surprised owners who
   had never asked for it, and every surface that set its own colour needed a
   second rule nobody remembered to write. */

/* The three Hebrew families an owner can pick from, vendored under
   /static/fonts (SIL OFL, see OFL.txt there) -- never a CDN, because this app
   is installed on other people's servers. Variable weight, split by script the
   way Google serves them, so a page loads only the family it uses and only the
   scripts it contains. */
@font-face { font-family: Rubik; font-style: normal; font-weight: 300 900; font-display: swap;
  src: url(fonts/rubik-hebrew.woff2) format("woff2");
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; }
@font-face { font-family: Rubik; font-style: normal; font-weight: 300 900; font-display: swap;
  src: url(fonts/rubik-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: Heebo; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url(fonts/heebo-hebrew.woff2) format("woff2");
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; }
@font-face { font-family: Heebo; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url(fonts/heebo-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: Assistant; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(fonts/assistant-hebrew.woff2) format("woff2");
  unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; }
@font-face { font-family: Assistant; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(fonts/assistant-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }

:root {
  --brand: #1a73e8;
  --brand-ink: #ffffff;   /* the text colour that reads on --brand */
  --brand-link: #1a73e8;  /* --brand as TEXT, readable on --card (settings.ink_on) */
  --brand-stage: #2c7eea; /* --brand as TEXT on the dark survey screen (settings.STAGE_BG) */
  --font: Rubik, Segoe UI, Arial, sans-serif;
  --btn-radius: 8px;
  --bg: #f6f7f9;
  --card: #ffffff;
  --ink: #202124;
  --muted: #5f6368;
  --border: #dadce0;
  --ok: #188038;
  --err: #c5221f;
  --warn: #8f4e00;   /* 5.7:1 on the amber tint; #b06000 was 4.3 */
  --warn-bg: #fef7e0;
  --radius: 10px;
  --shadow: 0 1px 3px rgba(60, 64, 67, .16);
}

* { box-sizing: border-box; }
/* The UA stylesheet hides [hidden] on HTML elements only; an inline SVG
   sprite needs telling, or it renders as a blank 300x150 block. */
svg[hidden] { display: none; }
/* And any author rule that sets `display` (`.field` is a block) beats the UA
   stylesheet's [hidden], so a field shown on demand was always shown. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.6 var(--font);
}

/* 🚨 Link TEXT is --brand-link, never --brand. The business ochre #ffc250
   is 1.6:1 as text on white, so every link in a description was a word you
   squinted at; --brand-link is the same hue, darkened (or lightened on the
   night preset) until it reads. A line, a border or a ring stays --brand —
   only text has to be read. test_brand_link.py lists the exceptions. */
a { color: var(--brand-link); }

.wrap { max-width: 1040px; margin: 0 auto; padding: 24px 16px 64px; }
.wrap--narrow { max-width: 460px; padding-top: 64px; }
/* A form with three time fields in a row wants more than a login form. */
.wrap--form { max-width: 620px; padding-top: 32px; }
/* Public pages. A sign-up page carries a video, a cover image and paragraphs
   of description; at the 460px a login form wants, the video was a postage
   stamp on a 2000px screen and the text wrapped every few words. */
.wrap--public { max-width: 760px; padding-top: 40px; }

/* Shadow mode: the admin walking the public flow as a visitor. The banner is
   deliberately loud — this page looks exactly like the real one and is not. */
.shadow-banner { margin: 0 0 14px; padding: 10px 14px; border-radius: 8px;
  background: #fef7e0; color: var(--warn); font-size: 14px; text-align: center; }
.shadow-email { margin: 12px 0 0; border: 1px dashed var(--border);
  border-radius: 10px; overflow: hidden; }
.shadow-email__subject { padding: 10px 14px; font-weight: 500;
  background: var(--bg); border-bottom: 1px solid var(--border); }

/* topbar */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px 16px; padding: 10px 20px; flex-wrap: wrap;
  background: var(--card); border-bottom: 1px solid var(--border);
}
.topbar__brand { display: flex; align-items: center; gap: 10px; min-width: 0;
  font-weight: 600; color: var(--ink); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar__nav a { white-space: nowrap; }
/* On a phone the name takes the first row and the nav the second, so
   neither wraps word by word. */
@media (max-width: 600px) {
  .topbar { padding: 8px 12px; }
  .topbar__brand { flex: 1 1 100%; }
  .topbar__nav { flex: 1 1 100%; justify-content: flex-start; margin: 0 -6px; }
}
.topbar__logo { height: 28px; width: auto; }
.brandmark { display: block; max-height: 72px; max-width: 220px; width: auto;
  margin: 0 auto 16px; }
/* The public frame: one card with a coloured strip as its top edge and the
   logo inside, the way v1 drew it. The templates' own .card is flattened so
   the page does not become a card inside a card. Logo at v1's 88px. */
.frame { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
.frame__bar { display: flex; height: 6px; }
.frame__bar > div { flex: 1; background: var(--brand); }
.frame__body { padding: 24px; }
.frame__body > .card { border: 0; box-shadow: none; padding: 0; border-radius: 0; }
.frame .brandmark { width: 88px; max-width: 88px; max-height: none; margin: 8px auto 18px; }
@media (min-width: 700px) { .frame__body { padding: 40px 48px; } }
.topbar__nav { display: flex; gap: 4px; }
.topbar__nav a { color: var(--muted); text-decoration: none; font-size: 15px;
  padding: 8px 10px; border-radius: 8px; line-height: 1.2; }
.topbar__nav a:hover { color: var(--ink); background: var(--bg); }
/* Where you are. A nav with no current item is a map with no "you are here". */
.topbar__nav a[aria-current="page"] { color: var(--brand-link); font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--brand); border-radius: 8px 8px 0 0; }
.topbar__brand { padding: 4px 0; }

/* The search field. One shell around the icon, the input and the button, so
   the three read as a single control and light up together — an input with a
   button parked beside it reads as two things that happen to be adjacent.
   The shell owns the border, the fill and the focus ring; the input inside it
   has none of the three, which is why it is not .input. */
.searchfield {
  display: flex; align-items: center; gap: 8px;
  padding: 5px; padding-inline-start: 14px;
  background: var(--bg); border: 1px solid var(--border);
  border-radius: 999px;
  transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.searchfield:hover { border-color: color-mix(in srgb, var(--brand) 35%, var(--border)); }
/* focus-within, not :focus: the ring belongs to the whole control, and the
   thing actually focused is the input or the button inside it. */
.searchfield:focus-within {
  background: var(--card); border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 18%, transparent);
}
.searchfield__input {
  flex: 1 1 auto; min-width: 0; padding: 8px 0;
  font: inherit; font-size: 15px; color: var(--ink);
  background: none; border: 0; outline: none;
}
.searchfield__input::placeholder { color: var(--muted); }
.searchfield__go {
  flex: none; padding: 9px 18px; font: inherit; font-size: 14px; font-weight: 500;
  color: var(--brand-ink); background: var(--brand);
  border: 0; border-radius: 999px; cursor: pointer;
}
.searchfield__go:hover { filter: brightness(.94); }
.searchfield__go:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
/* The leading icon is decoration inside the field, so it drops .ic's trailing
   margin and takes the muted colour until the field is focused. */
.ic--lead { margin: 0; width: 19px; height: 19px; color: var(--muted); }
.searchfield:focus-within .ic--lead { color: var(--brand); }

/* In the topbar it grows into the space the brand and the nav leave, and at
   phone width it takes a row of its own rather than squeezing the links —
   measured at 375px, where a third item on one line overflows the document. */
.topbar__search { flex: 1 1 340px; max-width: 520px; min-width: 0; }
@media (max-width: 600px) {
  .topbar { flex-wrap: wrap; }
  .topbar__search { flex-basis: 100%; max-width: none; order: 3; }
}

/* The results page's own box: a card that is a form, not a form inside one. */
/* The results page's own field. No card around it: the field IS the card here,
   and a box inside a box was two borders saying the same thing. */
.searchbox { margin-bottom: 28px; }
.searchbox__hint { margin: 10px 4px 0; color: var(--muted); font-size: 13px; }
.searchfield--lg { padding: 6px; padding-inline-start: 18px;
  background: var(--card); box-shadow: var(--shadow); }
.searchfield--lg .ic--lead { width: 22px; height: 22px; }
.searchfield--lg .searchfield__input { padding: 11px 0; font-size: 17px; }
.searchfield--lg .searchfield__go { padding: 11px 24px; font-size: 15px; }

/* blocks */
.card {
  background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow); padding: 24px;
}
.card--center { text-align: center; }
/* The approval queue. The one card on the dashboard that is waiting on a
   person, so it carries a rule in the warning colour rather than sitting in the
   page as one more identical white box. */
.card--queue { background: var(--warn-bg); border-color: #f0dfae; }
.card--queue .table { background: transparent; }
.card--queue h2 { color: var(--warn); }
/* Something missing that only the owner can supply — a session with no
   WhatsApp group of its own (settings → nag_event_group). Red rather than the
   queue's amber: amber is "waiting on you", this is "not there". */
.card--alert { background: #fce8e6; border-color: #f3b8b5; }
.card--alert h2 { color: var(--err); margin-top: 0; }
.card--alert .field__hint { color: var(--ink); }
.groupnag { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.groupnag .input { flex: 1 1 240px; min-width: 0; width: auto; }
form.groupnag { padding: 12px 0; border-top: 1px solid #f3b8b5; }
.groupnag__head { flex: 1 1 100%; }
.groupnag__head > * { display: block; }
.groupnag__none { margin: 12px 0 0; }
/* The date changed under people who registered for the old one
   (core/moved.py): amber like the queue, because it is waiting on the owner
   to send something, not missing something only they can supply. */
.card--moved { background: var(--warn-bg); border-color: #f0dfae; }
.card--moved h2 { color: var(--warn); margin-top: 0; }
.moved__people { margin: 0 0 12px; padding-inline-start: 20px; }
.moved__people li { margin: 2px 0; }
/* The recurring workshops on the dashboard (2026-10-07). A list, not a
   table: on a phone each one is a block and its button wraps under it. */
/* 🚨 Never `padding: 0` here: the list IS the card (`ul.card`), and a zero
   took the card's own padding away, so the text and the "מועד חדש" button
   touched its border (2026-10-08, Omri: "something is wrong with the frame
   on the left"). */
.workshops { list-style: none; margin: 0; padding: 18px 24px; }
@media (max-width: 600px) { .workshops { padding: 14px 16px; } }
.workshop { display: flex; flex-wrap: wrap; align-items: center;
  gap: 8px 16px; padding: 12px 0; border-top: 1px solid var(--border); }
.workshop:first-child { border-top: 0; padding-top: 0; }
.workshop__main { flex: 1 1 260px; min-width: 0; }
/* "סדנה 2" never breaks between the word and its number. */
.wnum { white-space: nowrap; }
.workshop__title { display: block; overflow-wrap: anywhere; }
.workshop__meta { margin: 2px 0 0; font-size: 13.5px; }
/* "דף ההנחיות", "קבוצת הוואטסאפ": a two-word link never breaks in half. */
.workshop__meta a, .workshop__meta .chip { white-space: nowrap; }
.workshop__excerpt { margin: 6px 0 0; font-size: 14px; color: var(--muted);
  max-width: 72ch; overflow-wrap: anywhere; }
.workshop__edit { margin: 8px 0 0; font-size: 14px; }
.workshop__edit summary { cursor: pointer; color: var(--brand-link); }
.workshop__rename { display: flex; flex-wrap: wrap; align-items: flex-end;
  gap: 8px 10px; margin: 10px 0 0; }
.workshop__rename .field { flex: 1 1 240px; min-width: 0; margin: 0; }
/* Two classes, so it outranks `.linkish`, defined further down. */
.workshop .workshop__ungroup { color: var(--err); }
.field--missing .field__label,
.field--missing .field__hint strong { color: var(--err); }
.field--missing .input { border-color: var(--err); background: #fffafa;
  box-shadow: 0 0 0 3px #fce8e6; }
.card h1 { margin-top: 0; font-size: 22px; }

.page-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin-bottom: 20px;
}
.page-head h1 { margin: 0; font-size: 24px; line-height: 1.3; }
.page-head--event { align-items: flex-start; }
.page-head__meta { margin: 4px 0 0; }
/* "סדנה 2 · מועד 34" above an event's title (2026-10-08): the numbers the
   owner talks about it by. Small, so the title stays the title. */
.page-head__ids { margin: 0 0 2px; font-size: 13.5px; font-weight: 500;
  color: var(--muted); }
.page-head__meta .badge { vertical-align: 1px; }

/* Where you are, above the title. Every screen under an event says so in
   the same three words, so "back" is never the only way out. */
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  font-size: 14px; color: var(--muted); margin: 0 0 10px; }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--brand-link); text-decoration: underline; }
.crumbs__sep { color: var(--border); }
.crumbs [aria-current] { color: var(--ink); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; max-width: 60vw; }

/* The day's actions, one row under the share box. The phase decides which
   button is the loud one; the row wraps on a phone and never widens it. */
.actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  margin: 0 0 20px; }
.actions form { margin: 0; }
.actions .btn { display: inline-flex; align-items: center; }

/* A heading inside a long form: more room above than below, so the fields
   read as belonging to the heading under them. */
.form__group { margin: 28px 0 12px; padding-top: 20px; font-size: 17px;
  border-top: 1px solid var(--border); }
.form__actions { display: flex; align-items: center; gap: 14px;
  flex-wrap: wrap; margin-top: 8px; }

/* The settings map. */
.jumpbar { display: flex; flex-wrap: wrap; gap: 8px 28px; margin: 0 0 20px;
  padding: 14px 18px; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); }
/* Three groups, each a heading over its links — not thirteen identical chips.
   The groups list the sections in the order the page shows them. */
.jumpbar { gap: 12px 32px; }
.jumpbar__group { display: flex; flex-direction: column; gap: 6px; }
.jumpbar__group > a { align-self: flex-start; }
.jumpbar__title { font-size: 13px; font-weight: 600; color: var(--ink);
  padding-bottom: 2px; border-bottom: 2px solid var(--brand); align-self: flex-start; }
.jumpbar__links { display: flex; flex-wrap: wrap; gap: 4px 6px; }
.jumpbar a { font-size: 14px; color: var(--ink); text-decoration: none;
  padding: 4px 10px; border-radius: 999px; background: var(--bg); }
.jumpbar a:hover { color: var(--brand-link); background: color-mix(in srgb, var(--brand) 10%, var(--card)); }
.card[id] { scroll-margin-top: calc(var(--jumpbar-h, 0px) + 16px); }

/* The one save for a long page, kept in view. */
.savebar { position: sticky; bottom: 0; display: flex; align-items: center;
  gap: 14px; margin: 0 -16px; padding: 12px 16px;
  background: color-mix(in srgb, var(--card) 88%, transparent);
  backdrop-filter: blur(8px); border-top: 1px solid var(--border); }

/* "הבא: …" — the dashboard's first sentence. One line, wraps on a phone. */
.next { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  margin: 6px 0 2px; font-size: 16px; }
.next__label { color: var(--muted); }
.next__name { font-weight: 600; text-decoration: none; }
.next__name:hover { text-decoration: underline; }
.next__when { color: var(--ink); }
.next__n { color: var(--muted); }
/* On a phone the head stacks: the "next" line takes the full width and the
   button sits under it, instead of a tall squeezed button beside the text. */
@media (max-width: 600px) {
  .page-head:has(.next) { flex-direction: column; align-items: stretch; }
  .page-head:has(.next) > .btn { align-self: flex-start; }
}

/* The day strip: live, or within three hours of the start. Three things,
   large, first — the room, the survey's QR, its switch. */
.daystrip { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px;
  margin: 0 0 16px; padding: 16px 18px; border-radius: var(--radius);
  background: color-mix(in srgb, var(--brand) 8%, var(--card));
  border: 1px solid color-mix(in srgb, var(--brand) 30%, var(--border)); }
.daystrip form { margin: 0; }
.daystrip .btn { display: inline-flex; align-items: center; font-size: 17px;
  padding: 12px 22px; }
.daystrip > p { margin: 0; }
/* Its two parts since 2026-09-30: the meeting, and the survey (a status
   line and one "הפעלת הסקר" button; the QR and the switch are on the survey
   screen). Side by side, a rule between; stacked on a phone. */
.daystrip__part { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.daystrip__part + .daystrip__part { padding-inline-start: 18px;
  border-inline-start: 1px solid color-mix(in srgb, var(--brand) 30%, var(--border)); }
.daystrip__label { font-size: 13px; color: var(--muted); }
.daystrip__row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
@media (max-width: 600px) {
  .daystrip__part { flex: 1 1 100%; }
  .daystrip__part + .daystrip__part { padding-inline-start: 0; border-inline-start: 0;
    padding-top: 14px; border-top: 1px solid color-mix(in srgb, var(--brand) 30%, var(--border)); }
}
/* "הסקר סגור · 4 שאלות" / "הסקר פתוח · 12 ענו", with a dot that is green
   while it is open: here and in the survey card. */
.livestatus { display: inline-flex; align-items: center; gap: 8px; font-weight: 500; }
.livestatus__dot { width: 10px; height: 10px; border-radius: 50%; background: #9aa0a6; flex: none; }
.livestatus--open .livestatus__dot { background: var(--ok);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 18%, transparent); }
.livestatus__note { font-size: 13px; color: var(--muted); }
/* On the day the share box folds to one line. */
.sharebox--fold > summary { cursor: pointer; color: var(--muted); font-size: 14px; }
.sharebox--fold[open] > summary { margin-bottom: 10px; }
/* The date picker's three selects, LTR so day-month-year read left to right
   like the digits do. */
.dateparts { display: flex; gap: 6px; }
/* 🚨 A date select is never narrower than what it shows (2026-09-30). They
   were `flex: 1 1 0; min-width: 0` in a third of a form row, so the
   duplicate form's proposed Friday 16 October 2026 read "16 | בר | 20" —
   the date was right and nobody could see it; on a phone each select was
   43px. Each one is as wide as its longest option now, the field holding
   them takes that room, and the two times beside it give way: one line on a
   desktop, the date alone above the times on a phone. */
.dateparts .input { flex: 1 0 auto; width: auto; padding-inline: 6px; }
.row .field:has(> .dateparts) { flex: 1 0 auto; }
.row .field:has(> .input--time) { flex-basis: 110px; }
/* A notice that carries its own buttons. */
.notice--actions p { margin: 0 0 10px; }
.notice--actions .btnrow { gap: 8px 14px; }
/* The settings map stays in view while the page scrolls under it -- on a
   screen wide enough for it. On a phone its groups wrap to half the screen,
   and a bar that tall covers what it jumps to. The room a section leaves for
   it is measured into --jumpbar-h by settings.html. */
.jumpbar { position: sticky; top: 8px; z-index: 2; }
@media (max-width: 600px) { .jumpbar { position: static; } }

/* The dashboard's two lists. */
.list { margin-bottom: 28px; }
/* A table with a subject column and three buttons cannot shrink to a phone
   without becoming one word per line; it scrolls in its box instead. */
@media (max-width: 600px) {
  /* On a phone each event (and each held reminder) is a small block: name,
     then the facts, then the buttons. The same markup, so the desktop table
     is not a second list. */
  .table--events thead, .card--queue thead { display: none; }
  .table--events, .table--events tbody,
  .card--queue .table, .card--queue tbody { display: block; }
  .table--events tr, .card--queue tr { display: flex; flex-wrap: wrap; align-items: center;
    gap: 2px 12px; padding: 12px 4px; border-bottom: 1px solid var(--border); }
  .table--events td, .card--queue td { display: block; padding: 0; border: 0; }
  .card--queue td { flex: 1 1 100%; font-size: 15px; }
  .card--queue td .muted { font-size: 13px; }
  .card--queue .cell-actions { margin-top: 8px; }
  .card--queue .actionrow { flex-wrap: wrap; white-space: normal; }
  .table--events .cell-name { flex: 1 1 100%; font-size: 16px; margin-bottom: 4px; }
  .table--events .cell-name .chip { display: inline-block; margin: 4px 0 0; }
  .table--events .cell-when { white-space: normal; color: var(--muted); font-size: 14px; }
  .cell-when__rel { display: inline; }
  .cell-when__rel::before { content: "· "; }
  .table--events .cell-num { font-size: 14px; }
  .table--events .cell-num:empty { display: none; }
  .table--events .cell-actions { flex: 1 1 100%; margin-top: 6px; text-align: start; }
}
.list__title { font-size: 16px; margin: 0 0 10px; color: var(--muted);
  font-weight: 600; }
.list__empty { margin: 0; }
.table--events .cell-name .chip { margin-inline-start: 8px; }
.table--events .cell-when { white-space: nowrap; }
.cell-when__rel { display: block; font-size: 13px; }
.cell-num { white-space: nowrap; }
.table--events td { vertical-align: top; }
@media (min-width: 601px) { .table--events .actionrow { justify-content: flex-end; } }
.search { position: relative; display: block; max-width: 360px; margin: 0 0 18px; }
.search .ic { position: absolute; inset-inline-start: 12px; top: 50%;
  transform: translateY(-50%); color: var(--muted); margin: 0; }
.search .input { padding-inline-start: 38px; }

/* The survey card, on its own סקר tab since 2026-10-02 (it was on במפגש):
   three steps, in the order they happen. The numbers are the order, which
   is the point of them. The QR is not here any more; it lives on the survey
   screen. The status line carries the close button while it is open. */
.svcard__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; }
.svcard__head h2 { margin: 0; }
.svcard__status { margin: 12px 0 0; display: flex; flex-wrap: wrap;
  align-items: center; gap: 8px 14px; }
.svcard__status form { margin: 0; }
/* "מי ענה על הסקר": the people the survey added, one per line. */
.svpeople { margin: 0 0 10px; padding-inline-start: 20px; }
.svpeople li { margin: 4px 0; overflow-wrap: anywhere; }
.svpeople__list { color: var(--ok); font-size: 13px; }
.svcard__count { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--border); }
.svstep p.svstep__gap { margin-bottom: 10px; }
.svcard__auto { margin: 10px 0 0; padding: 8px 12px; border-radius: 8px;
  background: var(--bg); font-size: 14px; max-width: 72ch; }
.svsteps { list-style: none; margin: 14px 0 0; padding: 0; }
.svstep { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 14px;
  padding: 16px 0 14px; border-top: 1px solid var(--border); }
.svstep__n { width: 32px; height: 32px; border-radius: 50%; display: grid;
  place-items: center; font-weight: 700; font-size: 15px; background: var(--bg);
  border: 1px solid var(--border); }
.svstep h3 { margin: 3px 0 8px; font-size: 16px; }
.svstep p { margin: 0; }
.svstep--off { opacity: .5; }
.svstep__line { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; }
.svstep .sharebox__row { margin-top: 12px; }
.input--inline { flex: 1 1 240px; max-width: 420px; font-size: 13px; color: var(--muted); }

.empty {
  background: var(--card); border: 1px dashed var(--border);
  border-radius: var(--radius); padding: 48px 24px; text-align: center;
}
.muted { color: var(--muted); }
p.muted { max-width: 72ch; }

/* forms */
.field { display: block; margin-bottom: 20px; text-align: start; }
.field__label { display: block; font-weight: 500; margin-bottom: 6px; }
.field__hint { display: block; color: var(--muted); font-size: 13px; margin-top: 6px;
  max-width: 72ch; }

.input {
  width: 100%; padding: 10px 12px; font: inherit; color: var(--ink);
  background: var(--card); border: 1px solid var(--border); border-radius: 8px;
}
.input:focus { outline: 2px solid var(--brand); outline-offset: 1px; border-color: var(--brand); }
.input--code { text-align: center; letter-spacing: .5em; font-size: 24px; }
.input--color { height: 44px; padding: 4px; }

.btn {
  display: inline-block; padding: 10px 20px; font: inherit; font-weight: 500;
  border: 1px solid transparent; border-radius: var(--btn-radius); cursor: pointer;
  text-decoration: none; text-align: center;
}
.btn--primary { background: var(--brand); color: var(--brand-ink); }
.btn--primary:hover { filter: brightness(.94); }
.btn--block { display: block; width: 100%; margin-top: 16px; }
/* 🚨 A disabled button LOOKS disabled (2026-10-10, Omri on event 39's
   notice: "the send button does not work"). There was no :disabled rule,
   so a locked send in the brand's colour, with a pointer cursor, read as a
   button that was broken. Two classes deep beats every .btn--* look, and
   three on hover beats their :hover rules (.btn--danger's paints pink). */
.btn.is-disabled, .btn:disabled, .btn:disabled:hover {
  background: var(--border); color: var(--muted);
  border-color: transparent; cursor: not-allowed; filter: none; }

/* table */
.table { width: 100%; border-collapse: collapse; background: var(--card); }
.table th, .table td {
  padding: 12px 14px; text-align: start; border-bottom: 1px solid var(--border);
}
.table th { font-size: 13px; color: var(--muted); font-weight: 500; }
.table td > a:first-child { display: inline-block; padding: 2px 0; font-weight: 500; }

.badge {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-size: 13px; background: #e8f0fe; color: #1557b0;
}
.badge--draft { background: #fef7e0; color: var(--warn); }
.badge--canceled { background: #fce8e6; color: var(--err); }

/* flashes */
.flashes { margin-bottom: 20px; }
.flash {
  margin: 0 0 8px; padding: 10px 14px; border-radius: 8px;
  background: #e6f4ea; color: var(--ok);
}
.flash--err { background: #fce8e6; color: var(--err); }
/* A flash that carries its next step as a button ("השאלות נשמרו." →
   "הפעלת הסקר"). */
.flash--row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; }

.foot {
  text-align: center; color: var(--muted); font-size: 12px; padding: 8px 0 24px;
}
.foot__text { display: block; font-size: 13px; margin-bottom: 4px; }

/* ── phase 1 components ──────────────────────────────────────────────────── */

.row { display: flex; gap: 12px; flex-wrap: wrap; }
.row .field { flex: 1 1 140px; }

/* The duplicate form's runs: one row per date, the weekday named above it. */
.runs { list-style: none; margin: 0; padding: 0; }
.runs__row + .runs__row { border-top: 1px dashed var(--border); padding-top: 10px; }
.runs__day { font-weight: 700; color: var(--ink); }

.check { display: flex; align-items: center; gap: 8px; margin: 8px 0; cursor: pointer; }
.check input { width: 18px; height: 18px; accent-color: var(--brand); flex: none; }

.choice { border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; margin: 0 0 20px; }
.choice legend { padding: 0 6px; }
.choice__hint { margin: 4px 0 0; }
.altdates { margin: 6px 0 0; margin-inline-start: 26px; padding-top: 6px; border-top: 1px dashed var(--border); }
.altdates .check { margin: 6px 0; }
/* A full date's form (core/seats.py): the dates ARE the choice, not a
   reveal under a card, so they stand on their own like any field. */
.altdates--open { margin: 0 0 16px; padding: 0; border: 0; }

/* The sign-up form's choice as cards (2026-09-29). Each card is the <label>
   of a real, visible radio, so a tap anywhere on it chooses — no script, and
   nothing hidden. 🚨 `min-width: 0`: a fieldset's default min-inline-size is
   its content's, which is how a long line widens a phone page. The chosen
   card is drawn by `:has()`; where it is unsupported the radio still shows
   the choice. `.choice` stays plain for the pick page, which shares it. */
.choice--cards { border: 0; padding: 0; margin: 0 0 20px; min-width: 0; }
.choice--cards legend { padding: 0; margin-bottom: 10px; font-size: 17px; }
.optcard { display: flex; align-items: flex-start; gap: 12px; margin: 0 0 10px;
  padding: 14px 16px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--card); cursor: pointer; min-width: 0; }
.optcard input { width: 20px; height: 20px; margin: 2px 0 0; flex: none;
  accent-color: var(--brand); }
.optcard:hover { border-color: color-mix(in srgb, var(--brand) 45%, var(--border)); }
.optcard:has(input:checked) { border: 2px solid var(--brand); padding: 13px 15px;
  background: color-mix(in srgb, var(--brand) 9%, var(--card)); }
.optcard:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: 2px; }
.optcard__text { display: block; min-width: 0; }
.optcard__title { display: block; font-weight: 500; font-size: 16px; color: var(--ink); }
.optcard__sub { display: block; margin-top: 2px; font-size: 14px; color: var(--muted);
  overflow-wrap: anywhere; }
.choice--cards .altdates { margin: -2px 0 10px; margin-inline-start: 16px; }
.check--small { font-size: 14px; color: var(--muted); }
.check--small input { width: 16px; height: 16px; }

/* The facts card under the title (2026-10-02): when, where, the places, the
   proof and the countdown, one per row, then the way to the form. Its own
   framed block on the page's grey, so the limit is a fact on a line of its
   own rather than a sentence the description runs straight on from. */
.facts { margin: 0 0 28px; padding: 16px 18px; border: 1px solid var(--border);
  border-radius: 12px; background: var(--bg); min-width: 0; }
.facts__row { display: flex; align-items: baseline; gap: 10px; margin: 0 0 10px;
  min-width: 0; line-height: 1.5; }
.facts__ic { flex: none; width: 1.5em; text-align: center; }
.facts__text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.facts__why { display: block; margin-top: 2px; font-size: 14px; color: var(--muted); }
/* The places: plain while they say only the limit, the seat bar's amber once
   they count what is left, framed once full. Fixed colours on the amber, so
   they read on every preset; the full row takes the card's own surfaces. */
.facts__seats--hot, .facts__seats--full { padding: 8px 10px; border-radius: 10px;
  margin-inline: -10px; }
.facts__seats--hot { background: var(--warn-bg); color: var(--warn);
  border: 1px solid #f5d58a; }
.facts__seats--hot .facts__why { color: var(--warn); }
.facts__seats--full { background: var(--card); color: var(--ink);
  border: 1px solid var(--border); }
.facts__go { margin-top: 6px; }
@media (max-width: 420px) {
  .facts { padding: 14px; }
  .facts__row { gap: 8px; }
  .facts__sep { display: none; }
  .facts__time { display: block; }
}
/* The same words again, small, framed and centred over the sign-up button. */
.seatchip { width: fit-content; max-width: 100%; margin: 4px auto 12px;
  padding: 4px 14px; border: 1px solid var(--border); border-radius: 999px;
  font-size: 14px; color: var(--ink); text-align: center; overflow-wrap: anywhere; }
.seatchip--hot { background: var(--warn-bg); color: var(--warn); border-color: #f5d58a; }

/* The ticket shop (web/tickets.py, 2026-10-10): one row per kind of ticket,
   the option card's frame, the name and price on one side and how many on
   the other. A row is a <label> around its select, so a tap on the name
   opens it. `min-width: 0` everywhere, the fieldset lesson above. */
.shop__kinds { border: 0; padding: 0; margin: 0 0 18px; min-width: 0; }
.shop__kinds legend { padding: 0; margin-bottom: 8px; font-size: 17px; }
.shop__phase { margin: -2px 0 10px; font-size: 14px; color: var(--muted); }
.shop__kind { display: flex; align-items: center; gap: 12px; margin: 0 0 10px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--card); cursor: pointer; min-width: 0; }
.shop__kind:has(select:focus-visible) { outline: 2px solid var(--brand); outline-offset: 2px; }
.shop__kind:has(option:checked:not([value="0"])) { border: 2px solid var(--brand);
  padding: 11px 13px; background: color-mix(in srgb, var(--brand) 9%, var(--card)); }
.shop__name { flex: 1 1 auto; min-width: 0; font-weight: 500; font-size: 16px;
  overflow-wrap: anywhere; }
.shop__price { flex: none; font-size: 16px; white-space: nowrap; }
.shop__price s { font-size: 14px; margin-inline-start: 4px; }
.shop__qty { flex: none; width: 72px; text-align: center; }
.shop__coupon { margin: 0 0 14px; }
.shop__coupon summary { cursor: pointer; color: var(--brand-link); font-size: 15px;
  margin-bottom: 8px; }
.shop__total { margin: 14px 0 10px; font-size: 18px; text-align: center; }
.shop__total b { font-size: 22px; }
.shop__total [data-discount] { display: block; font-size: 14px; }
.shopclosed .banner { margin-bottom: 12px; }
/* The parking question's instructions: the owner's words, line breaks kept. */
.shop__parking { margin: 4px 0 12px; padding: 10px 14px; border-radius: 10px;
  background: var(--bg); border: 1px solid var(--border); white-space: pre-line;
  overflow-wrap: anywhere; }

/* A ticket order, on the page the buyer comes back to: each line with its
   price, the code's discount, the total. */
.ordersum { margin: 16px 0; padding: 14px 16px; border-radius: 12px;
  background: var(--bg); border: 1px solid var(--border); min-width: 0; }
.ordersum__code { margin: 0 0 8px; color: var(--muted); }
.ordersum__lines { list-style: none; margin: 0; padding: 0; }
.ordersum__lines li { display: flex; justify-content: space-between; gap: 12px;
  padding: 6px 0; border-bottom: 1px solid var(--border); min-width: 0; }
.ordersum__lines li span:first-child { min-width: 0; overflow-wrap: anywhere; }
.ordersum__total { font-weight: 700; border-bottom: 0 !important; }

/* The owner's ticket editor: four narrow columns that stay a table on a
   phone, inside their own scrolling box. */
.table--tickets td { padding: 6px 4px; vertical-align: middle; }
.table--tickets .input { min-width: 0; }
.input--num { width: 100%; max-width: 110px; }
.table--tickets td:first-child .input { min-width: 120px; }

/* The door (door.html): big rows to tap with one thumb, the count on top. */
.doorcount { font-size: 18px; margin: 0 0 14px; }
.doorsearch { margin-bottom: 12px; }
.doorlist { list-style: none; margin: 0; padding: 0; }
.doorrow { margin: 0 0 8px; }
.doorrow form { margin: 0; }
.doorrow__btn { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; width: 100%; min-height: 60px; padding: 12px 14px; text-align: start;
  font: inherit; color: var(--ink); background: var(--card);
  border: 1px solid var(--border); border-radius: 12px; cursor: pointer; }
.doorrow__who { display: flex; flex-direction: column; min-width: 0; }
.doorrow__who b { font-size: 17px; overflow-wrap: anywhere; }
.doorrow__who .muted { font-size: 14px; overflow-wrap: anywhere; }
.doorrow__state { flex: none; font-size: 14px; color: var(--brand-link); }
.doorrow.is-in .doorrow__btn { background: #e6f4ea; border-color: #a8dab5; }
.doorrow.is-in .doorrow__state { color: #137333; font-weight: 700; }
.doorbox { display: inline-block; width: 18px; height: 18px; border: 1.5px solid var(--ink);
  border-radius: 3px; text-align: center; line-height: 16px; }
.table--door-print td, .table--door-print th { padding: 6px 8px; }
@media print {
  .topbar, .crumbs, .page-head__actions, footer { display: none !important; }
}
/* Who runs this, under the logo (`host_line`). Balanced, so on a phone it
   breaks into two even lines rather than leaving one word of a parenthesis
   on the second: "(Google" at the end of a right-to-left line, its ")" on
   the next, reads as a pair of brackets facing the wrong way. */
.hostline { margin: -8px 0 20px; text-align: center; font-size: 15px;
  color: var(--ink); overflow-wrap: anywhere; text-wrap: balance; }
.nowrap { white-space: nowrap; }
.datelist form { margin: 0; }

.fold { margin: 4px 0 20px; }
.fold summary { cursor: pointer; color: var(--brand-link); }
/* The delete fold: red where the rest of the form is brand-coloured, so it
   cannot be mistaken for one more setting. The button is red-tinted, not
   solid red -- a confirm() stands between it and the delete either way. */
.fold--danger { border-top: 1px solid var(--border); padding-top: 16px; margin-top: 24px; }
.fold--danger summary { color: var(--err); }
.btn--danger { background: #fce8e6; color: var(--err); border-color: #f3b8b5;
  display: inline-flex; align-items: center; }  /* the icon must not stretch the line */
.btn--danger:hover { background: #f9d6d3; }

.btn--quiet { background: var(--card); color: var(--ink); border-color: var(--border); }
.btn--quiet:hover { border-color: var(--muted); }
.btn.is-copied { border-color: var(--brand); color: var(--brand-link); }
/* A quiet button that is currently "on" (the survey is open): a brand tint. */
.btn--on { background: color-mix(in srgb, var(--brand) 12%, var(--card));
  border-color: color-mix(in srgb, var(--brand) 40%, var(--border)); color: var(--brand-link); }
.btn:focus-visible, .tab-link:focus-visible, .topbar__nav a:focus-visible,
.jumpbar a:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Drawn icons inside buttons and links: one stroke, one weight, sized to the
   text beside them. Emoji never lined up and never matched across devices. */
.ic { width: 1.05em; height: 1.05em; vertical-align: -0.18em; fill: none;
  stroke: currentColor; stroke-width: 1.75; stroke-linecap: round;
  stroke-linejoin: round; margin-inline-end: .45em; flex: none; }
.btn--sm .ic { margin-inline-end: .35em; }
.ic--solo { margin: 0; vertical-align: -0.2em; }

.sharebox { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 12px 16px; margin-bottom: 20px; }
.sharebox__row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sharebox__row + .sharebox__row { margin-top: 8px; }
.sharebox__label { font-size: 13px; color: var(--muted); flex: 0 0 auto;
  min-width: 96px; }
/* Every label-link-copy row, in the share box or not (the survey's): the
   field shrinks so the copy button stays beside it, not a line under it. */
.sharebox .input, .sharebox__row .input { flex: 1 1 240px; width: auto; min-width: 0; }
/* The long URL is there to be read, not pasted, so it steps back. */
.sharebox__row--quiet .input { font-size: 13px; color: var(--muted); }
.sharebox__channels { margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--border); }
.sharebox__channels summary { cursor: pointer; font-size: 13px;
  color: var(--muted); }
.sharebox__channels .sharebox__row { margin-top: 8px; }
.sharebox__channels .sharebox__label { min-width: 170px; }
.sharebox__channels .field__hint { margin: 8px 0 0; }

/* The אחרי tab's recording, summary and slides: label, link, open. */
/* One grid for all three rows, so a row with no link yet (and so no open
   button) keeps its field the same width as the rows that have one. */
.materials__links { display: grid; align-items: center; gap: 8px 10px;
  grid-template-columns: auto minmax(0, 1fr) auto; }
.materials__row { display: contents; }
.materials__label { grid-column: 1; font-size: 14px; color: var(--muted); }
.materials__row .input { grid-column: 2; min-width: 0; }
.materials__actions { grid-column: 3; display: flex; gap: 6px; }
.materials__check { grid-column: 2 / -1; margin: 0; font-size: 13px;
  color: var(--muted); }
/* A URL needs the width on a phone: the label goes above its field, and the
   two buttons under it — beside it they leave the address 100px. */
@media (max-width: 600px) {
  .materials__links { grid-template-columns: minmax(0, 1fr); row-gap: 4px; }
  .materials__label { grid-column: 1; margin-top: 6px; }
  .materials__row .input { grid-column: 1; }
  .materials__actions { grid-column: 1; flex-wrap: wrap; }
  .materials__check { grid-column: 1; }
}
.materials__auto { margin-top: 14px; }

/* "על מה הקליקו": one small table per email, under its name. */
.clicks__email { margin: 18px 0 6px; font-size: 15px; }
.clicks__email:first-of-type { margin-top: 4px; }
/* An address has no spaces to break at, and unbroken it widened its table
   to 572px at a 375px viewport. */
.clicks__link { overflow-wrap: anywhere; }
/* One width for the number columns, so the tables stacked under each other
   line up instead of each sizing to its own longest label. */
.table--clicks th:not(:first-child), .table--clicks td:not(:first-child) {
  width: 5.5em; }
/* The שיווק tab (2026-10-01): the post, a row per place, the list editor. */
.post__text { width: 100%; resize: vertical; font: inherit; line-height: 1.6; }
/* The three WhatsApp versions (core/post_versions.py): side by side on a
   computer, one under the other on a phone. Each box keeps its buttons at
   its foot, so three texts of different lengths still line up. */
.versions { display: grid; gap: 12px; margin: 4px 0 14px;
  grid-template-columns: repeat(3, minmax(0, 1fr)); }
.versions.is-waiting { opacity: .55; }
.version { display: flex; flex-direction: column; gap: 8px; min-width: 0;
  padding: 14px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--card); }
.version__style { margin: 0; font-size: 14px; font-weight: 600;
  color: var(--brand-link); }
.version__text { margin: 0; white-space: pre-line; line-height: 1.6;
  overflow-wrap: anywhere; }
.version__details { margin: auto 0 0; padding-top: 8px; white-space: pre-line;
  font-size: 13.5px; line-height: 1.5; color: var(--muted);
  border-top: 1px dashed var(--border); overflow-wrap: anywhere; }
.version__actions { display: flex; flex-wrap: wrap; gap: 8px; }
.version__actions form { margin: 0; }
.versions__status { display: flex; align-items: center; gap: 10px;
  margin: 0 0 12px; color: var(--muted); }
.versions__pulse { flex: none; width: 10px; height: 10px; border-radius: 50%;
  background: var(--brand); animation: versions-pulse 1.2s ease-in-out infinite; }
@keyframes versions-pulse { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .versions__pulse { animation: none; } }
.versions__retry { display: inline; margin: 0 8px 0 0; }
.versions__foot { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 8px 16px; }
.versions__foot .field__hint { margin: 0; flex: 1 1 22em; }
.versions__foot form { margin: 0; }
@media (max-width: 900px) {
  .versions { grid-template-columns: minmax(0, 1fr); }
}
.places__progress { margin: 0 0 8px; color: var(--muted); }
.places__progress b { color: var(--ink); }
.places { list-style: none; margin: 0 0 12px; padding: 0; }
/* The ✓, the name, the numbers on one line; the link and its buttons under
   them, the width of the row. */
.place { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 8px 12px; padding: 14px 0;
  border-top: 1px solid var(--border); }
.place__mark { grid-column: 1; margin: 0; }
.place__name { grid-column: 2; font-weight: 500; overflow-wrap: anywhere; }
.place__numbers { grid-column: 3; font-size: 13px; color: var(--muted);
  white-space: nowrap; }
.place__link { grid-column: 1 / -1; }
.place__tick { background: var(--card); color: var(--ink);
  border-color: var(--border); min-width: 8.5em; justify-content: center; }
.place__tick:hover { border-color: var(--muted); }
.place.is-posted .place__tick { background: #e6f4ea; color: var(--ok);
  border-color: #b7dfc2; }
.badge--kind { font-size: 12.5px; font-weight: 400; padding: 1px 8px;
  margin-inline-start: 4px; background: #f1f3f4; color: var(--muted); }
/* A phone: the ✓ gets its own line, the name and the numbers share the next. */
@media (max-width: 600px) {
  .place { grid-template-columns: minmax(0, 1fr) auto; }
  .place__mark { grid-column: 1 / -1; }
  .place__name { grid-column: 1; }
  .place__numbers { grid-column: 2; }
}
/* The editor: name, link, remove. One grid for every row (display:
   contents), so the fields line up; on a phone each row is its own block. */
.placesedit { display: grid; gap: 8px 10px; align-items: center;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) auto; margin: 12px 0; }
.placesedit__head { font-size: 13px; color: var(--muted); }
.placesedit__row { display: contents; }
.placesedit .input { width: 100%; min-width: 0; }
.placesedit__remove { margin: 0; white-space: nowrap; font-size: 14px; }
.placesedit__more { margin: 0 0 12px; }
@media (max-width: 600px) {
  .placesedit { display: block; }
  .placesedit__head { display: none; }
  .placesedit__row { display: grid; grid-template-columns: minmax(0, 1fr) auto;
    gap: 6px 10px; align-items: center; padding: 10px 0;
    border-top: 1px solid var(--border); }
  .placesedit__row input[name="label"] { grid-column: 1; grid-row: 1; }
  .placesedit__row > :last-child { grid-column: 2; grid-row: 1; }
  .placesedit__row input[name="url"] { grid-column: 1 / -1; grid-row: 2; }
}
.materials__message { margin-top: 16px; }
.materials__message textarea { width: 100%; resize: vertical; font: inherit;
  line-height: 1.6; }

/* The waiting-list segment pickers: a row of selects that reload the page.
   🚨 Pinned to the top of the screen (2026-10-10, Omri: "make the waiting
   list filters stay visible too"); its sticky box is the whole page. The
   page's own grey behind it, so the list scrolls under a clean edge. The
   send bar below sticks under it (.invite__send reads --filters-h). */
.filters { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end;
  margin-bottom: 16px; position: sticky; top: 0; z-index: 16;
  padding: 8px 0 10px; background: var(--bg);
  box-shadow: 0 8px 10px -10px rgba(60, 64, 67, .45); }
.filters__field { display: flex; flex-direction: column; gap: 4px;
  flex: 1 1 220px; max-width: 420px; }
/* The select and the date box are one height, so the pinned row lines up. */
.filters .input { min-height: 48px; }
.filters .btn { align-self: flex-end; }
/* The "waiting for" picker: a closed box that reads like a select and opens
   into checkboxes, so several runs can be one segment. Opens in flow, never
   floats -- a floating panel over the tiles is one more thing to get wrong
   at 375px. */
.picklist summary { cursor: pointer; list-style: none; }
.picklist summary::-webkit-details-marker { display: none; }
.picklist summary::after { content: "▾"; float: left; color: var(--muted); }
.picklist__body { border: 1px solid var(--border); border-top: 0;
  border-radius: 0 0 var(--radius) var(--radius); padding: 8px 12px;
  background: var(--card);
  /* Bounded since the filters are pinned (2026-10-10): every run of a
     busy installation, open at the top of the screen, covered the page. */
  max-height: 50vh; overflow-y: auto; }
.picklist__body .check { margin: 6px 0; }
.picklist__body .check span { overflow-wrap: anywhere; }
.picklist__body .btn { margin-top: 6px; }
@media (max-width: 480px) { .filters__field { flex-basis: 100%; max-width: none; } }

.tiles { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 20px; }
.tile { flex: 1 1 120px; background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 16px; text-align: center; }
.tile b { display: block; font-size: 28px; line-height: 1.2; }
.tile span { color: var(--muted); font-size: 13px; }
.tile small { font-size: 12.5px; }

section.card { margin-bottom: 20px; }
section.card h2 { margin-top: 0; font-size: 18px; }

.warn-inline { margin-top: 4px; font-size: 13px; color: var(--warn); }

.badge--upcoming { background: #e8f0fe; color: #1557b0; }
.badge--live { background: #fce8e6; color: var(--err); }
.badge--ended, .badge--off { background: #f1f3f4; color: var(--muted); }
/* A survey that is open: green, "go". */
.badge--open { background: #e6f4ea; color: var(--ok); }
.badge--sent { background: #e8f0fe; color: #1557b0; }
.badge--scheduled { background: #e6f4ea; color: var(--ok); }
.badge--skipped { background: #fef7e0; color: var(--warn); }
.badge--blocked { background: #fce8e6; color: var(--err); }
/* The waiting page's invite: the check row under the editor and its preview
   frame. Starts collapsed; grows once a preview has been posted into it. */
/* Two buttons side by side: 385px at a 375px viewport until they could wrap. */
.invite__checks { margin: 12px 0; flex-wrap: wrap; white-space: normal; }
/* 🚨 The send bar stays on the screen (2026-10-10, Omri: "make the waiting
   list send button stay visible"). It sits between the invitation and the
   list, outside both cards, so its sticky box is the whole form: pinned to
   the bottom edge while the invitation is being written above it, to the top
   edge while the names under it are ticked. */
.invite__send { position: sticky; top: calc(var(--filters-h, 0px) + 8px); bottom: 8px; z-index: 15;
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px;
  margin: 16px 0; padding: 12px 16px; background: var(--card);
  border: 1px solid color-mix(in srgb, var(--brand) 45%, var(--border));
  border-radius: var(--radius); box-shadow: 0 4px 16px rgba(60, 64, 67, .18); }
/* The date-change notice (event page, #moved) borrows the bar's look and
   not its pin: a short form whose bar holds the preview, the test copy and
   the send together, in place under the editor. Pinned, it covered the
   editor on a phone with three stacked buttons. */
.moved__send { position: static; }
/* The template bar: the select takes the room, the buttons wrap under it on a
   phone rather than widening the document. */
.tplbar__row { flex-wrap: wrap; white-space: normal; }
.tplbar__row .input { flex: 1 1 220px; width: auto; min-width: 0; }
.tplbar__new { margin: 8px 0 4px; }
.tplbar__new summary { cursor: pointer; color: var(--brand-link); }
.tplbar__new .tplbar__row { margin-top: 8px; }
/* The invitation's button text and its A/B second text: side by side where
   there is room, one under the other on a phone (each field's basis). */
.abfields { display: flex; flex-wrap: wrap; gap: 0 16px; }
.abfields .field { flex: 1 1 240px; min-width: 0; margin-bottom: 8px; }
.abfields__hint { margin: 0 0 20px; }
.abtest { margin: 0 0 20px; padding: 14px 16px; background: var(--bg);
  border: 1px solid var(--border); border-radius: var(--radius); }
.abtest__title { margin: 0 0 8px; font-size: 16px; }
.abtest__verdict { margin: 10px 0 0; max-width: 72ch; }
.table--ab td:first-child { min-width: 12em; }
.invite__preview { height: 0; border: 0; }
.invite__preview.is-open { height: 560px; border: 1px solid var(--border); }
.badge--confirmation, .badge--waiting { background: #f3e8fd; color: #6b21a8; }
/* "רק ההקלטה" — not the waiting list, so not its colour. */
.badge--vod { background: #e6f4ea; color: #1e6b34; }
/* Held for approval: the same amber the stale-date warning uses, because it is
   the same kind of fact — something is waiting for a person to look at it. */
.badge--hold { background: #fef7e0; color: var(--warn); }

/* public page */
.public .wrap { padding-top: 40px; }
.desc { margin: 16px 0; }
.desc p { margin: 0 0 12px; }
.desc h2, .desc h3 { margin: 20px 0 8px; }
.desc ul, .desc ol { margin: 0 0 12px; padding-inline-start: 22px; }
.desc blockquote { margin: 12px 0; padding-inline-start: 14px;
  border-inline-start: 3px solid var(--border); color: var(--muted); }
.whenbox { margin: 20px 0; padding: 14px 18px; border-radius: 10px;
  background: color-mix(in srgb, var(--brand) 8%, var(--card));
  border-inline-start: 4px solid var(--brand); line-height: 2; }
/* The hero, the way v1 showed it: full width, cropped to a band rather than
   pushing the form below the fold on a tall image. */
.cover { display: block; width: 100%; max-height: 360px; object-fit: cover;
  border-radius: 10px; margin: 0 0 16px; }
.cover--thumb { max-width: 320px; max-height: 160px; margin: 0 0 8px; }
.banner { margin: 0 0 12px; padding: 8px 14px; border-radius: 8px;
  background: #fce8e6; color: var(--err); font-weight: 500; text-align: center; }
.banner--quiet { background: #f1f3f4; color: var(--muted); }
.fineprint { text-align: center; color: var(--muted); font-size: 13px; margin: 12px 0 0; }
/* The line above a button that says what it leads to — the permanent group's
   promise, "bring a friend". Ink, never the brand colour (test_brand_link). */
.pitch { text-align: center; margin: 24px 0 0; line-height: 1.6; }
.pitch + p > .btn--block { margin-top: 10px; }

/* A guest appearance's materials page (core/guest.py): the "keep me
   updated" form, set apart under the materials by a rule, not a box. */
.guestjoin { margin: 28px 0 0; padding: 20px 0 0; border-top: 1px solid var(--border); }
.guestjoin h2 { font-size: 19px; margin: 0 0 12px; }

/* The check of a pasted list (the people tab of a guest appearance): what
   would be added, before anything is. */
.importcheck { margin: 12px 0; padding: 12px 16px; border-radius: var(--radius);
  background: #f1f3f4; }
.importcheck p { margin: 4px 0; }
.importcheck__list { margin: 4px 0 8px; padding-inline-start: 20px;
  max-height: 220px; overflow-y: auto; overflow-wrap: anywhere; }
.importcheck__list--bad { color: var(--muted); }

/* paid events: the offer block. Everything is min-width 0 / wraps, and the
   whole block was measured at 375px before it shipped. */
.offer__headline { font-size: 19px; font-weight: 500; margin: -8px 0 16px; color: var(--muted); }
.offer { margin: 20px 0; }
.offer__stack { margin: 0 0 12px; }
.offer__stack ul { padding-inline-start: 22px; }
.offer__price { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin: 16px 0; font-size: 18px; }
/* The price is text, so --brand-link: the ochre was 1.6:1 here. */
.offer__price b { font-size: 28px; color: var(--brand-link); }
.offer__anchor { color: var(--muted); font-size: 16px; }
.offer__guarantee { margin: 16px 0; padding: 14px 18px; border-radius: 10px;
  background: var(--bg); border: 1px dashed var(--border); }
.offer__guarantee-title { font-weight: 500; margin-bottom: 4px; }
.offer__guarantee p:last-child { margin-bottom: 0; }
.seatbar { margin: 16px 0; padding: 12px 16px; border-radius: 10px;
  background: #fef7e0; color: var(--warn); border: 1px solid #f5d58a;
  font-size: 15px; overflow-wrap: anywhere; }
.seatbar--closed { background: #f1f3f4; color: var(--muted); border-color: var(--border); }
.seatbar__why { display: block; margin-top: 4px; font-size: 14px; }
.faq { margin: 28px 0 0; }
.faq h2 { font-size: 18px; }
.badge--paid { background: #e6f4ea; color: #137333; }

/* The honeypot must be unreachable, not merely invisible: display:none is the
   first thing a bot checks for. The template also carries aria-hidden and
   tabindex="-1", so it is out of the tab order and unread by a screen reader.

   🚨 NOT `left: -9999px`. That is the usual recipe and it is wrong here: the
   offset element still counts towards the document's scrollable area, so the
   public page grew an 11,000px horizontal scroll that a phone user could swipe
   into. Clipping in place costs nothing and adds no overflow. */
.hp { position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; }

.linkish { background: none; border: 0; padding: 0; font: inherit;
  color: var(--brand-link); text-decoration: underline; cursor: pointer; }

.notice { margin: 0 0 20px; padding: 12px 16px; border-radius: var(--radius);
  background: var(--warn-bg); color: var(--warn); border: 1px solid #f0dfae; }
.flash--warn { background: #fef7e0; color: var(--warn); }

/* ── phase 2: tabs, composer ─────────────────────────────────────────────── */

.tabs { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 20px;
  border-bottom: 1px solid var(--border); }
.tab-link { padding: 10px 14px; font: inherit; color: var(--muted);
  background: none; border: 0; border-bottom: 3px solid transparent;
  cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  white-space: nowrap; }
/* What a tab holds, on the tab: "לפני · 1 ממתין" answers before the click. */
.chip { display: inline-block; padding: 1px 8px; border-radius: 999px;
  font-size: 12.5px; line-height: 1.5; font-weight: 500;
  background: var(--bg); color: var(--muted); border: 1px solid var(--border);
  text-decoration: none; white-space: nowrap; }
.tab-link.is-active .chip { background: color-mix(in srgb, var(--brand) 10%, var(--card));
  color: var(--brand-link); border-color: transparent; }
.chip--warn { background: var(--warn-bg); color: var(--warn); border-color: #f0dfae; }
.chip--open { background: #e6f4ea; color: var(--ok); border-color: transparent; }
.chip--err { background: #fce8e6; color: var(--err); border-color: #f3b8b5; }
a.chip:hover { border-color: currentColor; }
/* 🚨 On a phone the tabs WRAP. They scrolled sideways for one release with
   the scrollbar hidden, and three of the five tabs were simply not on the
   screen — nothing said the bar scrolled. Two rows of visible tabs beat one
   row of invisible ones; test_tabs_never_scroll_out_of_a_phone pins it. */
@media (max-width: 600px) {
  .tabs { gap: 0; }
  .tab-link { padding: 10px 10px; font-size: 15px; }
  .tab-link .chip { font-size: 11.5px; padding: 0 6px; }
}
.tab-link:hover { color: var(--ink); }
.tab-link.is-active { color: var(--brand-link); border-bottom-color: var(--brand); }

.tab-panel { display: none; }
.tab-panel.is-active { display: block; }

.page-head__actions { display: flex; gap: 8px; align-items: center; }
.btn--sm { padding: 5px 12px; font-size: 14px; }
/* 🚨 `.cell-actions` is a <td>, and a <td> must never be given `display: flex`
   (or grid, or anything else that is not a table display). It stops being a
   table cell, so it no longer stretches to the row's height and the table's
   own background stops painting behind it: measured 59px inside a 71px row on
   the dashboard, 59px inside 106px in the approval queue, with the page's grey
   showing above, below and beside the buttons. The row of buttons lives on an
   inner `.actionrow` instead, which is free to be flex because it is a <div>.
   `.actionrow` is also used on its own where there is no cell — the waiting
   list's header, the question editor's row.

   ⚠️ It is NOT called `.btnrow`, and renaming it to that breaks it quietly.
   `.btnrow` already exists further down this file (search for it: the
   phase-aware action strip) with 8px gaps and `flex-wrap: wrap`, and being
   defined later it wins on source order — so the cells silently get the
   strip's metrics and these rows start wrapping inside a table. Found the
   hard way; the name is deliberate. */
.cell-actions { text-align: end; }
.actionrow { display: flex; gap: 6px; align-items: center; white-space: nowrap; }
/* Inside a page header the actions are three buttons, not a table cell's pair
   of links; at phone width they must wrap rather than widen the document.
   Measured on the waiting list at 375px: 539px wide without this. */
.page-head .actionrow { flex-wrap: wrap; white-space: normal; }
/* The settings' templates card: "שינוי שם" folds open to a name box and a
   save button ON ONE LINE, and the row wraps so the open box takes a line of
   its own rather than pushing its button out over "מחיקה". */
.cell-actions .actionrow:has(.rename) { flex-wrap: wrap; justify-content: flex-end; }
.rename > summary { list-style: none; }
.rename > summary::-webkit-details-marker { display: none; }
.rename[open] { flex-basis: 100%; order: 2; }
.rename__row { display: flex; gap: 6px; margin-top: 6px; }
.rename__row .input { flex: 1 1 160px; min-width: 0; width: auto; padding: 6px 10px; }

.composer { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 20px;
  align-items: start; }
.composer__main { background: var(--card); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 24px; }
.composer__body { font-family: ui-monospace, Menlo, Consolas, monospace;
  font-size: 14px; line-height: 1.6; }
.composer__actions { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
/* 🚨 The email editor's save stays on the screen (2026-10-10, Omri), and
   the question editor's the same way (its save and the answers link). The
   form's last child, sticky to the bottom: the whole form is its sticky
   box, so it rides the bottom edge while the email is written. Stretched to
   the card's edges by the card's own padding. Only the button: the "save as
   a template" choice stays in its place above it. */
.composer__savebar { position: sticky; bottom: 0; z-index: 5; display: flex;
  align-items: center; gap: 12px; margin: 8px -24px -24px; padding: 12px 24px;
  background: color-mix(in srgb, var(--card) 92%, transparent);
  backdrop-filter: blur(6px); border-top: 1px solid var(--border);
  border-radius: 0 0 var(--radius) var(--radius); }
.composer__side { display: flex; flex-direction: column; gap: 16px;
  grid-column: 2; grid-row: 1; }
.composer__side .card { padding: 16px; }
.composer__side h2 { font-size: 15px; margin-bottom: 10px; }
/* The preview sits UNDER the editor, in the wide column, because the email it
   shows is 600px wide: in the 320px sidebar it was crushed to 288px and the
   date card wrapped to three lines. Tall enough for a whole reminder. */
.composer__previewcard { grid-column: 1; }
.composer__preview { width: 100%; height: 720px; border: 1px solid var(--border);
  border-radius: 8px; background: #fff; }
/* What finalize() adds on the way out. The editor holds the STORED copy, so
   the WhatsApp, pay and feedback buttons are simply not up there to look at —
   this list is the only place the page says they are going out at all. */
.composer__extrashead { margin-top: 10px; font-weight: 600; }
.composer__extras { list-style: none; margin: 4px 0 14px; padding: 0;
  display: flex; flex-direction: column; gap: 5px; max-width: 72ch; }
.composer__extra { color: var(--muted); font-size: 13px; line-height: 1.6;
  padding-inline-start: 18px; position: relative; }
.composer__extra::before { content: "+"; position: absolute; inset-inline-start: 0;
  color: var(--brand); font-weight: 700; }
.composer__extra--warn { color: var(--warn); }
.composer__extra--warn::before { content: "!"; color: var(--warn); }

code { background: rgba(127, 127, 127, .16); border-radius: 4px;
  padding: 1px 5px; font-size: .9em; }

@media (max-width: 860px) {
  .composer { grid-template-columns: 1fr; }
  .composer__side, .composer__previewcard { grid-column: auto; grid-row: auto; }
  .composer__preview { height: 520px; }
}

/* ── phase 3: questions, answers, waiting list, social proof ─────────────── */

.qfield { border: 1px solid var(--border); border-radius: 8px;
  padding: 12px 14px; margin: 0 0 16px; }
.qfield legend { padding: 0 6px; }
/* "אחר" with a box to write in (_question_fields.html). The row is the
   option's own look (.check, or .optcard on the survey), holding the
   label of the radio and the box beside it. 🚨 The box undoes the option
   input rules (`.check input`, `.optcard input` size a radio to 18-22px),
   or it renders as an 18px square. `min-width: 0` lets it shrink at 375px
   instead of widening the page. */
.qother__pick { display: flex; align-items: center; gap: 8px; flex: none;
  cursor: pointer; }
.qother__pick input { margin: 0; }
.qother .qother__text { flex: 1 1 auto; width: auto; height: auto; min-width: 0;
  margin: 0; padding: 7px 10px; }
.optcard--tap.qother { gap: 10px; }
/* Typing in the box: the box draws its own focus ring, so the card does
   not draw a second one around it. */
.optcard.qother:has(.qother__text:focus-visible) { outline: none; }
.optcard--tap .qother__pick { gap: 12px; }
.req { color: var(--err); }

.scale { display: flex; gap: 6px; flex-wrap: wrap; }
.scale__opt { display: flex; flex-direction: column; align-items: center;
  gap: 4px; padding: 6px 10px; border: 1px solid var(--border);
  border-radius: 8px; cursor: pointer; min-width: 40px; }
.scale__opt:has(input:checked) { border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 12%, transparent); }
.scale__opt input { accent-color: var(--brand); }

/* The survey during the meeting, on a phone (live.html, `cards=True` in
   _question_fields.html). Only there: the sign-up step, the feedback form and
   an answer from an email keep the plain look above. Choices are big tap
   cards (the sign-up form's .optcard), 0 to 10 is a grid of even tiles in
   two rows that fits 375px, the stars are five even boxes. */
.livecard h1 { text-wrap: balance; }
.livecard__anon { display: flex; align-items: center; gap: 8px; margin: -4px 0 18px;
  color: var(--muted); font-size: 14px; }
.livecard__lock { width: 16px; height: 16px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.livecard__send { font-size: 18px; padding: 14px 20px; border-radius: 12px; }
/* The "send me updates" box closes the about-you part; the questions start
   after a gap, so it does not read as part of the first question. */
.livecard__updates { margin-bottom: 26px; }
.qfield--cards { border: 0; padding: 0; margin: 0 0 26px; min-width: 0; }
.qfield--cards legend { padding: 0; margin-bottom: 10px; font-size: 17px;
  font-weight: 600; line-height: 1.4; }
.qfield__hint { margin: -4px 0 10px; font-size: 14px; color: var(--muted); }
.optcard--tap { align-items: center; min-height: 52px; margin: 0 0 8px; padding: 11px 14px; }
.optcard--tap:has(input:checked) { padding: 10px 13px; }
.optcard--tap input { width: 22px; height: 22px; margin: 0; }
.optcard--tap .optcard__title { font-size: 16.5px; overflow-wrap: anywhere; }
.scale--grid, .scale--stars { display: grid; gap: 8px; }
.scale--grid { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.scale--stars { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.scale--grid .scale__opt, .scale--stars .scale__opt { position: relative;
  justify-content: center; min-width: 0; padding: 0; border-radius: 12px;
  background: var(--card); }
.scale--grid .scale__opt { grid-column: span 2; height: 52px; font-size: 19px; font-weight: 600; }
/* 0 to 5 on the first row, 6 to 10 centred under it. */
.scale--grid .scale__opt:nth-child(7) { grid-column: 2 / span 2; }
.scale--stars .scale__opt { height: 62px; gap: 1px; }
/* The radio covers its tile, transparent: the tile is what is drawn and
   tapped, and the radio is still there for the keyboard and a reader. */
.scale--grid .scale__opt input, .scale--stars .scale__opt input { position: absolute;
  inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.scale--grid .scale__opt:has(input:focus-visible),
.scale--stars .scale__opt:has(input:focus-visible) { outline: 2px solid var(--brand-link); outline-offset: 2px; }
.scale--grid .scale__opt:has(input:checked) { background: var(--brand);
  border-color: var(--brand); color: var(--brand-ink); }
/* 3:1 at least, lit or not: a star is a control, not a decoration. */
.scale__star { font-size: 26px; line-height: 1; color: #80868b; }
.scale--stars small { font-size: 12.5px; color: var(--muted); }
/* A star lights up with every star before it. */
.scale--stars .scale__opt:has(input:checked),
.scale--stars .scale__opt:has(~ .scale__opt input:checked) { border-color: #e8b440;
  background: color-mix(in srgb, #fbbc04 12%, var(--card)); }
.scale--stars .scale__opt:has(input:checked) .scale__star,
.scale--stars .scale__opt:has(~ .scale__opt input:checked) .scale__star { color: #b07d00; }

.qlist { margin: 12px 0; }
.qrow { border: 1px solid var(--border); border-radius: 8px; padding: 12px;
  margin-bottom: 12px; background: var(--card); }
/* The question and its options are boxes that grow with what is typed
   (questions.js sizes them), never one line that cuts a long sentence off
   (2026-10-02, Omri: "the text is cut, I can't see it"). The question takes
   the whole width; the type sits under it. */
.qrow__head { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.qrow__label, .qrow__options { resize: none; overflow: hidden; line-height: 1.45;
  min-height: 0; }
.qrow__label { font-weight: 500; }
.qrow__type { width: auto; min-width: 150px; max-width: 100%; }
.qrow__opts { margin-top: 10px; }
.qrow__opts .field__hint { display: block; margin-top: 4px; }
.qrow__opts .check { margin: 8px 0 0; }
.qrow__foot { display: flex; justify-content: space-between; align-items: center;
  margin-top: 10px; gap: 12px; flex-wrap: wrap; }
.qrow__foot .check { margin: 0; }

.rule { border: 0; border-top: 1px solid var(--border); margin: 20px 0; }
.skip-form { text-align: center; margin-top: 14px; }
.datelist { list-style: none; padding: 0; margin: 16px 0 0; }
.datelist li { margin-bottom: 8px; }

/* results */
.sv { margin-bottom: 28px; }
.sv__q { font-size: 16px; margin: 0 0 10px; }
.sv__row { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.sv__label { flex: 0 0 30%; }
.sv__bar { flex: 1 1 auto; height: 20px; background: var(--bg);
  border-radius: 4px; overflow: hidden; }
.sv__bar i { display: block; height: 100%; background: var(--brand);
  min-width: 2px; }
.sv__n { flex: 0 0 90px; color: var(--muted); font-size: 13px; text-align: start; }
.sv__avg { margin: 0 0 10px; font-size: 15px; }
.sv__cols { display: flex; gap: 6px; align-items: flex-end; height: 110px; }
.sv__col { flex: 1 1 0; display: flex; flex-direction: column;
  justify-content: flex-end; align-items: center; height: 100%; }
.sv__col i { display: block; width: 100%; background: var(--brand);
  border-radius: 3px 3px 0 0; min-height: 2px; }
.sv__col span { font-size: 12px; color: var(--muted); margin-top: 4px; }
.sv__quotes { margin: 0; padding-inline-start: 20px; }
.sv__quotes li { margin-bottom: 6px; }
/* What was written in "אחר", under the bars (core/questions.py). */
.sv__others { margin: 8px 0 0; max-width: 72ch; }
.sv__others summary { cursor: pointer; font-size: 14px; color: var(--muted); }
.sv__others .sv__quotes { margin-top: 6px; overflow-wrap: anywhere; }
/* 🚨 The answers page's bar stays on the screen (2026-10-10, Omri): a jump
   to any question and the page's two buttons, sticky to the top of the page
   on its grey. The person search sticks inside its own card, under the bar
   (--answersbar-h, measured in answers.html), and a jump lands below the
   bar rather than behind it (scroll-margin-top). */
.answersbar { position: sticky; top: 0; z-index: 16; display: flex; flex-wrap: wrap;
  align-items: center; gap: 8px; margin: 0 0 16px; padding: 8px 0 10px;
  background: var(--bg); box-shadow: 0 8px 10px -10px rgba(60, 64, 67, .45); }
.answersbar__jump { flex: 1 1 260px; width: auto; min-width: 0; min-height: 48px; }
.answersbar .btn { display: inline-flex; align-items: center; min-height: 48px; }
.sv[id], #people { scroll-margin-top: calc(var(--answersbar-h, 0px) + 12px); }
.answers__search { position: sticky; top: var(--answersbar-h, 0px); z-index: 5;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px;
  margin: 0 0 8px; padding: 8px 0; background: var(--card); }
.answers__search .input { flex: 1 1 240px; width: auto; min-width: 0; }

/* The AI insight points over an open question (core/insights.py). A tinted
   panel above the answers, so it reads as a summary OF them. */
.insights { background: color-mix(in srgb, var(--brand) 8%, #fff);
  border: 1px solid color-mix(in srgb, var(--brand) 25%, #fff);
  border-radius: 10px; padding: 10px 14px; margin: 0 0 12px; max-width: 72ch; }
.insights__head { margin: 0 0 6px; font-size: 14px; }
.insights p { margin: 0; }
.insights__list { margin: 0; padding-inline-start: 20px; }
.insights__list li { margin-bottom: 4px; line-height: 1.5; }

.table-scroll { overflow-x: auto; }

/* public: video + social proof */
.vsl { position: relative; padding-top: 56.25%; margin: 16px 0;
  border-radius: 10px; overflow: hidden; background: #000; }
.vsl iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.proof { margin: 20px 0; }
.proof__rating { text-align: center; font-size: 18px; margin: 0 0 14px; }
.proof__quote { margin: 0 0 12px; padding: 12px 16px; border-radius: 10px;
  background: var(--bg); border-inline-start: 3px solid var(--brand); }
.proof__quote p { margin: 0 0 6px; }
.proof__quote cite { font-style: normal; font-size: 14px; }
.proof__stars { color: #f5b301; font-size: 14px; }
.proof__role { color: var(--muted); }

/* ── phase 4: integrations, attendance ───────────────────────────────────── */

.conn { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin: 0 0 12px; }
.conn .muted { flex: 1 1 260px; font-size: 14px; }

.attend { font-size: 17px; margin: 0 0 12px; }
.attend b { font-size: 26px; }
.attend-form { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.attend-form .input { flex: 0 0 140px; }

/* ── phase 5: the setup wizard ───────────────────────────────────────────── */

.steps { display: flex; gap: 8px; list-style: none; margin: 0 0 20px; padding: 0; }
.steps__i { flex: 1 1 0; display: flex; flex-direction: column; align-items: center;
  gap: 4px; padding: 10px 4px; border-radius: 8px; background: var(--card);
  border: 1px solid var(--border); color: var(--muted); font-size: 13px; }
.steps__i b { display: grid; place-items: center; width: 24px; height: 24px;
  border-radius: 999px; background: var(--border); color: var(--muted);
  font-size: 13px; }
.steps__i.is-active { border-color: var(--brand); color: var(--ink); }
.steps__i.is-active b { background: var(--brand); color: var(--brand-ink); }
.steps__i.is-done b { background: var(--ok); color: #fff; }

/* ---- the survey screen ("הפעלת הסקר", 2026-09-30) --------------------------
   One tab that is the presenter's control room AND what the room sees, shared
   in Zoom as it is. Dark, because it is projected. A bar along the top (the
   state and its switch, what the stage shows, the tools), then the stage: one
   state at a time, sized with container units so it reads on a projector and
   still fits a laptop. `--brand-stage` is the brand lightened until it reads
   on the dark (settings.admin_theme_vars); a button keeps --brand/--brand-ink. */
.btnrow { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0; }
.btnrow .btn { display: inline-flex; align-items: center; }
.btnrow form { margin: 0; }
body.present { background: #141517; color: #f4f5f6; }
body.present .wrap--stage { max-width: none; padding: 0; margin: 0; }
body.present .flashes { margin: 0; padding: 10px 16px 0; }
.screen { position: relative; display: flex; flex-direction: column;
  height: 100vh; height: 100dvh; min-height: 460px; overflow: hidden; }
.screen form { margin: 0; }
.pbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px 14px; padding: 10px 14px; background: #1c1d20; border-bottom: 1px solid #3a3d42;
  position: relative; z-index: 6; transition: opacity .25s, transform .25s; }
/* Fullscreen: the bar floats over the stage and goes after 3s without the
   mouse (present.js), so the room sees only the stage. */
.screen.is-full .pbar { position: absolute; inset-inline: 0; top: 0; }
.screen.is-full.is-idle .pbar { opacity: 0; transform: translateY(-100%); pointer-events: none; }
.screen.is-full.is-idle { cursor: none; }
.pbar__grp { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; }
.pill { display: inline-flex; align-items: center; gap: 8px; padding: 7px 14px; border-radius: 999px;
  font-weight: 600; font-size: 15px; background: #26282c; color: #c3c7cc; white-space: nowrap; }
.pill > i { width: 10px; height: 10px; border-radius: 50%; background: #80868b; }
.pill.is-open { background: rgba(91, 214, 130, .14); color: #a8e6b8; }
.pill.is-open > i { background: #5bd682; animation: pill-live 1.8s ease-in-out infinite; }
.pill__n { font-weight: 500; }
.pbar__auto { font-size: 14px; color: #c3c7cc; }
.pb { display: inline-flex; align-items: center; gap: 7px; min-height: 40px; padding: 7px 13px;
  border-radius: 9px; border: 1px solid #3a3d42; background: #26282c; color: #f4f5f6;
  font: inherit; font-size: 15px; font-weight: 500; cursor: pointer; white-space: nowrap;
  text-decoration: none; }
.pb:hover { border-color: #6b7078; }
.pb .ic, .seg .ic, .huge .ic { margin: 0; }
.pb--go { background: var(--brand); color: var(--brand-ink); border-color: transparent; }
.pb--icon { width: 40px; justify-content: center; padding: 0; font-weight: 700; }
.pb[aria-expanded="true"] { background: #3a3d42; border-color: #6b7078; }
.ic--fill { fill: currentColor; stroke: none; }
.seg { display: inline-flex; padding: 3px; gap: 3px; border-radius: 11px; background: #26282c;
  border: 1px solid #3a3d42; }
.seg button { display: inline-flex; align-items: center; gap: 7px; border: 0; background: transparent;
  color: #c3c7cc; padding: 6px 13px; border-radius: 8px; font: inherit; font-size: 15px;
  font-weight: 500; cursor: pointer; min-height: 34px; }
.seg button[aria-pressed="true"] { background: #f4f5f6; color: #141517; }
.pb:focus-visible, .seg button:focus-visible, .arrow:focus-visible, .huge:focus-visible,
.pop__link:focus-visible { outline: 2px solid var(--brand-stage); outline-offset: 2px; }

.stage { position: relative; flex: 1 1 auto; min-height: 0; container-type: size; }
.st { position: absolute; inset: 0; }
.st--center { display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 2.4cqh; padding: 4cqh 6cqw; }
.st-eyebrow { margin: 0; font-size: clamp(16px, 2cqw, 30px); color: #c3c7cc; text-wrap: balance; }
.st-title { margin: 0; font-size: clamp(28px, 4.6cqw, 64px); font-weight: 700; line-height: 1.15;
  text-wrap: balance; }
.st-sub { margin: 0; font-size: clamp(16px, 2cqw, 28px); color: #c3c7cc; max-width: 48ch;
  text-wrap: balance; }
.st-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; }
.huge { display: inline-flex; align-items: center; gap: .5em; font: inherit;
  font-size: clamp(22px, 3cqw, 42px); font-weight: 700; padding: .55em 1.35em; border-radius: 18px;
  border: 0; background: var(--brand); color: var(--brand-ink); cursor: pointer; text-decoration: none; }
.huge:hover { filter: brightness(1.06); }
.huge--quiet { background: #26282c; color: #f4f5f6; border: 1px solid #3a3d42; }

.st--qrlayout { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center;
  gap: 5cqw; padding: 5cqh 7cqw; }
.qrbig { width: min(78cqh, 44cqw); aspect-ratio: 1; background: #fff; border-radius: 18px;
  overflow: hidden; }
.qrbig img, .qrmini img { display: block; width: 100%; height: 100%; }
.st-qr__text { min-width: 0; }
.st-qr__cta { margin: 0; font-size: clamp(24px, 4.2cqw, 60px); font-weight: 700; line-height: 1.15;
  text-wrap: balance; }
.st-qr__pitch { margin: 1.4cqh 0 0; font-size: clamp(18px, 2.4cqw, 34px); color: #c3c7cc; line-height: 1.4; }
.st-qr__url { margin: 2cqh 0 0; font-size: clamp(18px, 2.7cqw, 40px); font-weight: 600;
  color: var(--brand-stage); overflow-wrap: anywhere; text-align: right; }
.st-qr__count { margin: 5cqh 0 0; display: flex; align-items: baseline; gap: .35em; flex-wrap: wrap; }
.st-qr__count b { display: inline-block; font-size: clamp(44px, 8.4cqw, 120px); line-height: 1;
  font-variant-numeric: tabular-nums; }
.st-qr__count span { font-size: clamp(18px, 2.6cqw, 36px); color: #c3c7cc; }
.bump { animation: bump .6s ease-out; }

.st--res { display: grid; grid-template-columns: minmax(0, 1fr) clamp(150px, 17cqw, 300px);
  gap: 3.5cqw; padding: 3.4cqh 7.5cqw 3cqh; }
.res { min-width: 0; min-height: 0; display: flex; flex-direction: column; }
.res__meta { display: flex; flex-wrap: wrap; gap: 6px 18px; margin: 0;
  font-size: clamp(15px, 1.8cqw, 24px); color: #c3c7cc; }
.res__q { margin: .25em 0 .7em; font-size: clamp(24px, 3.5cqw, 46px); line-height: 1.2;
  text-wrap: balance; }
.res__body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.res__empty { font-size: clamp(18px, 2.4cqw, 30px); color: #c3c7cc; margin: 2cqh 0; }
.bars { display: grid; gap: 1.8cqh; }
.barrow { display: grid; grid-template-columns: minmax(0, 34%) minmax(0, 1fr) 6.4em;
  align-items: center; gap: 1.6cqw; font-size: clamp(16px, 2.05cqw, 28px); }
.barrow__l { overflow-wrap: anywhere; line-height: 1.25; }
.barrow__t { height: clamp(18px, 4.4cqh, 42px); background: #26282c; border-radius: 8px; overflow: hidden; }
.barrow__f { display: block; height: 100%; min-width: 3px; background: var(--brand-stage);
  border-radius: 8px; }
.barrow__n { font-variant-numeric: tabular-nums; white-space: nowrap; }
.barrow__n span { color: #c3c7cc; }
.avg { margin: 0 0 2cqh; font-size: clamp(18px, 2.4cqw, 32px); }
.avg b { font-size: 1.25em; color: var(--brand-stage); }
.cols { flex: 1 1 auto; min-height: 120px; max-height: 46cqh; display: grid; grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr); gap: 1.1cqw; }
.col { display: flex; flex-direction: column; align-items: center; min-height: 0; }
.col__track { flex: 1 1 auto; width: 100%; min-height: 0; display: flex; flex-direction: column;
  justify-content: flex-end; align-items: center; }
.col__n { font-size: clamp(16px, 2.1cqw, 28px); font-weight: 700; margin-bottom: .25em;
  font-variant-numeric: tabular-nums; }
.col__n.is-zero { color: #9aa0a6; font-weight: 500; }
.col__bar { display: block; width: 100%; background: var(--brand-stage); border-radius: 8px 8px 3px 3px;
  min-height: 3px; }
.col__lbl { font-size: clamp(16px, 2.1cqw, 28px); margin-top: .35em; line-height: 1.2; white-space: nowrap; }
.col__lbl--stars { color: var(--brand-stage); letter-spacing: -.05em; font-size: clamp(12px, 1.5cqw, 22px); }
.res__body .insights { background: #222a36; border-color: #3a4a63; max-width: none;
  margin: 0 0 2.2cqh; padding: 1.6cqh 1.8cqw; }
.res__body .insights__head { color: #9cc2ff; font-size: clamp(14px, 1.7cqw, 22px); }
.res__body .insights__list li { color: #f4f5f6; font-size: clamp(16px, 2cqw, 27px); line-height: 1.35; }
.res__body .insights .muted { color: #c3c7cc; }
.quotes { list-style: none; margin: 0; padding: 0; flex: 1 1 auto; min-height: 0; overflow: hidden;
  display: flex; flex-wrap: wrap; gap: 1.2cqh 1cqw; align-content: flex-start; }
.quote { background: #26282c; border-radius: 12px; padding: .45em .85em;
  font-size: clamp(15px, 1.9cqw, 25px); line-height: 1.35; }
.quote--new { box-shadow: inset 0 0 0 2px var(--brand-stage); }
/* What was written in "אחר", under a choice's bars: the same chips, one
   size down, taking whatever room the bars leave. */
.others__head { margin: 2.6cqh 0 1cqh; font-size: clamp(15px, 1.8cqw, 24px); color: #c3c7cc; }
.quotes--others .quote { font-size: clamp(14px, 1.65cqw, 22px); }
/* A later page of "אחר" answers has no bars above it. */
.others__head--top { margin-top: 0; }
/* Its line is kept even while empty: filled in after the answers are
   measured, it would otherwise push the last row half off the screen. */
.more { margin: 1.2cqh 0 0; font-size: clamp(14px, 1.6cqw, 21px); color: #c3c7cc;
  min-height: 1.35em; line-height: 1.35; }
.res__aside { align-self: end; text-align: center; min-width: 0; }
.qrmini { width: 100%; aspect-ratio: 1; background: #fff; border-radius: 12px; overflow: hidden; }
.res__aside p { margin: .55em 0 0; font-size: clamp(14px, 1.6cqw, 22px); line-height: 1.3; }
.res__url { color: var(--brand-stage); font-weight: 600; overflow-wrap: anywhere; }
/* One line: "events.omri-iram.co.il/s/abcde" split in two is harder to type
   from across a room than a smaller one. */
.res__aside .res__url { font-size: clamp(12px, 1.12cqw, 18px); white-space: nowrap; }
.res__closed { border: 1px dashed #3a3d42; border-radius: 12px; padding: 1.2em .6em; color: #c3c7cc; }
.arrow { position: absolute; top: 50%; transform: translateY(-50%); width: clamp(44px, 5cqw, 72px);
  aspect-ratio: 1; border-radius: 50%; border: 1px solid #3a3d42; background: rgba(38, 40, 44, .9);
  color: #f4f5f6; display: grid; place-items: center; cursor: pointer; padding: 0; }
.arrow .ic { width: 55%; height: 55%; margin: 0; }
.arrow--prev { right: 1.5cqw; }
.arrow--next { left: 1.5cqw; }
.arrow:disabled { opacity: .25; cursor: default; }

.clock { position: absolute; top: 2.4cqh; left: 2cqw; z-index: 4; font-size: clamp(34px, 5.4cqw, 80px);
  font-weight: 700; line-height: 1.1; padding: .08em .42em; border-radius: 14px;
  background: rgba(20, 21, 23, .9); border: 1px solid #3a3d42; font-variant-numeric: tabular-nums; }
.clock.is-done { color: #f28b82; border-color: #f28b82; }
.pop { position: absolute; left: 14px; z-index: 8; width: min(330px, calc(100% - 28px));
  background: #202226; border: 1px solid #4a4e55; border-radius: 14px; padding: 14px;
  display: grid; gap: 12px; box-shadow: 0 16px 40px rgba(0, 0, 0, .45); }
.pop .seg { width: 100%; }
.pop .seg button { flex: 1 1 0; justify-content: center; }
.pop__row { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.pop__set { font-size: 26px; font-variant-numeric: tabular-nums; }
.pop__title { margin: 0; font-weight: 600; }
.pop__hint { margin: 0; font-size: 14px; color: #c3c7cc; }
.pop__link { justify-self: start; background: none; border: 0; color: #c3c7cc; text-decoration: underline;
  cursor: pointer; padding: 0; font: inherit; font-size: 14px; }
.keys { margin: 0; display: grid; gap: 6px; }
.keys div { display: flex; align-items: center; gap: 10px; }
.keys dt { margin: 0; min-width: 34px; }
.keys dd { margin: 0; color: #c3c7cc; }
.keys kbd { display: inline-grid; place-items: center; min-width: 28px; height: 28px; padding: 0 6px;
  border-radius: 6px; background: #26282c; border: 1px solid #6b7078; font: 600 14px/1 var(--font);
  color: #f4f5f6; }
.stoast { position: absolute; bottom: 18px; left: 50%; transform: translateX(-50%); z-index: 9;
  background: #f4f5f6; color: #141517; padding: 10px 18px; border-radius: 12px; font-weight: 500;
  max-width: calc(100% - 28px); }
@keyframes bump { 0% { transform: scale(1); } 30% { transform: scale(1.16); } 100% { transform: scale(1); } }
@keyframes pill-live { 0%, 100% { box-shadow: 0 0 0 3px rgba(91, 214, 130, .22); }
  50% { box-shadow: 0 0 0 7px rgba(91, 214, 130, .06); } }
@media (prefers-reduced-motion: reduce) {
  .bump, .pill.is-open > i { animation: none; }
  .pbar { transition: none; }
}
/* A laptop squeezed narrow, or a phone opening it by mistake: the stage
   stacks and scrolls instead of shrinking the QR to a stamp. */
@media (max-width: 760px) {
  .screen { height: auto; min-height: 100vh; overflow: visible; }
  .stage { container-type: inline-size; min-height: 70vh; }
  .st { position: relative; min-height: 70vh; }
  .st--qrlayout { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center;
    padding: 28px 18px; }
  .st--qrlayout .st-qr__url { text-align: center; }
  .st-qr__count { justify-content: center; }
  .qrbig { width: min(76cqw, 340px); }
  .st--res { grid-template-columns: minmax(0, 1fr); padding: 20px 56px 24px; }
  .res__aside { display: none; }
  .cols { height: 220px; max-height: none; flex: none; }
  .quotes { max-height: none; overflow: visible; }
}

/* ── The phone app (2026-10-09) ─────────────────────────────────────────────
   Omri: "rebuild the mobile experience", for the admin screens, phone-first,
   and on the home screen like an app (web/pwa.py). Approved mockup:
   claude.ai/artifact/Cs12KkHxPefvX7QxRYdtRR. On a phone the admin has a
   bottom bar with the four places, a slim top bar, events as cards with a
   date tile, and an event that opens on a list of its sections, each of which
   opens on its own with a way back (tabs.js). Every rule here is inside a
   max-width: 600px query or hides a phone-only thing above it: the computer
   view is what it was. */
.tabbar, .hub, .secbar, .cell-date, .cell-num__label, .next__day,
.install-card, .phone-signout, .phone-label, .setback { display: none; }

@media (max-width: 600px) {
  .wrap { padding-top: 16px; }

  /* The top bar: one slim row with the name; the nav and the search moved
     down to the bottom bar. */
  .topbar--app { min-height: 52px; padding: 8px 16px; }
  .topbar--app .topbar__nav, .topbar--app .topbar__search { display: none; }
  .topbar--app .topbar__brand { flex: 1 1 auto; font-size: 16px; }

  /* The bottom bar, above the phone's own gesture bar. */
  .tabbar { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    position: fixed; inset-inline: 0; bottom: 0; z-index: 30;
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
    background: var(--card); border-top: 1px solid var(--border);
    box-shadow: 0 -1px 6px rgba(60, 64, 67, .08); }
  .tabbar a { display: flex; flex-direction: column; align-items: center;
    justify-content: center; gap: 2px; min-height: 54px; font-size: 12.5px;
    font-weight: 500; line-height: 1.2; color: var(--muted); text-decoration: none;
    -webkit-tap-highlight-color: transparent; }
  .tabbar__ic { display: flex; padding: 4px 18px; border-radius: 999px; }
  .tabbar .ic { margin: 0; width: 22px; height: 22px; vertical-align: 0; }
  .tabbar a[aria-current="page"] { color: var(--brand-link); font-weight: 700; }
  .tabbar a[aria-current="page"] .tabbar__ic {
    background: color-mix(in srgb, var(--brand) 30%, var(--card)); }
  .tabbar a:focus-visible { outline: 2px solid var(--brand); outline-offset: -4px;
    border-radius: 14px; }
  body:has(.tabbar) { padding-bottom: calc(70px + env(safe-area-inset-bottom)); }
  /* A sticky save bar sits above the bottom bar, never under it. */
  body:has(.tabbar) .savebar { bottom: calc(68px + env(safe-area-inset-bottom)); }

  /* A screen under another: its parent as one back link, "→ אירועים". */
  .crumbs > a:not(:last-of-type), .crumbs__sep, .crumbs [aria-current] { display: none; }
  .crumbs > a:last-of-type { display: inline-flex; align-items: center; gap: 6px;
    min-height: 40px; color: var(--ink); font-weight: 500; }
  .crumbs > a:last-of-type::before { content: "→"; font-size: 18px; color: var(--muted); }

  /* A card's 24px is a tenth of a phone's width on each side. */
  .card { padding: 16px; }
  .card--alert h2 { font-size: 18px; line-height: 1.35; }
  /* The approval queue's rows (stacked by the older phone block above):
     `.table td`'s padding and rule are undone here too, so each held email
     is one block, not five ruled lines. */
  .card--queue h2 { font-size: 19px; }
  .card--queue td { padding: 2px 0; border: 0; }
  .card--queue tr:last-child { border-bottom: 0; }

  /* ── The events screen ── */
  .page-head:has(.next) h1 { font-size: 22px; }
  /* "הבא: …" is the first card: the next event, large, and on the day its
     two buttons (the meeting, the survey). */
  .next { margin: 10px 0 2px; padding: 14px 16px; border-radius: 14px;
    background: color-mix(in srgb, var(--brand) 10%, var(--card));
    border: 1px solid color-mix(in srgb, var(--brand) 35%, var(--border)); }
  .next__label { font-size: 13.5px; }
  .next__name { flex: 1 1 100%; font-size: 18px; line-height: 1.35; color: var(--ink); }
  .next__day { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px; flex: 1 1 100%; margin-top: 8px; }
  .next__day .btn { display: inline-flex; align-items: center; justify-content: center;
    min-height: 48px; padding: 8px 12px; }
  /* "אירוע חדש" floats above the bottom bar, where a thumb is. */
  .btn--fab { position: fixed; z-index: 25; inset-inline-end: 16px;
    bottom: calc(82px + env(safe-area-inset-bottom)); display: inline-flex;
    align-items: center; min-height: 52px; padding: 0 20px; border-radius: 16px;
    font-weight: 600; box-shadow: 0 6px 18px rgba(32, 33, 36, .2); }
  body:has(.btn--fab) { padding-bottom: calc(150px + env(safe-area-inset-bottom)); }

  /* Events as cards: a date tile, the name, the time, how many. The name's
     link is stretched over the whole card, so a tap anywhere opens the event;
     a chip that is a link of its own stays above the stretch. Duplicating is
     on the event itself (its action row), not on every card. */
  .list .table-scroll { overflow: visible; }
  .table--events, .table--events tbody { background: none; }
  .table--events tr { display: grid; grid-template-columns: 56px minmax(0, 1fr);
    column-gap: 12px; row-gap: 3px; align-items: start; position: relative;
    margin: 0 0 10px; padding: 12px; background: var(--card);
    border: 1px solid var(--border); border-radius: 14px; box-shadow: var(--shadow); }
  .table--events tr:active { background: var(--bg); }
  /* `.table td`'s padding and rule come later in this file than the older
     phone block above, so they won over it there; here they are undone. */
  .table--events td { grid-column: 2; padding: 0; border: 0; }
  .table--events .cell-num:empty { display: none; }
  .table--events .cell-when__rel { display: inline; font-size: inherit; }
  .table--events .cell-date { display: flex; grid-column: 1; grid-row: 1 / span 4;
    flex-direction: column; align-items: center; justify-content: center;
    height: 64px; border-radius: 12px; background: var(--bg);
    border: 1px solid var(--border); line-height: 1.15; text-align: center; }
  .cell-date__wd, .cell-date__mon { font-size: 11.5px; color: var(--muted); }
  .cell-date__day { font-size: 22px; font-weight: 700; color: var(--ink); }
  .table--events .cell-name { margin: 0; }
  .table--events .cell-name > a:first-child { color: var(--ink); font-weight: 600;
    text-decoration: none; padding: 0; }
  .table--events .cell-name > a:first-child::after { content: ""; position: absolute;
    inset: 0; border-radius: 14px; }
  .table--events .cell-name .chip { position: relative; z-index: 1; margin: 6px 0 0;
    margin-inline-end: 6px; }
  .table--events .cell-when { font-size: 14px; }
  .cell-when__date { display: none; }
  .table--events .cell-num { color: var(--muted); }
  .cell-num__label { display: inline; }
  .table--events .cell-actions .actionrow { display: none; }

  /* ── One event ── */
  .page-head--event h1 { font-size: 22px; }
  /* The share box: the link and its copy button on one line, the other two
     buttons sharing the next. */
  .sharebox { padding: 12px; }
  .sharebox__row { gap: 8px; }
  .sharebox__label { flex: 1 1 100%; min-width: 0; }
  /* 60%: wide enough that only the copy button fits beside it. With a zero
     basis the open button squeezed onto the line too and the link shrank
     to a sliver. */
  .sharebox__row .input { flex: 1 1 60%; font-size: 14px; }
  .sharebox__row > button.btn { flex: none; }
  .sharebox__row > a.btn { flex: 1 1 calc(50% - 4px); display: inline-flex;
    align-items: center; justify-content: center; padding-inline: 10px; }
  /* The list: the summary above, the sections here; the tabs and panels
     wait until one is opened. */
  html[data-evview="hub"] .tabs, html[data-evview="hub"] .tab-panel { display: none; }
  html[data-evview="hub"] .hub { display: block; }
  .hub { margin: 0 0 16px; background: var(--card); border: 1px solid var(--border);
    border-radius: 14px; box-shadow: var(--shadow); overflow: hidden; }
  .hub__row { display: flex; align-items: center; gap: 12px; min-height: 64px;
    padding: 10px 14px; color: var(--ink); text-decoration: none;
    border-top: 1px solid var(--border); -webkit-tap-highlight-color: transparent; }
  .hub__row:first-child { border-top: 0; }
  .hub__row:active { background: var(--bg); }
  .hub__ic { flex: none; display: flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 11px; background: var(--bg); }
  .hub__ic .ic, .hub__chev { margin: 0; width: 20px; height: 20px; vertical-align: 0; }
  .hub__chev { color: var(--muted); }
  .hub__text { flex: 1 1 auto; min-width: 0; }
  .hub__title { display: block; font-weight: 600; line-height: 1.3; }
  .hub__sub { display: block; font-size: 13.5px; color: var(--muted); line-height: 1.4;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .hub__sub .chip { font-size: 12.5px; }
  /* One section open: its bar with the way back, then the panel alone. */
  html[data-evview="section"] .evhead, html[data-evview="section"] .tabs { display: none; }
  html[data-evview="section"] .secbar { display: flex; }
  .secbar { position: sticky; top: 0; z-index: 20; align-items: center; gap: 4px;
    margin: -16px -16px 16px; padding: 6px 10px; min-height: 58px;
    background: var(--card); border-bottom: 1px solid var(--border); }
  .secbar__back { flex: none; display: flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; border-radius: 12px; color: var(--ink); }
  .secbar__back .ic { margin: 0; width: 22px; height: 22px; vertical-align: 0; }
  .secbar__text { flex: 1 1 auto; min-width: 0; }
  .secbar__title { margin: 0; font-size: 18px; line-height: 1.25; }
  .secbar__event { display: block; font-size: 12.5px; color: var(--muted);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

  .phone-label { display: inline; }

  /* ── Tables as cards (`.table--cards`): people, emails, the waiting list,
     search results. The same markup as the computer's table; each row a
     block, its cells lines. `.cell-title` and `.cell-badge` share the first
     line; a cell with `data-label` says what it is, since the headings are
     gone. Inside a card the rows are a list, outside it each is a card. */
  .table--cards thead { display: none; }
  .table--cards, .table--cards tbody { display: block; background: none; }
  .table--cards tr { display: flex; flex-wrap: wrap; align-items: center;
    gap: 3px 10px; margin: 0 0 10px; padding: 12px 14px; background: var(--card);
    border: 1px solid var(--border); border-radius: 14px; }
  .card .table--cards tr { margin: 0; padding: 12px 0; background: none; border: 0;
    border-bottom: 1px solid var(--border); border-radius: 0; }
  .card .table--cards tr:last-child { border-bottom: 0; }
  .table--cards td { display: block; flex: 1 1 100%; min-width: 0; padding: 0;
    border: 0; overflow-wrap: anywhere; }
  .table--cards td:empty { display: none; }
  .table--cards td[dir="ltr"] { text-align: right; font-size: 14.5px; }
  .table--cards td[data-label]::before { content: attr(data-label) " "; }
  .table--cards .cell-title { order: -2; flex: 1 1 auto; width: auto;
    font-weight: 600; font-size: 16px; }
  .table--cards .cell-badge { order: -1; flex: 0 1 auto; }
  .table--cards .muted { font-size: 14px; }
  .table--cards .cell-actions { margin-top: 6px; }
  .table--cards .actionrow { flex-wrap: wrap; justify-content: flex-start;
    white-space: normal; gap: 8px; }
  .table--cards .actionrow .btn { min-height: 40px; }
  /* With a box to tick: the box beside the lines, all of them. */
  .table--check tr { display: grid; grid-template-columns: 34px minmax(0, 1fr);
    column-gap: 8px; align-items: start; }
  .table--check td { grid-column: 2; }
  .table--check .cell-title, .table--check .cell-badge { order: 0; }
  .table--check .cell-check { grid-column: 1; grid-row: 1 / span 5; padding-top: 2px; }
  .table--check input[type="checkbox"] { width: 22px; height: 22px; margin: 0;
    accent-color: var(--brand); }
  .table--check thead { display: block; }
  .table--check thead tr { display: block; padding: 0 0 10px;
    border-bottom: 1px solid var(--border); }
  .table--check thead th { display: none; padding: 0; border: 0; }
  .table--check thead th:first-child { display: block; }
  .pickall__wrap { display: inline-flex; align-items: center; gap: 12px;
    min-height: 40px; font-weight: 500; color: var(--ink); cursor: pointer; }

  /* ── Settings: the map is the list, and one card opens alone (:target).
     The form, the save bar and every other card stay in the page, hidden. */
  body:has(.jumpbar) .list__title { display: none; }
  body:has(.jumpbar) .card[id] { display: none; }
  body:has(.jumpbar) .card[id]:target { display: block; }
  body:has(.card[id]:target) .jumpbar,
  body:has(.card[id]:target) .install-card,
  body:has(.card[id]:target) .page-head { display: none; }
  body:has(.jumpbar):not(:has(.card[id]:target)) .savebar { display: none; }
  /* The way back stays in view, like an event section's bar: the browser
     scrolls the opened card to the top, which would leave it above. */
  body:has(.card[id]:target) .setback { display: flex; align-items: center; gap: 8px;
    position: sticky; top: 0; z-index: 20; min-height: 56px; margin: -16px -16px 12px;
    padding: 0 14px; background: var(--card); border-bottom: 1px solid var(--border);
    color: var(--ink); font-size: 17px; font-weight: 600; text-decoration: none; }
  .setback .ic { margin: 0; width: 22px; height: 22px; }
  body:has(.card[id]:target) .card[id] { scroll-margin-top: 72px; }
  body:has(.card[id]:target) .phone-signout { display: none; }
  /* A card's own heading with a button beside it (נרשמים + ייצוא). */
  .card .page-head h2 { font-size: 19px; margin: 0; }
  .card .page-head .btn { white-space: nowrap; }
  .jumpbar { display: block; margin: 0 0 8px; padding: 0; background: none;
    border: 0; box-shadow: none; }
  .jumpbar__group { margin: 0 0 18px; gap: 8px; }
  .jumpbar__title { border: 0; padding: 0 4px; font-size: 13.5px; font-weight: 500;
    color: var(--muted); }
  .jumpbar__links { display: flex; flex-direction: column; gap: 0; overflow: hidden;
    background: var(--card); border: 1px solid var(--border); border-radius: 14px; }
  .jumpbar a { display: flex; align-items: center; justify-content: space-between;
    gap: 10px; min-height: 54px; padding: 0 16px; border-radius: 0; background: none;
    border-top: 1px solid var(--border); font-size: 16px; color: var(--ink); }
  .jumpbar a:first-child { border-top: 0; }
  .jumpbar a:hover { background: none; color: var(--ink); }
  .jumpbar a:active { background: var(--bg); }
  /* A chevron pointing onward (left, in Hebrew), drawn, not a glyph that
     the bidi algorithm might mirror. */
  .jumpbar a::after { content: ""; flex: none; width: 18px; height: 18px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235f6368' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E") center / contain no-repeat; }

  /* ── The editors and forms ── The email editor's save bar clears the
     bottom bar and takes the card's 16px edges here. */
  .composer__main { padding: 16px; }
  .composer__savebar { margin: 8px -16px -16px; padding: 10px 16px; }
  body:has(.tabbar) .composer__savebar { bottom: calc(68px + env(safe-area-inset-bottom)); }
  .composer__savebar .btn { flex: 1 1 auto; min-height: 48px;
    display: inline-flex; align-items: center; justify-content: center; }
  /* Two fields side by side are two cramped fields on a phone; one under the
     other. The date and the times keep their own rows (their rules carry
     :has(), which outranks this). */
  .row .field { flex-basis: 100%; }
  /* The answers page's bar, one row on a phone: the jump takes the room,
     the two buttons are their icons (their words stay for a screen reader
     in aria-label, and are clipped in place here). */
  .answersbar .btn { width: 48px; justify-content: center; padding: 0; flex: none; }
  .answersbar .btn .ic { margin: 0; width: 20px; height: 20px; }
  .answersbar__text { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .answersbar__jump { flex: 1 1 0; }
  /* The waiting list's pinned filters, one short row: the two side by side
     (each box says what it holds: "כל הסוגים", "כל התאריכים"), their labels
     kept for a screen reader by clipping in place, never by pushing them
     off the page. An opened date list takes the whole row. */
  .filters { gap: 8px; padding: 6px 0 8px; }
  .filters .filters__field { flex: 1 1 0; min-width: 0; max-width: none; }
  .filters .filters__field:has(.picklist[open]) { flex-basis: 100%; }
  .filters .field__label { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .filters .btn { flex: none; }
  /* The waiting list's send bar: above the bottom bar, its button the
     whole width. */
  body:has(.tabbar) .invite__send { bottom: calc(76px + env(safe-area-inset-bottom)); }
  .invite__send .btn { flex: 1 1 100%; min-height: 48px; }
  .invite__send [data-invite-lock] { font-size: 13.5px; }
  /* Number tiles three to a row, not two tall ones. */
  .tiles { gap: 8px; }
  .tile { flex: 1 1 28%; padding: 10px 8px; }
  .tile b { font-size: 22px; }
  .tile span { font-size: 12.5px; line-height: 1.35; display: block; }

  /* The settings page: installing the app, and signing out (the top bar's
     link is not on a phone). */
  .install-card[data-install]:not([hidden]) { display: flex; align-items: center;
    gap: 14px; margin: 0 0 16px; padding: 14px; border-radius: 14px;
    background: color-mix(in srgb, var(--brand) 10%, var(--card));
    border: 1px solid color-mix(in srgb, var(--brand) 35%, var(--border)); }
  .install-card img { flex: none; display: block; border-radius: 12px; }
  .install-card__text { flex: 1 1 auto; min-width: 0; display: flex;
    flex-direction: column; line-height: 1.4; }
  .install-card__text .muted { font-size: 13.5px; }
  .phone-signout { display: block; margin: 24px 0 0; }
  .phone-signout .btn { width: 100%; color: var(--err); }
}