/*
 * Component primitives. Every value here references a token from tokens.css.
 *
 * This file must not define :root. See tokens.css for why, and web_test.go for
 * the test that enforces it.
 */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--ink);
  background: var(--surface-sunken);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  line-height: var(--leading-tight);
  font-weight: var(--weight-bold);
  margin: 0 0 var(--space-4);
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }

p {
  margin: 0 0 var(--space-4);
  max-width: var(--measure);
}

a {
  color: var(--link);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

a:hover { color: var(--link-hover); }

/* Never removed, only replaced. A focus style that is merely `outline: none` is
   a keyboard user locked out of the page. */
:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--space-4);
}

.masthead {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding-block: var(--space-4);
}

/* The brand is the Sera wordmark (the sera_wordmark SVG, fill currentColor), so
   its colour is the link's and its size is the box height. */
.masthead__brand {
  display: block;
  height: 24px;
  color: var(--ink);
  text-decoration: none;
}

.masthead__brand svg { height: 100%; width: auto; display: block; }

.main { padding-block: var(--space-12); }

.card {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-8);
}

/* Console member record (SER-23): the operator notes. */
.note-list { list-style: none; margin: var(--space-6) 0 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.note { border: 1px solid var(--border); border-radius: var(--radius-md); padding: var(--space-4); background: var(--surface-sunken); }
.note__meta { font-size: var(--text-sm); margin-bottom: var(--space-2); }
/* Notes are entered in a multi-line textarea and stored with their breaks, so
   keep them on render (matches .event-detail__description). Escaping is
   unchanged — this is CSS, not an unescaped <br>. */
.note__body { margin: 0; white-space: pre-line; line-height: 1.6; }

.muted {
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

.definition-list {
  display: grid;
  grid-template-columns: minmax(8rem, max-content) 1fr;
  gap: var(--space-2) var(--space-6);
  margin: 0;
  font-size: var(--text-sm);
}

.definition-list dt {
  color: var(--ink-muted);
}

.definition-list dd {
  margin: 0;
  font-family: var(--font-mono);
}

.footer {
  padding-block: var(--space-8);
  color: var(--ink-muted);
  font-size: var(--text-xs);
}

/* Masthead + console navigation ------------------------------------------- */
.masthead__inner {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  flex-wrap: wrap;
}

.nav {
  display: flex;
  gap: var(--space-1);
  flex-wrap: wrap;
}

.nav__item {
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--ink-muted);
  text-decoration: none;
}

.nav__item:hover { color: var(--ink); background: var(--surface-sunken); }

.nav__item.is-active {
  color: var(--ink);
  background: var(--surface-sunken);
  font-weight: var(--weight-semibold);
}

.nav__item--soon {
  color: var(--ink-subtle);
  cursor: default;
}

.nav__item--soon:hover { background: none; color: var(--ink-subtle); }

/* Page head ---------------------------------------------------------------- */
.page-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-6);
}

.page-head h1 { margin: 0; }

/* Buttons ------------------------------------------------------------------ */
.button {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--accent-500);
  border-radius: var(--radius-sm);
  background: var(--accent-500);
  color: var(--ink-inverse);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
}

.button:hover { background: var(--accent-600); border-color: var(--accent-600); color: var(--ink-inverse); }

.button--primary { background: var(--highlight-500); border-color: var(--highlight-500); color: var(--black); }
.button--primary:hover { filter: brightness(0.95); background: var(--highlight-500); border-color: var(--highlight-500); color: var(--black); }

.button--ghost { background: transparent; color: var(--ink); border-color: var(--border-strong); }
.button--ghost:hover { background: var(--surface-sunken); color: var(--ink); border-color: var(--border-strong); }

.button--danger { background: transparent; color: var(--danger-500); border-color: var(--danger-500); }
.button--danger:hover { background: var(--danger-500); color: var(--ink-inverse); border-color: var(--danger-500); }

.button--small { padding: var(--space-1) var(--space-2); font-size: var(--text-xs); }

.icon-button {
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--ink-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  line-height: 1;
  padding: 0 var(--space-2);
}

.icon-button:hover { color: var(--danger-500); border-color: var(--danger-500); }

/* Filters ------------------------------------------------------------------ */
.filters { display: flex; gap: var(--space-2); flex-wrap: wrap; margin-bottom: var(--space-6); }

.filter {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  text-decoration: none;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-sm);
}

.filter:hover { color: var(--ink); }
.filter.is-active { color: var(--ink); background: var(--surface-sunken); font-weight: var(--weight-semibold); }

/* Tables ------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; }

.table {
  width: 100%;
  border-collapse: collapse;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  font-size: var(--text-sm);
}

.table th,
.table td {
  text-align: left;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}

.table th {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  background: var(--surface);
}

.table tbody tr:last-child td { border-bottom: none; }
.table__actions { text-align: right; white-space: nowrap; }

/* Badges ------------------------------------------------------------------- */
.badge {
  display: inline-block;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  line-height: 1.6;
  background: var(--surface-sunken);
  color: var(--ink-muted);
}

.badge--published,
.badge--active { background: var(--tint-success-bg); color: var(--grey-1); }
.badge--draft { background: var(--tint-info-bg); color: var(--deep-grape); }
.badge--disabled,
.badge--suspended { background: var(--tint-warning-bg); color: var(--grey-1); }
.badge--archived { background: var(--surface-sunken); color: var(--ink-subtle); }
/* Events list (SER-653): a row whose event is over. Amber, like the prototype's
   past-date pill, so it reads as a warning next to the status badge. */
.badge--date-passed { background: var(--tint-warning-bg); color: var(--grey-1); white-space: nowrap; }
/* The finance worksheet's thin-margin flag (CR-10): Sera keeps under the per-cover floor. */
.badge--thin-margin { background: var(--tint-warning-bg); color: var(--grey-1); white-space: nowrap; }
.badge--role { background: var(--tint-info-bg); color: var(--deep-grape); text-transform: none; letter-spacing: 0; }
/* Guest tags, cohort tags and release audiences (SER-282/329/472; styling SER-566):
   a segment/tag is a proper label ("Wine Lover"), not a status word, so it keeps
   its own casing like .badge--role. The grape info tint reads as a label rather
   than a green/amber state chip. */
.badge--segment { background: var(--tint-info-bg); color: var(--deep-grape); text-transform: none; letter-spacing: 0; }

/* Guest tags & cohort tags (SER-566 styling cleanup). The chip list on the member
   record and the manual/cohort create forms on the Tags page had no rules and fell
   back to raw inline flow; these give them the same quiet, aligned look as the rest
   of the console. */
.tag-chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
/* Each chip pairs its segment badge with an inline remove control (a one-button
   form); keep them on one baseline with a hairline gap. */
.tag-chip { display: inline-flex; align-items: center; gap: var(--space-1); }
.tag-chip .inline { display: inline-flex; }
.tag-chip__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.25rem;
  height: 1.25rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-subtle);
  font-size: var(--text-sm);
  line-height: 1;
  cursor: pointer;
}
.tag-chip__remove:hover { background: var(--surface-sunken); color: var(--ink); }
/* The add-a-tag pick-list (member record) and the manual create form (Tags page):
   a field plus its button on one line, wrapping on a narrow console. */
.tag-add,
.tag-create { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: var(--space-3) 0; }
.tag-create { max-width: 34rem; }
.tag-add select,
.tag-create input { flex: 1 1 12rem; min-width: 0; }
/* Admin-defined custom staff-profile fields on the member edit form: a stacked
   group, set off from the fixed prompts above it. */
.custom-fields { display: grid; gap: var(--space-3); margin-top: var(--space-4); }

/* Empty state -------------------------------------------------------------- */
.empty { text-align: center; }
.empty p { margin-inline: auto; }

/* Forms -------------------------------------------------------------------- */
.form {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-8);
  max-width: var(--page-lg);
}

.field { margin-bottom: var(--space-4); }

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

@media (max-width: 640px) {
  .field-row { grid-template-columns: 1fr; }
}

.field label {
  display: block;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  margin-bottom: var(--space-1);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
}

.field textarea { resize: vertical; }

.field-hint { font-size: var(--text-xs); color: var(--ink-muted); margin: var(--space-1) 0 0; }
.field-error { font-size: var(--text-xs); color: var(--danger-500); margin: var(--space-1) 0 0; font-weight: var(--weight-medium); }
/* A failed provider listing: styled like an error, but not .field-error, which the drawer's
   first-focus and the edit page's dirty check treat as a form 422. */
.ticketing__status--failed { color: var(--danger-500); font-weight: var(--weight-medium); }

/* Description editor: a formatting toolbar over the textarea and a live preview
   below it. The toolbar is aria-hidden until the script reveals it, so it never
   shows actions that only work with JS. */
.editor-toolbar {
  display: flex;
  flex-wrap: wrap; /* at phone width the buttons take a second row rather than pan the page (SER-765) */
  gap: var(--space-1);
  margin-bottom: var(--space-2);
}
.editor-toolbar[aria-hidden="true"] { display: none; }
.editor-toolbar__btn {
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink);
  font-size: var(--text-sm);
  line-height: 1.4;
  cursor: pointer;
}
.editor-toolbar__btn:hover { background: var(--surface-sunken); }
/* A legacy HTML description's convert prompt (SER-474). */
.editor-legacy {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
}
.editor-legacy__text { flex: 1 1 20rem; margin: 0; font-size: var(--text-sm); color: var(--grey-1); }
/* The description's formatting guide (docs/EVENT_COPY_STYLE.md in short). */
.field-hint > p { margin: 0; }
.editor-guide { margin-top: var(--space-1); }
.editor-guide summary { cursor: pointer; color: var(--link); }
.editor-guide ul { margin: var(--space-2) 0 0; padding-left: var(--space-6); }
.editor-guide li + li { margin-top: var(--space-1); }
.editor-guide code { font-size: inherit; color: var(--ink); }

.fieldset {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  margin-bottom: var(--space-4);
}

.fieldset legend { font-size: var(--text-sm); font-weight: var(--weight-semibold); padding-inline: var(--space-2); }

.form-actions { display: flex; gap: var(--space-3); align-items: center; margin-top: var(--space-6); }

/* The restaurant deal box (create forms, Schedule drawer): the restaurant's share
   shows only while "It splits with the restaurant" is ticked, with no script. */
.deal .deal__toggle { margin-bottom: var(--space-3); }
.deal:not(:has([data-deal-split-on]:checked)) .deal__split { display: none; }
/* An area editor's "Suggest price" and the split it priced. */
.suggest { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; margin-top: var(--space-2); }

/* UTM link builder (SER-295): the assembled URL sits beside its copy button, in
   a monospace field; the standard-link examples wrap rather than stretch their
   table cell. is-copied is the brief "Copied" acknowledgement on a copy button. */
.utm-output { display: flex; gap: var(--space-2); align-items: stretch; }
.utm-output input { flex: 1; font-family: var(--font-mono); }
.utm-output .button { white-space: nowrap; }
.utm-example { font-family: var(--font-mono); font-size: var(--text-xs); word-break: break-all; }
.button.is-copied { color: var(--accent-600); }

/* Alerts ------------------------------------------------------------------- */
.alert {
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  margin-bottom: var(--space-6);
}

.alert--error { background: var(--tint-warning-bg); color: var(--grey-1); border: 1px solid var(--danger-500); }

/* Publish + attach --------------------------------------------------------- */
.publish {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-6);
}

.attach { margin-top: var(--space-8); }
.attach__list { padding-left: var(--space-6); font-size: var(--text-sm); }
.attach__list li { margin-bottom: var(--space-1); }

/* Operator role controls --------------------------------------------------- */
.role-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-1); }
.role-list li { display: flex; align-items: center; gap: var(--space-2); }

.inline { display: inline-flex; gap: var(--space-2); align-items: center; margin: 0; }

/* Dashboard cards ---------------------------------------------------------- */
.dash-card { padding: var(--space-6); }

.dash-card__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-4);
}

.dash-card__head h2 { margin: 0; font-size: var(--text-xl); }
.dash-card__head a { font-size: var(--text-sm); }

.dash-card__subhead {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  margin: var(--space-4) 0 var(--space-2);
}

.stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  margin: 0;
}

.stat { margin: 0; }
.stat dt { font-size: var(--text-xs); color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.stat dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  line-height: 1.1;
}

.dash-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
}

.dash-list li { display: flex; flex-direction: column; }
.dash-list li .muted { font-size: var(--text-xs); }

.dash-empty { margin: 0; }
.dash-accrual { margin: 0 0 var(--space-4); }

/* Members ------------------------------------------------------------------ */
.members-tools {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
}

.members-tools .filters { margin-bottom: 0; }

/* Status filters sit directly on the list (SER-1059): one row of chips that
   scrolls sideways on a phone rather than wrapping into a block. */
.members-filters {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  margin-bottom: var(--space-3);
  -webkit-overflow-scrolling: touch;
}
.members-filters::-webkit-scrollbar { display: none; }
.members-filters .filter {
  flex: none;
  white-space: nowrap;
  text-transform: capitalize;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: var(--space-1) var(--space-3);
}
.members-filters .filter.is-active { border-color: var(--ink); }

.members-search-status { margin: 0 0 var(--space-3); font-size: var(--text-sm); color: var(--danger-500); }
.members-search-status:empty { display: none; }

/* Live search swaps the results region; dim it while a request is out. */
[data-members-results].is-loading { opacity: 0.55; transition: opacity 120ms ease-in; }

.members-about { margin-top: var(--space-6); font-size: var(--text-sm); }
.members-about summary { cursor: pointer; }

/* The phone-only one-line triage summary; the cards show on wider screens. */
.members-triage-line { display: none; }

@media (max-width: 640px) {
  .pulse.members-triage,
  .members-export { display: none; }
  .members-triage-line {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    margin: 0 0 var(--space-4);
    font-size: var(--text-sm);
  }
  .members-tools { display: block; }
  .search { width: 100%; }
  /* 16px stops iOS zooming the page when the box takes focus. */
  .members-tools .search input[type="search"] { min-width: 0; flex: 1; font-size: var(--text-base); padding: var(--space-2) var(--space-3); }

  /* Each member is a card: name and email, status, and the lifecycle actions
     (Verify, Invite, Suspend, Delete live only on this list) as a row beneath.
     Profile and joined stay on the record. */
  .members-table thead,
  .members-table .members-col-wide:not(.table__actions) { display: none; }
  .members-table,
  .members-table tbody { display: block; border: 0; background: none; }
  .members-table tr {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: var(--space-1) var(--space-3);
    align-items: start;
    position: relative;
    padding: var(--space-3) var(--space-4);
    margin-bottom: var(--space-2);
    background: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
  }
  .members-table td { display: block; padding: 0; border: 0; min-width: 0; overflow-wrap: anywhere; }
  .members-table .members-col-status { text-align: right; }
  /* The name link covers the whole card, so anywhere on it opens the record;
     the actions and the spam checkbox sit above that overlay. */
  /* No z-index on the cells above it: a z-index there would trap each row's
     confirm dialog (position: fixed) under the next row's buttons. Tree order
     alone paints the later, positioned cells over this overlay. */
  .members-table .members-col-member a.link::after { content: ""; position: absolute; inset: 0; z-index: 0; }
  .members-table td.table__actions {
    grid-column: 1 / -1;
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    white-space: normal;
    text-align: left;
  }
  /* View duplicates the card's own tap target; a viewer's row has nothing else. */
  .members-table td.table__actions > a.button { display: none; }
  .members-table td.table__actions:not(:has(form, button)) { display: none; }
  /* The likely-spam view adds a checkbox column: give it its own lane. */
  .members-table tr:has(.table__check) { grid-template-columns: auto 1fr auto; }
  /* The checkbox must sit above the card's link overlay; it holds no dialog, so
     unlike the actions cell a z-index here traps nothing. */
  .members-table td.table__check { position: relative; z-index: 1; grid-row: 1 / span 3; }
  .members-table tr:has(.table__check) td.table__actions { grid-column: 2 / -1; }
}

/* Likely-spam bulk delete (SER-289): a narrow checkbox column and a submit bar
   under the table. Only rendered on the likely-spam view. */
.table__check { width: 1px; white-space: nowrap; text-align: center; }
.bulk-bar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin: var(--space-4) 0;
}

.search { display: flex; gap: var(--space-2); align-items: center; margin: 0; }

.search input[type="search"] {
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
  min-width: 16rem;
}

.badge--applied,
.badge--waitlisted { background: var(--tint-info-bg); color: var(--deep-grape); }
.badge--deleted { background: var(--surface-sunken); color: var(--ink-subtle); }

.alert--notice { background: var(--tint-success-bg); color: var(--grey-1); }

.pagination {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-top: var(--space-4);
  font-size: var(--text-sm);
}

.pagination__links { display: flex; gap: var(--space-2); align-items: center; }

/* Accessibility ------------------------------------------------------------ */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Orders (SER-13) ---------------------------------------------------------- */
.badge--confirmed { background: var(--tint-success-bg); color: var(--grey-1); }
.badge--pending { background: var(--tint-info-bg); color: var(--deep-grape); }
.badge--cancelled { background: var(--surface-sunken); color: var(--ink-subtle); }
.badge--refunded { background: var(--tint-warning-bg); color: var(--grey-1); }

.orders-summary { padding: var(--space-6); margin-bottom: var(--space-6); }
.orders-summary .stat-row { margin-bottom: var(--space-4); }
.orders-note { margin: 0; font-size: var(--text-sm); }

.filter-form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-6);
  font-size: var(--text-sm);
}
.filter-form label { color: var(--ink-muted); }

.table__filter { font-size: var(--text-xs); margin-left: var(--space-2); white-space: nowrap; }
.table__ref { color: var(--ink-muted); font-family: var(--font-mono); font-size: var(--text-xs); white-space: nowrap; }
.orders-truncated { margin: var(--space-4) 0 0; }

/* Member web app (app.) --------------------------------------------------- */
/* The eatwithsera.com shell and pages, ported one for one (SER-49, SER-41).
   Measurements are the old Tailwind values: container 16px gutters, masthead
   56px (72px from lg), page column 552px (--page), headings text-4xl/6xl in
   the display face, pill buttons, 12px input radius. */

/* overflow-x: clip, not hidden, so the sticky .mh keeps working: an element a few px
   too wide would otherwise let the page pan sideways, and on iOS a sideways pan from
   the left edge reads as a back swipe. */
body.member {
  background: var(--surface);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  overflow-x: clip;
}

body.member .main { flex: 1; padding-block: 0; }
/* Widened to --page-xl (1378px) for the member surface only — matching the live
   site's real card-grid width at desktop breakpoints (tokens.css --container
   stays --page-lg for the console, which shares this same .container/base.html
   layout and must keep its narrower, text-friendly width). */
body.member .main > .container,
body.member .mh__inner,
body.member .mf__inner { padding-inline: var(--space-4); max-width: var(--page-xl); }

/* Masthead */
.mh {
  position: sticky;
  top: 0;
  z-index: 40;
}

.mh--guest,
.mh--member { background: var(--black); color: var(--paper); }
/* The global a:hover (--link-hover, near-black) and focus ring (deep grape) both
   vanish on the dark bar; the drawer is white and keeps the defaults. */
.mh__inner a:not(.mh__pill):hover { color: inherit; }
.mh__inner :focus-visible { outline-color: var(--off-white); }
.mh__drawer :focus-visible { outline-color: var(--accent-500); }

.mh__inner {
  display: flex;
  align-items: center;
  height: 56px;
}

.mh__brand {
  display: block;
  height: 24px;
  color: inherit;
  margin-right: auto;
}

.mh__brand svg { height: 100%; width: auto; display: block; }

.mh__links,
.mh__guest { display: none; }

.mh__burger {
  display: block;
  cursor: pointer;
  line-height: 0;
  color: inherit;
}

.mh__toggle { display: none; }

.mh__scrim {
  position: fixed;
  inset: 0;
  background: rgb(38 27 27 / 50%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 150ms var(--ease-out);
  cursor: pointer;
}

.mh__drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 66.666%;
  background: var(--white);
  color: var(--black);
  padding: var(--space-18) var(--space-6) var(--space-6);
  transform: translateX(100%);
  transition: transform 150ms var(--ease-out);
  overflow-y: auto;
}

.mh__close {
  position: fixed;
  top: 16px;
  right: 16px;
  color: var(--black);
  line-height: 0;
  opacity: 0;
  pointer-events: none;
  cursor: pointer;
  transition: opacity 150ms var(--ease-out);
}

.mh__toggle:checked ~ .mh__scrim { opacity: 1; pointer-events: auto; }
.mh__toggle:checked ~ .mh__drawer { transform: translateX(0); }
.mh__toggle:checked ~ .mh__close { opacity: 1; pointer-events: auto; }

.mh__drawer-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 36px;
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
}

.mh__drawer-links a,
.mh__signout {
  color: inherit;
  text-decoration: none;
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

.mh__drawer-sep { border-top: 1px solid var(--grey-1); padding-top: 36px; }

.mh__insta { display: inline-block; margin-top: 36px; color: var(--black); line-height: 0; }

/* [aria-current], not ="page" only: the merged "Bookings & Account" nav item is
   marked aria-current="true" (not "page") when the member is on /account, since
   the link itself points at /bookings — a different page, so "page" would be
   the wrong token there — but it must still show as the active nav item. */
.mh__links a[aria-current] { text-decoration: underline; text-underline-offset: 4px; }

/* Nav entries whose routes have not landed yet: the same words, no href. */
.mh__soon,
.mf__soon { color: inherit; cursor: default; }

@media (min-width: 1024px) {
  .mh__inner { height: 72px; }
  .mh__brand { height: 40px; }
  .mh__burger { display: none; }

  .mh__links {
    display: flex;
    gap: var(--space-8);
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    align-items: center;
  }

  .mh__links a { color: inherit; text-decoration: none; }

  .mh__guest { display: flex; align-items: center; gap: var(--space-8); }
  .mh__link { color: inherit; text-decoration: none; font-size: var(--text-base); font-weight: var(--weight-semibold); }

  .mh__pill {
    display: inline-block;
    color: inherit;
    text-decoration: none;
    font-weight: var(--weight-semibold);
    border: 1px solid currentColor;
    border-radius: 999px;
    padding: 14px 28px;
    line-height: 1.2;
  }

  .mh__pill:hover { background: var(--white); color: var(--black); }
}

@media (max-width: 1023.98px) {
  .mh__inner .mh__pill {
    display: inline-block;
    color: inherit;
    text-decoration: none;
    font-weight: var(--weight-semibold);
    font-size: var(--text-sm);
    border: 1px solid currentColor;
    border-radius: 999px;
    padding: 10px 20px;
    margin-right: var(--space-4);
    line-height: 1.2;
  }
  .mh__guest { display: flex; align-items: center; }
  .mh__guest .mh__link { display: none; }
}

/* Page column */
.member-page {
  width: 100%;
  max-width: var(--page);
  margin: var(--space-16) auto;
}

.member-page--center { text-align: center; }
.member-page--center p { margin-inline: auto; }

/* Left-aligned instead of centered: for a .member-page that sits below the
   shared Bookings/Account header (member_account.html), so the narrower form
   column's left edge lines up with the header and its tab row above, instead
   of floating centered under a full-width header. */
.member-page--flush { margin-left: 0; margin-right: 0; }

.member-wide { margin: var(--space-8) auto var(--space-22); }

.heading {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: var(--text-4xl);
  line-height: 48px;
  margin: 0 0 var(--space-8);
}

.heading--center { text-align: center; margin-bottom: 56px; }

.member-page__lead { margin: 0 0 var(--space-8); max-width: none; }

/* The events landing's "complete your profile" prompt (profile-prompt handoff):
   a dark card with a peach eyebrow, a display headline, an off-white pill CTA and
   an off-white ×. One stacked layout at every width. */
.profile-prompt {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0 0 var(--space-8);
  padding: 18px 18px 18px 20px;
  border-radius: 16px;
  background: var(--black);
  color: var(--off-white);
}
.profile-prompt__head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.profile-prompt__text { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.profile-prompt__eyebrow {
  margin: 0;
  font-size: 11px;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tint-peach);
}
.profile-prompt__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 24px;
  line-height: 1.05;
  letter-spacing: -0.015em;
}
/* The × keeps an 18px glyph but a 44×44 tap target, pulled into the corner so the
   glyph lines up with the card's padding. */
.profile-prompt__dismiss { flex: none; margin: -13px -13px 0 0; line-height: 0; }
.profile-prompt__x {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--off-white);
  cursor: pointer;
}
.profile-prompt__x:hover { background: rgb(248 245 242 / 0.12); }
.profile-prompt__open { display: flex; margin: 0; }
.profile-prompt__cta {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 18px;
  border: 0;
  border-radius: 999px;
  background: var(--off-white);
  color: var(--black);
  font: inherit;
  font-size: 14px;
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  cursor: pointer;
}
.profile-prompt__cta:hover { background: var(--white); }
.profile-prompt__x:focus-visible,
.profile-prompt__cta:focus-visible { outline: 2px solid var(--off-white); outline-offset: 2px; }

/* "Founding member · Since <month year>" pill under the Bookings/Account header's
   name heading. The brand guide's dark pill (SER-960 handoff): ink fill, a peach
   dot, then the two halves split by a muted middot. */
.member-page__founding {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 var(--space-6);
  padding: 7px 14px;
  border-radius: 999px;
  background: var(--black);
  color: var(--off-white);
  font-size: 11px;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.14em;
  line-height: 1.2;
  text-transform: uppercase;
}
.member-page__founding-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--deep-peach);
}
.member-page__founding-sep { opacity: 0.55; }
.member-page__founding-since { font-weight: var(--weight-medium); letter-spacing: 0.08em; }
.member-page__aside { text-align: center; font-size: var(--text-sm); color: var(--grey-2); margin: var(--space-4) 0 0; max-width: none; }
.member-page__resend { margin-top: var(--space-8); text-align: center; }
.member-page__resend .btn-outline { margin-top: var(--space-4); }

/* The Bookings/Profile/Dining Preferences/(Friends & Referrals)/Data & Security
   tab row under the shared header (member_bookings_account_header). Plain links
   with aria-current, like the top nav — no JS needed. flex-wrap because the row
   holds four or five items (grown from the original two), so it wraps rather
   than overflowing at phone widths. */
.member-subtabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  list-style: none;
  margin: 0 0 var(--space-8);
  padding: 0;
  font-size: var(--text-lg);
}
.member-subtabs a {
  display: inline-block;
  padding-bottom: var(--space-2);
  border-bottom: 2px solid transparent;
  color: var(--grey-2);
  font-weight: var(--weight-medium);
  text-decoration: none;
}
.member-subtabs a[aria-current="page"] {
  color: var(--ink);
  font-weight: var(--weight-semibold);
  border-bottom-color: var(--ink);
}

/* The account Preferences tab (SER-960). Built to the brand-guide handoff's
   measurements: a 640px intro, then a 900px form whose fields sit 28px apart.
   Seating is checkboxes drawn as cards and the interests are checkboxes drawn
   as pills; the inputs are visually hidden, never removed, so keyboard and
   screen-reader use is the native control's. */
.acct-tab { display: flex; flex-direction: column; gap: 40px; }
.acct-tab__intro { display: flex; flex-direction: column; gap: 10px; max-width: 640px; }
.acct-tab__eyebrow {
  margin: 0;
  font-size: 12px;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--eyebrow);
}
.acct-tab__heading {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 44px;
  line-height: 1;
  letter-spacing: -0.018em;
}
.acct-tab__lead { margin: 0; font-size: 16px; line-height: 1.5; }

.acct-form { display: flex; flex-direction: column; gap: 28px; max-width: 900px; }
.acct-field { display: flex; flex-direction: column; gap: 8px; min-width: 0; margin: 0; padding: 0; border: 0; }
fieldset.acct-field { gap: 12px; }
.acct-label { padding: 0; font-size: 14px; font-weight: var(--weight-semibold); color: var(--ink); }
.acct-help { margin: 0; font-size: 13px; color: var(--fg-muted); }

.acct-input {
  box-sizing: border-box;
  width: 100%;
  height: 48px;
  padding: 0 16px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
}
.acct-input::placeholder { color: var(--fg-subtle); }
.acct-input:focus { outline: none; border-color: var(--ink); }
.acct-input:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
/* A fixed prefix ("@", "linkedin.com/in/") inside the box, before the input. */
.acct-input--prefixed { display: flex; align-items: center; gap: 2px; }
.acct-input--prefixed:focus-within { border-color: var(--ink); }
.acct-input__prefix { flex: none; color: var(--fg-subtle); white-space: nowrap; }
.acct-input--prefixed input {
  flex: 1;
  min-width: 0;
  height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
}
.acct-input--prefixed input:focus { outline: none; }
.acct-input--prefixed:has(input:focus-visible) { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.prefs-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.prefs-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 16px;
  border-radius: 12px;
  background: var(--white);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  cursor: pointer;
}
.prefs-card__title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 20px;
  line-height: 1.1;
  letter-spacing: -0.015em;
}
.prefs-card:hover { box-shadow: inset 0 0 0 1px var(--ink); }
.prefs-card:has(input:checked) { background: var(--black); color: var(--off-white); box-shadow: none; }
.prefs-card:has(input:focus-visible) { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.prefs-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.prefs-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  padding: 9px 14px;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--ink);
  font-size: 13px;
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  cursor: pointer;
}
.prefs-chip:hover { box-shadow: inset 0 0 0 1px var(--ink); }
.prefs-chip:has(input:checked) { background: var(--black); color: var(--off-white); box-shadow: none; }
.prefs-chip:has(input:focus-visible) { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* The real radio/checkbox, kept in the accessibility tree and focus order. */
.prefs-card input,
.prefs-chip input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.acct-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.acct-row--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.acct-input--area { height: auto; min-height: 112px; padding: 12px 16px; line-height: 1.5; resize: vertical; }

/* A section after the first on a tab (Profile's Marketing emails): a hairline and generous space, so each reads as its own
   short chapter under the same eyebrow/heading treatment. */
.acct-tab--next { margin-top: 64px; padding-top: 48px; border-top: 1px solid var(--line); }
h2.acct-tab__eyebrow { line-height: 1.4; }

/* A one-field form with its button on the same line (Friends & Referrals'
   referred-by and add-friend), the button aligned to the input, not the label. */
.acct-inline { display: flex; align-items: flex-end; gap: 12px; margin: 0; }
.acct-inline .acct-field { flex: 1; }
.acct-button {
  flex: none;
  height: 48px;
  padding: 0 22px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--line-strong);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.acct-button:hover { box-shadow: inset 0 0 0 1px var(--ink); }
.acct-button:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

/* A link styled as the dark pill (Bookings' "Browse events"). */
a.acct-save { display: inline-block; text-decoration: none; }
a.acct-button { display: inline-flex; align-items: center; text-decoration: none; }
.acct-button--small { height: 36px; padding: 0 16px; font-size: 13px; }
.acct-input--small { height: 36px; padding: 0 12px; font-size: 13px; width: 12rem; }
/* iOS Safari zooms the page into any field under 16px when it takes focus, and
   leaves it zoomed. The desktop sizes above stay; on touch screens every member
   field is at least 16px. */
@media (pointer: coarse) {
  .acct-input, .acct-input--small { font-size: 16px; }
}
.acct-inline--tight { gap: 8px; align-items: center; }

/* A titled group within a tab (Bookings' Coming up and Past): the label is the
   brand guide's field label, a step down from the display heading above it. */
.acct-group { display: flex; flex-direction: column; gap: 16px; }
.acct-subhead { margin: 0; font-size: 14px; font-weight: var(--weight-semibold); color: var(--ink); }

/* Orders, exports, sign-in methods and passkeys as hairline rows on white, the
   brand guide's input surface, so a list sits in the same family as the fields. */
.acct-list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
  border-radius: 12px;
  background: var(--white);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}
.acct-list__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  border-top: 1px solid var(--line);
}
.acct-list__item:first-child { border-top: 0; }
.acct-list__item--wrap { flex-wrap: wrap; }
.acct-list__item form { margin: 0; }
.acct-list__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.acct-list__title {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 20px;
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--ink);
  text-decoration: none;
}
.acct-list__title:hover { text-decoration: underline; text-underline-offset: 3px; }
.acct-list__meta { font-size: 13px; color: var(--fg-muted); }
.acct-list__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* Friends as pills with a remove control, the brand guide's chip shape. */
.acct-pills { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.acct-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 6px 6px 14px;
  border-radius: 999px;
  background: var(--black);
  color: var(--off-white);
  font-size: 13px;
  font-weight: var(--weight-semibold);
}
.acct-pill form { margin: 0; display: inline-flex; }
.acct-pill__remove {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgb(248 245 242 / 16%);
  color: inherit;
  font: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.acct-pill__remove:hover { background: rgb(248 245 242 / 32%); }
.acct-pill__remove:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.acct-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 12px; }
.acct-save {
  padding: 14px 22px;
  border: 0;
  border-radius: 999px;
  background: var(--black);
  color: var(--off-white);
  font: inherit;
  font-size: 15px;
  font-weight: var(--weight-semibold);
  line-height: 1.2;
  cursor: pointer;
}
.acct-save:hover { background: var(--grey-1); }
.acct-save:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

@media (max-width: 40rem) {
  .acct-tab__heading { font-size: 36px; }
  .prefs-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .acct-row { grid-template-columns: 1fr; }
  .acct-inline { flex-direction: column; align-items: stretch; }
}

/* Member data-export list (SER-56): each request's date, status and download. */
.export-list { list-style: none; margin: var(--space-4) 0 0; padding: 0; display: flex; flex-direction: column; }
.export { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-4); padding: var(--space-3) 0; border-top: 1px solid var(--border); }
.export__meta { color: var(--ink-muted); font-size: var(--text-sm); }

.link { color: var(--black); text-decoration: underline; }
.link--bold { font-weight: var(--weight-semibold); }

@media (min-width: 1024px) {
  .member-page { margin-block: var(--space-22); }
  .heading { font-size: var(--text-6xl); line-height: 67.2px; }
}

/* Fields (the old x-forms.input) */
.mfield { margin-bottom: var(--space-6); }

.mfield__label {
  display: block;
  font-weight: var(--weight-semibold);
  margin-bottom: var(--space-2);
}

.mfield__input {
  display: block;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--grey-4);
  border-radius: var(--radius-lg);
  background: var(--white);
  color: var(--black);
  font: inherit;
  line-height: 1.5;
}

.mfield__input::placeholder { color: var(--grey-3); }
.mfield__input:focus { outline: none; border-color: var(--black); }
.mfield__input:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.mfield__input--code {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  letter-spacing: 0.3em;
  text-align: center;
  padding-block: var(--space-2);
}

.mfield__error { margin: var(--space-2) 0 0; font-size: var(--text-sm); color: var(--danger-500); }

/* Buttons (btn-filled, btn-outline) */
.btn-filled,
.btn-outline {
  display: block;
  width: 100%;
  padding: 14px 20px;
  border-radius: 999px;
  font: inherit;
  font-weight: var(--weight-semibold);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  line-height: 1.25;
  margin-bottom: var(--space-4);
}

.btn-filled { background: var(--black); color: var(--white); border: 1px solid var(--black); }
.btn-filled:hover { background: var(--paper); color: var(--black); }

.btn-outline { background: transparent; color: var(--black); border: 1px solid var(--black); }
.btn-outline:hover { background: var(--black); color: var(--white); }

@media (min-width: 1024px) {
  .member-page__resend .btn-outline { display: inline-block; width: auto; }
}

/* Event cards (a first pass; SER-51 completes the page) */
.event-cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 1024px) {
  .event-cards { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
}

/* The member event/booking card chrome, matched to the live site's card component
   (eatwithsera.com: rounded-2xl = 1rem, a subtle paper border at rest, a white
   surface, and the shadow only on hover — not at rest). It sits on the
   .event-card__link wrapper: an <a> on the events list, linking to the event, and
   a .card-stretch <div> on every bookings card, whose stretched title link opens
   its booking page at /bookings/{id}. Before this, the
   list card carried a resting shadow with no border, so once real cover images
   landed the bookings cards read as square-cornered and cramped. */
.event-card__link {
	display: block;
	background: var(--white);
	border: 1px solid var(--paper);
	border-radius: var(--radius-2xl);
	overflow: hidden;
	transition: border-color 150ms ease, box-shadow 150ms ease;
}
.event-card__link { color: inherit; text-decoration: none; }
/* sera-site's bg-paper card: sold out or coming soon, nothing to act on yet. */
.event-card__link--muted { background: var(--paper); }
/* The events-list cover tag (Sold out, Coming soon, Waitlist open), sera-site's
   EventTag: a white pill on the cover's bottom-right edge, overhanging it by 6px, so
   it sits on .event-card__cover rather than inside the clipped .event-card__image. */
.event-card__cover { position: relative; }
.event-card__tag {
  position: absolute; z-index: 1; right: var(--space-4); bottom: -6px;
  display: flex; align-items: center; gap: var(--space-1);
  height: 32px; padding: var(--space-1) var(--space-2);
  background: var(--white); border-radius: var(--radius-md); box-shadow: var(--shadow-tag); /* rounded-lg, shadow-md */
  font-size: var(--text-xs); color: var(--ink); white-space: nowrap;
}
.event-card__tag svg { flex: none; }
.event-card__link:hover { border-color: var(--grey-4); box-shadow: var(--shadow-card); }
/* A Coming soon card is not a link (sera-site #65), so it takes no hover. */
.event-card__link--static:hover { border-color: var(--paper); box-shadow: none; }
.event-card__image { height: 160px; background: var(--paper); overflow: hidden; } /* h-40 on the live site */
/* The cover photograph fills the card's image box; the focal point (SER-52) is set
   inline as object-position, so a portrait crop keeps the subject in frame. The
   <picture> wrapper (present when the variant ladder is ready) must fill the box
   too, or the img's height:100% resolves against an auto-height inline element. */
.event-card__image picture { display: block; width: 100%; height: 100%; }
.event-card__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.event-card__body { padding: var(--space-4); }
/* Clamped to 2 lines and reserved at that height (min-height, keyed to its own
   font-size via em rather than a hardcoded rem, so it tracks --text-lg if that
   ever changes) so a 1-line title takes the same vertical space a 2-line one
   does — otherwise cards in the same grid end up visibly different heights. */
.event-card__title {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-tight);
  margin: 0 0 var(--space-1);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(2 * var(--leading-tight) * 1em);
}
/* One icon + one line of text per fact (date, venue city), flowed two-per-row
   into an auto/1fr grid — the calendar/pin svg and its <span> are siblings, not
   wrapped in a further element, matching the old site's card meta grid.
   min-height reserves two rows' worth of height regardless of how many actually
   render, so a card with no location (the second icon+text pair simply absent)
   is not shorter than one that has it. */
.event-card__meta {
  margin: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  /* Without this, a lone date row (no location) stretches to fill the whole
     reserved min-height and then centers within it — sitting visibly lower
     than the date row on a same-row card that has both facts. Rows should
     stack from the top and leave any reserved slack at the bottom instead. */
  align-content: start;
  gap: var(--space-1) var(--space-2);
  font-size: var(--text-sm);
  color: var(--grey-2);
  min-height: calc(2 * var(--leading-normal) * 1em + var(--space-1));
}
.meta-icon { justify-self: center; }
/* The bookings card's ticket count: no icon (icon parity was date + location
   only), so it sits as its own plain line below the meta grid. */
.event-card__meta-plain { margin: var(--space-2) 0 0; font-size: var(--text-sm); color: var(--grey-2); }
/* The bookings card's status chip on the cover (SER-815) — none for the common
   confirmed case, set for anything a member needs to notice (Confirming,
   Refunded, Cancelled, "1 of 4 refunded"). */
.event-card__image { position: relative; }
.event-card__chip {
  position: absolute; top: var(--space-3); left: var(--space-3);
  padding: var(--space-1) var(--space-3); border-radius: 999px;
  background: var(--white); box-shadow: var(--shadow-badge);
  font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--ink);
}

/* Bookings (SER-815): the soonest booking large, the rest as cards, past bookings
   as compact rows so they stop competing with what's ahead. */
.booking-next { margin-bottom: var(--space-6); overflow: hidden; }
.booking-next__image { height: 200px; }
.booking-next__body { display: grid; gap: var(--space-1); }
.booking-next__eyebrow { font-size: 12px; font-weight: var(--weight-semibold); letter-spacing: 0.14em; text-transform: uppercase; color: var(--eyebrow); }
.booking-next__title { font-family: var(--font-display); font-size: var(--text-2xl); line-height: var(--leading-tight); margin: 0; }
@media (min-width: 768px) {
  .booking-next { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
  .booking-next__image { height: auto; min-height: 260px; }
  .booking-next__body { align-content: center; padding: var(--space-8); gap: var(--space-2); }
  .booking-next__title { font-size: var(--text-4xl); }
}
.booking-rows { list-style: none; margin: 0; padding: 0; display: grid; background: var(--white); border: 1px solid var(--paper); border-radius: var(--radius-2xl); overflow: hidden; }
.booking-rows > li + li { border-top: 1px solid var(--paper); }
.booking-row { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; gap: var(--space-3); align-items: center; padding: var(--space-3) var(--space-4); color: inherit; text-decoration: none; }
.booking-row:hover { background: var(--off-white); }
.booking-row__thumb { display: block; width: 56px; height: 56px; border-radius: var(--radius-md); overflow: hidden; background: var(--paper); filter: grayscale(.85) contrast(.9); }
/* The <picture> wrapper must fill the box too, as on the cards (.event-card__image picture). */
.booking-row__thumb picture,
.booking-row__thumb img { width: 100%; height: 100%; display: block; }
.booking-row__thumb img { object-fit: cover; }
.booking-row__body { display: grid; gap: 2px; min-width: 0; }
.booking-row__title { font-weight: var(--weight-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.booking-row__meta { font-size: var(--text-sm); color: var(--grey-2); }
.booking-row__stamp { font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--grey-2); }
.booking-row__stamp--warn { color: var(--warning-ink); }
@media (min-width: 1024px) {
  .booking-rows { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .booking-rows > li + li { border-top: 0; }
  .booking-rows > li:nth-child(n+3) { border-top: 1px solid var(--paper); }
}
/* The events-list card's action, matched to the live site's card button (a
   bordered, rounded-lg, full-width control that inverts to solid black on
   hover) rather than plain underlined text — the
   whole card is still the one <a>, so the invert triggers off the card's own
   :hover rather than the span having its own. */
.event-card__book-btn {
  display: block;
  margin-top: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--grey-4);
  border-radius: var(--radius-md);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-align: center;
  transition: border-color 150ms ease, background 150ms ease, color 150ms ease;
}
.event-card__link:hover .event-card__book-btn {
  border-color: var(--black);
  background: var(--black);
  color: var(--white);
}

/* Events list sections (SER-51) */
.events-section { font-family: var(--font-body); font-size: var(--text-2xl); font-weight: var(--weight-semibold); margin: var(--space-12) 0 var(--space-6); }
.events-section:first-of-type { margin-top: 0; }
.events-empty { margin: 0 0 var(--space-8); color: var(--grey-2); }

/* Members landing navigation cards (SER-57) */
.nav-cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 1024px) {
  /* auto-fit, so the row is filled by however many cards there are — the landing
     renders two (Events, Community) and must not leave an empty third cell. */
  .nav-cards { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: var(--space-6); }
}

.nav-card__link { display: block; color: inherit; text-decoration: none; background: var(--white); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-card); }
.nav-card__image { height: 180px; background: var(--paper); }
.nav-card__body { padding: var(--space-4); }
.nav-card__title { font-family: var(--font-body); font-size: var(--text-lg); font-weight: var(--weight-semibold); margin: 0 0 var(--space-1); }
.nav-card__desc { margin: 0; font-size: var(--text-sm); color: var(--grey-2); }

/* Community WhatsApp group cards (SER-57). Static, hard-coded; the card image
   is a static marketing photo with AVIF/WebP siblings, not the media-row
   pipeline (ADR-0014 applies to the markup, not the storage). */
.wa-cards {
  list-style: none;
  margin: 0 0 var(--space-8);
  padding: 0;
  display: grid;
  gap: var(--space-4);
}

@media (min-width: 1024px) {
  .wa-cards { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
}

.wa-card { display: flex; flex-direction: column; background: var(--white); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-card); }
.wa-card__image { height: 180px; background: var(--paper); overflow: hidden; }
.wa-card__image picture { display: block; width: 100%; height: 100%; }
.wa-card__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.wa-card__body { display: flex; flex-direction: column; flex-grow: 1; padding: var(--space-4); }
.wa-card__title { font-family: var(--font-body); font-size: var(--text-lg); font-weight: var(--weight-semibold); margin: 0 0 var(--space-1); }
.wa-card__desc { margin: 0 0 var(--space-4); font-size: var(--text-sm); color: var(--grey-2); }
.wa-card__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-1);
  margin-top: auto;
  padding: 10px 14px;
  border: 1px solid var(--grey-4);
  border-radius: var(--radius-lg);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--black);
  text-decoration: none;
}
.wa-card__cta:hover { background: var(--black); border-color: var(--black); color: var(--white); }

/* Event detail (SER-52). */
.event-detail__hero { position: relative; height: 220px; background: var(--paper); border-radius: var(--radius-lg); margin-bottom: var(--space-8); overflow: hidden; }
.event-detail__hero picture { display: block; width: 100%; height: 100%; }
.event-detail__hero-img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Hero carousel (SER-52 parity with sera-site's image_1_path..image_10_path
   carousel): every slide stays in the DOM and the track scroll-snaps, so a
   member with no JS still sees and can swipe/scroll between every banner —
   the nonced script below only adds the button/dot controls on top. */
.event-detail__hero-track {
  display: flex;
  width: 100%;
  height: 100%;
  overflow-x: auto;
  overscroll-behavior-x: contain; /* a swipe past the first photo stays in the track, not page scroll or history nav */
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.event-detail__hero-track::-webkit-scrollbar { display: none; }
.event-detail__hero-slide { flex: 0 0 100%; height: 100%; scroll-snap-align: start; }
.event-detail__hero-slide picture,
.event-detail__hero-slide .event-detail__hero-img { display: block; width: 100%; height: 100%; }
.event-detail__hero-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--white);
  background: rgba(255, 255, 255, 0.15);
  cursor: pointer;
}
.event-detail__hero-nav:hover { background: rgba(255, 255, 255, 0.3); }
.event-detail__hero-nav--prev { left: var(--space-4); }
.event-detail__hero-nav--next { right: var(--space-4); }
.event-detail__hero-dots {
  position: absolute;
  z-index: 2;
  bottom: var(--space-3);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
.event-detail__hero-dot { width: 8px; height: 8px; padding: 0; border: 0; border-radius: 999px; background: rgba(255, 255, 255, 0.5); cursor: pointer; }
.event-detail__hero-dot[aria-current="true"] { background: var(--white); }
.event-detail__body { display: flex; flex-direction: column; gap: var(--space-6); }
.event-meta { list-style: none; margin: 0 0 var(--space-6); padding: 0; display: grid; gap: var(--space-3); }
.event-meta__item { margin: 0; display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-base); color: var(--grey-1); }
/* Ink like the old site's glyphs, while the text beside them stays grey-1. */
.event-meta__icon { flex: none; width: 20px; height: 20px; color: var(--ink); }
.event-detail__rule { border: 0; border-top: 1px solid var(--grey-4); margin: var(--space-8) 0; }

.event-detail__early-access { margin: var(--space-2) 0 0; font-size: 0.875rem; color: var(--ink-muted); }
/* No white-space: pre-line here. The description is rendered through
   descriptionHTML, which already emits the line breaks as <br /> (nl2br for a
   legacy HTML description; hard wraps for a Markdown one), the way the public site
   does; pre-line would ALSO honour a preserved newline and double every break.
   Normal white-space collapses that newline, matching sera-site. */
/* Clipped: a legacy description carries its author's inline styles (SER-873), and
   nothing in one may paint outside the description's own box. */
.event-detail__description { color: var(--grey-1); line-height: 1.6; overflow: hidden; overflow: clip; }
/* The branded Markdown render (SER-474). A Markdown description is a small,
   allowlisted set of elements with no inline styling (internal/eventdesc), so
   every event's copy takes its look from here: body type for prose, the display
   face for headings (shifted down a level, since the title is the <h1>), brand
   links and rules. The same wrapper class is on the console's live preview, so
   the operator sees exactly this. Scoped to the --markdown modifier, which the
   member page and the preview set only for a Markdown description, so a legacy
   HTML description keeps exactly the styling it had. */
.event-detail__description--markdown > :first-child { margin-top: 0; }
.event-detail__description--markdown > :last-child { margin-bottom: 0; }
.event-detail__description--markdown p,
.event-detail__description--markdown ul,
.event-detail__description--markdown ol,
.event-detail__description--markdown blockquote { margin: 0 0 var(--space-4); }
.event-detail__description--markdown h2,
.event-detail__description--markdown h3,
.event-detail__description--markdown h4,
.event-detail__description--markdown h5,
.event-detail__description--markdown h6 {
  margin: var(--space-6) 0 var(--space-2);
  color: var(--ink);
  font-family: var(--font-display);
  line-height: var(--leading-tight);
}
.event-detail__description--markdown h2 { font-size: var(--text-2xl); }
.event-detail__description--markdown h3 { font-size: var(--text-xl); }
.event-detail__description--markdown h4,
.event-detail__description--markdown h5,
.event-detail__description--markdown h6 { font-size: var(--text-lg); }
.event-detail__description--markdown ul,
.event-detail__description--markdown ol { padding-left: var(--space-6); }
.event-detail__description--markdown li + li { margin-top: var(--space-1); }
.event-detail__description--markdown strong { color: var(--ink); font-weight: var(--weight-semibold); }
.event-detail__description--markdown a { color: var(--link); text-decoration: underline; text-underline-offset: 0.15em; }
.event-detail__description--markdown a:hover { color: var(--link-hover); }
.event-detail__description--markdown blockquote {
  padding-left: var(--space-4);
  border-left: 3px solid var(--highlight-500);
  color: var(--grey-2);
  font-style: italic;
}
.event-detail__description--markdown hr { border: 0; border-top: 1px solid var(--grey-4); margin: var(--space-6) 0; }
.event-detail__description--markdown img { max-width: 100%; height: auto; border-radius: var(--radius-md); }
.event-detail__panel { display: flex; flex-direction: column; gap: var(--space-3); }

/* Waitlist card (SER-1071): eyebrow, heading and line, then the Seats stepper and the
   Join pill, in the order a member reads them. Every not-bookable state renders it
   (the eyebrow says which), with or without the join form, and the joined (Leave) state. */
.event-waitlist {
  display: flex; flex-direction: column; gap: 18px;
  padding: 22px 20px;
  background: var(--white); border: 1px solid var(--line); border-radius: 16px;
}
.event-waitlist__head { display: flex; flex-direction: column; gap: 6px; }
.event-waitlist__eyebrow {
  margin: 0; font-size: 11px; font-weight: var(--weight-semibold);
  letter-spacing: .14em; text-transform: uppercase; color: var(--deep-peach);
}
.event-waitlist__title {
  margin: 0; font-family: var(--font-display); font-weight: var(--weight-bold, 700);
  font-size: 28px; line-height: 1.05; letter-spacing: -.015em; color: var(--black);
}
.event-waitlist__line { margin: 0; font-size: 14px; line-height: 1.5; color: var(--fg-muted); }
.event-waitlist__form { display: flex; flex-direction: column; gap: 18px; margin: 0; }
.event-waitlist__form .mfield__error { margin: 0; }
.event-waitlist__seats {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
.event-waitlist__label { font-size: 15px; font-weight: var(--weight-semibold); }
.event-waitlist__stepper { display: flex; align-items: center; gap: 14px; }
.event-waitlist__step {
  width: 40px; height: 40px; padding: 0; border: 0; border-radius: 999px;
  display: grid; place-items: center;
  background: none; color: var(--black); box-shadow: inset 0 0 0 1px var(--line-strong);
  cursor: pointer; transition: box-shadow .12s, opacity .12s;
}
.event-waitlist__step[hidden] { display: none; }
.event-waitlist__step:hover:not([aria-disabled="true"]) { box-shadow: inset 0 0 0 1px var(--black); }
.event-waitlist__step[aria-disabled="true"] { opacity: .35; cursor: not-allowed; }
/* The number reads as plain text between the buttons; with no JS (buttons hidden) it is
   still a working field. */
.event-waitlist__num {
  width: 2.5em; padding: 4px 0; border: 0; background: none; text-align: center;
  font: inherit; font-size: 17px; font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums; color: var(--black);
  -moz-appearance: textfield; appearance: textfield;
}
.event-waitlist__num::-webkit-outer-spin-button,
.event-waitlist__num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.event-waitlist__join,
.event-waitlist__leave {
  display: block; width: 100%; padding: 15px 22px; border-radius: 999px;
  font: inherit; font-size: 15px; font-weight: var(--weight-semibold); line-height: 1.25;
  text-align: center; cursor: pointer;
}
.event-waitlist__join { background: var(--black); color: var(--off-white); border: 1px solid var(--black); }
.event-waitlist__join:hover { background: var(--off-white); color: var(--black); }
.event-waitlist__leave { background: none; color: var(--black); border: 0; box-shadow: inset 0 0 0 1px var(--line-strong); }
.event-waitlist__leave:hover { box-shadow: inset 0 0 0 1px var(--black); }
.event-waitlist form { margin: 0; }

/* Gallery and Menu (SER-1071): two outline pills side by side, one alone spans the row.
   24px under the waitlist card (the panel's gap plus this margin). */
.event-detail__extras { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.event-waitlist + .event-detail__extras { margin-top: var(--space-3); }
.event-detail__extra {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 14px; border: 0; border-radius: 999px;
  background: none; color: var(--black); box-shadow: inset 0 0 0 1px var(--line-strong);
  font: inherit; font-size: 14px; font-weight: var(--weight-semibold); line-height: 1.25;
  text-decoration: none; cursor: pointer;
}
.event-detail__extra:only-child { grid-column: 1 / -1; }
.event-detail__extra:hover { box-shadow: inset 0 0 0 1px var(--black); color: var(--black); }
.event-detail__extra svg { flex: 0 0 auto; }

/* Book action near the top of the page, and the persistent mobile Book bar (SER-553).
   Both are mobile-only (hidden in the desktop breakpoint below, where the panel CTA is
   already beside the content) and render the same member_book_link. */
.event-detail__book-top { margin: 0 0 var(--space-6); }
.event-detail__book-top .btn-filled { margin: 0; }

/* Fixed to the viewport bottom, not sticky: the checkout .sp-bar can be sticky
   because it lives inside a bounded .spx-scroll (100dvh flex shell, overflow-y:auto),
   but this bar is a last child in the normal document flow, where a sticky bottom has
   no travel range and would only appear at the page end. Fixed keeps it pinned through
   the whole scroll; .event-detail--booking reserves matching space so it never covers
   the panel or footer. Mobile-only (hidden in the desktop breakpoint below). */
.event-book-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  background: color-mix(in oklab, var(--surface-raised) 92%, transparent);
  backdrop-filter: blur(8px);
  border-top: 1px solid var(--border);
  transition: transform .2s ease, opacity .2s ease, visibility 0s linear 0s;
}
.event-book-bar .btn-filled { margin: 0; }
/* Scroll-revealed (SER-1133, js/event-book-bar.js). With scripting on, the bar starts
   concealed here in CSS, so a cold load never paints it before the script arrives; the
   script adds --revealed once the top Book has scrolled away. With no JS the query does
   not match and the bar always shows. Concealed is slid below the viewport, then
   visibility:hidden once the slide ends, so the off-screen button leaves the tab order. */
@media (scripting: enabled) {
  .event-book-bar:not(.event-book-bar--revealed) {
    transform: translateY(100%); opacity: 0; visibility: hidden; pointer-events: none;
    transition: transform .2s ease, opacity .2s ease, visibility 0s linear .2s;
  }
}
@media (prefers-reduced-motion: reduce) {
  .event-book-bar, .event-book-bar:not(.event-book-bar--revealed) { transition: none; }
}
/* Room at the foot of the whole page (below the footer, which sits outside .main) so
   the fixed bar overlays empty space, not the panel or the footer. On body so it
   reserves space after every sibling; only an event on sale to the member carries has-book-bar. */
body.member.has-book-bar { padding-bottom: calc(5rem + env(safe-area-inset-bottom, 0px)); }

/* TL;DR summary and its Read more toggle (SER-553). */
.event-detail__summary { color: var(--grey-1); line-height: 1.6; font-size: var(--text-lg); margin: 0 0 var(--space-4); }
.event-detail__read-more {
  display: inline-block; padding: 0; background: none; border: 0; font: inherit;
  font-weight: var(--weight-semibold); color: var(--link);
  text-decoration: underline; text-underline-offset: 0.15em; cursor: pointer;
}
.event-detail__read-more:hover { color: var(--link-hover); }

@media (min-width: 1024px) {
  .event-detail__hero { height: 400px; }
  .event-detail__body { flex-direction: row; align-items: flex-start; gap: var(--space-8); }
  .event-detail__main { flex: 3 1 0; padding-right: var(--space-6); }
  .event-meta__icon { width: 24px; height: 24px; }
  .event-detail__panel { flex: 2 1 0; background: var(--white); border-radius: var(--radius-lg); padding: var(--space-8) var(--space-4); }
  /* The top button and fixed bar exist to reach a CTA that is far below the fold on a
     stacked mobile layout; on desktop the panel CTA is already in the side column, so
     drop them and the reserved space. */
  .event-detail__book-top, .event-book-bar { display: none; }
  body.member.has-book-bar { padding-bottom: 0; }
}

/* Event gallery lightbox (SER-52). Hidden until the nonced script opens it; a
   member with no JS keeps the hero and the rest of the page. */
body.gallery-open { overflow: hidden; }
.event-gallery {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  padding: var(--space-6);
  background: rgba(0, 0, 0, 0.92);
}
.event-gallery__backdrop { position: absolute; inset: 0; border: 0; padding: 0; background: transparent; cursor: default; }
.event-gallery__close {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--white);
  background: rgba(255, 255, 255, 0.15);
  cursor: pointer;
}
.event-gallery__close:hover { background: rgba(255, 255, 255, 0.3); }
.event-gallery__stage { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; max-width: min(1100px, 100%); }
.event-gallery__slide { margin: 0; }
.event-gallery__full-img { display: block; max-width: 100%; max-height: 70vh; object-fit: contain; border-radius: var(--radius-lg); }
.event-gallery__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  font-size: var(--text-2xl);
  line-height: 1;
  color: var(--white);
  background: rgba(255, 255, 255, 0.15);
  cursor: pointer;
}
.event-gallery__nav:hover { background: rgba(255, 255, 255, 0.3); }
.event-gallery__nav--prev { left: var(--space-4); }
.event-gallery__nav--next { right: var(--space-4); }
.event-gallery__thumbs {
  position: relative;
  z-index: 1;
  display: flex;
  gap: var(--space-2);
  max-width: 100%;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
}
.event-gallery__thumb { padding: 0; border: 2px solid transparent; border-radius: var(--radius-sm); background: none; cursor: pointer; line-height: 0; }
.event-gallery__thumb[aria-current="true"] { border-color: var(--white); }
.event-gallery__thumb-img { display: block; width: 64px; height: 64px; object-fit: cover; border-radius: var(--radius-sm); }

/* Footer */
.mf {
  background: var(--black);
  color: var(--paper);
  border-radius: var(--space-6) var(--space-6) 0 0;
}

.mf__inner {
  display: grid;
  gap: var(--space-12);
  padding-block: var(--space-16);
}

.mf__brand-col { order: 2; }
.mf__brand { display: inline-block; height: 40px; color: var(--off-white); margin-bottom: var(--space-8); }
.mf__brand svg { height: 100%; width: auto; display: block; }
.mf__address { font-size: var(--text-sm); line-height: 1.5rem; color: var(--paper); margin: 0; }

.mf__cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-12) var(--space-2);
}

.mf__head { font-size: var(--text-sm); color: var(--paper); margin-bottom: var(--space-4); }
.mf__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); font-weight: var(--weight-semibold); color: var(--off-white); }
.mf__list a { color: inherit; text-decoration: none; }
.mf__contact { grid-column: span 2; }
.mf__list--contact { grid-template-columns: 1fr 1fr; align-items: center; }
.mf__insta { display: inline-block; line-height: 0; color: var(--paper); }

@media (min-width: 1024px) {
  .mf__inner { grid-template-columns: 1fr 1fr; padding-block: var(--space-18); }
  .mf__brand-col { order: 0; }
  .mf__brand { margin-bottom: var(--space-16); }
  .mf__cols { grid-template-columns: repeat(3, 1fr); column-gap: var(--space-6); }
  .mf__contact { grid-column: auto; }
  .mf__list--contact { grid-template-columns: 1fr; }
}

/* Console shell — the Focus sidebar layout (SER-2 decision: Direction C) --------
 * A persistent left sidebar plus the page body, for the signed-in console only.
 * The member surface and the sign-in page keep the .masthead layout above. Every
 * value references a token; this file still defines no :root (see tokens.css). */
.console {
  display: grid;
  grid-template-columns: 248px 1fr;
  min-height: 100vh;
  background: var(--surface-sunken);
}

.side {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  overflow-y: auto;
  background: var(--surface-raised);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-4) var(--space-3);
}

.side__brand {
  display: block;
  align-self: flex-start;
  box-sizing: content-box;
  height: 28px;
  color: var(--ink);
  text-decoration: none;
  padding: var(--space-2) var(--space-3) var(--space-1);
}

.side__brand svg { height: 100%; width: auto; display: block; }

.side__kicker {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-subtle);
  padding: 0 var(--space-3) var(--space-3);
}

.side__nav { display: flex; flex-direction: column; gap: var(--space-4); }
.side__group { display: flex; flex-direction: column; gap: 2px; }

.side__label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-subtle);
  padding: 0 var(--space-3);
  margin-bottom: var(--space-1);
}

/* Sidebar rows reuse .nav__item — the class the console nav has always used, and
   the one the router-gating tests recognise — restyled from the old masthead pill
   into a full-width row within the sidebar. */
.side .nav__item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-decoration: none;
}

.side .nav__item:hover { background: var(--surface-sunken); color: var(--ink); }

.side .nav__item.is-active {
  background: var(--surface-sunken);
  color: var(--ink);
  font-weight: var(--weight-semibold);
  box-shadow: inset 3px 0 0 var(--accent-500);
}

.side .nav__item--soon { color: var(--ink-subtle); cursor: default; }
.side .nav__item--soon:hover { background: none; color: var(--ink-subtle); }

.side__icon { width: 18px; height: 18px; flex: 0 0 18px; }

.side__soon {
  margin-left: auto;
  font-size: 0.625rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-1);
}

/* Admin (SER-651): a native <details> whose summary is styled as a nav row, so
   it hovers and focuses like its siblings; the chevron turns when open. */
.side__admin > summary { list-style: none; cursor: pointer; }
.side__admin > summary::-webkit-details-marker { display: none; }
.side__admin-chev {
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  margin-left: auto;
  opacity: 0.6;
  transition: transform 0.15s;
}
.side__admin[open] .side__admin-chev { transform: rotate(90deg); }
.side__admin-items {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 2px;
  padding-left: var(--space-4);
}
@media (prefers-reduced-motion: reduce) {
  .side__admin-chev { transition: none; }
}

.side__foot {
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-3) var(--space-1);
  border-top: 1px solid var(--border);
}

.side__me { display: flex; align-items: center; gap: var(--space-2); font-size: var(--text-sm); color: var(--ink-muted); }

.side__signout {
  background: none;
  border: 0;
  padding: var(--space-1) var(--space-2);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--link);
  cursor: pointer;
  border-radius: var(--radius-sm);
}
.side__signout:hover { color: var(--link-hover); background: var(--surface-sunken); }

/* The page body sits beside the sidebar, with the roomier padding Direction C
   leans on. Pages that need a narrower measure (the event form) keep their own
   max-width. */
.console__main { min-width: 0; padding: var(--space-8) var(--space-12); }

/* Dashboard (Focus): the greeting, the needs-attention queue, the at-a-glance
   cards. The card internals (.dash-card, .stat, .dash-list) are unchanged. */

.section-heading {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  margin: 0 0 var(--space-4);
}

.section-heading--muted {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  font-weight: var(--weight-semibold);
  margin-top: var(--space-8);
}

.queue-section { margin-bottom: var(--space-8); }
.queue { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); }

.qitem {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

.qitem__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
  border-radius: var(--radius-md);
}
.qitem__icon svg { width: 20px; height: 20px; }
.qi-warn { background: var(--tint-warning-bg); color: var(--grey-1); }

.qitem__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.qitem__body a { text-decoration: none; }

.at-glance {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
  gap: var(--space-6);
}

/* Operator dashboard (SER-468): the "right now" row and the revenue deltas. Built
   from the same card, stat and queue tokens as the rest of the dashboard. */
.pulse {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
  gap: var(--space-6);
  margin-bottom: var(--space-8);
}

.pulse .stat-row { margin-bottom: var(--space-4); }
.stat--delta dd { font-size: var(--text-2xl); }
.delta--up { color: var(--deep-grape); }
.delta--down { color: var(--alert-500); }
.delta--flat { color: var(--ink-muted); }
.revenue-alltime { font-size: var(--text-xs); }

/* Role-contextual dashboard (SER-652): the KPI row and the "Needs you" task
   cards, after the console prototype's Dashboard. */
.dash-sub { margin: var(--space-1) 0 0; }
.dash-eyebrow { margin-top: 0; }
.dash-foot { margin-top: var(--space-6); font-size: var(--text-sm); }

.kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: var(--space-3);
  margin: var(--space-6) 0 var(--space-8);
}
.kpi {
  margin: 0;
  padding: var(--space-4) var(--space-4) var(--space-3);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  min-width: 0;
}
.kpi dt {
  font-size: var(--text-xs);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-weight: var(--weight-semibold);
}
.kpi dd {
  margin: 6px 0 0;
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.kpi dd a { color: inherit; text-decoration: none; }
.kpi small { display: block; margin-top: 5px; font-size: var(--text-xs); color: var(--ink-subtle); }

.tasks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.taskcard {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  padding: 13px 15px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.taskcard__sev { width: 9px; height: 9px; border-radius: 50%; margin-top: 6px; flex: none; background: var(--ink-subtle); }
.taskcard--crit { border-left: 3px solid var(--danger-500); }
.taskcard--crit .taskcard__sev { background: var(--danger-500); }
.taskcard--warn { border-left: 3px solid var(--highlight-500); }
.taskcard--warn .taskcard__sev { background: var(--highlight-500); }
.taskcard--info .taskcard__sev { background: var(--accent-500); }
.taskcard__main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.taskcard__t { font-weight: var(--weight-semibold); }
.taskcard__d { font-size: var(--text-sm); color: var(--ink-muted); }
.taskcard .button { flex: none; }
.dash-empty--box {
  padding: var(--space-4);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
}
@media (max-width: 560px) {
  .taskcard { flex-wrap: wrap; }
  .taskcard .button { margin-left: calc(9px + var(--space-3)); }
}

/* A desk tool first, but the sidebar folds to a wrapping top strip on a narrow
   viewport rather than eating the screen. */
@media (max-width: 900px) {
  .console { grid-template-columns: 1fr; }
  .side {
    position: static;
    height: auto;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-2);
  }
  .side__nav { flex-direction: row; flex-wrap: wrap; gap: var(--space-2); }
  .side__label { display: none; }
  .side__admin { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .side__admin-items { flex-direction: row; flex-wrap: wrap; margin-top: 0; padding-left: 0; }
  .side__foot { margin: 0 0 0 auto; border: 0; padding: 0; }
  .console__main { padding: var(--space-6); }
}

/* Member record (Focus) — a reading surface: identity summary, the SER-24
   dietary placeholder, and operator notes. Tokens only; no new :root. */
.record { max-width: 760px; }

/* Member record as an operator surface (SER-471 redesign): a wider record than
   the reading column, a safety-first dietary band and at-a-glance hero above a
   two-column reading layout — the team's Profile on the left, the member's own
   preferences/tags/attendance/payments on the right. */
.record--ops { max-width: var(--page-xl); }
/* Cards inside a column are spaced by the column's flex gap, so drop their own
   bottom margin; the top-level dietary band keeps the default record-block gap. */
.record-col .record-block { margin-bottom: 0; }
.record-legal { font-family: var(--font-body); font-size: var(--text-lg); font-weight: var(--weight-regular); color: var(--ink-muted); }
.record-pref-flag { font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-subtle); }
/* Member-since chip (SER-24 header declutter): background info beside the
   name, deliberately quiet — no colour like the dietary/status pills next to it,
   just a muted border, icon and short date. Replaces the old "At a glance"
   four-card row (.record-hero, removed): Status and Member since are now a pill
   and this chip in the header itself; Home region duplicated the summary line
   below and Attendance duplicated the Attendance section's own list, so both
   were dropped rather than relocated. */
.meta-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 0 var(--space-2) 0 6px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--surface-sunken);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  line-height: 1.7;
  flex-shrink: 0;
}
.meta-chip svg { width: 13px; height: 13px; flex: 0 0 13px; }

/* The Attendance heading's own count (SER-24 header declutter): replaces the
   "At a glance" card that repeated it beside the list below. */
.section-heading__count { font-family: var(--font-body); font-weight: var(--weight-regular); color: var(--ink-muted); }
.record-cols { display: grid; grid-template-columns: 1.6fr 1fr; gap: var(--space-6); align-items: start; }
.record-col { display: flex; flex-direction: column; gap: var(--space-6); min-width: 0; }
/* The append-only notes read as the Profile card's free-text log, set off from
   the structured prompts above by a rule. */
.record-notes { margin-top: var(--space-6); padding-top: var(--space-6); border-top: 1px solid var(--border); }
.record-notes .section-heading { font-size: var(--text-lg); }
@media (max-width: 60rem) {
  .record-cols { grid-template-columns: 1fr; }
}

.record-head { margin-bottom: var(--space-8); }
.record-back { font-size: var(--text-sm); }
.record-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3); margin: var(--space-3) 0 var(--space-1); }
.record-title h1 { margin: 0; }
.record-summary { margin: 0; }
/* The member's own bio (SER-565), read-only under the name: a short paragraph in
   the record head, distinct from the team's .staff-bio in the Profile card. */
.record-bio { margin: 0 0 var(--space-2); color: var(--ink); max-width: 60ch; }
.record-actions { margin: var(--space-4) 0 0; }
.record-block { margin-bottom: var(--space-6); }
.record-note-form { box-shadow: none; padding: 0; border: 0; margin-bottom: var(--space-6); max-width: none; }
/* Staff profile (SER-471): the team's bio reads as a short paragraph above the
   structured prompts; the edit form folds away under a <details> once captured. */
.staff-bio { margin: 0 0 var(--space-4); color: var(--ink); }
.staff-updated { margin: var(--space-3) 0 0; font-size: var(--text-sm); }
.record-edit { margin-top: var(--space-4); }
.record-edit > summary { cursor: pointer; font-size: var(--text-sm); font-weight: var(--weight-medium); text-decoration: underline; }
.record-edit[open] > summary { margin-bottom: var(--space-4); }
.record-edit .record-note-form { margin-bottom: 0; }

/* An honest "not built yet" placeholder for a section the console will grow into
   (here SER-24). Matches the dimmed "soon" language of the sidebar. */
.placeholder {
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-2);
  background: color-mix(in srgb, var(--grey-4) 8%, transparent);
}
.placeholder .badge { background: var(--surface-sunken); }
.placeholder strong { font-size: var(--text-lg); }
.placeholder .muted { max-width: var(--measure); }

/* A sticky action bar that stays reachable while filling a long form (the new-event
   form's no-JS fallback). Tokens only, no new :root. */
.form-actions--sticky {
  position: sticky;
  bottom: 0;
  margin: var(--space-6) calc(-1 * var(--space-8)) calc(-1 * var(--space-8));
  padding: var(--space-4) var(--space-8);
  background: var(--surface-raised);
  border-top: 1px solid var(--border);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

.menu-types { margin-bottom: var(--space-4); }

/* Menu builder rows (SER-571): each existing type, section and dish is an inline
   edit form with its reorder (up/down) and remove controls beside it. Tokens only;
   no new :root. */
.menu-rows { display: flex; flex-direction: column; gap: var(--space-3); margin-bottom: var(--space-4); }
.menu-row { display: flex; gap: var(--space-3); align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
.menu-row__edit { display: flex; gap: var(--space-3); align-items: center; flex-wrap: wrap; flex: 1 1 16rem; margin: 0; }
.menu-row__edit input { flex: 1 1 auto; }
.menu-row__actions { display: flex; gap: var(--space-2); align-items: center; flex: 0 0 auto; }
.menu-row__actions form { margin: 0; }

/* Event lifecycle (SER-475): the member-facing phase pill, the draft banner and
   the Go live checklist. The pill is sentence-case, unlike the uppercase status badge beside
   it, so the stored status and the derived phase read as two different facts.
   Tokens only; no new :root. */
.phase {
  display: inline-block;
  padding: 0.1rem var(--space-2);
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: 1.6;
  white-space: nowrap;
}
.phase--draft { border-color: var(--accent-500); color: var(--deep-grape); background: var(--tint-info-bg); }
.phase--releasing_soon,
.phase--coming_soon { border-color: var(--accent-500); color: var(--deep-grape); }
.phase--members { border-color: var(--tint-salmon); background: var(--tint-salmon); color: var(--grey-1); }
.phase--bookable { border-color: var(--success-500); background: var(--tint-success-bg); color: var(--grey-1); }
.phase--sold_out,
.phase--waitlist { border-color: var(--danger-500); background: var(--tint-warning-bg); color: var(--grey-1); }
.phase--disabled,
.phase--gated { background: var(--tint-warning-bg); color: var(--grey-1); }
.phase--past,
.phase--archived { background: var(--surface-sunken); color: var(--ink-subtle); }

.draft-banner {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-left: 3px solid var(--accent-500);
  border-radius: var(--radius-sm);
  background: var(--tint-info-bg);
  color: var(--deep-grape);
  font-size: var(--text-sm);
}

.lifecycle-facts__late { color: var(--danger-500); font-weight: var(--weight-semibold); }

.go-live { margin-block: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--border); }
.go-live__form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3) var(--space-4); margin-block: var(--space-4); }
.go-live__confirm { display: flex; align-items: baseline; gap: var(--space-2); flex: 1 1 20rem; font-size: var(--text-sm); }
.go-live__confirm input { flex: 0 0 auto; }
/* The go-live gate checklist (SER-660): approved copy and a banner, each a ✓ or ○
   row; the block reads in the warning tint until both are met. */
.gate { margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--tint-warning-bg); }
.gate--ok { border-color: var(--success-500); background: var(--tint-success-bg); }
.gate__items { margin: 0; padding: 0; list-style: none; display: grid; gap: var(--space-2); }
.gate__item { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2); font-size: var(--text-sm); }
.gate__mk { flex: 0 0 1.25em; font-weight: var(--weight-semibold); color: var(--ink-subtle); }
.gate__item.is-ok .gate__mk { color: var(--success-500); }
.gate__text { flex: 1 1 16rem; }
.gate__action { margin: 0; }
.gate__note { margin: var(--space-2) 0 0; font-size: var(--text-xs); color: var(--ink-muted); }
.event-overview__go-live { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin: 0; }

/* Early-access audiences (SER-659): one checkbox per line under the timeline dates. */
.tl-audiences { border: 0; padding: 0; margin: var(--space-3) 0 0; }
.tl-audiences legend { font-weight: var(--weight-semibold); padding: 0; }
.tl-audiences__choice { display: flex; align-items: center; gap: var(--space-2); margin: var(--space-1) 0 0; font-weight: var(--weight-regular, 400); }

/* Neighbourhood picker (the event form's "search or add" dialog). A generic
   centered-card dialog, kept unscoped from any one field so a later picker
   (e.g. a similar city/venue lookup) can reuse it rather than each field
   growing its own overlay. */
.dialog-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-6);
  background: rgba(0, 0, 0, 0.5);
}
.dialog {
  position: relative;
  width: min(28rem, 100%);
  max-height: 85vh;
  overflow-y: auto;
  padding: var(--space-6);
  border-radius: var(--radius-lg);
  background: var(--white);
}
.dialog__close {
  position: absolute;
  top: var(--space-3);
  right: var(--space-3);
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 999px;
  font-size: var(--text-xl);
  line-height: 1;
  background: transparent;
  cursor: pointer;
}
.dialog__close:hover { background: var(--surface-sunken); }

/* Ticketing modal add/edit (2c). The seating-area and sitting add/edit forms render
   inline and POST normally without JavaScript; console-ticketing-modals.js sets
   [data-js-modals] on the root, which hides the inline forms, reveals their Add/Edit
   triggers, and overlays the opened one as a modal reusing the .dialog card above. So
   without JS the operator sees the forms in flow; with it, a calm page of triggers. */
.modal-trigger { margin-top: var(--space-2); }
html:not([data-js-modals]) .modal-trigger { display: none; }
html:not([data-js-modals]) .modal-form__close,
html:not([data-js-modals]) .modal-form__cancel { display: none; }
html[data-js-modals] .modal-form { display: none; }
html[data-js-modals] .modal-form.is-open {
  display: flex;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  padding: var(--space-6);
  background: rgba(0, 0, 0, 0.5);
}
html[data-js-modals] .modal-form.is-open > .dialog { margin: auto; }

.neighbourhood-results { list-style: none; margin: 0 0 var(--space-4); padding: 0; display: grid; gap: var(--space-1); max-height: 12rem; overflow-y: auto; }
.neighbourhood-results__item {
  display: block;
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  text-align: left;
  font-size: var(--text-sm);
  cursor: pointer;
}
.neighbourhood-results__item:hover { background: var(--surface-sunken); }
.neighbourhood-add { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--border); }
.neighbourhood-add summary { cursor: pointer; font-weight: var(--weight-medium); }
.neighbourhood-add__confirm { display: flex; align-items: baseline; gap: var(--space-2); font-size: var(--text-sm); margin: var(--space-3) 0; }
.neighbourhood-add__confirm input { flex: 0 0 auto; }

/* Member record — dietary, attendance (SER-24). A dietary requirement is a
   must-read constraint: visually distinct from a preference and from "nothing
   captured" (ADR-0004). Tokens only; no new :root. */
.constraint {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-4);
  border: 1px solid var(--red);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--red) 8%, var(--surface-raised));
}
.constraint svg { width: 20px; height: 20px; flex: 0 0 20px; color: var(--red); margin-top: 2px; }
.constraint__label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--weight-semibold);
  color: var(--red);
  margin-bottom: var(--space-1);
}
/* A stack of structured constraints, most severe first. The plain .constraint
   above (free text of unstated severity) stays red; these modifiers colour a
   structured constraint by the KIND of rule it is, so an operator scanning the
   record sees an allergy apart from a by-choice avoidance at a glance. */
.constraint-list {
  list-style: none;
  margin: 0 0 var(--space-3);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.constraint--allergy { border-color: var(--red); background: color-mix(in srgb, var(--red) 8%, var(--surface-raised)); }
.constraint--allergy svg, .constraint--allergy .constraint__label { color: var(--red); }
.constraint--intolerance { border-color: var(--highlight-500); background: color-mix(in srgb, var(--highlight-500) 10%, var(--surface-raised)); }
.constraint--intolerance svg, .constraint--intolerance .constraint__label { color: var(--highlight-500); }
.constraint--avoid { border-color: var(--accent-500); background: color-mix(in srgb, var(--accent-500) 7%, var(--surface-raised)); }
.constraint--avoid svg, .constraint--avoid .constraint__label { color: var(--accent-500); }
/* A dislike (SER-664) is a preference, not a rule: muted and outlined, never the
   red of the plain .constraint above nor any severity colour (ADR-0004). */
.constraint--dislike { border-color: var(--border); background: var(--surface-sunken); }
.constraint--dislike svg, .constraint--dislike .constraint__label { color: var(--grey-1); }

/* Member /account constraint rows: the term and its severity on the left, a
   compact inline Remove on the right (the member surface's buttons are otherwise
   full-width pills, which would be wrong per row). The console list has no Remove
   and its own svg+body layout, so these member-only parts do not touch it. */
.constraint__text { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; }
.constraint__term { color: var(--ink); overflow-wrap: anywhere; }
.constraint__remove { margin-left: auto; }
.constraint__remove .btn-outline--small,
.btn-outline--small {
  display: inline-block;
  width: auto;
  padding: var(--space-1) var(--space-3);
  margin-bottom: 0;
  font-size: var(--text-sm);
}
.constraint-add { margin-top: var(--space-4); }

/* "Not captured" reads as its own state — dashed, muted, never mistakable for a
   filled-in "no requirements". */
.nodata {
  margin: 0;
  padding: var(--space-4);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--ink-muted);
  font-style: italic;
  background: color-mix(in srgb, var(--grey-4) 8%, transparent);
}
.nodata strong { color: var(--ink); font-style: normal; }

.attend-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.attend {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
}
.attend:last-child { border-bottom: 0; }

/* Stated preferences (SER-22) on the console member record: a small definition
   list, one row per stated slot. Read-only display, kept visually calmer than the
   dietary constraints above — it ranks, it never gates. */
.prefs { margin: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.pref {
  display: grid;
  grid-template-columns: 10rem 1fr;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
}
.pref:last-child { border-bottom: 0; }
.pref dt { color: var(--ink-muted); font-size: var(--text-sm); }
.pref dd { margin: 0; color: var(--ink); }
@media (max-width: 40rem) { .pref { grid-template-columns: 1fr; gap: var(--space-1); } }
.attend__event a { text-decoration: none; }

/* The hidden attribute must win over any component display (a flex row, a grid
   panel), so JS toggling with `hidden` always holds. */
[hidden] { display: none !important; }

/* Platform Health (SER-ops) — the admin infra-operations tab. Tokens only; this
 * file still defines no :root (tokens.css owns it). Semantic status colour
 * (healthy / degraded / down) is the brand tints — mint, salmon, red — kept
 * distinct from the grape accent, so "needs attention" reads without relying on
 * the accent hue. No new interactivity: the tab is static server-render. */

/* Meta row under the page head: as-of time, region, and the opt-in refresh. */
.ops-meta {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  margin-bottom: var(--space-8);
}
.ops-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--ink-subtle); }
.ops-refresh { display: flex; align-items: center; gap: var(--space-2); margin-left: auto; }
.ops-toggle { display: inline-flex; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); overflow: hidden; font-size: var(--text-xs); }
.ops-toggle a { padding: 2px var(--space-2); text-decoration: none; color: var(--ink-muted); }
.ops-toggle a:hover { background: var(--surface-sunken); color: var(--ink); }
.ops-toggle a.is-on { background: var(--accent-500); color: var(--ink-inverse); }

/* Overall status pill — semantic, not the accent. */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  border: 1px solid transparent;
}
.status-pill .lamp { width: 9px; height: 9px; border-radius: 50%; box-shadow: 0 0 0 3px rgb(255 255 255 / 50%) inset; }
.status-pill--operational { background: var(--tint-success-bg); color: var(--grey-1); border-color: color-mix(in srgb, var(--tint-mint) 55%, var(--grey-1)); }
.status-pill--operational .lamp { background: var(--grey-1); }
.status-pill--degraded { background: var(--tint-warning-bg); color: var(--grey-1); border-color: var(--danger-500); }
.status-pill--degraded .lamp { background: var(--danger-500); }
.status-pill--down { background: var(--alert-500); color: var(--white); border-color: var(--alert-500); }
.status-pill--down .lamp { background: var(--white); }

/* A small uppercase tag for the plane a card describes (e.g. eu). */
.plane-tag {
  display: inline-block;
  font-size: 0.625rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--weight-semibold);
  color: var(--ink-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-1);
  vertical-align: middle;
}

/* Health badges — extend the existing .badge vocabulary. */
.badge--healthy { background: var(--tint-success-bg); color: var(--grey-1); }
.badge--degraded { background: var(--tint-warning-bg); color: var(--grey-1); }
.badge--down { background: var(--alert-500); color: var(--white); }

/* Dietary pills (SER-24 pill redesign, replacing the single SER-564 badge): one
   small chip per structured constraint, beside the member's name for the
   at-event glance. Coloured by the SAME severity palette .constraint--* below
   already uses — no new colours, only color-mix() tints of the existing
   --red/--highlight-500/--accent-500 tokens, exactly as .constraint--intolerance
   and .constraint--avoid already do. Rendered as <button popovertarget> (not a
   plain span), so a tap opens the full detail — the floor's tablets have no
   hover. Not uppercased (the base .badge uppercases), because it carries a real
   requirement term ("Shellfish"), not a status word. */
.badge--dietary {
  /* font: inherit undoes the <button> UA stylesheet's own font (needed since
     this pill is a button, not a span), but it's a shorthand that also resets
     .badge's font-size/weight/line-height to inherit — restate them, same as
     .sp-party__num and every other font: inherit rule in this file does. */
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: 1.6;
  text-transform: none;
  border: 1px solid transparent;
  cursor: pointer;
  appearance: none;
  /* flex-shrink: 0 so a pill is never squeezed to a sliver in the non-wrapping
     title row (the h1/status keep their content width); the row wraps to a new
     line instead. A long term still ellipsizes at max-width, but the full text
     is always recoverable via the pill's own popover. */
  flex-shrink: 0;
  max-width: 22ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.badge--dietary-allergy {
  background: var(--alert-500);
  color: var(--white);
  border-color: var(--alert-500);
}
.badge--dietary-intolerance {
  background: color-mix(in srgb, var(--highlight-500) 18%, var(--surface-raised));
  color: var(--ink);
  border-color: var(--highlight-500);
}
.badge--dietary-avoid {
  background: color-mix(in srgb, var(--accent-500) 12%, var(--surface-raised));
  color: var(--ink);
  border-color: var(--accent-500);
}
/* The explicit "nothing captured" pill (ADR-0004: absence must never be
   silence). Reuses the same warm-amber pairing .badge--suspended already ships,
   so it reads as "needs attention," never as an allergy itself. */
.badge--dietary-unconfirmed { background: var(--tint-warning-bg); color: var(--grey-1); }

/* Wraps one member's dietary pills in a row (SER-24). Same idea as .tag-chips,
   a smaller gap since pills sit right beside the name/status badge, not in
   their own section. */
.dietary-pills { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); }

/* Free-text dietary notes (SER-24 pill redesign): not a pill (unstated
   severity, no strictness to colour-code), but must not simply vanish now that
   the full Dietary card is gone — a quiet line, still visible without a click.
   Italic distinguishes it as a quoted member statement rather than editorial
   copy like .record-bio just below it. */
.record-dietary-note { margin: var(--space-2) 0 0; font-style: italic; white-space: pre-line; }

/* One dietary pill's detail popover (native Popover API — no JS): reuses the
   exact .constraint card language the old full Dietary card used per row (icon +
   label + body), just shown on demand for ONE item instead of a permanent list
   for all of them. Centres over the page by the UA's default popover layout;
   .pill-card carries the visible chrome so the [popover] box itself stays
   unstyled/transparent. */
[popover].dietary-pill-popover { border: none; padding: 0; margin: auto; max-width: min(320px, calc(100vw - var(--space-8))); background: transparent; }
[popover].dietary-pill-popover::backdrop { background: rgb(38 27 27 / 28%); }
.pill-card {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
  box-shadow: var(--shadow-panel);
}
.pill-card svg { width: 20px; height: 20px; flex: 0 0 20px; margin-top: 2px; }
.pill-card__label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--weight-semibold);
  margin-bottom: var(--space-1);
}
.pill-card__term { margin: 0; color: var(--ink); }
.pill-card--allergy svg, .pill-card--allergy .pill-card__label { color: var(--red); }
.pill-card--intolerance svg, .pill-card--intolerance .pill-card__label { color: var(--highlight-500); }
.pill-card--avoid svg, .pill-card--avoid .pill-card__label { color: var(--accent-500); }
.pill-card--unconfirmed svg, .pill-card--unconfirmed .pill-card__label { color: var(--deep-lemon); }

/* Needs-attention queue — reuse .queue / .qitem, add severity stripes + a red icon. */
.qitem--warn { border-left: 4px solid var(--danger-500); }
.qitem--crit { border-left: 4px solid var(--alert-500); }
.qi-crit { background: var(--alert-500); color: var(--white); }
.ops-sub { font-size: var(--text-sm); color: var(--ink-muted); }

/* Stat tiles and numbers use tabular figures so columns line up. */
.ops-num { margin: 0; font-family: var(--font-display); font-size: var(--text-3xl); font-weight: var(--weight-bold); line-height: 1.1; font-variant-numeric: tabular-nums; }
.ops-num small { font-family: var(--font-body); font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--ink-subtle); }
.ops-stat-warn dd { color: var(--danger-500); }

.ops-note { margin: var(--space-4) 0 0; font-size: var(--text-xs); color: var(--ink-subtle); max-width: var(--measure); }
.ops-unavail { margin: var(--space-2) 0 0; font-size: var(--text-sm); color: var(--ink-muted); font-style: italic; }
.ops-muted { color: var(--ink-muted); font-size: var(--text-sm); max-width: var(--measure); }
.ops-foot { margin-top: var(--space-8); font-size: var(--text-xs); color: var(--ink-subtle); max-width: var(--measure); }

/* Label/value rows and a thin meter for the database cards. */
.ops-kv { display: flex; justify-content: space-between; gap: var(--space-4); padding: var(--space-2) 0; border-bottom: 1px dotted var(--border); font-size: var(--text-sm); }
.ops-kv:last-of-type { border-bottom: none; }
.ops-kv .k { color: var(--ink-muted); }
.ops-kv .v { font-variant-numeric: tabular-nums; font-weight: var(--weight-medium); }
.ops-warn { color: var(--danger-500); font-weight: var(--weight-semibold); }
.ops-meter { height: 6px; border-radius: 999px; background: var(--surface-sunken); overflow: hidden; margin-top: var(--space-1); }
.ops-meter > i { display: block; height: 100%; background: var(--accent-500); }
.ops-meter > i.ops-warn { background: var(--danger-500); }

/* GCP placeholder chips. */
.ph-signals { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.ph-signals span { font-size: var(--text-xs); color: var(--ink-muted); border: 1px solid var(--border); border-radius: 999px; padding: 2px var(--space-2); background: var(--surface-raised); }

/* Job-queue tables sit flush inside their card (the card supplies the border). */
.ops-flush { padding: 0; overflow: hidden; }
.ops-pad { padding: var(--space-6) var(--space-6) 0; }
.ops-hint { font-size: var(--text-xs); color: var(--ink-subtle); }
.ops-r { text-align: right; font-variant-numeric: tabular-nums; }
.ops-kind { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink); }
.ops-lasterr { display: block; font-family: var(--font-body); font-size: var(--text-xs); color: var(--ink-muted); margin-top: 2px; }
.ops-row-warn { background: color-mix(in srgb, var(--tint-salmon) 22%, transparent); }

/* A card that spans two grid tracks (the wide job tables); folds to one when narrow. */
.ops-span-2 { grid-column: span 2; }
@media (max-width: 900px) {
  .ops-span-2 { grid-column: auto; }
  .ops-refresh { margin-left: 0; }
}

/* Slack notification routing (SER-268): one card per notification kind, each a
   small form — a channel <select> and an on/off checkbox. .stack spaces the cards;
   .route-row lays each form's label and controls out and folds to one column when
   narrow. Selects reuse the .field control styling explicitly (these controls are
   not inside a .field wrapper). */
.stack { display: flex; flex-direction: column; gap: var(--space-4); }

.route-row__head { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.route-row__title { margin: 0; font-size: var(--text-base); }
.route-row__kind { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--ink-muted); }
.route-row__updated { font-size: var(--text-xs); color: var(--ink-subtle); margin-left: auto; }

.route-row__controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-3);
  flex-wrap: wrap;
}
/* The Save controls and the "Send test" button are two sibling forms (HTML forbids
   nested forms); the save form is the flex row that carries the picker + toggle. */
.route-row__save {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  flex: 1 1 auto;
  margin: 0;
}
.route-row__test { margin: 0; }
.route-row__channel { flex: 1 1 16rem; min-width: 0; }
.route-row__channel select {
  width: 100%;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink);
  font: inherit;
  font-size: var(--text-sm);
}
.route-row__enabled { display: inline-flex; align-items: center; gap: var(--space-1); font-size: var(--text-sm); white-space: nowrap; }
.route-row__controls select:disabled,
.route-row__controls input:disabled,
.route-row__controls button:disabled { opacity: 0.55; cursor: not-allowed; }

@media (max-width: 640px) {
  .route-row__controls { align-items: stretch; }
  .route-row__channel { flex-basis: 100%; }
}

/* Event overview (SER-470): the read-only performance view an event opens to. */

/* Event head (SER-686): the title block beside the event's state and actions — the
   phase pill, Live / Door, View event page, Share — which wrap under the title on a
   narrow screen. The record's own links sit below as quiet small buttons. */
.ehead { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--space-4) var(--space-6); margin: var(--space-4) 0 var(--space-8); }
.ehead__main { flex: 1 1 340px; min-width: min(100%, 340px); }
.ehead h1 { margin: 0 0 var(--space-2); text-wrap: balance; }
.ehead__when { margin: 0; color: var(--ink-muted); }
.ehead__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.ehead__actions .modal-trigger { margin-top: 0; }
.ehead__links { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: var(--space-2); margin: 0; }

/* Tile groups (SER-686): labelled rows of bordered headline figures — the overview's
   Money and What's left to sell. A tile's tone colours its figure: grape for the
   headline, red for comped (revenue foregone), amber for held, and the urgency tones
   for a supply that is nearly gone or sold out, whose word replaces the caption. */
.tilegroups { display: grid; grid-template-columns: 1.7fr 1fr; gap: var(--space-6); align-items: start; margin-bottom: var(--space-6); }
.tilegroups > :only-child { grid-column: 1 / -1; }
.tilegroup > .eyebrow { display: block; margin-bottom: var(--space-3); font-size: var(--text-xs); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-muted); font-weight: var(--weight-semibold); }
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: var(--space-3); margin: 0; }
.tile { background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-4) var(--space-4) var(--space-3); min-width: 0; }
.tile dt { margin: 0; font-size: var(--text-xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); font-weight: var(--weight-semibold); }
.tile dd { margin: var(--space-2) 0 0; font-family: var(--font-display); font-weight: var(--weight-medium); font-size: 1.9rem; line-height: 1; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.tile small { display: block; margin-top: var(--space-1); font-size: var(--text-xs); color: var(--ink-subtle); }
.tile--accent dd { color: var(--accent-500); }
.tile--comp dd, .tile--crit dd { color: var(--alert-500); }
.tile--hold dd { color: #9a6b1e; }
.tile--warn dd { color: #a86a12; }
.tile .tile__status { font-size: 0.66rem; font-weight: var(--weight-bold); text-transform: uppercase; letter-spacing: 0.04em; }
.tile--warn .tile__status { color: #a86a12; }
.tile--crit .tile__status { color: var(--alert-500); }
@media (max-width: 900px) {
  .tilegroups { grid-template-columns: 1fr; }
}

/* Share rows (SER-686): one channel's tagged link per row, the URL truncated beside
   its Copy button. */
.share-dialog { width: min(35rem, 100%); }
.share-dialog .section-heading { margin-top: 0; }
.sharerow { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) 0; border-bottom: 1px solid var(--border); }
.sharerow:last-child { border-bottom: 0; }
.sharerow__meta { flex: 1; min-width: 0; }
.sharerow__c { font-weight: var(--weight-semibold); font-size: var(--text-sm); }
.sharerow__u { font-size: var(--text-xs); color: var(--ink-subtle); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html:not([data-js-modals]) .share-dialog { width: auto; margin-top: var(--space-6); border: 1px solid var(--border); }

/* History list (SER-686): a compact who / what / when log, the lifecycle glance's
   last few entries. */
.hist { list-style: none; margin: var(--space-3) 0 0; padding: 0; font-size: var(--text-sm); }
.hist li { display: grid; grid-template-columns: 5.5rem minmax(0, 1fr) minmax(0, 7.5rem); gap: var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
.hist li:last-child { border-bottom: 0; }
.hist__who { font-weight: var(--weight-semibold); }
.hist__when { color: var(--ink-subtle); text-align: right; font-size: var(--text-xs); }
.lifeglance { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2) var(--space-3); margin: 0; font-size: var(--text-sm); }
.lifeglance__missing { color: var(--alert-500); }
.lifeglance__due { margin: var(--space-2) 0 0; font-size: var(--text-sm); }

/* Owner (SER-559) reads as a quiet chip in the record head, not a full card: a
   muted label + the name in a neutral pill — deliberately not the grape info tint
   the draft phase pill uses, so the two chips read as different things. */
.record-owner { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: var(--space-3) 0 0; font-size: var(--text-sm); }
.record-owner__label { color: var(--ink-muted); text-transform: uppercase; font-size: var(--text-xs); letter-spacing: 0.04em; font-weight: var(--weight-semibold); }
.owner-chip {
  display: inline-block;
  padding: 0 var(--space-2);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
  color: var(--ink);
  font-weight: var(--weight-medium);
  line-height: 1.7;
}

/* The overview body is the member-record ops grid (.record-cols): comps & holds left,
   who's booked + the lifecycle glance right. The tiles and the ticket sales lead full
   width above it; Activity trails full width below. */
.event-overview__body { margin-bottom: var(--space-6); }
@media (min-width: 60.01rem) {
  .event-overview__body { grid-template-columns: 1.4fr 1fr; }
}

/* The activity log is an audit strip, not the page's centrepiece: smaller text and
   tighter rows than the default table, with the timestamp column muted and shrunk to
   its content so the "who did what" reads first. */
.event-overview__activity { font-size: var(--text-sm); }
.event-overview__activity th, .event-overview__activity td { padding-top: var(--space-2); padding-bottom: var(--space-2); }
.event-overview__activity-when { white-space: nowrap; width: 1%; }

/* The event form's Edit log (SER-661): one line per changed copy field — who, which
   field, when — over a boxed word diff. Insertions sit on the mint tint, deletions on
   the salmon tint struck through, so the change reads without colour alone. The diff
   keeps the copy's own line breaks (pre-wrap); elided unchanged text is an ellipsis. */
.copylog { list-style: none; margin: 0; padding: 0; }
.copylog__item { padding: var(--space-3) 0; border-bottom: 1px solid var(--border); }
.copylog__item:last-child { border-bottom: 0; }
.copylog__top { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: baseline; font-size: var(--text-sm); }
.copylog__who { font-weight: 600; }
.copylog__when { margin-left: auto; color: var(--ink-subtle); white-space: nowrap; }
.copylog__diff {
  margin-top: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  color: var(--ink-muted);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.copylog__diff ins { background: var(--tint-success-bg); color: var(--ink); text-decoration: none; border-radius: 2px; padding: 0 2px; }
.copylog__diff del { background: var(--tint-warning-bg); color: var(--danger-500); border-radius: 2px; padding: 0 2px; }
.copylog__gap { color: var(--ink-subtle); }

/* Ticket sales (SER-654): each sitting a bordered <details> open by default, its seating
   areas as rows with a sold / held / comp segment bar (below). */
.event-overview__sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.event-overview .sitsale { border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-raised); margin-bottom: var(--space-3); overflow: hidden; }
.event-overview .sitsale.is-full { border-color: var(--highlight-500); }
.event-overview .sitsale__sum {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-2) var(--space-3);
  padding: var(--space-3) var(--space-4);
  cursor: pointer;
  list-style: none;
}
.event-overview .sitsale__sum::-webkit-details-marker { display: none; }
.event-overview .sitsale__t { display: flex; align-items: center; gap: var(--space-2); font-family: var(--font-display); font-size: var(--text-lg); }
.event-overview .sitsale__t::before {
  content: "";
  width: 0.45em;
  height: 0.45em;
  border-right: 2px solid var(--ink-muted);
  border-bottom: 2px solid var(--ink-muted);
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}
.event-overview .sitsale[open] .sitsale__t::before { transform: rotate(45deg); }
.event-overview .sitsale__c { font-size: var(--text-sm); color: var(--ink-muted); font-variant-numeric: tabular-nums; text-align: right; }
.event-overview .sitsale__c.is-tight { color: var(--ink); font-weight: var(--weight-semibold); }
.event-overview .sitsale__sum .salesbar { grid-column: 1 / -1; }
.event-overview .sitsale__body { padding: 0 var(--space-4) var(--space-2); border-top: 1px solid var(--border); }
.event-overview .salesrow { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; padding: var(--space-3) 0; border-bottom: 1px solid var(--border); }
.event-overview .salesrow:last-child { border-bottom: 0; }
.event-overview .salesrow__name { font-weight: var(--weight-semibold); }
.event-overview .salesrow__sub { font-size: var(--text-sm); }
.event-overview .salesrow__right { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); font-size: var(--text-sm); }
.event-overview .salesrow__right .salesbar { width: 8rem; }
.event-overview__subhead { margin: var(--space-4) 0 var(--space-2); font-size: var(--text-sm); color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.04em; font-weight: var(--weight-semibold); }
.event-overview .sitline { display: grid; grid-template-columns: 1fr auto; gap: var(--space-1) var(--space-3); padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
.event-overview .sitline .salesbar { grid-column: 1 / -1; }
.event-overview .sitsale__none { margin: var(--space-3) 0; font-size: var(--text-sm); }
.event-overview__more { margin-top: var(--space-2); }
.event-overview__more > summary { cursor: pointer; color: var(--link); font-weight: var(--weight-semibold); font-size: var(--text-sm); }
.event-overview__more[open] > summary { margin-bottom: var(--space-2); }
@media (max-width: 40rem) {
  .event-overview .salesrow__right .salesbar { width: 100%; }
  .event-overview .sitsale__sum { grid-template-columns: 1fr; }
  .event-overview .sitsale__c { text-align: left; }
}

/* Segment bars (SER-654, SER-686): sold / held / comp against the unsold track, with the
   legend and the chips that repeat the held and comp counts in words. Unscoped so any
   page showing inventory can reuse them. Sold is grape, held lemon, comp sage, and the
   track the pale blue left to sell. */
.salesbar { display: flex; height: 8px; border-radius: 999px; background: var(--track); overflow: hidden; box-shadow: inset 0 0 0 1px rgb(38 27 27 / 9%); }
.salesbar > i { display: block; height: 100%; }
.seg-sold { background: var(--accent-500); }
.seg-held { background: var(--highlight-500); }
.seg-comp { background: var(--comp); }
.seg-left { background: var(--track); }
.heldchip, .compchip { font-size: var(--text-xs); font-weight: var(--weight-bold); border-radius: 999px; padding: 0 var(--space-2); line-height: 1.7; }
.heldchip { background: color-mix(in oklab, var(--highlight-500) 18%, transparent); color: #7c4f16; }
.compchip { background: color-mix(in oklab, var(--comp) 18%, transparent); color: #3f5648; }
.seglegend { display: flex; flex-wrap: wrap; gap: var(--space-4); margin: var(--space-3) 0 0; font-size: var(--text-xs); color: var(--ink-muted); }
.seglegend i { display: inline-block; width: 9px; height: 9px; border-radius: 2px; margin-right: var(--space-1); vertical-align: middle; }

/* Command palette (⌘K) — a top-anchored search-and-navigate modal injected into
   the console shell by command-palette.js. Its own backdrop, aligned near the top
   like a launcher rather than centred like the field dialogs; tokens only. */
.cmdk-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-16) var(--space-6) var(--space-6);
  background: rgb(38 27 27 / 45%);
}
.cmdk {
  display: flex;
  flex-direction: column;
  width: min(40rem, 100%);
  max-height: 70vh;
  overflow: hidden;
  background: var(--white);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.cmdk__field {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--border);
}
.cmdk__icon { flex: 0 0 auto; width: 20px; height: 20px; color: var(--ink-subtle); }
.cmdk__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0;
  border: 0;
  background: transparent;
  font: inherit;
  font-size: var(--text-lg);
  color: var(--ink);
}
.cmdk__input:focus { outline: none; }
.cmdk__input::placeholder { color: var(--ink-subtle); }
.cmdk__kbd {
  flex: 0 0 auto;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ink-muted);
}
.cmdk__body { overflow-y: auto; padding: var(--space-2); }
.cmdk__group { padding: var(--space-2) 0; }
.cmdk__heading {
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-subtle);
}
.cmdk__list { list-style: none; margin: 0; padding: 0; }
.cmdk__item {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
}
.cmdk__item.is-active { background: var(--surface-sunken); }
.cmdk__label { flex: 0 0 auto; font-weight: var(--weight-medium); }
.cmdk__sub {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  font-size: var(--text-sm);
  color: var(--ink-muted);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cmdk__item .badge { flex: 0 0 auto; margin-left: auto; }
.cmdk__empty,
.cmdk__hint-line {
  margin: 0;
  padding: var(--space-3);
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

/* Member picker — the inline search-and-select field for "link to member" on the
   unlinked-payments queue (member-picker.js). Reuses .cmdk__label/.cmdk__sub/
   .cmdk__empty so a result row reads the same here as in the command palette. */
.member-picker { position: relative; display: inline-flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
/* A readable floor on the search field itself, so the typed term and the chosen
   name are not clipped to a table cell's width; capped to the container so it does
   not force horizontal scroll on a phone. */
.member-picker [data-member-picker-input] { min-width: 12rem; max-width: 100%; }
.member-picker__view { flex: 0 0 auto; font-size: var(--text-sm); }
/* .member-picker__list is the JS-owned portal box appended once to <body> and
   positioned via getBoundingClientRect() (escapes .table/.table-wrap overflow
   clipping). The fetched fragment's <ul> goes INSIDE it as .member-picker__options
   — a separate class, not this one, so the two don't double up on box styling
   (border/shadow/padding/scroll) when the fragment is spliced in. */
.member-picker__list {
  position: fixed;
  z-index: 1000;
  /* member-picker.js sizes the box to a 320px floor (place()) so "Name  email"
     reads in full and near-identical names are told apart; these are the no-JS /
     pre-place fallback and the hard viewport cap that keeps it on screen. */
  width: 22rem;
  min-width: 20rem;
  max-width: calc(100vw - 1rem);
  max-height: 16rem;
  overflow-y: auto;
  padding: var(--space-1);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}
.member-picker__options { margin: 0; padding: 0; list-style: none; }
.member-picker__row { display: flex; align-items: center; gap: var(--space-2); }
.member-picker__item {
  flex: 1 1 auto;
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 0;
  background: none;
  text-align: left;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font: inherit;
  color: var(--ink);
}
.member-picker__item:hover,
.member-picker__item.is-active { background: var(--surface-sunken); }
.member-picker__peek { flex: 0 0 auto; font-size: var(--text-xs); padding: 0 var(--space-2); }

/* The event forms' "Find the venue" field (SER-768, venue-picker.js): the results sit
   in flow under the input, not portalled like .member-picker__list, since the field is
   never inside a clipping table. Reuses the member picker's option rows. */
.venue-picker { position: relative; }
.venue-picker__results {
  position: absolute;
  z-index: 50;
  left: 0;
  right: 0;
  max-height: 18rem;
  overflow-y: auto;
  padding: var(--space-1);
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}
.venue-picker__group {
  padding: var(--space-2) var(--space-3) var(--space-1);
  font-size: var(--text-xs);
  color: var(--ink-muted, var(--ink));
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.venue-picker__item { flex-wrap: wrap; }
.venue-picker__scope {
  margin: 0;
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
  color: var(--ink-muted, var(--ink));
}

/* ── Native checkout: seat picker (SER-517, SER-539, SER-576) ────────────────────────
   A focused, self-contained booking flow that owns the viewport (member_checkout.html
   overrides "layout" — no site masthead or marketing footer). seat-picker.js enhances the
   server-rendered radio form into a tap-to-advance wizard with collapsing summary rows and a
   sticky pay bar. On a phone the card fills the screen; from 540px it floats as a modal over a
   dimmed plum/gold "event page" backdrop, like a restaurant booking widget.

   Palette is the "Sera Seat Picker" mock's plum + gold on warm paper, scoped to
   body.checkout-page so it never re-themes the rest of the (navy-accent) member app, with a
   dark mode that follows the system. Type/spacing use the app's own tokens (display serif,
   the --space/--text/--radius scale). */
body.checkout-page {
  --sp-ground: #F0EEE9;
  --sp-surface: #FBFAF8;
  --sp-surface-2: #EAE5DE;
  --sp-ink: #241A20;
  --sp-muted: #7C6F76;
  --sp-line: #E2DBD4;
  --sp-line-strong: #D3C9C0;
  --sp-accent: #7C2E4C;
  --sp-accent-ink: #FBF7F3;
  --sp-accent-soft: #F1E2E9;
  --sp-gold: #A5854F;
  --sp-ok: #3F6B50;
  --sp-ok-soft: #E4EDE5;
  --sp-shadow: 0 1px 2px rgba(36,26,32,.05), 0 8px 24px -12px rgba(36,26,32,.18);
  --sp-room: #150E12;
  min-height: 100dvh;
  margin: 0;
  background: var(--sp-surface);
  color: var(--sp-ink);
  color-scheme: light;
}
/* The checkout flattens the shared member layout wrappers (.main / .container) so its
   self-contained card can go full-bleed, edge to edge on a phone and centered on desktop. */
body.checkout-page .main { padding: 0; margin: 0; }
body.checkout-page .container { display: contents; }
@media (prefers-color-scheme: dark) {
  body.checkout-page {
    --sp-ground: #15110F;
    --sp-surface: #211A1E;
    --sp-surface-2: #2C2329;
    --sp-ink: #F1E8EC;
    --sp-muted: #A4949C;
    --sp-line: #342A31;
    --sp-line-strong: #443743;
    --sp-accent: #E08FAA;
    --sp-accent-ink: #2A1620;
    --sp-accent-soft: #392430;
    --sp-gold: #CBA96A;
    --sp-ok: #86BE98;
    --sp-ok-soft: #24302A;
    --sp-shadow: 0 1px 2px rgba(0,0,0,.4), 0 10px 26px -14px rgba(0,0,0,.6);
    color-scheme: dark;
  }
}

/* The app card. Phone: exactly 100dvh, so .spx-scroll (not the document) is the scroller
   and the sticky .sp-bar has a travel range (SER-825: with min-height the column grew with
   its content, the document scrolled instead, and the bar only showed at the end).
   Desktop: a centered device, bounded the same way below. */
.spx-app {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  height: 100dvh;
  background: var(--sp-surface);
}
.spx-app [hidden] { display: none !important; }

.spx-topbar {
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  padding: 14px 20px;
  background: color-mix(in oklab, var(--sp-surface) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--sp-line);
}
/* The sera_wordmark SVG at the member masthead's phone size (.mh__brand). It stays 24px on
   desktop too: there the checkout is a 460px card, not a full-width masthead. */
.spx-wordmark {
  display: block;
  height: 24px;
  color: var(--sp-ink);
  text-decoration: none;
}
.spx-wordmark svg { height: 100%; width: auto; display: block; }
/* The global a:hover (--link-hover, near-black) and focus ring (deep grape) both vanish on the
   dark checkout, so its links keep their own color on hover and ring in the accent. */
.spx-wordmark:hover { color: var(--sp-ink); }
body.checkout-page :focus-visible { outline-color: var(--sp-accent); }
.spx-close {
  width: 34px; height: 34px; border-radius: 999px;
  display: grid; place-items: center;
  color: var(--sp-muted); font-size: 22px; line-height: 1; text-decoration: none;
  border: 1px solid transparent;
}
.spx-close:hover { color: var(--sp-accent); border-color: var(--sp-line); }

.spx-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; }

/* The dimmed "event page" behind the card — desktop only. */
.spx-backdrop { display: none; }

.seatpicker { padding: 6px 20px 28px; }
.seatpicker [hidden] { display: none !important; }
.spx-hint { text-align: center; color: var(--sp-muted); font-size: var(--text-xs); margin: var(--space-4) 0 0; }

/* Event masthead */
.seatpicker__masthead { margin: 16px 0 6px; }
.seatpicker__eyebrow {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  letter-spacing: .16em; text-transform: uppercase; color: var(--sp-gold);
}
.seatpicker__eyebrow::after { content: ""; flex: 1; height: 1px; background: var(--sp-line); }
.seatpicker__event {
  margin: 12px 0 8px;
  font-family: var(--font-display); font-size: var(--text-4xl);
  line-height: 1.02; color: var(--sp-ink); text-wrap: balance;
}
.seatpicker__sub { margin: 0; color: var(--sp-muted); font-size: var(--text-sm); max-width: 40ch; }

/* Numbered panel header for the active step */
.sp-panelhead { display: flex; align-items: baseline; gap: 10px; margin: 18px 0 14px; }
.sp-panelhead__step { font-size: var(--text-sm); font-weight: var(--weight-bold, 700); color: var(--sp-accent); font-variant-numeric: tabular-nums; }
.sp-panelhead__title { font-size: var(--text-xs); font-weight: var(--weight-semibold); letter-spacing: .14em; text-transform: uppercase; color: var(--sp-muted); }

/* Guests stepper */
.sp-party {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px;
  background: var(--sp-surface); border: 1px solid var(--sp-line);
  border-radius: var(--radius-lg); box-shadow: var(--sp-shadow);
  margin-bottom: var(--space-4);
}
.sp-party__label { font-weight: var(--weight-semibold); }
.sp-party__label small { display: block; color: var(--sp-muted); font-weight: var(--weight-medium); font-size: var(--text-xs); }
.sp-party__counter { display: inline-flex; align-items: center; gap: var(--space-1); }
.sp-party__btn {
  width: 40px; height: 40px; border-radius: 999px;
  border: 1px solid var(--sp-line-strong); background: var(--sp-surface);
  color: var(--sp-ink); font-size: var(--text-xl); line-height: 1;
  display: grid; place-items: center; cursor: pointer;
  transition: border-color .12s, color .12s;
}
.sp-party__btn:hover:not(:disabled) { border-color: var(--sp-accent); color: var(--sp-accent); }
.sp-party__btn:disabled { opacity: .35; cursor: not-allowed; }
.sp-party__num {
  width: 44px; text-align: center; border: 0; background: none;
  font: inherit; font-size: var(--text-lg); font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums; color: var(--sp-ink);
  -moz-appearance: textfield; appearance: textfield;
}
.sp-party__num::-webkit-outer-spin-button,
.sp-party__num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.sp-fieldhead {
  font-size: var(--text-xs); font-weight: var(--weight-semibold);
  letter-spacing: .12em; text-transform: uppercase; color: var(--sp-muted);
  margin: 0 0 var(--space-3);
}
.sp-day {
  font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--weight-medium);
  color: var(--sp-ink); margin: var(--space-4) 0 var(--space-2);
}

/* Time slots + seat areas share the card idiom */
.sp-slots, .sp-areas { display: flex; flex-direction: column; gap: var(--space-2); }
.sp-slots { margin-bottom: var(--space-4); }
.sp-slot, .sp-area {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: var(--space-3);
  padding: 14px 16px;
  background: var(--sp-surface); border: 1px solid var(--sp-line);
  border-radius: var(--radius-lg); box-shadow: var(--sp-shadow);
  cursor: pointer;
  transition: border-color .12s, box-shadow .12s, transform .1s;
}
.sp-slot input, .sp-area input {
  position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none;
}
.sp-slot:hover:not(.is-sold), .sp-area:hover:not(.is-sold) { border-color: var(--sp-accent); }
.sp-slot:active:not(.is-sold), .sp-area:active:not(.is-sold) { transform: scale(.995); }
.sp-slot:has(input:checked), .sp-area:has(input:checked) {
  border-color: var(--sp-accent);
  box-shadow: inset 0 0 0 1px var(--sp-accent);
}
.sp-slot:has(input:focus-visible), .sp-area:has(input:focus-visible) {
  outline: 2px solid var(--sp-accent); outline-offset: 2px;
}
.sp-slot__time { flex: 1; font-size: var(--text-lg); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.sp-slot__go { color: var(--sp-line-strong); font-size: var(--text-xl); line-height: 1; }
.sp-slot:hover:not(.is-sold) .sp-slot__go { color: var(--sp-accent); }
.sp-slot__tag, .sp-area__tag { font-size: var(--text-xs); font-weight: var(--weight-semibold); letter-spacing: .04em; text-transform: uppercase; color: var(--sp-muted); }
.sp-slot.is-sold, .sp-area.is-sold { cursor: not-allowed; opacity: .55; box-shadow: none; }
.sp-slot.is-sold .sp-slot__time { text-decoration: line-through; text-decoration-color: var(--sp-line-strong); }

/* Seat-area card: an accent stripe, a serif name, and a stacked price. */
.sp-area { padding: 0; gap: 0; align-items: stretch; }
.sp-area__stripe { width: 5px; flex: none; background: var(--sp-accent); opacity: .85; }
.sp-area.is-sold .sp-area__stripe { background: var(--sp-line-strong); }
.sp-area__body { flex: 1; min-width: 0; padding: 14px 16px; }
.sp-area__name { display: block; font-family: var(--font-display); font-size: var(--text-xl); color: var(--sp-ink); }
.sp-area__desc { display: block; font-size: var(--text-sm); color: var(--sp-muted); margin-top: 3px; }
.sp-area.is-sold .sp-area__name { text-decoration: line-through; text-decoration-color: var(--sp-line-strong); }
.sp-area__price {
  flex: none; display: flex; flex-direction: column; justify-content: center; align-items: flex-end;
  gap: 1px; padding: 14px 16px; text-align: right; border-left: 1px solid var(--sp-line);
}
.sp-area__amount { font-size: var(--text-lg); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; color: var(--sp-ink); }
.sp-area__per { font-size: var(--text-xs); color: var(--sp-muted); letter-spacing: .03em; }
.sp-area__tag { align-self: center; padding: 0 12px; }

.sp-noseats { color: var(--sp-muted); font-size: var(--text-sm); padding: var(--space-2) 0; }

/* Add-ons (SER-658): a quiet list on the review screen; a tick box or a guest count each. */
.sp-addons { display: flex; flex-direction: column; gap: var(--space-2); }
.sp-addon {
  display: flex; align-items: center; gap: var(--space-3); padding: 12px 16px;
  background: var(--sp-surface); border: 1px solid var(--sp-line); border-radius: var(--radius-lg);
}
.sp-addon.is-sold { opacity: .55; }
.sp-addon__body { flex: 1; min-width: 0; }
.sp-addon__name { display: block; font-weight: var(--weight-semibold); color: var(--sp-ink); }
.sp-addon__desc { display: block; font-size: var(--text-sm); color: var(--sp-muted); margin-top: 2px; }
.sp-addon__price { display: block; font-size: var(--text-sm); color: var(--sp-muted); margin-top: 2px; font-variant-numeric: tabular-nums; }
.sp-addon__qty { width: 4.5em; flex: none; text-align: center; }
.sp-addon__check { flex: none; width: 22px; height: 22px; accent-color: var(--sp-accent); }
.sp-addon__tag { flex: none; font-size: var(--text-xs); color: var(--sp-muted); letter-spacing: .06em; text-transform: uppercase; }

/* Collapsing summary rows for completed steps (JS only) */
.sp-crumbs { display: flex; flex-direction: column; gap: var(--space-2); margin: 4px 0 8px; }
.sp-crumb {
  display: flex; align-items: center; gap: var(--space-3); width: 100%; text-align: left;
  padding: 12px 14px;
  background: var(--sp-surface); border: 1px solid var(--sp-line);
  border-radius: var(--radius-lg); box-shadow: var(--sp-shadow); cursor: pointer;
}
.sp-crumb:hover { border-color: var(--sp-accent); }
.sp-crumb__k { font-size: var(--text-xs); letter-spacing: .12em; text-transform: uppercase; color: var(--sp-muted); }
.sp-crumb__v { flex: 1; min-width: 0; font-weight: var(--weight-semibold); }
.sp-crumb__edit { font-size: var(--text-xs); font-weight: var(--weight-semibold); letter-spacing: .06em; text-transform: uppercase; color: var(--sp-accent); }

/* Review receipt (shown at the pay step) */
.sp-receipt {
  background: var(--sp-surface); border: 1px solid var(--sp-line);
  border-radius: var(--radius-lg); box-shadow: var(--sp-shadow); overflow: hidden;
  margin-bottom: var(--space-4);
}
.sp-rrow { display: flex; justify-content: space-between; gap: 12px; padding: 12px 16px; border-bottom: 1px solid var(--sp-line); }
.sp-rrow:last-child { border-bottom: 0; }
.sp-rrow__k { color: var(--sp-muted); }
.sp-rrow__v { font-weight: var(--weight-semibold); text-align: right; }
.sp-rrow--total { background: var(--sp-surface-2); }
.sp-rrow--total .sp-rrow__v { font-size: var(--text-lg); font-variant-numeric: tabular-nums; }
.sp-paylabel { font-size: var(--text-xs); font-weight: var(--weight-semibold); letter-spacing: .1em; text-transform: uppercase; color: var(--sp-muted); margin: 0 2px var(--space-2); }

/* When enhanced, the raw submit is replaced by the sticky bar */
.sp--js .sp-continue { display: none; }
.sp-continue { width: 100%; margin-top: var(--space-2); }

.sp-bar {
  position: sticky; bottom: 0; z-index: 10;
  display: flex; align-items: center; gap: var(--space-4);
  margin: var(--space-4) -20px 0;
  padding: 14px 20px calc(14px + env(safe-area-inset-bottom, 0px));
  background: color-mix(in oklab, var(--sp-surface) 92%, transparent);
  backdrop-filter: blur(10px);
  border-top: 1px solid var(--sp-line);
}
/* Phone (SER-825): the picker fills the scroller as a column and its content box grows, so
   the bar sits at the bottom of the screen on a short step too, not mid-screen under the
   content. While the bar shows it is the column's last box, and the picker's bottom
   padding would stop the sticky bar 28px short of the screen edge. */
@media (max-width: 539.98px) {
  .seatpicker { display: flex; flex-direction: column; min-height: 100%; }
  .seatpicker__body { flex: 1 0 auto; }
  .seatpicker:has(> .sp-bar:not([hidden])) { padding-bottom: 0; }
}
.sp-bar__lead { display: flex; flex-direction: column; min-width: 0; }
.sp-bar__total { font-size: var(--text-lg); font-weight: var(--weight-semibold); font-variant-numeric: tabular-nums; }
.sp-bar__sub { font-size: var(--text-xs); color: var(--sp-muted); }
.sp-bar__cta {
  flex: 1; margin: 0; border: 0; cursor: pointer;
  background: var(--sp-accent); color: var(--sp-accent-ink);
  border-radius: 999px; padding: 15px 22px;
  font: inherit; font-weight: var(--weight-semibold); letter-spacing: .02em;
}
/* Also .btn-filled, whose paper-and-black :hover would otherwise replace the accent pill,
   disabled included. */
.sp-bar__cta:hover { background: var(--sp-accent); color: var(--sp-accent-ink); }
.sp-bar__cta:hover:not(:disabled) { filter: brightness(1.06); }
.sp-bar__cta:disabled { opacity: .45; cursor: not-allowed; }

/* Express row (SER-814): wallet + Link buttons first in the pay step (above the fold on a phone); an "or" rule heads the Payment Element */
.sp-express { margin-bottom: var(--space-4); }
.sp-express.is-busy { opacity: .45; pointer-events: none; }
.sp-or {
  display: flex; align-items: center; gap: var(--space-3);
  margin: 0 2px var(--space-4);
  font-size: var(--text-xs); letter-spacing: .1em; text-transform: uppercase; color: var(--sp-muted);
}
.sp-or::before, .sp-or::after { content: ""; flex: 1; border-top: 1px solid var(--sp-line); }
.sp-express[hidden], .sp-or[hidden], .sp-paylabel[hidden] { display: none; }
#payment-element { margin-bottom: var(--space-4); }
.sp-secure { font-size: var(--text-xs); color: var(--sp-muted); text-align: center; margin: var(--space-3) 0 0; }
.seatpicker__error {
  margin-top: var(--space-4); padding: var(--space-3) var(--space-4);
  background: var(--sp-accent-soft);
  border: 1px solid var(--sp-accent); border-radius: var(--radius-md);
  color: var(--sp-accent); font-size: var(--text-sm);
  scroll-margin-bottom: calc(6rem + env(safe-area-inset-bottom, 0px)); /* clear of the pinned .sp-bar */
}

/* Confirmation (return page) */
.sp-confirm { padding: 40px 24px; text-align: center; }
.sp-seal { width: 66px; height: 66px; border-radius: 999px; margin: 8px auto 20px; display: grid; place-items: center; background: var(--sp-accent-soft); color: var(--sp-accent); }
.sp-seal--ok { background: var(--sp-ok-soft); color: var(--sp-ok); }
.sp-confirm__h { margin: 0 0 8px; font-family: var(--font-display); font-size: var(--text-3xl, var(--text-2xl)); color: var(--sp-ink); }
.sp-confirm__p { color: var(--sp-muted); max-width: 34ch; margin: 0 auto 22px; }
.sp-confirm__cta {
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; cursor: pointer; text-decoration: none;
  background: var(--sp-accent); color: var(--sp-accent-ink);
  border-radius: 999px; padding: 14px 24px; font-weight: var(--weight-semibold);
}
/* Also .btn-filled, whose paper-and-black :hover would otherwise replace the accent pill. */
.sp-confirm__cta:hover { background: var(--sp-accent); color: var(--sp-accent-ink); filter: brightness(1.06); }
.sp-confirm__back { display: inline-block; margin-top: 22px; color: var(--sp-accent); font-weight: var(--weight-semibold); }
.sp-confirm__back:hover { color: var(--sp-accent); }

/* Desktop: the picker pops over the dimmed event page, like a restaurant booking widget. */
@media (min-width: 540px) {
  body.checkout-page { min-height: 100dvh; background: var(--sp-room); }
  body.checkout-page .main {
    display: flex; align-items: center; justify-content: center;
    min-height: 100dvh; padding: 32px;
  }
  .spx-backdrop { display: block; position: fixed; inset: 0; z-index: 0; overflow: hidden; }
  .spx-wash {
    position: absolute; inset: -25%;
    background:
      radial-gradient(55% 45% at 28% 18%, rgba(124,46,76,.55), transparent 70%),
      radial-gradient(45% 45% at 84% 86%, rgba(165,133,79,.30), transparent 72%);
  }
  .spx-ghost {
    position: absolute; inset: 0; display: grid; place-items: center; text-align: center;
    font-family: var(--font-display); font-weight: var(--weight-semibold);
    font-size: clamp(64px, 13vw, 168px); letter-spacing: -.02em; line-height: .92; padding: 0 6%;
    color: rgba(255,255,255,.06); user-select: none;
  }
  .spx-scrim { position: absolute; inset: 0; background: rgba(9,5,8,.5); backdrop-filter: blur(3px); }
  .spx-app {
    min-height: 0;
    width: 100%; max-width: 460px;
    height: min(880px, calc(100dvh - 64px));
    border-radius: 26px; overflow: hidden;
    border: 1px solid var(--sp-line);
    box-shadow: 0 40px 120px -34px rgba(0,0,0,.72), 0 10px 34px -14px rgba(0,0,0,.5);
    animation: sp-pop .42s cubic-bezier(.2,.7,.2,1) both;
  }
  .seatpicker__event { font-size: var(--text-5xl, var(--text-4xl)); }
  @keyframes sp-pop { from { opacity: 0; transform: translateY(16px) scale(.975); } to { opacity: 1; transform: none; } }
}
@media (min-width: 540px) and (prefers-reduced-motion: reduce) { .spx-app { animation: none; } }

/* New-event wizard (console_event_new) ------------------------------------- */
/* A calm, narrow, one-thing-at-a-time flow. Sera is an in-person experiences
   company first: this keeps the tech out of the way. The steps are plain stacked
   sections without JS; console-event-wizard.js reveals the progress rail and the
   per-step actions and shows one step at a time. */
.wizard {
  max-width: 40rem;
}
.wizard-progress {
  display: flex;
  gap: var(--space-6);
  margin: 0 0 var(--space-8);
  padding: 0;
  list-style: none;
}
.wizard-progress__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--ink-subtle);
}
.wizard-progress__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border: 1.5px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface-raised);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  color: var(--ink-subtle);
}
.wizard-progress__item.is-current,
.wizard-progress__item.is-done {
  color: var(--ink);
}
.wizard-progress__item.is-current .wizard-progress__num {
  border-color: var(--accent-500);
  background: var(--accent-500);
  color: var(--ink-inverse);
}
.wizard-progress__item.is-done .wizard-progress__num {
  border-color: var(--tint-success-bg);
  background: var(--tint-success-bg);
  color: var(--ink);
}
.wizard-step__head {
  margin-bottom: var(--space-6);
}
.wizard-step__eyebrow {
  margin: 0 0 var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
/* The step heading is focused on a step change so a screen reader announces the
   step; it is not a control, so it carries no focus ring. */
.wizard-step .section-heading:focus {
  outline: none;
}
.wizard-actions {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  margin-top: var(--space-8);
}

/* The draft "finish later" checklist on the event overview's set-up card.
   Reassures an operator that the fast draft is saved and shows what is left,
   without nagging: it is quiet, and every item links to where it is done. */
.finish-later {
  margin-bottom: var(--space-8);
  background: var(--tint-info-bg);
  border-color: var(--tint-grape);
}
.finish-later__list {
  margin: var(--space-4) 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.finish-later__item {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  font-size: var(--text-sm);
}
.finish-later__mark {
  flex: 0 0 auto;
  font-weight: var(--weight-bold);
  color: var(--accent-500);
}
.finish-later__item.is-done .finish-later__label {
  color: var(--ink-muted);
}

/* Live event "door" page (console_event_live, SER-98) ---------------------- */
/* The operator view for running an event live: a phone in the hand at the door,
   an iPad at the station. Tap targets are large; the headcount band stays in view;
   arrival reads at a glance. Tokens only, like the rest of the console. */
.live-page__head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-bottom: var(--space-4);
}
.live-page__back {
  font-size: var(--text-sm);
  color: var(--ink-muted);
  text-decoration: none;
}
.live-page__back:hover { color: var(--ink); }
.live-page__title h1 { margin: 0; }
.live-page__title p {
  margin: var(--space-1) 0 0;
  font-size: var(--text-sm);
  color: var(--ink-muted);
}

.tabnum { font-variant-numeric: tabular-nums; }

/* Headcount band — sticky, so the night's shape is always in view. */
.band {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}
.band__top { display: flex; justify-content: space-between; align-items: center; }
.live-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: var(--space-1) var(--space-3);
  border-radius: 999px;
  background: var(--surface-sunken);
  color: var(--ink-muted);
}
.live-pill i { width: 7px; height: 7px; border-radius: 999px; background: var(--ink-subtle); }
.live-pill--live { background: var(--tint-warning-bg); color: var(--grey-1); }
.live-pill--live i { background: var(--red); animation: live-pulse 1.8s infinite; }
.live-pill--soon { background: var(--tint-info-bg); color: var(--deep-grape); }
.live-pill--soon i { background: var(--deep-grape); }
@keyframes live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

.stats { display: flex; gap: var(--space-6); align-items: flex-end; margin-top: var(--space-3); }
.stat { line-height: 1; }
.stat b {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}
.stat b .of { color: var(--ink-subtle); font-size: var(--text-xl); }
.stat span {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
}
.stat--next { margin-left: auto; text-align: right; }
.stat--next b {
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--highlight-500);
}
.meter {
  margin-top: var(--space-3);
  height: 7px;
  border-radius: 999px;
  background: var(--surface-sunken);
  overflow: hidden;
}
.meter i { display: block; height: 100%; background: var(--accent-500); border-radius: 999px; }

.live-empty {
  padding: var(--space-8) var(--space-4);
  text-align: center;
  color: var(--ink-muted);
  font-size: var(--text-sm);
}

/* Sittings — each a block of guests under its time. A <details>/<summary> pair
   (SER-98 two-sitting collapse): a sitting that hasn't started yet renders
   closed until its own time arrives (event_live.go sets the `open` attribute
   from sittingState), so a second, later sitting doesn't compete with the one
   actually being worked. Marker removed on .sitting__hd since it is now a
   <summary> — a chevron communicates the same "expandable" affordance without
   the default browser triangle's inconsistent sizing/position across browsers. */
.sitting { margin-bottom: var(--space-6); }
.sitting__hd {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-1) var(--space-2);
  cursor: pointer;
  list-style: none;
}
.sitting__hd::-webkit-details-marker { display: none; }
.sitting__hd::after {
  content: "";
  width: 0.5em;
  height: 0.5em;
  margin-left: var(--space-1);
  border-right: 2px solid var(--ink-muted);
  border-bottom: 2px solid var(--ink-muted);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
}
.sitting[open] > .sitting__hd::after { transform: rotate(-135deg); }
.sitting__time {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  font-variant-numeric: tabular-nums;
}
.sitting--unknown .sitting__time {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--ink-muted);
}
.sitting__label { font-size: var(--text-sm); color: var(--ink-muted); }
.sitting__count {
  margin-left: auto;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  font-variant-numeric: tabular-nums;
  color: var(--grey-1);
  background: var(--surface-sunken);
  padding: var(--space-1) var(--space-2);
  border-radius: 999px;
}
.tag-next {
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--black);
  background: var(--highlight-500);
  padding: var(--space-1) var(--space-2);
  border-radius: 999px;
}
.sitting--next .cards { box-shadow: inset 3px 0 0 var(--highlight-500); border-radius: var(--radius-lg); }

.cards { display: flex; flex-direction: column; gap: var(--space-2); }

/* Guest row — the check-in grain. */
.guest {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.guest.is-in { border-left: 3px solid var(--tint-mint); }
.guest__main { min-width: 0; flex: 1 1 auto; }
.guest__name { font-weight: var(--weight-semibold); }
.guest__name a { color: inherit; text-decoration: none; }
.guest__name a:hover { text-decoration: underline; }
.guest.is-in .guest__name { color: var(--grey-1); }
.guest__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
  margin-top: var(--space-1);
  font-size: var(--text-sm);
  color: var(--ink-muted);
}
.chip {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  padding: 0 var(--space-2);
  border-radius: 999px;
  line-height: 1.6;
  background: var(--surface-sunken);
  color: var(--grey-1);
}
.chip--comp { background: var(--tint-info-bg); color: var(--deep-grape); }
.chip--party { background: var(--surface-sunken); color: var(--grey-1); }
/* Same severity colour mapping as .badge--dietary-* (the profile page's
   popover pill), but a plain non-interactive chip: the roster card already
   refreshes every few seconds, so a tappable popover here would be fragile. */
.chip--dietary-allergy { background: var(--alert-500); color: var(--white); }
.chip--dietary-intolerance { background: color-mix(in srgb, var(--highlight-500) 18%, var(--surface-raised)); color: var(--ink); }
.chip--dietary-avoid { background: color-mix(in srgb, var(--accent-500) 12%, var(--surface-raised)); color: var(--ink); }
/* A dislike is a preference, not a rule (SER-664): outlined and muted like a
   seating pref, so it never reads as one of the three severity colours above. */
.chip--dietary-dislike { background: var(--surface-sunken); color: var(--grey-1); border: 1px solid var(--border); }
/* Same warm-amber pairing as .badge--dietary-unconfirmed: signals "something
   needs a look", distinct from the three severity colours above. */
.chip--dietary-note { background: var(--tint-warning-bg); color: var(--grey-1); }
.chip--pref { background: var(--surface-sunken); color: var(--grey-1); }
/* A birthday around the night (SER-960): warm, so the door notices it. */
.chip--birthday { background: var(--tint-salmon); color: var(--ink); }
.chip--visits { background: var(--surface-sunken); color: var(--grey-1); }
.arrived-at {
  flex: none;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--grey-1);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* One-tap check-in — a large, thumb-friendly target that fills when arrived. */
.checkin { flex: none; margin: 0; display: flex; }
.tap {
  width: 48px;
  height: 48px;
  border-radius: 999px;
  border: 2px solid var(--border-strong);
  background: var(--surface);
  color: var(--ink-subtle);
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
  transition: transform 0.08s var(--ease-out), background 0.15s, border-color 0.15s, color 0.15s;
  -webkit-tap-highlight-color: transparent;
}
.tap svg { width: 22px; height: 22px; opacity: 0.5; }
.tap:hover { border-color: var(--accent-500); color: var(--accent-500); }
.tap:active { transform: scale(0.92); }
.tap:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.guest.is-in .tap { background: var(--accent-500); border-color: var(--accent-500); color: var(--ink-inverse); }
.guest.is-in .tap svg { opacity: 1; }
.tap--static { cursor: default; opacity: 0.6; }

/* Door guest sheet (SER-663, CR-11). Opened by tapping a guest's name; lives
   outside #live-root so the roster poll never wipes it. A centred modal on an
   iPad or desktop, a bottom sheet on a phone (max-width 600px). Hidden until
   .is-open, which the server sets for the no-JS page and door-guest-sheet.js
   sets otherwise. */
.chip--first { background: var(--tint-salmon); color: var(--grey-1); }
.chip--in { background: var(--tint-success-bg); color: var(--grey-1); }
.gsheet-modal {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  padding: 6vh var(--space-4);
  overflow-y: auto;
  background: rgba(0, 0, 0, 0.45);
}
.gsheet-modal.is-open { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; }
html.gsheet-locked { overflow: hidden; }
.gsheet-modal__box {
  width: min(560px, 100%);
  min-width: 0;
  box-sizing: border-box;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-panel);
}
.gsheet-modal__box:empty { display: none; }
.gsheet { display: flex; flex-direction: column; min-height: 0; flex: 1; }
.gsheet__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--border);
}
.gsheet__head h2 { margin: 0; font-size: var(--text-lg); }
.gsheet__head h2:focus { outline: none; }
.gsheet__x {
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  font-size: var(--text-xl);
  line-height: 1;
  color: var(--ink-muted);
  text-decoration: none;
}
.gsheet__x:hover { background: var(--surface-sunken); color: var(--ink); }
.gsheet__body { padding: var(--space-4) var(--space-6); overflow-y: auto; flex: 1; }
.gsheet__top { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-3); margin-bottom: var(--space-4); }
.gsheet__avatar {
  flex: none;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--tint-grape);
  color: var(--deep-grape);
  font-weight: var(--weight-semibold);
}
.gsheet__who { flex: 1; min-width: 0; }
.gsheet__seat { font-family: var(--font-display); font-size: var(--text-lg); line-height: 1.2; }
.gsheet__profile { flex: none; font-size: var(--text-sm); }
.gsheet__sec { padding: var(--space-3) 0; border-top: 1px solid var(--border); }
.gsheet__sec h3 { margin: 0 0 var(--space-2); font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.gsheet__sec h3 small { font-weight: var(--weight-regular); color: var(--ink-muted); }
.gsheet__empty, .gsheet__hint { margin: 0 0 var(--space-2); font-size: var(--text-sm); color: var(--ink-muted); }
.gsheet__legend { margin: var(--space-2) 0 0; font-size: var(--text-xs); color: var(--ink-muted); }
.gsheet form { margin: 0; }
.dietrows { list-style: none; margin: 0 0 var(--space-2); padding: 0; display: grid; gap: var(--space-2); }
.dietrow { display: flex; align-items: center; flex-wrap: wrap; gap: var(--space-2); }
.dietrow .chip { min-width: 78px; text-align: center; }
.sevseg {
  display: inline-flex;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  overflow: hidden;
}
.sevseg button {
  border: 0;
  background: transparent;
  padding: 4px 10px;
  min-height: 32px;
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--ink-muted);
  cursor: pointer;
}
.sevseg button.is-on { background: var(--accent-500); color: var(--ink-inverse); }
.iact {
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-muted);
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
}
.iact:hover { background: var(--surface-sunken); color: var(--ink); }
.dietchips { display: flex; flex-wrap: wrap; gap: var(--space-2); margin: var(--space-2) 0; }
.dietchip {
  display: inline-block;
  padding: 5px 11px;
  min-height: 32px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--surface);
  font: inherit;
  font-size: var(--text-sm);
  color: var(--ink);
  cursor: pointer;
}
.dietchip.is-on { background: var(--accent-500); border-color: var(--accent-500); color: var(--ink-inverse); }
.dietchip--static { cursor: default; opacity: 0.75; }
.dietother { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.dietother input[type="text"] { flex: 1 1 8rem; min-width: 0; }
.ghist, .gconns, .glog { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.ghist li { font-size: var(--text-sm); }
.gconn { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: var(--space-2); }
.gconn a { display: flex; flex-direction: column; text-decoration: none; color: var(--ink); }
.gconn a span { font-size: var(--text-xs); color: var(--ink-muted); }
.gnote textarea { width: 100%; box-sizing: border-box; resize: vertical; font: inherit; }
.gnote--static { margin: 0; white-space: pre-wrap; font-size: var(--text-sm); }
.glog p { margin: 0; white-space: pre-wrap; font-size: var(--text-sm); }
.glog small { color: var(--ink-muted); font-size: var(--text-xs); }
.gsheet__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-6);
  border-top: 1px solid var(--border);
}
.autosave { font-size: var(--text-xs); color: var(--ink-muted); display: inline-flex; align-items: center; gap: 6px; }
.autosave::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: currentColor; opacity: 0.5; }
.autosave.is-on { color: var(--success-500); font-weight: var(--weight-semibold); }
.autosave.is-on::before { opacity: 1; }
.autosave.is-error { color: var(--error); font-weight: var(--weight-semibold); }

/* Phone: the sheet rises from the bottom edge, full width, with a handle, the
   footer pinned, and 16px text in the fields so iOS does not zoom on focus. */
@media (max-width: 600px) {
  .gsheet-modal { padding: 0; }
  .gsheet-modal.is-open { justify-content: flex-end; }
  .gsheet-modal__box {
    width: 100%;
    max-height: 92vh;
    border-radius: 22px 22px 0 0;
    border-bottom: 0;
    animation: gsheet-rise 0.18s var(--ease-out);
  }
  .gsheet-modal__box::before {
    content: "";
    display: block;
    width: 38px;
    height: 4px;
    margin: 8px auto 0;
    border-radius: 2px;
    background: var(--border-strong);
  }
  .gsheet__head { padding: var(--space-2) var(--space-4) var(--space-3); }
  .gsheet__body { padding: var(--space-3) var(--space-4); }
  .gsheet__foot {
    position: sticky;
    bottom: 0;
    background: var(--surface-raised);
    padding: var(--space-3) var(--space-4) calc(var(--space-3) + env(safe-area-inset-bottom, 0px));
  }
  .gsheet__foot .button { flex: 1; text-align: center; }
  .gsheet textarea, .gsheet input[type="text"], .gsheet select { font-size: 16px; }
  .sevseg button { padding: 4px 12px; }
}
@keyframes gsheet-rise { from { transform: translateY(14px); } to { transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .live-pill--live i { animation: none; }
  .tap { transition: none; }
  .gsheet-modal__box { animation: none; }
}

/* Door roster fidelity (SER-703) ---------------------------------------------- */
/* The mock's roster: back link stacked over the title, the Arrived figure on one
   baseline, each sitting ONE card of flat guest rows with an initials avatar,
   the pooled "Notes for tonight", and the sheet's bordered connection cards. */
.live-page__head { flex-direction: column; align-items: flex-start; gap: var(--space-3); }
.band .stat b span {
  display: inline;
  margin: 0;
  font-size: inherit;
  text-transform: none;
  letter-spacing: normal;
  color: inherit;
}
.band .stat b .of { color: var(--ink-subtle); font-size: var(--text-xl); }
.band .stat b { white-space: nowrap; }
.guest__meta .chip { white-space: nowrap; }

.sitting {
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  margin-bottom: var(--space-3);
  overflow: hidden;
}
.sitting__hd { padding: var(--space-4); }
.sitting--next { box-shadow: var(--shadow-card), inset 3px 0 0 var(--highlight-500); }
.sitting--next .cards { box-shadow: none; border-radius: 0; }
.cards { gap: 0; padding: 0 var(--space-4) var(--space-2); }
.guest {
  padding: var(--space-3) 0;
  background: none;
  border: 0;
  border-top: 1px solid var(--border);
  border-radius: 0;
  box-shadow: none;
}
.guest.is-in { border-left: 0; }
.guest__meta .seat { font-size: var(--text-sm); color: var(--ink-muted); }
.guest.is-in .arrived-at { color: var(--accent-500); font-weight: var(--weight-semibold); }
.avatar {
  flex: none;
  width: 38px;
  height: 38px;
  display: inline-grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-sunken);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
}
.hasnote { margin-left: var(--space-2); color: var(--highlight-500); font-size: var(--text-sm); }
.chip--last { background: var(--surface-sunken); color: var(--ink-muted); border: 1px solid var(--border); }
.chip--conn { background: var(--tint-info-bg); color: var(--deep-grape); }

.sitting--notes .sitting__time { font-family: var(--font-body); font-size: var(--text-base); font-weight: var(--weight-bold); }
.sitting--notes .sitting__count { background: none; color: var(--ink-muted); }
.guest__note { margin: var(--space-1) 0 0; font-size: var(--text-sm); color: var(--ink-muted); white-space: pre-line; }

.gsheet__flags .guest__meta { margin-top: 0; }
.ghist { list-style: disc; padding-left: var(--space-4); gap: var(--space-1); color: var(--ink-muted); }
.gconns { gap: var(--space-2); }
.gconn {
  border: 1px solid var(--border);
  background: var(--surface-raised);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
}
.gconn a { flex: 1; }
.gcombine { display: flex; gap: var(--space-2); margin-top: var(--space-2); }
.gcombine .button { flex: 1; }

@media (max-width: 600px) {
  .sitting__label,
  .guest__meta .chip--last,
  .guest__meta .chip--pref { display: none; }
  .avatar { width: 32px; height: 32px; }
  .tap { width: 40px; height: 40px; }
  .band .stat b { font-size: var(--text-2xl); }
  .gsheet__flags .guest__meta .chip--last,
  .gsheet__flags .guest__meta .chip--pref { display: inline; }
}

/* Dashboard greeting and Your events (SER-704) ----------------------------- */
/* The time-of-day hello over the heading, and "Your events" as whole-row links
   carrying ONE pill each: the most severe flag, or On track. */
.dash-hi { margin: 0; color: var(--ink-muted); font-size: var(--text-sm); }
.dash-yours { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-2); }
.dyev {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  padding: 10px 14px;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--ink);
  text-decoration: none;
}
.dyev:hover { border-color: var(--border-strong); }
.dyev:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.dyev__n { flex: 1 1 14rem; min-width: 0; font-weight: var(--weight-semibold); }
.dyev__when { font-size: var(--text-sm); white-space: nowrap; }
.dyev__flag {
  padding: 2px 9px;
  border-radius: 999px;
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  white-space: nowrap;
}
.dyev__flag--crit { background: var(--alert-500); color: var(--ink-inverse); }
.dyev__flag--warn { background: color-mix(in srgb, var(--highlight-500) 18%, transparent); color: var(--warning-ink); }
.dyev__flag--ok { background: var(--tint-success-bg); color: var(--success-ink); }
/* The sidebar footer now names the operator: when name and Sign out do not fit
   one line, Sign out drops beneath (as the mock stacks them), and a name too long
   for the whole line ellipsizes rather than wrapping. */
.side__foot { flex-wrap: wrap; }
.side__me { min-width: 0; max-width: 100%; }
.side__me > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side__signout { flex: none; white-space: nowrap; }

/* ---------------------------------------------------------------------------
   Create-event modal (SER-712): the mock's .cmodal "Create event" dialog, opened
   from "New event" by console-create-modal.js. The shell lives in console_nav.html;
   the form fragment is console_event_new.html's create_modal. Day-row names,
   their remove controls and "+ Add a day" show only on a multi-day form
   ([data-multiday]).
   --------------------------------------------------------------------------- */
.cmodal {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  place-items: start center;
  padding: 6vh 16px;
  overflow-y: auto;
  background: rgb(38 27 27 / 40%);
  opacity: 0;
  visibility: hidden; /* closed: out of the tab order, not just transparent */
  pointer-events: none;
  transition: opacity 0.16s var(--ease-out), visibility 0.16s;
}
/* Visible at once on open (so focus() can land); the visibility delay is only on close. */
.cmodal.is-open { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity 0.16s var(--ease-out); }
.cmodal__box {
  display: flex;
  flex-direction: column;
  width: min(560px, 100%);
  max-height: 88vh;
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-pop);
}
.cmodal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--border);
}
.cmodal__head h3 { margin: 0; font-family: var(--font-display); font-size: 1.3rem; font-weight: 400; }
.cmodal__x {
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
.cmodal__x:hover { background: var(--surface-sunken); color: var(--ink); }
.cmodal__content,
.cmodal__form { display: flex; flex-direction: column; min-height: 0; }
.cmodal__body { padding: var(--space-6); overflow-y: auto; }
.cmodal__lede { color: var(--ink-muted); margin: 0 0 var(--space-6); }
.cmodal__body .field > label,
.cmodal__label { display: block; font-size: 0.8rem; font-weight: var(--weight-semibold); margin-bottom: var(--space-1); }
.cmodal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-top: 1px solid var(--border);
}
.cmodal__form:not([data-multiday]) .cmodal__multi { display: none; }
.cmodal__form[aria-busy="true"] .cmodal__foot { opacity: 0.6; pointer-events: none; }
.cmodal__addday {
  margin-top: var(--space-1);
  padding: 5px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-sunken);
  color: var(--accent-500);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.cmodal__addday:hover { border-color: var(--border-strong); }
.dayrow { display: flex; gap: var(--space-3); align-items: center; margin-bottom: 8px; }
.dayrow input { min-width: 0; }
.dayrow input[type="date"] { max-width: 180px; }
.dayrow__remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 28px;
  height: 28px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink-subtle);
  cursor: pointer;
}
.dayrow__remove:hover { background: var(--surface-sunken); color: var(--ink); border-color: var(--border); }
.dayrow__remove svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; }
.dayrow:only-child .dayrow__remove,
.cmodal__form:not([data-multiday]) .dayrow__remove { display: none; }
.cnext {
  margin-top: var(--space-2);
  padding: var(--space-4);
  background: var(--surface-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.cnext b { font-size: 0.85rem; }
.cnext ul { margin: 8px 0 0; padding-left: 18px; font-size: 0.83rem; color: var(--ink-muted); }

/* ---------------------------------------------------------------------------
   Seating-area order rules (SER-706). Member side: an area outside the party's
   per-order bounds greys like a sold-out one but is not struck through (it is the
   wrong party size, not sold out); a low-stock area stays pickable and its "N left"
   tag takes the accent; the event page's "Only N left" sits under Book.
   --------------------------------------------------------------------------- */
.sp-area.is-off { cursor: not-allowed; opacity: .55; box-shadow: none; }
.sp-area.is-off .sp-area__stripe { background: var(--sp-line-strong); }
.sp-area.is-low .sp-area__tag { color: var(--sp-accent); }
.event-detail__low-stock { margin: var(--space-2) 0 0; font-size: 0.875rem; font-weight: 600; color: var(--ink); }

/* Tiles (SER-701): the bordered figure tiles of the console prototype — an uppercase
   label over a display-face number. Shared with the event overview's money and
   left-to-sell tiles (SER-686); these five rules match that branch's exactly, so the
   two definitions agree whichever lands second. .tile--hi picks out the figures to
   read first; .tiles--pulse is the events list's row of five, which fills its width. */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: var(--space-3); margin: 0; }
.tile { background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-4) var(--space-4) var(--space-3); min-width: 0; }
.tile dt { margin: 0; font-size: var(--text-xs); letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-muted); font-weight: var(--weight-semibold); }
.tile dd { margin: var(--space-2) 0 0; font-family: var(--font-display); font-weight: var(--weight-medium); font-size: 1.9rem; line-height: 1; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
.tile small { display: block; margin-top: var(--space-1); font-size: var(--text-xs); color: var(--ink-subtle); }
.tile--hi dd { color: var(--accent-500); }
.tiles--pulse { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); margin: var(--space-6) 0; }

/* Events list (SER-701): the prototype's needs-attention strip, "Up next" card grid,
   pill filters and compact whole-row links. */
.eyebrow {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-weight: var(--weight-semibold);
}
.attn { background: var(--tint-salmon); border-radius: var(--radius-md); padding: var(--space-4); margin-bottom: var(--space-6); }
.attn__h {
  margin: 0 0 var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: var(--weight-bold);
  color: var(--grey-1);
}
.attn__row { display: flex; align-items: center; gap: var(--space-3); font-size: var(--text-sm); color: var(--grey-1); }
.attn__row + .attn__row { margin-top: var(--space-2); }
.attn__row a:not(.button) { color: inherit; }
.attn__open { margin-left: auto; background: var(--surface-raised); }
.evsec { margin-top: var(--space-6); }
.evsec__h { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-3); flex-wrap: wrap; }
.evsec__more { margin-top: var(--space-4); font-size: var(--text-xs); }
.evsec__more .filter { padding: 0; font-size: inherit; }
.evsec__past { margin: var(--space-4) 0 0; font-size: var(--text-sm); }
.evsec__past a { font-weight: var(--weight-semibold); }
.upgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--space-3); }
.upcard {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-4);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.12s var(--ease-out), box-shadow 0.12s var(--ease-out);
}
.upcard:hover { border-color: var(--border-strong); box-shadow: var(--shadow-panel); }
.upcard__top { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.upcard__when { font-size: var(--text-xs); color: var(--ink-muted); }
.upcard__name { font-family: var(--font-display); font-size: 1.15rem; line-height: 1.2; }
.upcard__venue { font-size: var(--text-sm); color: var(--ink-muted); }
.upcard__foot { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: auto; padding-top: var(--space-2); }
.upcard__left { font-weight: var(--weight-semibold); font-size: var(--text-sm); }
.filters--pills { margin-bottom: 0; gap: 6px; }
.filters--pills .filter {
  border: 1px solid var(--border);
  background: var(--surface-raised);
  color: var(--ink-muted);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
}
.filters--pills .filter.is-active { background: var(--accent-500); border-color: var(--accent-500); color: var(--ink-inverse); }
.evline {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: 11px var(--space-4);
  margin-bottom: var(--space-2);
  background: var(--surface-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  color: var(--ink);
  text-decoration: none;
  transition: border-color 0.12s var(--ease-out);
}
.evline:hover { border-color: var(--border-strong); }
.evline__n { flex: 1; min-width: 0; font-weight: var(--weight-semibold); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.evline__w { min-width: 120px; font-size: var(--text-xs); color: var(--ink-muted); white-space: nowrap; text-align: right; }
.evline__l { min-width: 90px; font-size: var(--text-xs); color: var(--ink-subtle); white-space: nowrap; text-align: right; }
.evline--past { opacity: 0.72; }
.evline .phase,
.upcard .phase { display: inline-flex; align-items: center; gap: 6px; padding: 4px 11px; line-height: 1; }
.evline .phase::before,
.upcard .phase::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: 0.9; }
@media (max-width: 640px) {
  .evline__w, .evline__l { display: none; }
}

/* Overview Comps & holds (SER-702): comp and hold rows on one table, told apart by an
   inset bar and tint (green comp, gold hold) the legend under it names. Issue comp is
   a disclosure in the head; open, it drops to its own full-width line below the chips. */
.chipbtn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: var(--space-1) var(--space-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-sunken);
  color: var(--accent-500);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  cursor: pointer;
}
.chipbtn:hover { background: var(--tint-grape); }
.alloc__head { align-items: center; margin-bottom: var(--space-4); }
.alloc__head .eyebrow { margin-right: auto; }
.alloc__issue > summary { list-style: none; }
.alloc__issue > summary::-webkit-details-marker { display: none; }
.alloc__issue[open] { order: 3; flex-basis: 100%; }
.alloc__issue[open] > summary { margin-bottom: var(--space-3); }
.tbl { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.tbl th {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border);
  color: var(--ink-muted);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.05em;
  text-align: left;
  text-transform: uppercase;
}
.tbl td { padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border); vertical-align: middle; }
.tbl tr:last-child td { border-bottom: 0; }
.tbl .tbl__when { white-space: nowrap; }
.tbl tr.row-comp td { background: color-mix(in srgb, var(--comp) 9%, transparent); }
.tbl tr.row-hold td { background: color-mix(in srgb, var(--highlight-500) 9%, transparent); }
.tbl tr.row-comp td:first-child { box-shadow: inset 3px 0 0 var(--comp); }
.tbl tr.row-hold td:first-child { box-shadow: inset 3px 0 0 var(--highlight-500); }
.cstatus {
  border-radius: 999px;
  padding: 1px var(--space-2);
  font-size: 0.64rem;
  font-weight: var(--weight-bold);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}
.cstatus--emailed { background: var(--tint-grape); color: var(--deep-grape); }
.cstatus--checked { background: var(--tint-mint); color: var(--grey-1); }
.cstatus--reserved { background: var(--surface-sunken); color: var(--ink-muted); }
.fintag {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0 var(--space-2);
  color: var(--ink-subtle);
  font-size: 0.64rem;
  font-weight: var(--weight-semibold);
  white-space: nowrap;
}
.rowacts { display: flex; justify-content: flex-end; gap: var(--space-1); margin: 0; }
.hint { margin: var(--space-2) 0 0; color: var(--ink-muted); font-size: var(--text-xs); }
.tbl .hint { margin: 0; }

/* Comp dialogs (SER-708): the Issue comp modal's Existing member / New guest toggle,
   the comp row's icon actions, and the no-JS fallbacks. With JS the disclosure's
   summary gives way to the modal trigger and the toggle; without it both recipient
   fields show and a row's Edit and Cancel forms sit in flow under the table. */
.alloc__issue-btn.modal-trigger { margin-top: 0; }
html[data-js-modals] .alloc__issue > summary { display: none; }
html[data-js-modals] .alloc__issue[open] { order: initial; flex-basis: auto; }
.rtoggle {
  display: inline-flex;
  gap: 3px;
  margin-bottom: var(--space-4);
  padding: 3px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-sunken);
}
.rtoggle button {
  padding: 6px 14px;
  border: 0;
  border-radius: 3px;
  background: none;
  color: var(--ink-muted);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.rtoggle button.is-on { background: var(--surface-raised); color: var(--ink); box-shadow: var(--shadow-panel); }
html:not([data-js-modals]) .rtoggle { display: none; }
html[data-js-modals] .rtoggle__nojs { display: none; }
.chk { display: flex; gap: var(--space-2); align-items: flex-start; margin-top: var(--space-2); font-size: var(--text-sm); }
.chk input { margin-top: 3px; }
.dialog--comp { width: min(32rem, 100%); }
.dialog--comp .form { padding: 0; border: 0; background: none; box-shadow: none; }
.dialog--comp .member-picker { display: flex; }
.dialog--comp .member-picker [data-member-picker-input] { flex: 1 1 auto; }
.dialog--comp .chk + .field-hint { margin-bottom: var(--space-4); }
.dialog--comp .field-hint:empty { display: none; }
.rowacts .iact { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; }
.rowacts .iact svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; }
html:not([data-js-modals]) .alloc .modal-form { margin-top: var(--space-4); }
html:not([data-js-modals]) .alloc .modal-form .dialog { width: 100%; padding: var(--space-4); border: 1px solid var(--border); }
.alloc__flash { margin: 0 0 var(--space-3); }

/* Overview Who's booked (SER-702): one line per guest, the party and its chips beside
   the name and the seat area pushed right. Dietary uses the door's chip--dietary-*. */
.att {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-sm);
}
.att:last-child { border-bottom: 0; }
.att__seat { margin-left: auto; color: var(--ink-muted); text-align: right; }
.att .party {
  border-radius: 999px;
  padding: 0 var(--space-2);
  background: var(--tint-grape);
  color: var(--accent-500);
  font-size: 0.7rem;
  font-weight: var(--weight-semibold);
}
.att .addonchip {
  border-radius: 999px;
  padding: 0 var(--space-2);
  background: color-mix(in srgb, var(--comp) 16%, transparent);
  color: var(--grey-1);
  font-size: 0.66rem;
  font-weight: var(--weight-bold);
}

/* Overview Manage grid (SER-705): one tile per editor, each a drawer or, until its
   drawer lands, a link to the edit-page tab. */
.manage-card .event-overview__sec-head { margin-bottom: var(--space-4); }
.manage-card .event-overview__sec-head .muted { font-size: var(--text-xs); }
.manage {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-3);
}
.mtile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
}
.mtile__title { margin: 0; font-family: var(--font-body); font-size: 1rem; font-weight: var(--weight-semibold); }
.mtile p { flex: 1; margin: 0; font-size: var(--text-xs); color: var(--ink-muted); }
.mtile .button { align-self: flex-start; margin-top: var(--space-2); }

/* Editor drawer (SER-705): a 600px panel from the right over a scrim, a full-width
   sheet on a phone. Closed it is off-screen and out of the tab order. */
.scrim {
  position: fixed;
  inset: 0;
  z-index: 800;
  background: rgb(38 27 27 / 38%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s var(--ease-out);
}
.scrim.is-open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 810;
  display: flex;
  flex-direction: column;
  width: min(600px, 96vw);
  height: 100%;
  background: var(--surface);
  box-shadow: var(--shadow-pop);
  transform: translateX(100%);
  visibility: hidden;
  transition: transform 0.24s var(--ease-out), visibility 0.24s;
}
.drawer.is-open { transform: none; visibility: visible; transition: transform 0.24s var(--ease-out); }
.drawer__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-6);
  border-bottom: 1px solid var(--border);
  background: var(--surface-raised);
}
.drawer__head h3 { margin: 0; font-family: var(--font-display); font-size: 1.2rem; font-weight: 400; }
.drawer__body { flex: 1; overflow-y: auto; padding: var(--space-6); }
.iconbtn {
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink-muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
html.drawer-locked { overflow: hidden; }
@media (max-width: 600px) {
  .drawer { width: 100%; }
  .drawer__head { padding: var(--space-3) var(--space-4); }
  .drawer__body { padding: var(--space-4); }
}
/* The edit page's panels, flattened into the drawer: no card chrome, no panel title
   (the drawer head names it). */
.drawer .card, .drawer .form { max-width: none; margin: 0 0 var(--space-6); padding: 0; border: 0; border-radius: 0; background: none; box-shadow: none; }
.drawer .section-subheading { margin: var(--space-6) 0 var(--space-2); font-family: var(--font-body); font-size: 1rem; font-weight: var(--weight-semibold); }
.drawer .tl-audiences__choice input { width: auto; padding: 0; }
.drawer .tabpanel > .section-heading:first-child { display: none; }
.drawer .field-row { gap: var(--space-4); }
.drawer .form-actions--sticky { position: static; }
.drawer-panel__lede { margin: 0 0 var(--space-4); font-size: var(--text-sm); }
.drawer-form__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-6);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--text-xs);
}
.drawer-sec { margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--border); }
.drawer-sec__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); }
.drawer-sec__head .section-subheading { margin: 0; }
/* The Basics drawer's day rows: a date, a name on a multi-day event, and Remove. */
.drawer-days__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); }
.drawer-days__head .section-subheading { margin: 0; }
.drawer-day { margin-bottom: var(--space-2); }
.drawer-day__fields { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.drawer-day__fields input {
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink);
  font: inherit;
}
.drawer-day__fields input[type="date"] { max-width: 11rem; }
.drawer-day__fields input[type="text"] { flex: 1 1 10rem; }
/* "Change these automatically": the confirm-schedule gate as a switch. Turning it on
   posts the confirmation; it is shown on, or off and unavailable, otherwise. */
.autoswitch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.autoswitch__box {
  display: inline-grid;
  place-items: center;
  width: 16px;
  height: 16px;
  border: 1px solid var(--border-strong);
  border-radius: 3px;
  background: var(--surface-raised);
  color: var(--ink);
  font-size: 0.7rem;
}
.autoswitch.is-on .autoswitch__box { border-color: var(--success-500); }
.autoswitch.is-on, .autoswitch.is-disabled { cursor: default; }
.autoswitch.is-disabled { color: var(--ink-subtle); }

/* Shared row-editor modal (SER-705): the #modal later drawers open over the drawer. */
.modal {
  position: fixed;
  inset: 0;
  z-index: 850;
  display: grid;
  place-items: start center;
  padding: 5vh 16px;
  overflow-y: auto;
  background: rgb(38 27 27 / 40%);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.16s var(--ease-out), visibility 0.16s;
}
.modal.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
.modal__box { width: min(560px, 100%); background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-pop); }
.modal__head { display: flex; align-items: center; justify-content: space-between; padding: var(--space-4) var(--space-6); border-bottom: 1px solid var(--border); }
.modal__head h3 { margin: 0; font-family: var(--font-display); font-size: 1.25rem; font-weight: 400; }
.modal__body { padding: var(--space-6); }
.modal__foot { display: flex; justify-content: flex-end; gap: var(--space-3); padding: var(--space-4) var(--space-6); border-top: 1px solid var(--border); }
.modal__foot:empty { display: none; }

/* Save toast (SER-705): "Saved — you're still right here", bottom centre. */
.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  z-index: 950;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--black);
  color: var(--off-white);
  box-shadow: var(--shadow-pop);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  opacity: 0;
  pointer-events: none;
  transform: translateX(-50%) translateY(20px);
  transition: opacity 0.22s var(--ease-out), transform 0.22s var(--ease-out);
}
.toast.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }
.toast__tick { color: var(--tint-mint); }
/* A drawer that could not open says so in the same toast, without the tick. */
.toast--error .toast__tick { display: none; }
.ehead__state { display: inline-flex; align-items: center; gap: var(--space-2); }

/* ---------------------------------------------------------------------------
   Menu drawer (SER-709): the menu as section cards with inline names, a choose
   min–max where the guest chooses, and dish rows of a name over a secondary line.
   The range hides under a fixed format (set, multi) unless a card's range error
   pins it. Advanced holds the menus, dish capacities and the chef's text.
   --------------------------------------------------------------------------- */
.menu-draft__format { max-width: 18rem; }
.menu-draft__hint { margin: 0 0 var(--space-4); }
.menu-draft__note { margin-top: var(--space-3); }
.menucard {
  margin-bottom: var(--space-3);
  padding: var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-raised);
}
.menucard__head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2); }
.menucard .iact { width: 28px; height: 28px; font-size: var(--text-base); flex: none; }
.secname,
.dishname,
.dishdesc {
  min-width: 0;
  padding: 6px var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink);
  font-family: inherit;
}
.secname { flex: 1 1 10rem; font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.minmax { display: flex; align-items: center; gap: var(--space-1); color: var(--ink-muted); font-size: var(--text-xs); white-space: nowrap; }
.minmax input {
  width: 3.25rem;
  padding: 4px 6px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font: inherit;
}
.menu-draft__sections.is-fixed .menucard:not(.is-pinned) [data-menu-draft-range] { display: none; }
.menucard__scope { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-2); color: var(--ink-muted); font-size: var(--text-xs); }
.menucard__scope select { width: auto; }
.dishrow { display: flex; flex-direction: column; gap: 5px; padding: 6px 0; border-bottom: 1px dashed var(--border); }
.dishrow:last-child { border-bottom: 0; }
.dishrow__top { display: flex; align-items: center; gap: var(--space-2); }
.dishname { flex: 1; font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.dishdesc { border-color: var(--border); color: var(--ink-muted); font-size: var(--text-xs); font-style: italic; }
[data-menu-draft-dishes] + .chipbtn { margin-top: var(--space-2); }
.menu-advanced > summary { cursor: pointer; margin: 0; }
.menu-advanced[open] > summary { margin-bottom: var(--space-3); }
.menu-advanced .section-subheading { margin-top: var(--space-4); }
.menu-caps { display: grid; gap: var(--space-2); }
.menu-cap { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.menu-cap__name { flex: 1 1 10rem; margin: 0; font-size: var(--text-sm); }
.menu-cap input { width: 7rem; }
.menu-cap .field-error { flex-basis: 100%; margin: 0; }
.menu-chef { margin-top: var(--space-6); }
@media (max-width: 600px) {
  .minmax { order: 3; flex-basis: 100%; }
}

/* Marketing editor (SER-710): the drawer's full-screen variant, a near-full-viewport
   panel with the copy on the left and the public-page preview and Edit log on the
   right. Under 820px it is one column, with Edit / Preview / Edit log tabs. */
.drawer.drawer--full {
  top: 3vh;
  right: max(2vw, calc((100vw - 1400px) / 2));
  width: 96vw;
  max-width: 1400px;
  height: 94vh;
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.drawer--full .drawer__body { padding: 0; overflow: hidden; }
.drawer--full .drawer-panel { height: 100%; }
.mktpage { display: grid; grid-template-columns: 1.05fr 0.95fr; height: 100%; }
.mkt__editor { min-width: 0; overflow-y: auto; padding: var(--space-6); border-right: 1px solid var(--border); }
.mkt__side2 { min-width: 0; overflow-y: auto; padding: var(--space-6); background: var(--surface-sunken); }
.mkt__editor .form { margin-bottom: 0; }
.mkt__editor .fieldset { margin: var(--space-6) 0 0; padding: var(--space-6) 0 0; border: 0; border-top: 1px solid var(--border); border-radius: 0; }
.mkt__editor .fieldset legend { float: left; width: 100%; margin-bottom: var(--space-2); padding: 0; font-size: 1rem; }
.mkt__editor .fieldset legend + * { clear: both; }
.sub { margin-top: var(--space-6); padding-top: var(--space-6); border-top: 1px solid var(--border); }
.sub__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-bottom: var(--space-2); }
.sub__title { margin: 0; font-family: var(--font-body); font-size: 1rem; font-weight: var(--weight-semibold); }
.mkttabs { display: flex; gap: var(--space-4); margin-bottom: var(--space-4); border-bottom: 1px solid var(--border); }
.mkttab {
  padding: var(--space-2) var(--space-1);
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--ink-muted);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.mktpage[data-mkt-tab="edit"] [data-mkttab="edit"],
.mktpage[data-mkt-tab="preview"] [data-mkttab="preview"],
.mktpage[data-mkt-tab="log"] [data-mkttab="log"] { color: var(--ink); border-bottom-color: var(--accent-500); }
.mktpage:not([data-mkt-tab="log"]) [data-mktpane="log"],
.mktpage[data-mkt-tab="log"] [data-mktpane="preview"] { display: none; }
@media (min-width: 821px) {
  .mkttab--edit { display: none; }
  .mktpage[data-mkt-tab="edit"] .mkttab[data-mkttab="preview"] { color: var(--ink); border-bottom-color: var(--accent-500); }
}
@media (max-width: 820px) {
  .drawer.drawer--full { top: 0; right: 0; width: 100%; height: 100%; border-radius: 0; }
  .drawer--full .drawer__body { overflow-y: auto; }
  .drawer--full .drawer-panel, .mktpage { height: auto; }
  .mktpage { grid-template-columns: 1fr; }
  .mkt__side2 { order: -1; padding: var(--space-3) var(--space-4) 0; background: none; }
  .mkt__editor { padding: var(--space-4); border-right: 0; overflow: visible; }
  .mktpage[data-mkt-tab="edit"] .mktpane,
  .mktpage:not([data-mkt-tab="edit"]) .mkt__editor { display: none; }
  .mktpage:not([data-mkt-tab="edit"]) .mkt__side2 { padding-bottom: var(--space-4); }
}
/* The images and their controls: the role picker (Banner or Gallery, the current one
   pressed), the focal point, order and remove, then the upload form. */
.mktimgs { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: var(--space-3); margin: var(--space-3) 0 0; padding: 0; list-style: none; }
.mktimg { display: flex; flex-direction: column; gap: var(--space-2); }
.mktimg__img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-sunken); }
.mktimg__img--empty { display: flex; align-items: center; justify-content: center; color: var(--ink-muted); font-size: var(--text-xs); }
.mktimg.is-banner .mktimg__img { outline: 2px solid var(--accent-500); outline-offset: 1px; }
.mktimg__roles { display: flex; border: 1px solid var(--border); border-radius: 999px; overflow: hidden; }
.mktimg__roles button {
  flex: 1;
  padding: 3px 0;
  border: 0;
  background: var(--surface-raised);
  color: var(--ink-muted);
  font: inherit;
  font-size: 0.7rem;
  font-weight: var(--weight-semibold);
  cursor: pointer;
}
.mktimg__roles button + button { border-left: 1px solid var(--border); }
.mktimg__roles button[aria-pressed="true"] { background: var(--tint-grape); color: var(--ink); cursor: default; }
.mktimg__role { font-size: var(--text-xs); color: var(--ink-muted); }
/* The focal-point picker (SER-61), shared with the media page: the whole image with
   a marker where the focal point sits; console-media-focal.js moves it on a click. */
.focal { position: relative; display: inline-block; max-width: 100%; line-height: 0; cursor: crosshair; }
.focal img { display: block; max-width: 100%; height: auto; border-radius: var(--radius-sm); }
.focal__marker {
  position: absolute;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border: 2px solid var(--white);
  border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.6);
  pointer-events: none;
}
.focal__unavailable { display: inline-block; padding: var(--space-6) var(--space-4); color: var(--ink-muted); font-size: var(--text-xs); background: var(--surface-sunken); border-radius: var(--radius-sm); }
.mktimg__focal { display: block; }
.mktimg__focal img { width: 100%; border: 1px solid var(--border); }
.mktimg.is-banner .mktimg__focal img { outline: 2px solid var(--accent-500); outline-offset: 1px; }
.mktimg__focal .focal__unavailable { display: block; }
/* An image's variant state: ready reads as done, failed as needing attention, the
   rest as in progress. Not badge--{status}: orders use pending and failed too. */
.mediastate { align-self: flex-start; }
.mediastate--ready { background: var(--tint-success-bg); color: var(--grey-1); }
.mediastate--failed { background: var(--tint-warning-bg); color: var(--danger-500); }
.mktimg__focalform { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); font-size: var(--text-xs); color: var(--ink-muted); }
.mktimg__focalform input { width: 3.75rem; padding: 2px var(--space-1); font: inherit; }
.mktimg__acts { display: flex; flex-wrap: wrap; gap: var(--space-1); }
.mktimg__remove { margin-left: auto; }
.mktimg__acts .chipbtn:disabled { opacity: 0.4; cursor: default; }
.chipbtn--danger { color: var(--danger-500); }
.mktupload { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-3); }
.mktupload .field-hint, .mktupload .field-error { flex-basis: 100%; margin: 0; }
/* Wallet pass art (migration 0063), in the Marketing drawer and on the media page:
   two slots, each the focal picker beside its wallet crop previews. A preview is a
   box at the rendition's aspect; console-media-focal.js places the image the way
   the generator crops it. */
.passart__slots { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.passart__slot { display: grid; grid-template-columns: minmax(0, 240px) 1fr; gap: var(--space-3); align-items: start; }
@media (max-width: 640px) { .passart__slot { grid-template-columns: 1fr; } }
.passart__focal { display: block; }
.passart__focal img { width: 100%; border: 1px solid var(--border); }
.passart__empty { display: grid; place-items: center; min-height: 8rem; padding: var(--space-4); color: var(--ink-muted); font-size: var(--text-xs); background: var(--surface-sunken); border-radius: var(--radius-sm); text-align: center; }
.passart__meta { display: grid; gap: var(--space-2); }
.passart__meta p { margin: 0; }
.passart__title { margin: 0; font-size: var(--text-sm); }
.passart__warning { color: var(--danger-500); font-size: var(--text-xs); }
.passart__focalform { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); font-size: var(--text-xs); color: var(--ink-muted); }
.passart__focalform input { width: 3.75rem; padding: 2px var(--space-1); font: inherit; }
.passart__upload { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); font-size: var(--text-xs); }
.passart__upload .field-error { flex-basis: 100%; margin: 0; }
.wallet-previews { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: start; }
.wallet-preview { margin: 0; display: grid; gap: var(--space-1); max-width: 375px; flex: 1 1 220px; }
.wallet-preview figcaption { font-size: var(--text-xs); color: var(--ink-muted); }
.wallet-preview--poster { flex: 0 0 140px; }
.wallet-preview__crop { overflow: hidden; border-radius: var(--radius-sm); background: var(--deep-grape); }
.wallet-preview__crop img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* The banner's strip preview sits in an image card, a flex column, where the
   preview's 220px flex basis would be its height. */
.mktimg__wallet { flex: none; max-width: none; }
/* The social card: the banner's 1200x630 crop, then the link preview's lines. */
.ogcard { max-width: 360px; overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-raised); }
.ogcard__img { display: block; width: 100%; aspect-ratio: 1200 / 630; object-fit: cover; }
.ogcard__img--empty { display: flex; align-items: center; justify-content: center; padding: var(--space-4); background: linear-gradient(135deg, var(--accent-500), var(--deep-grape)); color: var(--off-white); font-size: var(--text-xs); text-align: center; }
.ogcard__meta { display: flex; flex-direction: column; gap: 2px; padding: var(--space-2) var(--space-3); border-top: 1px solid var(--border); font-size: var(--text-xs); }
.ogcard__url { overflow: hidden; color: var(--ink-subtle); text-overflow: ellipsis; white-space: nowrap; }
.ogcard__sum { color: var(--ink-muted); }
/* The public-page preview: an approximation of the member event page. */
.pv { overflow: hidden; border: 1px solid var(--border); border-radius: var(--radius-lg); background: var(--surface-raised); box-shadow: var(--shadow-card); }
.pv__banner { display: block; width: 100%; height: 180px; object-fit: cover; }
.pv__banner--empty { display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, var(--tint-grape), var(--paper)); color: var(--ink-subtle); font-size: var(--text-xs); }
.pv__body { padding: var(--space-6); }
.pv__phase { color: var(--accent-500); font-size: 0.66rem; font-weight: var(--weight-bold); letter-spacing: 0.06em; text-transform: uppercase; }
.pv__title { margin: 6px 0; font-family: var(--font-display); font-size: 1.6rem; font-weight: 400; }
.pv__when { margin: 0 0 10px; color: var(--ink-muted); font-size: var(--text-sm); }
.pv__sum { margin: 0 0 var(--space-2); font-weight: var(--weight-medium); }
.pv__desc { color: var(--ink-muted); font-size: var(--text-sm); }
.pv__gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); margin: 14px 0; }
.pv__gallery img { width: 100%; aspect-ratio: 1; object-fit: cover; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.pv__cta { display: flex; align-items: center; justify-content: space-between; margin-top: 6px; padding-top: 12px; border-top: 1px solid var(--border); }
.pv__price { font-family: var(--font-display); font-size: 1.2rem; }
.pv__book { padding: var(--space-2) 20px; border-radius: 999px; background: var(--highlight-500); color: var(--black); font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.pv__empty { color: var(--ink-subtle); font-family: var(--font-body); font-size: var(--text-sm); font-style: italic; font-weight: var(--weight-regular); }
details.adv { margin-top: var(--space-6); padding-top: var(--space-4); border-top: 1px solid var(--border); }
details.adv > summary { color: var(--accent-500); font-size: var(--text-sm); font-weight: var(--weight-semibold); list-style: none; cursor: pointer; }
details.adv > summary::-webkit-details-marker { display: none; }
details.adv > summary::before { content: "+ "; }
details.adv[open] > summary::before { content: "\2013  "; }
details.adv > div { margin-top: var(--space-2); }

/* ---- Record facts (CR-10): the statement page's term/value list, and the Finance
   drawer's read-only VAT and card rate. A two-column grid of dt/dd pairs, one per
   row, stacking on a phone. ---- */
.record-facts {
  display: grid;
  grid-template-columns: minmax(10rem, 1fr) minmax(0, 1.4fr);
  margin: 0 0 var(--space-4);
  font-size: var(--text-sm);
}
.record-facts dt,
.record-facts dd { margin: 0; padding: var(--space-2) 0; border-bottom: 1px solid var(--border); }
.record-facts dt { padding-right: var(--space-4); color: var(--ink-muted); }
.record-facts dd { text-align: right; font-variant-numeric: tabular-nums; }
.record-facts dt:last-of-type,
.record-facts dd:last-of-type { border-bottom: 0; }
.record-facts dt strong,
.record-facts dd strong { color: var(--ink); }
@media (max-width: 600px) {
  .record-facts { grid-template-columns: 1fr; }
  .record-facts dt { padding-bottom: 0; border-bottom: 0; }
  .record-facts dd { padding-top: var(--space-1); text-align: left; }
}

/* ---- Finance breakdown (SER-711): the Finance drawer's single column, from what
   guests paid through what Sera wires the restaurant to what Sera keeps. ---- */
.fin { font-size: var(--text-sm); font-variant-numeric: tabular-nums; }
.finrow {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.finrow:last-child { border-bottom: 0; }
.finrow__val { flex-shrink: 0; text-align: right; }
.finrow--head {
  margin-top: var(--space-2);
  border-bottom-color: var(--border-strong);
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 500;
}
.finrow--total { font-weight: var(--weight-bold); }
.finrow--pay { color: var(--accent-500); font-size: 1.05rem; }
.finrow--warn { color: var(--deep-amber); font-weight: var(--weight-semibold); }
.finrow--sub,
.finsub { color: var(--ink-subtle); font-size: 0.78rem; }
.finrow .neg { color: var(--red); }
.fin-blocked { margin: 0; }

/* ---- Finance worksheet editor (SER-711): the Finance drawer's edit view. Money
   inputs carry their currency; a sponsor is one grid row (name, amount, restaurant
   %, Sera %, actions). ---- */
.inline-money { display: flex; align-items: center; gap: var(--space-2); }
.inline-money .cur { color: var(--ink-muted); font-weight: var(--weight-semibold); }
.fin-edit input[type="text"],
.fin-edit select {
  padding: 6px var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-raised);
  color: var(--ink);
  font: inherit;
}
.fin-edit__agreed { max-width: 20rem; }
.fin-edit__save { margin-top: var(--space-3); padding-top: 0; border-top: 0; }
.fin-area { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: 6px 0; border-bottom: 1px solid var(--border); }
.fin-area:last-child { border-bottom: 0; }
.fin-area label { flex: 1 1 12rem; font-size: var(--text-sm); }
.fin-area input { max-width: 7rem; }
.sponsor-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 7.5rem 4rem 4rem auto;
  gap: var(--space-2);
  align-items: center;
  margin: 0 0 var(--space-2);
  font-size: var(--text-sm);
}
.sponsor-row input { width: 100%; min-width: 0; }
.sponsor-row .inline-money { gap: var(--space-1); }
.sponsor-row__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--weight-semibold); }
.sponsor-row__sera { color: var(--ink-muted); text-align: center; }
.sponsor-row__acts { display: inline-flex; align-items: center; gap: var(--space-1); }
.sponsor-row--fixed { grid-template-columns: minmax(0, 1fr) 7.5rem 4rem 4rem; }
@media (max-width: 560px) {
  .sponsor-row { grid-template-columns: 1fr 1fr 1fr; }
  .sponsor-row__name, .sponsor-row > select { grid-column: 1 / -1; }
}

/* Schedule & tickets drawer (SER-707): the areas, sittings, add-ons and holds as
   tables under .sub heads, each row's duplicate/edit/delete icons, and the row
   editors (area, sitting, add-on, hold) that open over the drawer. */
.sub--first { margin-top: var(--space-4); padding-top: 0; border-top: 0; }
.tbl__wrap { overflow-x: auto; }
.tbl .num { text-align: right; white-space: nowrap; }
.tbl th.num { text-align: right; }
.tbl tr.tbl__group th { padding-top: var(--space-4); color: var(--ink); font-size: var(--text-xs); letter-spacing: 0.05em; text-transform: uppercase; }
.sched .chipbtn.modal-trigger { margin-top: 0; }
/* At phone width the head's chip ("+ Add sitting") keeps to one line (SER-765). */
.sched .sub__head .chipbtn { flex: none; white-space: nowrap; }
.sched .tbl th, .sched .tbl td { padding: var(--space-2); }
.sched .tbl td:last-child { width: 1%; }
.sched .rowacts { flex-wrap: nowrap; }
.sched .rowacts .iact { margin: 0; border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--ink-subtle); }
.sched .rowacts .iact:hover { border-color: var(--border); background: var(--surface-sunken); color: var(--ink); }
.sched .rowacts form.inline { display: inline-flex; margin: 0; }
/* The shared .sub, .chk and details.adv (above) with the mock's drawer spacing. */
.sched .sub__head { margin-bottom: var(--space-3); }
.sched .chk { align-items: center; }
.sched .chk input { margin-top: 0; accent-color: var(--accent-500); }
.sched details.adv { margin-top: var(--space-4); }
.sched details.adv > div { margin-top: var(--space-4); }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-4); }
@media (max-width: 640px) {
  .grid2 { grid-template-columns: 1fr; }
  /* The save toast is pinned 26px up; room below the footer keeps it off Done (SER-765). */
  .sched .drawer-form__actions { padding-bottom: 88px; }
}
.dialog--wide { width: min(36rem, 100%); }
.sched-form .field { margin-bottom: var(--space-3); }
.sched-price, .sched-fee, .sched-qty { max-width: 220px; }
.sched-low { max-width: 280px; }
.perseat { margin: var(--space-2) 0 var(--space-1); }
.perseat__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-top: var(--space-1); }
.perseat__row input { max-width: 80px; }
.feepanel {
  margin-top: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface-sunken);
  font-size: 0.85rem;
}
.feepanel .frow { display: flex; justify-content: space-between; gap: var(--space-3); padding: 3px 0; }
.feepanel .frow.head { margin-bottom: 2px; padding-bottom: 6px; border-bottom: 1px solid var(--border); font-weight: var(--weight-semibold); }
.feepanel .frow.foot { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--border); font-size: 0.76rem; }
.feepanel .fees-sub { margin: 9px 0 2px; color: var(--ink-muted); font-size: 0.66rem; letter-spacing: 0.06em; text-transform: uppercase; }
.feepanel .rate { color: var(--ink-subtle); font-size: 0.78rem; font-weight: 400; }
.sched-alloc { margin-top: var(--space-2); padding-top: var(--space-4); }
.allocrow { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); padding: 6px 0; border-bottom: 1px solid var(--border); }
.allocrow:last-of-type { border-bottom: 0; }
.allocrow__a { flex: 1; margin: 0; font-size: 0.88rem; font-weight: 400; }
.allocrow input { max-width: 88px; }
.allocrow .field-error { flex-basis: 100%; margin: 0; }

/* ── Owner inline editor (SER-742) ─────────────────────────────────────────
   The overview head's owner picker, the mock's ownerEditor: one row of label,
   select, Save and a link-style Cancel in place of the owner chip; Change, the
   button that opens it, is link-style too. */
.owner-inline { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: var(--space-3) 0 0; font-size: var(--text-sm); }
.owner-inline select { width: auto; max-width: 100%; padding: 5px 9px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm); font: inherit; background: var(--surface-raised); color: var(--ink); }
.owner-inline__cancel, .record-owner__change { background: none; border: 0; padding: 0; cursor: pointer; font: inherit; color: var(--link); font-weight: var(--weight-semibold); }
.owner-inline__error { flex-basis: 100%; margin: 0; }

/* ── Lifecycle drawer (SER-745) ────────────────────────────────────────────
   The mock's edLifecycle: the gate box with link-style actions, six phase cards in
   a 3×2 grid (each a verb when it can be taken, the current one highlighted), the
   schedule grid with "Change these automatically", and a quiet "More actions"
   disclosure for the curation verbs. */
.linkbtn { background: none; border: 0; padding: 0; margin-left: auto; cursor: pointer; font: inherit; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--link); text-decoration: none; }
.linkbtn:hover { text-decoration: underline; }
.drawer .gate { margin: 0 0 var(--space-3); }
.drawer .gate__item { align-items: center; }
.drawer .gate__item.is-ok .gate__mk { color: var(--comp); }
.drawer .gate__note { font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--ink); }
.lifeseg { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); margin: var(--space-3) 0 var(--space-2); }
@media (max-width: 640px) { .lifeseg { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.lifeseg__form { display: contents; }
.lifeseg__card { display: block; width: 100%; min-height: 100%; padding: var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-raised); color: var(--ink); font: inherit; text-align: left; cursor: pointer; }
button.lifeseg__card:hover { border-color: var(--border-strong); background: var(--surface-sunken); }
.lifeseg__card.is-static { cursor: not-allowed; opacity: 0.6; }
.lifeseg__card--done.is-static { opacity: 0.75; }
.lifeseg__card--current { border-color: var(--accent-500); box-shadow: inset 0 0 0 1px var(--accent-500); background: var(--tint-grape); cursor: default; }
.lifeseg__k { display: block; font-size: var(--text-sm); font-weight: var(--weight-semibold); }
.lifeseg__d { display: block; margin-top: 2px; font-size: var(--text-xs); line-height: 1.3; color: var(--ink-muted); }
.lifeseg__done { color: var(--comp); font-weight: var(--weight-semibold); }
.lifeseg__caption { margin: 0 0 var(--space-2); font-size: var(--text-sm); }
.autoswitch2 { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); font-weight: var(--weight-semibold); color: var(--ink-muted); cursor: pointer; }
.autoswitch2 input { width: 16px; height: 16px; margin: 0; accent-color: var(--accent-500); }
.autoswitch2:has(input:disabled) { cursor: not-allowed; opacity: 0.6; }
.lc-grid { margin-top: var(--space-3); }
.lc-grid .field { margin: 0; }
.lc-readonly { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); margin: var(--space-3) 0 0; font-size: var(--text-sm); }
.lc-readonly dt { color: var(--ink-muted); font-size: var(--text-xs); font-weight: var(--weight-semibold); }
.lc-readonly dd { margin: 2px 0 0; }
.lc-more > summary { cursor: pointer; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--ink-muted); }
.lc-more__list { display: grid; gap: var(--space-2); margin-top: var(--space-3); }
.lc-more__list form { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin: 0; font-size: var(--text-xs); }
.button--quiet { background: transparent; color: var(--ink); border-color: var(--border); }
.button--quiet:hover { background: var(--surface-sunken); border-color: var(--border-strong); }
.dialog__title { margin: 0 0 var(--space-3); font-size: var(--text-lg); }

/* ── Basics drawer (SER-745) ───────────────────────────────────────────────
   The mock's edBasics: name | shape and venue | neighbourhood on one row each (the
   city rides inline beside the neighbourhood), a plain description, and the rest
   under More details. */
.drawer .grid2 { margin-bottom: var(--space-4); }
.drawer .grid2 .field { margin-bottom: 0; }
.nbh-inline { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 3fr); gap: var(--space-2); }
.basics-more > summary { cursor: pointer; font-size: var(--text-sm); font-weight: var(--weight-semibold); color: var(--ink-muted); }
.basics-more[open] > summary { margin-bottom: var(--space-3); }
.drawer .drawer-days { margin-bottom: var(--space-4); }

/* ── Finance modal (SER-746) ───────────────────────────────────────────────
   The drawer shell as a centered modal (data-drawer-center), the mock's
   openFinanceView / openFinanceEdit; full screen at phone width. The sponsor rows
   are edited inline in the one worksheet form. */
.drawer.drawer--center {
  top: 50%;
  left: 50%;
  right: auto;
  width: min(640px, calc(100vw - 32px));
  height: auto;
  max-height: min(90vh, 900px);
  border-radius: var(--radius-lg);
  transform: translate(-50%, -46%);
  opacity: 0;
}
.drawer.drawer--center.is-open { transform: translate(-50%, -50%); opacity: 1; }
@media (max-width: 600px) {
  .drawer.drawer--center { top: 0; left: 0; width: 100%; height: 100%; max-height: none; border-radius: 0; transform: none; }
  .drawer.drawer--center.is-open { transform: none; }
}
.fin-edit__rest { margin: 0 0 var(--space-4); font-size: var(--text-sm); }
.fin-statement-link { margin-left: auto; }
/* The statement page's tables scroll inside .table-wrap; its visually-hidden
   spans are absolutely positioned, so the wrapper must contain them or the page
   pans sideways at phone width (SER-765). */
.table-wrap { position: relative; }
/* Marketing (SER-746): the channel copy fieldset sits in its own .sub, so it takes
   the section's rule and spacing rather than drawing a second one. */
.mkt__editor .sub > .fieldset { margin: 0; padding: 0; border: 0; }
.mkt__editor .sub > .fieldset > legend { margin-bottom: var(--space-1); padding: 0; font-weight: var(--weight-semibold); }
.mkt__foot { position: sticky; bottom: 0; background: var(--surface); }
/* A read-only operator's panels (SER-760): the controls sit in a disabled fieldset
   that draws nothing of its own. */
.plainset { min-width: 0; margin: 0; padding: 0; border: 0; }

/* ── Set up this event (SER-758) ───────────────────────────────────────────
   A draft with nothing to sell: the where-to-start card holds the Manage grid. */
.setup-card .manage { margin-top: var(--space-4); }
.setup-card__progress { margin: var(--space-2) 0 0; }

/* ── Restaurant from the venue (SER-747) ───────────────────────────────────
   ev_restaurant_missing: the event's venue and one click in place of the old
   "no restaurant" dead end; and the worksheet's invoice checklist before paying. */
.venue-fix { margin: 0 0 var(--space-4); padding: var(--space-3) var(--space-4); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface-sunken); }
.venue-fix__venue { margin: 0 0 var(--space-2); }
.venue-fix .field-hint { margin: var(--space-2) 0 0; }
.invoice-check { margin: 0 0 var(--space-4); }
.invoice-check__list { margin: 0; padding: 0; list-style: none; font-size: var(--text-sm); }
.invoice-check__item { padding: 2px 0; color: var(--ink); }
.invoice-check__item span[aria-hidden] { display: inline-block; width: 1.2em; color: var(--ink-subtle); }
.invoice-check__item.is-done span[aria-hidden] { color: var(--success-ink); }

/* Add to Wallet badges (layouts/member_wallet_badges.html). Each badge is shown
   unaltered at its own proportions; the gap is both brands' clear space. The block
   has no outer spacing of its own: in a bookings card it is a footer under a
   hairline, and every other page that includes it spaces it in its own <style>. */
.wallet-badges { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); }
.wallet-badges__link { display: inline-flex; line-height: 0; }
.wallet-badges__link--apple { border-radius: 8px; }   /* the artwork's own corners, so the focus ring hugs it */
.wallet-badges__link--google { border-radius: 999px; }
.wallet-badges__link:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.wallet-badges__link img { display: block; height: 48px; width: auto; }
.event-card__body > .wallet-badges { margin-top: var(--space-4); padding-top: var(--space-4); border-top: 1px solid var(--paper); }

/* A card that is clickable as a whole but holds other links: the title's link is
   stretched over the card, and anything else clickable inside must be raised above
   it, as the wallet badges are below. */
.card-stretch { position: relative; }
.card-stretch__link { color: inherit; text-decoration: none; }
.card-stretch__link::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius-2xl); }
.card-stretch__link:focus-visible { outline: none; }
.card-stretch__link:focus-visible::after { outline: var(--focus-ring); outline-offset: -3px; }
/* Only the badges themselves take the click; the space beside them still opens the card. */
.card-stretch .wallet-badges { position: relative; z-index: 1; pointer-events: none; }
.card-stretch .wallet-badges__link { pointer-events: auto; }

@media print { .no-print { display: none !important; } }

/* ── The sign-up door and the two-step join form (design handoff 2026-10) ──
   One card, centred on the paper background: the door (sign-up and sign-in
   share it, .door--entry) at 720px and the form steps (.door--form) at 620px.
   Values are the handoff's own; the body face stays Jokker where the mock says
   Inter. Full-bleed under 640px so the phone gets the whole width. */
.door-page { padding: var(--space-16) 16px var(--space-22); }
.door {
  box-sizing: border-box;
  width: 100%;
  margin: 0 auto;
  background: var(--off-white);
  border: 1px solid var(--line);
  border-radius: 20px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  color: var(--black);
  animation: door-in 380ms var(--ease-door) both;
}
.door--entry { max-width: 720px; padding: 64px 100px; gap: 28px; }
.door--form { max-width: 620px; padding: 48px 56px; gap: 22px; }
@keyframes door-in { from { opacity: 0; } to { opacity: 1; } }

.door__head { display: flex; flex-direction: column; gap: 10px; }
.door--entry .door__head { align-items: center; gap: 18px; text-align: center; }
.door__symbol { width: 40px; height: 40px; color: var(--black); }
.door__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 56px;
  line-height: 1;
  letter-spacing: -0.018em;
}
.door--entry .door__title { font-size: 60px; }
.door__title--step2 { font-size: 48px; }
.door__sub { margin: 0; font-size: 16px; line-height: 1.5; max-width: none; }
.door--entry .door__sub { color: var(--ink); font-size: 20px; line-height: 1.4; font-weight: var(--weight-medium); }
.door__eyebrow {
  margin: 0;
  font-size: 12px;
  font-weight: var(--weight-semibold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--peach);
}

.door__form { display: flex; flex-direction: column; gap: 22px; margin: 0; }
.door__stack { display: flex; flex-direction: column; gap: 12px; }
.door__notice { margin: 0; font-size: 14px; color: var(--danger-500); text-align: center; }
.door--form .door__notice { text-align: left; }
.door__caption { margin: 0; font-size: 13px; color: var(--fg-muted); text-align: center; max-width: none; }

/* Inputs: one height and border for every field on these screens. */
.door__input {
  box-sizing: border-box;
  display: block;
  width: 100%;
  height: 48px;
  padding: 0 16px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--white);
  color: var(--black);
  font: inherit;
  font-size: 16px;
  transition: border-color 140ms var(--ease-door);
}
.door__input--email { height: 52px; padding: 0 18px; }
.door__input::placeholder { color: var(--fg-subtle); opacity: 1; }
.door__input:focus { outline: none; border-color: var(--black); }
.door__input:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.door__input[aria-invalid="true"] { border-color: var(--danger-500); }
textarea.door__input { height: 72px; padding: 14px 16px; font-size: 15px; line-height: 1.5; resize: vertical; }
select.door__input {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%23261B1B' stroke-width='1.75' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  font-size: 15px;
  cursor: pointer;
}
/* iOS focus zoom: see .acct-input--small. */
@media (pointer: coarse) { textarea.door__input, select.door__input { font-size: 16px; } }
select.door__input:has(option[value=""]:checked) { color: var(--fg-subtle); }
select.door__input option { color: var(--black); }

.door__field { display: flex; flex-direction: column; gap: 8px; border: 0; margin: 0; padding: 0; min-width: 0; }
.door__label { font-size: 14px; font-weight: var(--weight-semibold); padding: 0; }
.door__label-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.door__optional { font-size: 13px; color: var(--fg-muted); }
.door__error { margin: 0; font-size: 13px; color: var(--danger-500); }

/* Mobile: the country-code select sits beside the number. */
.door__phone { display: flex; gap: 8px; }
.door__phone .door__input--cc {
  width: auto;
  flex: none;
  padding: 0 34px 0 14px;
  font-size: 16px;
  font-weight: var(--weight-medium);
  color: var(--black);
  background-size: 16px 16px;
  background-position: right 12px center;
}
.door__phone .door__input--number { flex: 1; min-width: 0; }

/* Buttons: pills. Dark is the primary, outline the providers, ghost the skip. */
.door-btn {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 14px 22px;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 15px;
  font-weight: var(--weight-semibold);
  line-height: 1.25;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 140ms var(--ease-door), transform 140ms var(--ease-door), box-shadow 140ms var(--ease-door);
}
.door-btn:active { transform: scale(0.985); }
.door-btn:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.door-btn--block { width: 100%; }
.door-btn--dark { background: var(--black); color: var(--off-white); }
.door-btn--dark:hover { background: #3a2c2b; }
.door-btn--outline { background: transparent; color: var(--black); box-shadow: inset 0 0 0 1px var(--line-strong); }
.door-btn--outline:hover { box-shadow: inset 0 0 0 1px var(--black); }
.door-btn--ghost { background: transparent; color: var(--black); }
.door-btn--ghost:hover { background: rgb(38 27 26 / 6%); }

.door__or { display: flex; align-items: center; gap: 14px; font-size: 13px; color: var(--fg-muted); }
.door__or::before, .door__or::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.door__providers { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.door__providers--one { grid-template-columns: 1fr; }

.door__foot { display: flex; flex-direction: column; gap: 8px; align-items: center; font-size: 13px; color: var(--fg-muted); text-align: center; }
.door__foot p { margin: 0; max-width: none; }
.door__foot a, .door__terms a { color: inherit; text-decoration: underline; }
.door__foot .door__link, .door__foot a.door__link {
  color: var(--black);
  font: inherit;
  font-weight: var(--weight-semibold);
  text-decoration: underline;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
.door__terms { margin: 0; font-size: 13px; color: var(--fg-muted); text-align: center; max-width: none; }

/* The email opt-in: its own claret block, with the checkbox at the left. The
   whole block is the label, so a tap anywhere toggles it. It must start
   unticked (PECR/GDPR). */
.door-optin {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 20px 22px;
  border-radius: 16px;
  background: var(--claret);
  color: var(--off-white);
  cursor: pointer;
}
.door-optin__box {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  box-sizing: border-box;
  width: 22px;
  height: 22px;
  margin: 2px 0 0;
  border: 1.5px solid var(--off-white);
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  transition: background-color 140ms var(--ease-door);
}
.door-optin__box:checked {
  background: var(--off-white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237E2F31' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7.5'/%3E%3C/svg%3E") center / 16px 16px no-repeat;
}
.door-optin__box:focus-visible { outline: 2px solid var(--off-white); outline-offset: 2px; }
.door-optin__text { display: flex; flex-direction: column; gap: 4px; }
.door-optin__title { font-size: 16px; font-weight: var(--weight-semibold); }
.door-optin__body { font-size: 15px; line-height: 1.5; }

/* "What brings you to Sera?": checkboxes drawn as tappable pills. The input is
   visually hidden but stays focusable, so the keyboard and screen readers get a
   real checkbox. */
.door-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.door-chip { position: relative; display: inline-flex; }
.door-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }
.door-chip span {
  display: inline-flex;
  align-items: center;
  padding: 9px 14px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: var(--weight-semibold);
  color: var(--black);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  cursor: pointer;
  user-select: none;
  transition: background-color 140ms var(--ease-door), color 140ms var(--ease-door), transform 140ms var(--ease-door);
}
.door-chip span:active { transform: scale(0.985); }
.door-chip input:checked + span { background: var(--black); color: var(--off-white); box-shadow: none; }
.door-chip input:focus-visible + span { outline: var(--focus-ring); outline-offset: var(--focus-offset); }

.door__actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

/* The passkey offer on the events page after an email-code sign-in
   (member_events): a native modal dialog in the door's card style, centred over a
   dimmed, blurred page, and a sheet from the bottom on a phone. passkeys.js opens
   it, so it never shows where a passkey cannot be made. */
.pk-dialog {
  box-sizing: border-box;
  width: min(440px, calc(100% - 32px));
  max-width: none;
  padding: 40px 36px 28px;
  border: 1px solid var(--line);
  border-radius: 20px;
  background: var(--off-white);
  color: var(--black);
  box-shadow: 0 40px 120px -34px rgb(0 0 0 / 55%), 0 10px 34px -14px rgb(0 0 0 / 35%);
}
.pk-dialog[open] { animation: pk-pop 380ms var(--ease-door) both; }
.pk-dialog::backdrop { background: rgb(9 5 8 / 50%); backdrop-filter: blur(3px); }
.pk-dialog__inner { display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }
.pk-dialog__icon { display: grid; place-items: center; width: 56px; height: 56px; margin-bottom: 4px; border-radius: 50%; background: var(--paper); }
.pk-dialog__icon svg { width: 26px; height: 26px; }
.pk-dialog__eyebrow { margin: 0; font-size: 11px; font-weight: var(--weight-semibold); letter-spacing: 0.14em; text-transform: uppercase; color: var(--peach); }
.pk-dialog__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 34px;
  line-height: 1.02;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.pk-dialog__text { margin: 0; font-size: 16px; line-height: 1.5; color: rgb(38 27 26 / 78%); max-width: 32ch; }
.pk-dialog__error { margin: 0; font-size: 14px; color: var(--danger-500); max-width: none; }
.pk-dialog__actions { display: flex; flex-direction: column; gap: 8px; width: 100%; margin-top: 10px; }
.pk-dialog__fine { margin: 2px 0 0; font-size: 13px; color: var(--fg-muted); max-width: none; }
@keyframes pk-pop { from { opacity: 0; transform: translateY(14px) scale(0.975); } to { opacity: 1; transform: none; } }
@keyframes pk-rise { from { transform: translateY(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .pk-dialog[open] { animation: none; } }

/* "No more passwords": a quiet note just above the door card, in the info tint,
   for members arriving from the old site. Same width as the card. */
.door-note {
  box-sizing: border-box;
  display: flex;
  gap: 14px;
  align-items: flex-start;
  width: 100%;
  max-width: 720px;
  margin: 0 auto 14px;
  padding: 16px 18px;
  border-radius: 16px;
  background: var(--tint-info-bg);
  color: var(--black);
  animation: door-in 380ms var(--ease-door) both;
}
.door-note__icon { flex: none; display: grid; place-items: center; width: 34px; height: 34px; border-radius: 50%; background: var(--off-white); }
.door-note__icon svg { width: 18px; height: 18px; }
.door-note__body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.door-note__title { margin: 0; font-size: 15px; font-weight: var(--weight-bold); max-width: none; }
.door-note__text { margin: 0; font-size: 14px; line-height: 1.5; color: rgb(38 27 26 / 78%); max-width: none; }
.door-note__close {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  margin: -4px -6px 0 0;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--black);
  cursor: pointer;
}
.door-note__close:hover { background: rgb(38 27 26 / 8%); }
.door-note__close:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-offset); }
.door-note__close svg { width: 14px; height: 14px; }

@media (max-width: 640px) {
  .door-page { padding: 0; }
  .door { border: 0; border-radius: 0; }
  .door-note { margin: 12px 12px 0; width: auto; padding: 14px; gap: 12px; }
  .door-note__icon { display: none; }
  .pk-dialog { width: 100%; margin: auto 0 0; padding: 14px 22px 28px; border-bottom: 0; border-radius: 24px 24px 0 0; }
  .pk-dialog[open] { animation-name: pk-rise; }
  .pk-dialog__inner::before { content: ""; width: 40px; height: 4px; margin-bottom: 14px; border-radius: 999px; background: var(--line-strong); }
  .pk-dialog__title { font-size: 30px; }
  .door--entry, .door--form { padding: 32px 20px 48px; }
  .door--entry .door__title { font-size: 44px; }
  .door__title { font-size: 40px; }
  .door__title--step2 { font-size: 36px; }
}

@media (prefers-reduced-motion: reduce) {
  .door { animation: none; }
  .door-btn, .door-chip span, .door__input, .door-optin__box { transition: none; }
  .door-btn:active, .door-chip span:active { transform: none; }
}

/* A reason already on record (member_welcome): shown chosen, not toggleable. */
.door-chip input:disabled + span { cursor: default; }
.door-chip input:disabled + span:active { transform: none; }

/* Step 1's "joined before with Google or Apple?" line: a sign-out button that
   reads as a link inside the muted caption. */
.door__switch { margin: 0; }
.door__switch .door__link { color: var(--black); font: inherit; font-weight: var(--weight-semibold); text-decoration: underline; background: none; border: 0; padding: 0; cursor: pointer; }

/* The members list's confirm-first Verify/Invite (unconfirmed email) sits in a row
   of inline action forms, so its trigger drops the stacked-form top margin. */
.table__actions .modal-trigger { margin-top: 0; }
/* The dialog lives in that nowrap, right-aligned cell; it reads as normal prose. */
.table__actions .modal-form { white-space: normal; text-align: left; }

/* ---------------------------------------------------------------------------
   Phones and touch (SER-1061). Two breakpoints: 900px, where the sidebar stops
   fitting beside the page, and 640px, a phone. */

/* The top-bar buttons and the drawer wrapper exist for phones only. On a desktop
   the wrapper's children lay out as direct children of .side, as before. */
.side__drawer { display: contents; }
.side__barbtn { display: none; }

@media (max-width: 900px) {
  /* With console-nav.js running, the sidebar is a sticky top bar and the nav and
     sign-out move into a drawer below it. Without it, the wrapping strip above
     stays (the Menu button is never revealed). */
  /* A block shell, so the sticky bar's containing block is the whole page
     rather than a grid row of its own height. */
  .console { display: block; }
  .side[data-nav-js] {
    position: sticky;
    top: 0;
    z-index: 60;
    flex-wrap: nowrap;
    gap: var(--space-1);
    padding: var(--space-2) var(--space-3);
    border-right: 0;
    border-bottom: 1px solid var(--border);
  }
  .side[data-nav-js] .side__brand { align-self: center; height: 24px; padding: var(--space-1) var(--space-2); margin-right: auto; }
  .side[data-nav-js] .side__kicker { display: none; }
  .side__barbtn:not([hidden]) {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 44px;
    min-width: 44px;
    justify-content: center;
    padding: 0 var(--space-3);
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--ink);
    font: inherit;
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    cursor: pointer;
  }
  .side__barbtn:not([hidden]):hover,
  .side__toggle[aria-expanded="true"] { background: var(--surface-sunken); }

  .side[data-nav-js] .side__drawer { display: none; }
  .side[data-nav-js].is-open .side__drawer {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    position: fixed;
    top: var(--console-bar-h, 61px);
    left: 0;
    right: 0;
    bottom: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--space-4) var(--space-3) calc(var(--space-6) + env(safe-area-inset-bottom));
    background: var(--surface-raised);
  }
  /* Inside the drawer the nav reads as the desktop column again, undoing the
     strip rules above. */
  .side[data-nav-js] .side__nav { flex-direction: column; flex-wrap: nowrap; gap: var(--space-4); }
  .side[data-nav-js] .side__label { display: block; }
  .side[data-nav-js] .side__admin { flex-direction: column; flex-wrap: nowrap; align-items: stretch; }
  .side[data-nav-js] .side__admin-items { flex-direction: column; flex-wrap: nowrap; margin-top: 2px; padding-left: var(--space-4); }
  .side[data-nav-js] .nav__item { min-height: 44px; }
  .side[data-nav-js] .side__foot {
    margin: 0;
    padding: var(--space-3) var(--space-3) 0;
    border-top: 1px solid var(--border);
    flex-direction: column;
    align-items: flex-start;
  }
  .side[data-nav-js] .side__signout { min-height: 44px; padding: 0 var(--space-2); }
  html.side-open { overflow: hidden; }
}

/* Below the phone bar, not under it (--console-bar-h is 0 or unset elsewhere). */
.band { top: var(--console-bar-h, 0px); }
html { scroll-padding-top: var(--console-bar-h, 0px); }

@media (max-width: 640px) {
  .console__main { padding: var(--space-4); }
  .qitem { flex-wrap: wrap; }
}

/* Two-up card rows never ask for more than the screen: a 20rem minimum is wider
   than a 360px phone once the page padding is taken. */
.at-glance { grid-template-columns: repeat(auto-fill, minmax(min(20rem, 100%), 1fr)); }
.pulse { grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr)); }

/* Touch screens, at any width: text fields at 16px so iOS does not zoom the page
   on focus, and the small controls tall enough to hit (44px, the iOS target). */
@media (pointer: coarse) {
  .console input:not([type="checkbox"], [type="radio"], [type="range"], [type="color"], [type="file"], [type="hidden"]),
  .console select,
  .console textarea { font-size: 16px; }
  /* No Escape key to point at on a touch screen. */
  .cmdk__kbd { display: none; }
  /* Filter chips where they sit as a row of controls (status filters, paging).
     A .filter inline in a sentence (Events' "Off the site", the waitlist's back
     link) stays text-sized. */
  .console .button--small,
  .filters .filter,
  .pagination__links .filter {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
  }
}

/* At-event surfaces on a phone (SER-1062). The overview's Tonight card shows only
   here; tiles and the home KPIs pack two to a row (their captions stay: a caption
   is a dash's reason or the figure's period), and Manage drops each editor's
   description to one row per editor (a new event's set-up card keeps them), so what an operator in the room needs is
   within a thumb or two. */
.tonight { display: none; }
@media (max-width: 640px) {
  .tonight {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--space-2) var(--space-3);
    margin-bottom: var(--space-4);
    padding: var(--space-4);
    background: var(--surface-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
  }
  .tonight__count { margin: 0; font-size: var(--text-sm); }
  .tonight__count strong { font-family: var(--font-display); font-size: 1.6rem; font-variant-numeric: tabular-nums; }
  .tonight__door { grid-row: span 2; min-height: 44px; display: inline-flex; align-items: center; }
  .tonight .record-inline-link { display: inline-flex; align-items: center; min-height: 44px; justify-self: start; }
  .event-overview .tilegroups { gap: var(--space-4); margin-bottom: var(--space-4); }
  .event-overview .tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .event-overview .tile,
  .tiles--pulse .tile { padding: var(--space-3); }
  .event-overview .tile dd,
  .tiles--pulse .tile dd { font-size: 1.5rem; }
  .manage-card .mtile p,
  .manage-card .event-overview__sec-head .muted { display: none; }
  .manage-card .manage { grid-template-columns: 1fr; gap: var(--space-2); }
  .manage-card .mtile { flex-direction: row; align-items: center; justify-content: space-between; padding: var(--space-2) var(--space-3); }
  .manage-card .mtile .button { margin-top: 0; align-self: center; }
  .kpi-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2); margin: var(--space-4) 0 var(--space-6); }
  .kpi { padding: var(--space-3); }
  .kpi dd { font-size: var(--text-2xl); }
}

/* The live door's offline pill (SER-1063): door-poll.js shows it when the roster
   poll or a check-in tap cannot reach the server. A toast pinned to the bottom,
   clear of the sticky headcount band, so it is in view wherever the list is
   scrolled. */
.door-offline {
  position: fixed;
  left: var(--space-4);
  right: var(--space-4);
  bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
  z-index: 40;
  max-width: 32rem;
  margin: 0 auto;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-lg);
  background: var(--tint-warning-bg);
  color: var(--grey-1);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  /* It has no controls; a tap on the guest row under it goes through. */
  pointer-events: none;
}
.door-offline[hidden] { display: none; }
