@layer components {
  /* Body bg matches the wood so the texture covers viewport edges and
     doesn't flash a different color past the shell during scroll bounce. */
  html:has(.stay-shell.manage-shell),
  body:has(.stay-shell.manage-shell) {
    background-color: var(--ink);
  }

  /* ── Manage shell ────────────────────────────────────────────
     Borrows Circle's admin posture (cool slate accents, dense data
     rows) but keeps Gather's section-head pattern (UPPERCASE slate
     title on a slate rule) so the back office still feels like part
     of the same product. */

  /* Hide the regular Gather topnav links on /manage so the page
     reads as the admin surface — only the brand mark and the role
     badge remain in the topnav. The manage-shell-head provides its
     own page heading underneath. */

  /* Manage shell — wood-grain background sits behind the white paper.
     No landscape SVG, no clip, no masonite tray; just rich wood texture
     across the viewport with the white sheet floating on top. */
  .stay-shell.manage-shell {
    flex-direction: column;
    align-items: stretch;
    padding: 92px var(--space-6) var(--space-9);
    /* The back office is the dark room in BOTH modes — var(--ink) here
       inverted to light in dark mode and stranded the white chrome. */
    background: var(--cork);
  }
  /* Inverted nav on the back-office surface — white on black. */
  .stay-shell.manage-shell .stay-nav-brand,
  .stay-shell.manage-shell .stay-nav-brand:hover { color: #fff; }
  .stay-shell.manage-shell .stay-nav-link { color: rgba(255,255,255,0.78); }
  .stay-shell.manage-shell .stay-nav-link:hover { color: #fff; }
  /* Office tag beside the wordmark on the admin surface. */
  .manage-office-tag {
    display: inline-block;
    padding: 2px 9px;
    /* Mode-independent: white tag on the always-dark office scene. */
    background: #fff;
    color: #111;
    font-family: var(--sans);
    font-size: var(--cap-md);
    letter-spacing: var(--tracking-cap-wide);
    text-transform: uppercase;
    font-weight: var(--weight-semibold);
    transition: opacity 220ms ease, transform 220ms ease;
  }
  .stay-nav-brand.scrolled + .manage-office-tag {
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
  }
  /* Inverted nav: the +New pill needs a white outline to read on black. */
  .stay-shell.manage-shell .home-nav-cta {
    background: transparent;
    border: 1px solid #fff;
    color: #fff;
  }
  .stay-shell.manage-shell .home-nav-cta:hover {
    background: #fff;
    color: #111;
  }
  .stay-shell.manage-shell .stay-nav { position: fixed; }

  .manage-paper {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    background: var(--paper);
    border-radius: 0;
    box-shadow:
      0 1px 0 rgba(0, 0, 0, 0.04),
      0 18px 50px rgba(0, 0, 0, 0.30);
    overflow: hidden;
  }

  /* Tabs sit centered at the top of the paper. */
  /* Square segmented toggle — matches the host-folder sub-tabs: a centered
     track with a filled active segment, sharp corners. */
  .manage-tabs {
    display: flex;
    width: fit-content;
    max-width: 100%;
    margin: 18px auto;
    gap: 0;
    padding: 4px;
    background: rgba(0, 0, 0, 0.06);
    border: 1px solid rgba(0, 0, 0, 0.10);
    border-radius: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .manage-tabs::-webkit-scrollbar { display: none; }
  /* Same reasoning as the folder's host-tabs: `margin: auto` centres a
     strip that overflows, which starts the row mid-word. Seven office tabs
     hide 207px on a phone, so this one needs it more. (Aug 11) */
  @media (max-width: 800px) {
    .manage-tabs { margin-left: 0; margin-right: 0; max-width: none; }
  }
  /* Same edge-fade contract as the folder's host-tabs. */
  .manage-tabs.can-scroll-right {
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, black calc(100% - 32px), transparent);
  }
  .manage-tabs.can-scroll-left {
    -webkit-mask-image: linear-gradient(to left, black calc(100% - 32px), transparent);
    mask-image: linear-gradient(to left, black calc(100% - 32px), transparent);
  }
  .manage-tabs.can-scroll-left.can-scroll-right {
    -webkit-mask-image: linear-gradient(to right, transparent, black 32px, black calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, transparent, black 32px, black calc(100% - 32px), transparent);
  }
  .manage-tab {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    color: var(--ink-soft);
    text-decoration: none;
    padding: 9px 18px;
    border-radius: 0;
    white-space: nowrap;
    transition: background 0.12s ease, color 0.12s ease;
  }
  .manage-tab:hover {
    color: var(--ink);
    background: var(--hover-wash);
    text-decoration: none;
  }
  .manage-tab.active,
  .manage-tab.active:hover {
    background: var(--ink);
    color: var(--paper);
  }

  /* ── Page body ───────────────────────────────────────────── */
  .manage-paper-body { padding: 32px 40px 48px; }
  .manage-page {
    padding: 0;
  }

  /* The /manage paper speaks in pills — tabs, role badges, year chips,
     filter pills are all round, so the CTAs are too. */
  .manage-paper .btn,
  .manage-paper .btn-paper,
  .manage-paper .btn-paper--danger { border-radius: 999px; }
  .manage-page-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 20px;
  }
  .manage-page-h {
    font-family: var(--display);
    font-style: normal;
    font-weight: var(--weight-semibold);
    font-size: 26px;
    line-height: 1.15;
    margin: 0;
    color: var(--ink);
  }
  .manage-page-rollup {
    font-size: 13px;
    color: var(--ink-soft);
    margin: 6px 0 0;
  }
  .manage-crumb {
    font-size: 12px;
    margin: 0 0 12px;
  }
  .manage-crumb a {
    color: var(--ink-soft);
    text-decoration: none;
    border-bottom: 1px solid var(--hover-edge);
    padding-bottom: 1px;
  }
  .manage-crumb a:hover { color: var(--ink); border-bottom-color: var(--ink); }

  /* ── Flash banners ───────────────────────────────────────────
     Quiet slate-tinted notice — same low-opacity surface used for the
     host sub-tabs etc. No coloured left bar; notice and alert read the
     same (the message text carries the meaning). */
  .manage-flash {
    margin: 0 0 16px;
    padding: 12px 16px;
    background: rgba(0, 0, 0, 0.05);
    border: 1px solid var(--hover-edge);
    border-radius: 0;
    font-size: 14px;
    line-height: 1.5;
    color: var(--ink);
  }

  /* ── Filter bar ──────────────────────────────────────────── */
  .manage-filter {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 16px;
    padding: 10px 14px;
    background: rgba(0, 0, 0, 0.035);
    border-radius: 0;
  }
  .manage-filter-q {
    flex: 1;
    border: 1px solid var(--hover-edge);
    background: var(--paper);
    font-family: inherit;
    font-size: 14px;
    padding: 8px 12px;
    border-radius: 4px;
    color: var(--ink);
  }
  .manage-filter-q:focus { outline: none; border-color: var(--slate); }
  .manage-filter-roles {
    display: flex;
    gap: 4px;
    flex-shrink: 0;
  }
  .manage-filter-pill {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    color: var(--ink-soft);
    text-decoration: none;
    padding: 6px 10px;
    border-radius: 999px;
    transition: background 0.12s ease, color 0.12s ease;
  }
  .manage-filter-pill:hover {
    background: var(--hover-wash);
    color: var(--ink);
    text-decoration: none;
  }
  .manage-filter-pill.active {
    background: var(--ink);
    color: var(--paper);
  }

  /* ── Tables ──────────────────────────────────────────────── */
  .manage-table-wrap {
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 0;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .manage-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
  }
  .manage-table th {
    text-align: left;
    font-family: var(--sans);
    font-weight: var(--weight-bold);
    color: var(--ink-faint);
    padding: 12px 16px;
    background: rgba(0, 0, 0, 0.02);
    border-bottom: 1px solid var(--paper-edge);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
  }
  .manage-table th.right { text-align: right; }
  .manage-table td {
    padding: 12px 16px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
    color: var(--ink);
    vertical-align: middle;
  }
  .manage-table td.right { text-align: right; }
  .manage-table tr:last-child td { border-bottom: none; }
  .manage-table tr:hover td { background: var(--hover-wash); }
  .manage-table .btn-quiet { white-space: nowrap; }

  .manage-row-person {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    color: inherit;
  }
  .manage-row-person:hover { text-decoration: none; }
  .manage-row-person:hover .manage-row-name { color: var(--slate); }
  .manage-row-name {
    font-family: var(--display);
    font-size: 15px;
    color: var(--ink);
    line-height: 1.2;
    transition: color 0.12s ease;
  }
  .manage-row-email {
    font-size: 12.5px;
    color: var(--ink-soft);
    margin-top: 2px;
  }

  /* Year chips. */
  .manage-year-chips {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 4px;
  }
  .manage-year-chip {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.04em;
    color: var(--slate);
    background: rgba(0, 0, 0, 0.05);
    border: 1px solid var(--hover-edge);
    border-radius: 999px;
    padding: 2px 8px;
    line-height: 1.4;
  }

  /* Per-row actions menu. */
  .manage-row-actions {
    position: relative;
    display: inline-block;
  }
  .manage-row-actions[open] .manage-row-actions-trigger {
    background: rgba(0, 0, 0, 0.08);
  }
  .manage-row-actions-trigger {
    list-style: none;
    cursor: pointer;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--ink-soft);
    font-size: 16px;
    line-height: 1;
    user-select: none;
  }
  .manage-row-actions-trigger::-webkit-details-marker { display: none; }
  .manage-row-actions-trigger:hover {
    background: var(--hover-wash-strong);
    color: var(--ink);
  }
  .manage-row-actions-menu {
    position: absolute;
    top: calc(100% + 4px);
    right: 0;
    z-index: 10;
    min-width: 200px;
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 0;
    box-shadow: 0 8px 24px rgba(20, 15, 5, 0.18);
    padding: 6px;
    text-align: left;
  }
  .manage-row-action {
    display: block;
    padding: 8px 12px;
    border-radius: 4px;
    font-size: 13px;
    color: var(--ink);
    text-decoration: none;
  }
  .manage-row-action:hover {
    background: var(--hover-wash);
    text-decoration: none;
    color: var(--ink);
  }
  .manage-row-action--danger { color: var(--required); }
  .manage-row-action--danger:hover { background: rgba(185, 74, 74, 0.08); color: var(--required); }
  /* A button_to-rendered action (DELETE) reads as a plain menu item: let the
     button take the row directly and strip the native button chrome. */
  .manage-row-actions-menu form { display: contents; }
  button.manage-row-action {
    width: 100%;
    text-align: left;
    border: 0;
    background: none;
    cursor: pointer;
  }
  .manage-row-action-divider {
    height: 1px;
    background: rgba(0, 0, 0, 0.08);
    margin: 4px 0;
  }

  /* A primary CTA paired with the more-actions menu, right-aligned in a cell. */
  .manage-row-end {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    justify-content: flex-end;
  }

  /* Small pill button for table rows ("Manage"). Paper-toned so a column
     of them stays quiet; fills with ink on hover. */
  .manage-row-btn {
    appearance: none;
    -webkit-appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 26px;
    padding: 0 14px;
    border: 1px solid var(--ink-faint);
    border-radius: 999px;
    background: transparent;
    color: var(--ink-soft);
    font-family: var(--sans);
    font-size: 12px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.02em;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
  }
  .manage-row-btn:hover {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
    text-decoration: none;
  }

  /* Host avatars + first names inside a Gatherings row. */
  .manage-hosts {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 12px;
  }
  .manage-host {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    color: var(--ink);
    white-space: nowrap;
  }
  .manage-host-name { line-height: 1.2; }

  /* "Happening now" pill on the in-progress gathering. */
  .manage-now-badge {
    display: inline-block;
    margin-left: 4px;
    font-family: var(--sans);
    font-size: 9px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    color: var(--paid);
    background: color-mix(in srgb, var(--paid) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--paid) 30%, transparent);
    border-radius: 999px;
    padding: 1px 7px;
    vertical-align: middle;
    white-space: nowrap;
  }

  /* Past gatherings read back quieter — muted names, faded folder glyph. */
  .manage-section--past .manage-row-name { color: var(--ink-soft); }
  .manage-section--past .manage-folder-glyph { opacity: 0.5; }
  .manage-section--past .manage-table tr:hover .manage-row-name { color: var(--slate); }

  /* ── Members "table" — a div-grid (not a real <table>) so a row can
     morph in place into a compact inline editor. Columns are fixed-width
     so the header and every row line up exactly. */
  .manage-mtable {
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 0;
    overflow: hidden;
  }
  .manage-mrow-summary {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 120px 150px 110px 84px;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
  }
  .manage-mtable-head {
    background: rgba(0, 0, 0, 0.02);
    border-bottom: 1px solid var(--paper-edge);
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: var(--weight-bold);
  }
  .manage-mrow { border-bottom: 1px solid rgba(0, 0, 0, 0.05); }
  .manage-mrow:last-child { border-bottom: none; }
  .manage-mrow:not(.expanded):hover .manage-mrow-summary { background: var(--hover-wash); }
  .manage-mrow.expanded { background: var(--hover-wash-strong); }

  .manage-mrow-cell { min-width: 0; }
  .manage-mrow-cell--act { text-align: right; }
  .manage-mrow-cell--person {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  button.manage-mrow-cell--person {
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
  }
  button.manage-mrow-cell--person:hover .manage-row-name { color: var(--slate); }
  .manage-mrow-id { display: flex; flex-direction: column; min-width: 0; }
  .manage-mrow-id .manage-row-name,
  .manage-mrow-id .manage-row-email {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  /* ── Inline morph editor ──────────────────────────────────────
     When a row is expanded the summary swaps out for a compact form
     (built from the standard .nom-* fields) in the same band of space. */
  .manage-mrow-edit { display: none; padding: 14px 16px 16px; }
  .manage-mrow.expanded .manage-mrow-summary { display: none; }
  .manage-mrow.expanded .manage-mrow-edit { display: block; }

  .manage-medit-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
    font-family: var(--display);
    font-size: 16px;
    color: var(--ink);
  }

  /* Compact nom-fields inside the editor — tighter than the form pages. */
  .manage-mrow-edit .nom-grid-2 { gap: 12px 18px; }
  .manage-mrow-edit .nom-field { margin-bottom: 0; }
  .manage-mrow-edit .nom-input,
  .manage-mrow-edit .nom-select { font-size: 14px; padding: 7px 2px; }
  .manage-mrow-edit .nom-label { font-size: 12px; margin-bottom: 3px; }

  .manage-medit-roles {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    padding-top: 4px;
  }
  .manage-medit-role {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 14px;
    color: var(--ink);
    cursor: pointer;
  }

  .manage-medit-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid rgba(0, 0, 0, 0.07);
  }
  .manage-medit-actions-right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  /* "Remove from platform" is button_to — let its button sit in the row. */
  .manage-medit-actions form { display: contents; }

  .manage-medit-links {
    display: flex;
    flex-direction: column;
    gap: 7px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px dashed var(--hover-edge);
  }
  .manage-medit-links form { display: inline; }
  .manage-medit-link {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-size: 12.5px;
    color: var(--ink-soft);
  }
  .manage-medit-link code {
    font-family: ui-monospace, SFMono-Regular, monospace;
    font-size: 11px;
    color: var(--ink-soft);
    background: rgba(0, 0, 0, 0.04);
    padding: 2px 6px;
    border-radius: 3px;
  }
  .manage-medit-link-tag {
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: var(--weight-bold);
    white-space: nowrap;
  }

  /* Pill button variants for the editor — filled (Save) and danger (Remove). */
  .manage-row-btn--go {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
  }
  .manage-row-btn--go:hover { background: var(--ink-hover); border-color: var(--ink-hover); color: var(--paper); }
  .manage-row-btn--danger { border-color: rgba(185, 74, 74, 0.5); color: var(--required); }
  .manage-row-btn--danger:hover { background: var(--required); border-color: var(--required); color: var(--paper); }

  /* ── Members table on mobile — collapsed rows fold to two tight lines:
     [avatar + name/email ........... Edit] / [role · years]. The role
     badge and exchange-year chips always drop to their own second line
     (the ::after spacer forces the wrap) so they never crowd the Edit
     button or split apart unpredictably. */
  @media (max-width: 860px) {
    .manage-mtable-head { display: none; }
    .manage-mrow-summary {
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      gap: 6px 10px;
      padding: 10px 14px;
    }
    /* flex-basis 0 (not auto): with wrap on, auto lets a long email's
       max-content width fill the line and shove Edit underneath it — a
       30-character member email did exactly that at 390px. Basis 0 keeps
       both cells on line one and the email truncates instead. */
    .manage-mrow-cell--person { flex: 1 1 0; min-width: 0; order: 1; }
    .manage-mrow-cell--act    { order: 2; flex: 0 0 auto; }
    .manage-mrow-summary::after {
      content: "";
      flex-basis: 100%;
      height: 0;
      order: 3;
    }
    .manage-mrow-cell--role   { order: 4; flex: 0 0 auto; }
    .manage-mrow-cell--years  { order: 5; flex: 0 0 auto; }
    .manage-mrow-cell--seen   { display: none; }
    .manage-mrow-edit { padding: 12px 14px 14px; }
  }

  .manage-empty {
    padding: 32px 0;
    text-align: center;
  }

  /* ── Forms (Add/Edit person) ─────────────────────────────── */
  .manage-form {
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 0;
    padding: 32px 36px;
    max-width: 720px;
  }
  .manage-form-section {
    padding-bottom: 24px;
    margin-bottom: 24px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
  }
  .manage-form-section:last-of-type {
    border-bottom: none;
    margin-bottom: 0;
  }
  .manage-form-section .host-section-head {
    margin: 0 0 14px;
  }

  .manage-radio-list {
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
  .manage-radio {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 4px;
    cursor: pointer;
  }
  .manage-radio:hover { background: var(--hover-wash); }
  .manage-radio input { margin-top: 4px; flex-shrink: 0; }
  .manage-radio-title {
    font-size: 14px;
    font-weight: var(--weight-semibold);
    color: var(--ink);
    line-height: 1.3;
  }
  .manage-radio-help {
    font-size: 12.5px;
    color: var(--ink-soft);
    line-height: 1.5;
    margin-top: 2px;
  }

  .manage-check-group {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .manage-check {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 6px 8px;
    border-radius: 4px;
    font-size: 14px;
    color: var(--ink);
    line-height: 1.5;
    cursor: pointer;
  }
  .manage-check:hover { background: var(--hover-wash); }
  .manage-check input { margin-top: 4px; flex-shrink: 0; }

  .manage-form-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    margin-top: 28px;
    padding-top: 20px;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
  }
  .manage-form-actions--with-danger {
    justify-content: space-between;
  }
  /* button_to renders its button inside a <form>; let the button take part
     in the flex row directly (same trick as the avatar menu's sign-out). */
  .manage-form-actions form { display: contents; }

  /* Person edit page header — large avatar + identity + quick actions. */
  .manage-person-head {
    align-items: center;
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 0;
    padding: 20px 24px;
  }
  .manage-person-id {
    display: flex;
    align-items: center;
    gap: 16px;
  }
  .manage-person-quick {
    display: flex;
    gap: 10px;
    flex-shrink: 0;
  }

  /* Tokens list inside the edit page. */
  .manage-tokens {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .manage-tokens li {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
    font-size: 13px;
  }
  .manage-tokens li:last-child { border-bottom: none; }
  .manage-token-label {
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: var(--weight-bold);
    width: 130px;
    flex-shrink: 0;
  }
  .manage-token-val {
    flex: 1;
    font-family: ui-monospace, SFMono-Regular, monospace;
    font-size: 12px;
    color: var(--ink-soft);
    background: rgba(0, 0, 0, 0.04);
    padding: 4px 8px;
    border-radius: 3px;
  }

  /* ── Sections (Logistics, Place, Gatherings) ────────────── */
  .manage-section {
    margin-top: 36px;
  }
  /* When a section is the first thing under the page heading (Gatherings),
     don't double up the gap — the section head already carries its own. */
  .manage-page-head + .manage-section {
    margin-top: 8px;
  }
  .manage-section .host-section-head {
    margin-bottom: 16px;
  }

  /* Flag row at top of Logistics. */
  .manage-flag-row {
    list-style: none;
    margin: 0 0 28px;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
  }
  .manage-flag {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px 16px;
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 0;
  }
  .manage-flag--warn { border-color: rgba(185, 110, 50, 0.35); background: rgba(185, 110, 50, 0.05); }
  .manage-flag--info { border-color: var(--hover-edge); background: rgba(0, 0, 0, 0.03); }
  .manage-flag-count {
    font-family: var(--display);
    font-style: normal;
    font-weight: var(--weight-semibold);
    font-size: 26px;
    line-height: 1;
    color: var(--ink);
  }
  .manage-flag-label {
    font-size: 11px;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--ink-soft);
    font-weight: var(--weight-bold);
  }

  /* Place lists + prose. */
  .manage-place-list {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .manage-place-list li {
    padding: 10px 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
    font-size: 14px;
    color: var(--ink);
    line-height: 1.5;
  }
  .manage-place-list li:last-child { border-bottom: none; }
  .manage-place-prose {
    font-size: 14px;
    line-height: 1.65;
    color: var(--ink);
    margin: 0 0 12px;
  }
  .manage-place-prose:last-child { margin-bottom: 0; }

  .manage-folder-glyph {
    font-size: 22px;
    line-height: 1;
    flex-shrink: 0;
  }

  /* ── Activity ────────────────────────────────────────────── */
  .manage-activity {
    list-style: none;
    margin: 0;
    padding: 0;
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: 0;
    overflow: hidden;
  }
  .manage-activity-row {
    display: grid;
    grid-template-columns: 130px 1fr;
    gap: 16px;
    padding: 14px 18px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.05);
    font-size: 14px;
  }
  .manage-activity-row:last-child { border-bottom: none; }
  .manage-activity-when {
    font-family: var(--sans);
    font-size: 12px;
    letter-spacing: 0.04em;
    color: var(--ink-faint);
  }
  .manage-activity-body { color: var(--ink); }
  .manage-activity-where {
    display: inline-block;
    margin-left: 8px;
    font-size: 12px;
    color: var(--slate);
    background: rgba(0, 0, 0, 0.04);
    border: 1px solid var(--hover-edge);
    border-radius: 999px;
    padding: 1px 8px;
  }

  /* ── Role-badge variants ─────────────────────────────────── */
  .role-badge {
    display: inline-flex;
    align-items: center;
    font-family: var(--sans);
    font-size: 10px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    padding: 2px 9px;
    border-radius: 999px;
    border: 1px solid;
  }
  .role-badge--member {
    color: var(--ink-soft);
    background: rgba(0, 0, 0, 0.04);
    border-color: rgba(0, 0, 0, 0.14);
  }
  .role-badge--host {
    color: var(--pip-host-fg);
    background: rgba(138, 100, 41, 0.08);
    border-color: rgba(138, 100, 41, 0.30);
  }
  .role-badge--organizer {
    color: var(--paper);
    background: var(--slate);
    border-color: var(--slate);
  }

  /* ── Stays calendar (month grid) ─────────────────────────── */
  .manage-page-actions {
    display: flex;
    gap: 6px;
    align-items: center;
  }
  .scal-monthbar {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    margin: 0 0 20px;
  }
  .scal-monthbar-center {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 28px;
  }
  .scal-monthbar-end {
    display: flex;
    justify-content: flex-end;
  }
  .scal-monthbar-label {
    font-family: var(--display);
    font-style: normal;
    font-weight: var(--weight-semibold);
    font-size: 22px;
    color: var(--ink);
    margin: 0;
    min-width: 200px;
    text-align: center;
  }
  .scal-monthbar-arrow {
    font-size: 18px;
    color: var(--ink-soft);
    text-decoration: none;
    padding: 4px 12px;
    border-radius: 4px;
    transition: background 120ms ease, color 120ms ease;
  }
  .scal-monthbar-arrow:hover {
    color: var(--ink);
    background: rgba(0,0,0,0.05);
  }
  .scal-monthbar-today {
    font-size: 11px;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--ink-soft);
    text-decoration: none;
    padding: 6px 12px;
    border-radius: 4px;
    border: 1px solid var(--hover-edge);
    transition: background 120ms ease, color 120ms ease;
  }
  .scal-monthbar-today:hover {
    color: var(--ink);
    background: rgba(0,0,0,0.04);
  }
  .scal-legend {
    list-style: none;
    padding: 0;
    margin: 0 0 14px;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    font-size: 12px;
    color: var(--ink-soft);
  }
  .scal-legend li {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }
  .scal-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
  }
  .scal-grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 0;
    border: 1px solid rgba(0,0,0,0.08);
    border-radius: 4px;
    position: relative;
    overflow: hidden;
  }
  .scal-dow {
    background: rgba(0,0,0,0.04);
    padding: 6px 8px;
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.10em;
    color: var(--ink-soft);
    text-align: center;
    border-bottom: 1px solid rgba(0,0,0,0.08);
  }
  .scal-day {
    background: var(--paper);
    min-height: 110px;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 4px;
    /* Only horizontal week dividers — no vertical day dividers, so gathering
       bars span flush across consecutive days with zero visual seam. */
    border-bottom: 1px solid rgba(0,0,0,0.08);
  }
  .scal-day--out { background: rgba(0,0,0,0.02); }
  .scal-day--out .scal-day-num { color: var(--ink-faint); }
  .scal-day--today { background: var(--pink-tag-bg); }
  .scal-day--today .scal-day-num { font-weight: var(--weight-semibold); color: var(--pink); }
  .scal-day-num {
    font-size: 11px;
    color: var(--ink-soft);
    text-align: right;
    padding: 6px 8px 0;
  }
  .scal-bars {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 4px;
  }
  .scal-bar {
    height: 14px;
    display: flex;
    align-items: center;
    padding: 0 4px;
    color: #fff;
    font-size: 10px;
    line-height: 1;
    overflow: hidden;
    /* Square edges by default — bars look continuous across day cells. */
    border-radius: 0;
  }
  .scal-bar--start { border-top-left-radius: 3px; border-bottom-left-radius: 3px; padding-left: 6px; }
  .scal-bar--end   { border-top-right-radius: 3px; border-bottom-right-radius: 3px; padding-right: 6px; }
  .scal-bar--empty { background: transparent !important; }
  .scal-bar-label {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.02em;
  }

  .scal-entries {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    gap: 4px 6px;
    padding: 0 6px 8px;
  }
  .scal-entry {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    line-height: 1.25;
    color: var(--ink);
    max-width: 100%;
    cursor: default;
  }
  .scal-avatar {
    position: relative;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    overflow: hidden;
    flex-shrink: 0;
    box-shadow: 0 0 0 1.5px var(--ring, #888);
    background: var(--paper-warm-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .scal-avatar img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
  }
  .scal-avatar-initials {
    font-size: 7px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.02em;
    color: var(--ink-soft);
    text-transform: uppercase;
  }
  /* Gathering-less ("solo") stays read with a dotted ring instead of a
     solid one — same lodging colour, just a different stitch. */
  .scal-entry--solo .scal-avatar {
    box-shadow: none;
    outline: 1.5px dotted var(--ring, #888);
    outline-offset: -0.5px;
  }
  .scal-entry-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  /* CSS tooltip — chats instantly on hover (vs native title's ~1s delay) */
  .scal-entry[data-tooltip]:hover::after,
  .scal-entry[data-tooltip]:focus::after {
    content: attr(data-tooltip);
    position: absolute;
    bottom: calc(100% + 6px);
    left: 50%;
    transform: translateX(-50%);
    background: rgba(20, 15, 5, 0.92);
    color: #fff;
    font-size: 11px;
    line-height: 1.3;
    padding: 5px 8px;
    border-radius: 4px;
    white-space: nowrap;
    pointer-events: none;
    z-index: 20;
    box-shadow: 0 2px 8px rgba(0,0,0,0.18);
  }
  .scal-entry[data-tooltip]:hover::before,
  .scal-entry[data-tooltip]:focus::before {
    content: "";
    position: absolute;
    bottom: calc(100% + 1px);
    left: 50%;
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: rgba(20, 15, 5, 0.92);
    pointer-events: none;
    z-index: 20;
  }

  /* ── Mobile ──────────────────────────────────────────────────
     Borrowed posture from Circle: paper hugs the viewport, tabs
     wrap, dense tables scroll horizontally, headers stack, action
     menus compress. */
  @media (max-width: 1024px) {
    .stay-shell.manage-shell { padding: 84px var(--space-4) var(--space-7); }
    .manage-paper-body { padding: 28px 28px 40px; }
  }

  @media (max-width: 768px) {
    .stay-shell.manage-shell { padding: 80px 12px var(--space-6); }
    .manage-paper {
      border-radius: 4px;
      box-shadow:
        0 1px 0 rgba(0, 0, 0, 0.04),
        0 8px 22px rgba(20, 15, 5, 0.18);
    }
    .manage-paper-body { padding: 22px 18px 32px; }

    .manage-tabs {
      flex-wrap: nowrap;
      overflow-x: auto;
      max-width: 100%;
      gap: 0;
      padding: 4px;
      -webkit-overflow-scrolling: touch;
    }
    .manage-tab {
      font-size: 10px;
      letter-spacing: 0.10em;
      padding: 9px 12px;
    }

    .manage-page-head {
      flex-direction: column;
      align-items: flex-start;
      gap: 12px;
    }
    .manage-page-h { font-size: 22px; }

    .manage-filter {
      flex-direction: column;
      align-items: stretch;
      gap: 10px;
    }
    .manage-filter-roles { flex-wrap: wrap; }

    .manage-table {
      min-width: 640px;
      font-size: 13px;
    }
    .manage-table th, .manage-table td {
      padding: 10px 12px;
    }

    /* Flag row — 2 cols. */
    .manage-flag-row {
      grid-template-columns: repeat(2, 1fr);
      gap: 8px;
    }

    /* Forms — full-width, less padding. */
    .manage-form {
      padding: 22px 18px;
      border-radius: 0;
    }
    .nom-grid-2 { grid-template-columns: 1fr; }

    .manage-form-actions {
      flex-direction: column-reverse;
      align-items: stretch;
      gap: 10px;
    }
    .manage-form-actions--with-danger {
      flex-direction: column-reverse;
    }
    .manage-form-actions--with-danger > .row {
      flex-direction: column-reverse;
      gap: 10px;
    }
    .manage-form-actions .btn,
    .manage-form-actions .btn-paper { width: 100%; }

    /* Person edit head — stack identity + quick actions. */
    .manage-person-head { flex-direction: column; align-items: flex-start; gap: 16px; }
    .manage-person-quick { flex-wrap: wrap; }

    /* Tokens row stacks. */
    .manage-tokens li {
      flex-wrap: wrap;
      gap: 6px 10px;
    }
    .manage-token-label { width: auto; }
    .manage-token-val { flex: 1 1 100%; }

    /* Activity rows — when on top of each other. */
    .manage-activity-row {
      grid-template-columns: 1fr;
      gap: 4px;
    }

    /* Logistics / await list — wrap rather than overflow. */
    .host-await-list li {
      flex-wrap: wrap;
      gap: 8px 10px;
    }
    .host-await-list li .muted { flex: 1 1 100%; }
  }

  /* ── Stay requests (Requests tab) ──────────────────────────────────
     A feed of cards — one per gathering-less stay a member has asked
     for. Each carries a lodging picker (greyed where it can't fit) +
     Approve, and a tucked-away "turn down" form. */
  .manage-tab-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    margin-left: 5px;
    border-radius: 999px;
    background: var(--pink);
    color: #fff;
    font-size: 11px;
    font-weight: var(--weight-bold);
    line-height: 1;
    vertical-align: middle;
  }
  .manage-tab.active .manage-tab-badge { background: var(--pink); }

  .manage-requests {
    display: flex;
    flex-direction: column;
    gap: var(--space-5);
    margin-top: var(--space-5);
  }
  .manage-request {
    background: var(--paper);
    border: 1px solid var(--hover-edge);
    border-radius: 0;
    padding: var(--space-5) var(--space-6);
    box-shadow: 0 1px 0 rgba(0, 0, 0, 0.03);
  }
  .manage-request-head {
    display: flex;
    align-items: center;
    gap: var(--space-4);
  }
  .manage-request-id { min-width: 0; }
  .manage-request-name {
    font-family: var(--display);
    font-style: normal;
    font-weight: var(--weight-medium);
    font-size: 17px;
    color: var(--ink);
    line-height: 1.2;
  }
  .manage-request-meta {
    font-family: var(--sans);
    font-size: 12.5px;
    color: var(--ink-faint);
    margin-top: 2px;
  }
  /* Clicking the avatar opens the same profile modal as the roster. */
  .manage-request-avatar {
    flex-shrink: 0;
    display: inline-flex;
    text-decoration: none;
  }
  /* The note the requester left — their own words, shown in full so the
     host reads the background as the applicant's input, not a chip. */
  .manage-request-note {
    margin: var(--space-4) 0 0 calc(var(--space-3) + 24px); /* indent past the avatar column */
    padding: var(--space-4);
    background: rgba(0, 0, 0, 0.045);
  }
  .manage-request-note-label {
    font-family: var(--sans);
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    color: var(--ink-faint);
    margin: 0 0 var(--space-2);
  }
  .manage-request-note-body {
    font-family: var(--sans);
    font-size: 14px;
    line-height: 1.6;
    color: var(--ink);
    margin: 0;
    white-space: pre-wrap;
  }
  .manage-request-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--space-4);
    margin-top: var(--space-5);
    padding-top: var(--space-4);
    border-top: 1px solid rgba(0, 0, 0, 0.10);
  }
  .manage-request-approve {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
  }
  .manage-request-lodging { max-width: 280px; }
  .manage-request-decline { margin-left: auto; }
  .manage-request-decline-toggle { cursor: pointer; list-style: none; }
  .manage-request-decline-toggle::-webkit-details-marker { display: none; }
  .manage-request-decline-toggle::marker { content: ""; }
  .manage-request-decline-form {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-3);
    flex-wrap: wrap;
  }
  .manage-request-decline-form .input { min-width: 240px; }

  /* Turn down, honestly (Neal, Aug 3): the toggle opens a full-width panel
     naming the two ways to say no — quietly (nothing sent) or with a note
     (emailed). Open, it takes the whole actions row so the choice reads
     as one moment, not a crowded corner. */
  .manage-request-actions .request-decline[open] { flex-basis: 100%; margin-left: 0; }
  .request-decline-ways {
    margin-top: var(--space-3);
    padding: var(--space-4);
    border: 1px solid rgba(0, 0, 0, 0.10);
    border-radius: 8px;
    display: grid;
    gap: var(--space-4);
  }
  .request-decline-lead {
    font-family: var(--sans);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--ink-soft);
    margin: 0;
  }
  .request-decline-way { display: grid; gap: var(--space-2); justify-items: start; }
  .request-decline-way-title {
    font-family: var(--sans);
    font-size: var(--cap-md);
    letter-spacing: var(--tracking-cap);
    text-transform: uppercase;
    font-weight: var(--weight-bold);
    color: var(--ink-faint);
    margin: 0;
  }
  .request-decline-way-what {
    font-family: var(--sans);
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--ink-soft);
    margin: 0;
  }
  .request-decline-note {
    width: 100%;
    max-width: 480px;
    resize: vertical;
    font-family: var(--sans);
    font-size: 14px;
    line-height: 1.5;
  }
  .request-decline-way form { display: grid; gap: var(--space-3); justify-items: start; width: 100%; }

  /* "Party size" reveal on a pending request — same toggle chrome as the
     "Turn down" one (it borrows .manage-request-decline-toggle on its summary). */
  .manage-request-party-form {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-3);
  }

  /* Inline party-size cell in the confirmed-stays table. */
  .manage-stays-party-form {
    display: flex;
    align-items: center;
    gap: var(--space-3);
  }
  .manage-stays-party-save { padding: 5px 10px; font-size: 12px; }

  /* Section subhead on the Stays tab — "Awaiting a yes" / "Confirmed stays". */
  .manage-subhead {
    font-family: var(--sans);
    font-size: var(--cap-md);
    letter-spacing: var(--tracking-cap-wide);
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: var(--weight-bold);
    margin: var(--space-7) 0 var(--space-4);
  }
  .manage-subhead:first-of-type { margin-top: var(--space-5); }

  /* The confirmed-stays table outgrows the paper on phones. It scrolls
     inside this wrapper, and the same edge-fade contract as .manage-tabs
     (tab-strip toggles the classes) tells a thumb there's more to swipe —
     the Save pill used to sit half-cut at 390px with no hint. */
  .manage-stays-scroll {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .manage-stays-scroll.can-scroll-right {
    -webkit-mask-image: linear-gradient(to right, black calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, black calc(100% - 32px), transparent);
  }
  .manage-stays-scroll.can-scroll-left {
    -webkit-mask-image: linear-gradient(to left, black calc(100% - 32px), transparent);
    mask-image: linear-gradient(to left, black calc(100% - 32px), transparent);
  }
  .manage-stays-scroll.can-scroll-left.can-scroll-right {
    -webkit-mask-image: linear-gradient(to right, transparent, black 32px, black calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, transparent, black 32px, black calc(100% - 32px), transparent);
  }

  /* Plain table of confirmed solo stays. */
  .manage-stays-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--sans);
    font-size: 13.5px;
  }
  .manage-stays-table th {
    text-align: left;
    font-size: var(--cap-md);
    letter-spacing: var(--tracking-cap);
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: var(--weight-bold);
    padding: 0 var(--space-3) var(--space-2);
    border-bottom: 1px solid var(--hover-edge);
  }
  .manage-stays-table td {
    padding: var(--space-3);
    color: var(--ink-soft);
    border-bottom: 1px solid rgba(0, 0, 0, 0.07);
    vertical-align: middle;
  }
  /* Keep this a real <td> — flexing the cell itself drops it out of the table
     layout so its row divider stops lining up with the rest of the row. */
  .manage-stays-person {
    color: var(--ink);
    font-weight: var(--weight-medium);
  }
  .manage-stays-person-id {
    display: flex;
    align-items: center;
    gap: var(--space-3);
  }
  .manage-stays-act { text-align: right; white-space: nowrap; }
  .manage-stays-row--past td { opacity: 0.55; }

  @media (max-width: 768px) {
    .scal-day { min-height: 72px; padding: 4px 4px 6px; }
    .scal-entry { font-size: 10px; }
    .scal-entry-name { max-width: 100%; }
    .manage-request-decline { margin-left: 0; }
  }

  @media (max-width: 480px) {
    .stay-shell.manage-shell { padding: 76px 6px var(--space-5); }
    .manage-paper-body { padding: 18px 14px 28px; }
    .manage-tabs { padding: 4px; gap: 0; }
    .manage-tab { padding: 8px 10px; }
    .manage-flag-row { grid-template-columns: 1fr; }
    .scal-day { min-height: 56px; }
    .scal-day-num { font-size: 10px; }
  }
}

/* Master-calendar additions (Jul 16): party tag + happening chips. */
@layer components {
  .scal-entry-plus {
    color: var(--ink-faint);
    font-size: 10.5px;
    font-weight: var(--weight-semibold);
    margin-left: 2px;
  }
  .scal-hap {
    display: block;
    font-size: 10.5px;
    line-height: 1.3;
    color: var(--ink-soft);
    background: var(--paper-warm);
    border-left: 2px solid var(--ink-faint);
    border-radius: 3px;
    padding: 2px 5px;
    margin-top: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

@layer components {
  /* ── The backdrop library (Jul 16) — organizer-curated scenery hosts
     pick as gathering backgrounds. ── */
  .place-bg-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 12px;
    margin: 12px 0;
  }
  .place-bg-item { display: flex; flex-direction: column; gap: 4px; }
  .place-bg-thumb {
    width: 100%;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--hover-edge);
  }
  .place-bg-remove { align-self: flex-start; font-size: 12px; color: var(--ink-faint); }
  .place-bg-form { display: flex; gap: 10px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
  .place-bg-input { max-width: 340px; }

  /* The stock strip on a gathering's basics rail. */
  .basics-stock {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
    gap: 8px;
    margin: 8px 0 4px;
  }
  .basics-stock-choice { position: relative; cursor: pointer; display: block; }
  .basics-stock-choice input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
  }
  .basics-stock-thumb {
    width: 100%;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    border-radius: 6px;
    border: 2px solid transparent;
    transition: border-color 100ms ease, transform 100ms ease;
  }
  .basics-stock-choice:hover .basics-stock-thumb { transform: scale(1.03); }
  .basics-stock-choice input:checked + .basics-stock-thumb { border-color: var(--ink); }
}

@layer components {
  /* ── The booking book's truth band (Jul 16). ── */
  .stays-truth {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    background: var(--paper);
    border: 1px solid var(--hover-edge);
    border-radius: var(--radius-md);
    padding: 16px 20px;
    margin-bottom: 18px;
  }
  .stays-truth-h {
    font-size: var(--cap-sm);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-cap);
    text-transform: uppercase;
    color: var(--ink-faint);
    margin-bottom: 8px;
  }
  .stays-truth-rows { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
  .stays-truth-rows li { font-size: 13.5px; color: var(--ink-soft); }
  .stays-truth-rows strong { color: var(--ink); }
  .stays-truth-quiet { margin: 0; font-size: 13.5px; }
  @media (max-width: 700px) { .stays-truth { grid-template-columns: 1fr; } }
}

@layer components {
  /* Payments section in organizer Settings (Jul 30) */
  .manage-rule { border: none; border-top: 1px solid var(--hover-edge); margin: 28px 0 20px; }
  .pay-provider-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 8px;
    margin-top: 8px;
  }
  .pay-provider-opt {
    display: flex; align-items: center; gap: 8px;
    padding: 10px 12px; border: 1px solid var(--hover-edge);
    border-radius: var(--radius-xs, 6px); cursor: pointer;
    transition: border-color 0.12s, background 0.12s;
  }
  .pay-provider-opt:hover { border-color: var(--ink-faint); }
  .pay-provider-opt:has(input:checked) { border-color: var(--ink); background: var(--hover-wash); }
  .pay-provider-name { font-size: 13.5px; font-weight: var(--weight-semibold); color: var(--ink); }
  .pay-provider-tag {
    margin-left: auto; font-size: 11px; letter-spacing: 0.04em;
    color: var(--ink-faint); text-transform: uppercase; font-weight: var(--weight-semibold);
    flex-shrink: 0; white-space: nowrap; padding-right: 2px;
  }
  .pay-proof-check { display: flex; gap: 8px; align-items: flex-start; cursor: pointer; font-size: 13px; color: var(--ink-soft); line-height: 1.5; }
  .pay-proof-check input { margin-top: 3px; }

  /* The honest first option — "No contributions" spans the grid so its
     hint has room to say what it means. */
  .pay-provider-opt--none { grid-column: 1 / -1; align-items: flex-start; }
  .pay-provider-opt--none input { margin-top: 3px; }
  .pay-provider-body { display: flex; flex-direction: column; gap: 2px; }
  .pay-provider-hint {
    font-size: 12px; font-weight: var(--weight-normal);
    color: var(--ink-soft); line-height: 1.4;
  }

  /* "Your community's words" — the vocabulary fold beneath the essentials. */
  .settings-words { margin: 4px 0 20px; }
  .settings-words-summary {
    cursor: pointer;
    font-size: var(--cap-lg);
    letter-spacing: var(--tracking-cap-tight);
    text-transform: uppercase;
    font-weight: var(--weight-semibold);
    color: var(--ink-soft);
    padding: 6px 0;
    list-style-position: outside;
  }
  .settings-words-summary:hover { color: var(--ink); }
  .settings-words[open] .settings-words-summary { margin-bottom: 14px; }
}

@layer components {
  /* "How it reads" — the composed-sentence preview atop Settings. */
  .nom-reads-panel {
    background: var(--paper-warm);
    border: 1px solid var(--paper-edge);
    border-radius: var(--radius-md);
    padding: 14px 18px;
    margin-bottom: 26px;
    max-width: 560px;
  }
  .nom-reads-title {
    margin: 0 0 8px;
    font-size: var(--cap-lg);
    letter-spacing: var(--tracking-cap-tight);
    text-transform: uppercase;
    font-weight: var(--weight-semibold);
    color: var(--ink-faint);
  }
  .nom-reads-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: 6px;
    font-size: 14px;
    color: var(--ink-soft);
    font-style: italic;
  }
}

@layer components {
  /* The setup checklist — essentials with their done-ness. */
  .setup-checklist-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; font-size: 14px; }
  .setup-checklist-item { display: flex; align-items: baseline; gap: 8px; color: var(--ink-soft); }
  .setup-checklist-item--done { color: var(--ink-faint); }
  .setup-checklist-mark { font-weight: var(--weight-bold); flex: none; }
  .setup-checklist-item--done .setup-checklist-mark { color: var(--paid); }
  .setup-checklist-label { font-weight: var(--weight-semibold); color: inherit; }
  .setup-checklist-note { color: var(--ink-faint); }
  .setup-checklist-foot { margin: 10px 0 0; font-size: 12.5px; color: var(--ink-faint); }
  .setup-checklist-foot a { color: inherit; text-decoration: underline; }
}

@layer components {
  /* ── The contact sheet — a roster made to be printed ──────────────────
     One warm page on screen; the @media print block below strips the app
     away and leaves black-on-white paper. Rendered by
     shared/_contact_sheet for the OFFICE roster, and reused by
     gathering/report.html.erb — the folder's own contact sheet was absorbed
     into the report on Aug 6. */
  .contact-sheet {
    max-width: 720px;
    margin: 40px auto 80px;
    padding: 44px 48px;
    background: var(--paper);
    border: 1px solid var(--paper-edge);
    border-radius: var(--radius-lg);
    box-shadow: 0 12px 32px var(--paper-shadow);
  }
  .contact-sheet-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 28px;
  }
  .contact-sheet-head { margin-bottom: 24px; }
  .contact-sheet-title {
    font-family: var(--display);
    font-size: 26px;
    font-weight: var(--weight-bold);
    color: var(--ink);
    margin: 6px 0 2px;
  }
  .contact-sheet-meta { margin: 0; font-size: 14px; color: var(--ink-soft); }
  .contact-sheet-empty { margin: 24px 0 0; }

  .contact-sheet-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
  }
  .contact-sheet-table th {
    text-align: left;
    font-size: var(--cap-sm);
    letter-spacing: var(--tracking-cap);
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: var(--weight-semibold);
    padding: 0 12px 8px 0;
    border-bottom: 1px solid var(--ink-faint);
  }
  .contact-sheet-table td {
    padding: 9px 12px 9px 0;
    border-bottom: 1px solid var(--hover-edge);
    color: var(--ink-soft);
    vertical-align: top;
  }
  .contact-sheet-name { color: var(--ink); font-weight: var(--weight-semibold); white-space: nowrap; }

  /* On a phone the sheet keeps every column on screen: tighter paper
     margins, names allowed to wrap, long emails allowed to break. */
  @media (max-width: 480px) {
    .contact-sheet { padding: 28px 18px; margin: 16px auto 60px; }
    .contact-sheet-name { white-space: normal; }
    .contact-sheet-table td { word-break: break-word; }
  }

  /* The quiet doorway — sits inside a rollup line, inherits its color. */
  .contact-sheet-link {
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
  }
  .contact-sheet-link:hover { color: var(--ink); }

  /* Print: the sheet IS the page. App chrome, buttons, landscape — gone.
     Hard black-on-white is the point of the medium here, not a theme,
     so these are the only deliberate non-token colors. */
  /* ── THE LOOK BOOK ────────────────────────────────────────────────
     The report's other shape: a face at a size you can recognise across a
     kitchen, the name under it, and whatever columns the host ticked under
     that. Rides the .contact-sheet chrome, so it inherits the same paper on
     screen and the same @media print stripping below — Print / Save as PDF
     is the deliverable, and there is no PDF generator to keep alive.
     (Aug 18, for the food team and for Brenda's document.) */
  .lookbook {
    list-style: none;
    margin: 24px 0 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 26px 20px;
  }
  .lookbook-card { break-inside: avoid; text-align: left; }
  /* Tokens, not paper colors. These were originally #3f3a33 on #ece7dd —
     near-black on cream, which is right for paper and unreadable on the dark
     theme, where an email under a face came out barely darker than the page.
     Nothing was lost on print by fixing it: the print block below already
     forces `.contact-sheet, .contact-sheet * { color: #000 !important }`, so
     those hardcoded values never reached a printer in the first place. They
     only ever applied to the screen, and only worked on half of it. (Aug 19) */
  .lookbook-face {
    aspect-ratio: 1;
    border-radius: 10px;
    overflow: hidden;
    background: var(--paper-warm-2);
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .lookbook-face img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .lookbook-initials { font-size: 34px; font-weight: 600; color: var(--ink-soft); letter-spacing: .02em; }
  .lookbook-name { margin: 10px 0 2px; font-weight: 650; font-size: 15px; line-height: 1.25; }
  .lookbook-detail { margin: 3px 0 0; font-size: 12.5px; line-height: 1.35; color: var(--ink-soft); }
  .lookbook-label {
    display: block;
    font-size: 10px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--ink-faint);
  }

  @media print {
    /* Four to a row on paper, and never a face split across two pages. */
    .lookbook { grid-template-columns: repeat(4, 1fr); gap: 18px 14px; }
    .lookbook-face { border-radius: 6px; }
    .lookbook-name { font-size: 12px; }
    .lookbook-detail { font-size: 10px; }
    .lookbook-label { font-size: 8px; }
    /* The placeholder background is a theme token now, so on a dark-themed
       machine with "print backgrounds" switched on it would lay a dark green
       square under initials the print rules have already forced to black.
       Same answer the table avatars use: drop the fill, draw an outline —
       and only where there is no photo to cover it. */
    .lookbook-face { background: transparent !important; }
    .lookbook-face:not(:has(img)) { border: 1px solid #000; }
  }

  @media print {
    body:has(.contact-sheet) { background: #fff !important; }
    body:has(.contact-sheet) > *:not(.contact-sheet) { display: none !important; }
    .contact-sheet-actions { display: none !important; }
    .contact-sheet {
      max-width: none;
      margin: 0;
      padding: 0;
      background: #fff;
      border: none;
      border-radius: 0;
      box-shadow: none;
    }
    .contact-sheet, .contact-sheet * { color: #000 !important; }
    .contact-sheet-table th { border-bottom-color: #000; }
    .contact-sheet-table td { border-bottom-color: #ccc; }
  }
}

@layer components {
  /* ── The participant report — the contact sheet with columns you pick ──
     Same paper, same print rules (it wears .contact-sheet, so everything
     above applies); this block is only what the roster doesn't have: a
     wider sheet, the picker, and a sortable head. (Aug 5) */
  .contact-sheet--wide { max-width: 1040px; }

  .report-acts { display: inline-flex; align-items: center; gap: var(--space-4); }

  /* The picker. Deliberately plain — it's a form the host reads once and
     then edits by muscle memory. */
  .report-picker {
    margin: 0 0 24px;
    padding: 18px 20px;
    border: 1px solid var(--paper-edge);
    border-radius: var(--radius-md);
    background: var(--hover-wash);
  }
  .report-picker-head { margin-bottom: 14px; }
  .report-picker-h {
    font-family: var(--display);
    font-size: 15px;
    font-weight: var(--weight-semibold);
    color: var(--ink);
    margin: 0 0 4px;
  }
  .report-picker-help { margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink-soft); }
  /* Only rendered when there is more than one group — a gathering with no
     asks shows a single grid and looks exactly as it did. (Aug 24) */
  .report-picker-group {
    font-size: 11px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin: 0 0 8px;
  }
  .report-picker-group + .report-picker-grid { margin-bottom: 16px; }
  .report-picker-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 8px 16px;
  }
  /* A question is a sentence, not a word. "Acknowledge you have read the
     Disclaimer" wraps to three lines in a column sized for "Airport", and a
     centred checkbox then floats to the middle of it — the grid goes ragged
     and the whole panel reads as sloppy. Wider columns for the questions,
     and every box aligned to its first line. (Aug 24) */
  .report-picker-grid--asks {
    grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  }
  .report-pick {
    display: flex;
    align-items: start;
    gap: 8px;
    font-size: 14px;
    color: var(--ink);
    cursor: pointer;
  }
  .report-pick input { flex: none; margin-top: 2px; }
  .report-picker-foot {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    margin-top: 16px;
  }
  .report-picker-note { font-size: 12.5px; color: var(--ink-faint); }

  /* Eleven columns don't fit a phone. The wrap scrolls sideways on screen
     and is told to stop existing in print, where nothing is clipped. */
  .report-table-wrap { overflow-x: auto; }
  .report-table td { vertical-align: middle; }
  .report-cell-photo { width: 40px; padding-right: 8px; }

  .report-sort-btn {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    cursor: pointer;
  }
  .report-sort-btn:hover { color: var(--ink); }
  .report-table th[aria-sort="ascending"] .report-sort-btn::after  { content: " ↑"; }
  .report-table th[aria-sort="descending"] .report-sort-btn::after { content: " ↓"; }

  .report-foot { margin: 16px 0 0; font-size: 12.5px; color: var(--ink-faint); }

  /* Screen only. On paper this is the one line that says how old the sheet
     in your hand is. */
  .report-asof { display: none; }

  /* ── THE ROSTER CARD ───────────────────────────────────────────────
     The printout: a face, a name under it, and everything the host asked
     for beside it, one fact per line. Measured against the real
     eighteen-person Exchange Week roster — six people to a page, seven
     pages for forty. The face is free: shrinking it from 1.15in to 0.88in
     barely moves the block height, because the facts need that room
     anyway. So it keeps the big face. */
  .report-cards { display: none; }

  @media print {
    .roster-card {
      display: flex;
      gap: 22px;
      align-items: flex-start;
      /* 13, measured. Card padding turned out to be what cost a page, not
         the gap between facts: at 18 a driver's sheet fits five people, at
         13 it fits six, and the separation between people is carried by the
         rule anyway. The gap between facts is what actually fixed the
         congestion, and it is nearly free. */
      padding: 13px 0;
      border-top: 1px solid #ddd;
      break-inside: avoid;
      page-break-inside: avoid;
    }
    .roster-card:first-child { border-top: 1px solid #000; }
    .roster-card-who { flex: none; width: 110px; text-align: center; }
    .roster-card-face {
      display: block;
      width: 110px;
      height: 110px;
      object-fit: cover;
      border-radius: 4px;
    }
    /* Printers drop backgrounds, so a filled initials chip would print as
       black ink on the white it just dropped. Outline it, the way the table
       avatars already do. */
    .roster-card-face--none {
      display: flex;
      align-items: center;
      justify-content: center;
      border: 1px solid #000;
      background: transparent;
      font-weight: 600;
      font-size: 26px;
    }
    .roster-card-name {
      margin: 6px 0 0;
      font-size: 13.5px;
      font-weight: 650;
      line-height: 1.15;
      color: #000;
    }
    .roster-card-facts { margin: 0; flex: 1 1 auto; min-width: 0; }
    /* 13.3px is 10pt, the floor of Butterick's 10–12pt for printed body
       text. It was 12.5px — 9.4pt — which is below the range, and this page
       is read at arm's length in a kitchen or a car park rather than held
       like a book. Line spacing 1.35 sits mid-range of his 120–145%; the
       value column runs about 76 characters, inside his 45–90. */
    .roster-card .fact {
      display: flex;
      gap: 12px;
      align-items: baseline;
      font-size: 13.3px;
      line-height: 1.4;
      color: #000;
    }
    /* Line spacing governs the lines INSIDE a wrapped value. BETWEEN facts
       there was nothing at all, and twelve separate thoughts stacked with no
       separation read as a wall however good the leading is. On a normal
       sheet this costs no pages: the face already sets the block height and
       the facts do not fill it. (Neal, Aug 24: "somewhat congested".) */
    .roster-card .fact + .fact { margin-top: 5px; }
    /* Labels are captions, not body — 9.5px is 7.1pt, which is where a
       business card sets its small print. The 7% tracking is Butterick's
       5–12% for all caps. Anything that would need a second line goes above
       its value instead: "all caps are fine for less than one line." */
    .roster-card .fact dt {
      flex: none;
      width: 86px;
      font-size: 9.5px;
      letter-spacing: 0.07em;
      text-transform: uppercase;
      /* Darker than the screen wants. Print drops contrast, and these are
         already 7pt. */
      color: #5a5a5a;
    }
    .roster-card .fact dd { margin: 0; flex: 1 1 auto; }

    /* ── PROSE ─────────────────────────────────────────────────────
       A bio is read; an airport code is glanced at. They had identical
       treatment, which is most of why this page was not enjoyable to read.
       Prose leaves the label grid: a quiet label above, then a paragraph
       with its own leading and its own measure.

       The typeface does NOT change. tokens.css says "ABC Prophet display +
       system sans body, no serif, no mono" on purpose, so the separation is
       made with the other three variables Butterick names — size, leading
       and line length — rather than by adding a face. 58ch keeps the measure
       inside his 45–90 with room to spare. */
    .roster-card .fact--prose { display: block; margin: 12px 0; }
    .roster-card .fact--prose + .fact { margin-top: 12px; }
    .roster-card .fact--prose dt { display: block; width: auto; margin-bottom: 3px; }
    .roster-card .fact--prose dd {
      font-family: var(--sans);
      font-size: 13.8px;
      line-height: 1.62;
      max-width: 58ch;
      color: #1a1a1a;
    }
    /* A label too long to share a line sits above its value rather than
       wrapping to three lines of tiny caps beside a one-word answer.
       The VALUE still starts in the value column. Letting it run full width
       would break the one alignment this layout exists for — a driver
       reading one column straight down — and it would push the line to
       about 90 characters, the outer edge of Butterick's 45–90. Indented,
       it stays near 76 and the column holds. */
    .roster-card .fact--stacked { display: block; margin-top: 3px; }
    .roster-card .fact--stacked dt { display: block; width: auto; }
    .roster-card .fact--stacked dd { padding-left: 96px; }
  }

  @media print {
    .report-picker, .report-foot { display: none !important; }
    .report-table-wrap { overflow: visible !important; }
    .report-asof {
      display: block;
      margin: 2px 0 0;
      font-size: 11px;
      color: #444;
    }
    /* Nobody should be split across two pages. */
    .report-table tr { break-inside: avoid; }
    /* The em dash is a screen affordance. Paper gets the blank. */
    .on-screen-only { display: none !important; }
    /* Printers drop backgrounds, so an initials chip would print as black
       ink on the white it just dropped — invisible. Outline it instead. */
    .report-table .avatar {
      background: transparent !important;
      border: 1px solid #000;
    }
    .report-table .avatar-photo { border: 0; }
    /* Sort arrows are a screen affordance; on paper they read as data. */
    .report-sort-btn::after { content: "" !important; }

    /* ── PAPER GETS ITS OWN MARKUP ─────────────────────────────────
       The table is hidden and gathering/_report_cards is shown instead.
       This was three rounds of bending the table into a card list with
       print CSS, and each round lost a specificity fight to a rule written
       for the screen: a label printed PHOTO across a face, then
       position:relative beat position:absolute and dropped the face back
       into the flow. The fourth round stopped fighting. (Aug 24) */
    .report-table-wrap { display: none !important; }
    .report-cards { display: block !important; }
    /* The photo is EXCLUDED from the label/value rule above rather than
       fighting it. Twice now a plain .report-cell-photo rule lost to that
       selector's attribute-plus-:not() specificity — first the label printed
       PHOTO over the face, then position:relative beat position:absolute and
       dropped the face back into the flow, shoving every label down. A rule
       that has to out-specify another rule is a rule in the wrong place. */
  }
}

@layer components {
  /* ── A ROSTER IS A LIST OF PEOPLE, NOT A SPREADSHEET ──────────────
     Five columns — guest, cabin, diet, driving, invite link — need about
     850px, and .manage-table carries a min-width of 640px besides. On a
     390px phone that left 461px off the right edge and the first thing
     cut was the Cabin: "Peñasco" read "Peña", the header read "CABI".
     The wrap keeps a scrollbar on screen (Aug 5) so nothing was lost, but
     a host standing in the lodge asking who is in Peñasco should not have
     to drag a table sideways to find out.

     Below 600px each row becomes a small block: the person, then their
     facts as label/value pairs, then the actions. Same markup, same data,
     no horizontal scroll at all. The lodgings page already made this
     call — it collapses to a summary rather than forcing a Gantt onto a
     phone — and the roster should agree with it.

     THIS LIVES IN manage.css ON PURPOSE. It was written in folder.css
     first and silently lost: `.manage-table--stacks` is one class, not
     two, so it ties `.manage-table td` on specificity, and manage.css
     loads later. The stacking applied and the borders and min-width did
     not, which read as three rows per guest inside a table still 640px
     wide. Rules that override a component belong beside it. (Aug 11) */
  /* 900, not 600. The sweep found the roster still scrolling 101px at
     tablet width, hiding the invite link — the same fault the phone had,
     just less of it. The table wants ~850px and a tablet has 820, so the
     breakpoint belongs above the table's natural width rather than at a
     round number. (Aug 11) */
  @media (max-width: 900px) {
    .manage-table--stacks { min-width: 0; }
    .manage-table--stacks thead { display: none; }
    .manage-table--stacks,
    .manage-table--stacks tbody,
    .manage-table--stacks tr,
    .manage-table--stacks td { display: block; width: 100%; }

    /* One divider per person, not one per fact. */
    .manage-table--stacks tr {
      padding: 14px 16px;
      border-bottom: 1px solid var(--paper-edge);
    }
    .manage-table--stacks tr:last-child { border-bottom: 0; }
    .manage-table--stacks tr:hover td { background: transparent; }

    .manage-table--stacks td {
      border-bottom: 0;
      padding: 2px 0;
      text-align: left;
    }
    .manage-table--stacks td.right { text-align: left; }
    .manage-table--stacks td:first-child { padding-bottom: 8px; }

    /* The column head has nowhere else to live once the head is gone. */
    .manage-table--stacks td[data-label]::before {
      content: attr(data-label);
      display: inline-block;
      min-width: 58px;
      color: var(--ink-faint);
      font-size: 12px;
      font-weight: var(--weight-semibold);
      letter-spacing: 0.02em;
    }

    .manage-table--stacks .people-link-cell {
      justify-content: flex-start;
      gap: 16px;
      padding-top: 8px;
    }
  }
}

@layer components {
  /* PAYMENT FIELDS THAT APPLY (Neal, Aug 14) — the settings page showed every
     field for every method at once. On Square, "Handle (for Venmo, Cash App,
     PayPal, or Zelle)", the payment-link URL and the screenshot checkbox are
     all dead controls, and the checkbox's own copy admits it: "Doesn't apply
     to Square." Same rule as the blank slates — don't render a control that
     cannot do anything.

     Pure CSS on :has(), deliberately. A Stimulus controller would mean a new
     file, a registration and an importmap pin, and a dangling registration in
     application.js once took the whole framework down on every page. This
     needs no JavaScript to be correct. */
  .pay-only { display: none; }

  /* A @-handle: the four apps you pay a person on. */
  .place-address-form:has(input[name="payment[provider]"][value="venmo"]:checked)   .pay-only--handle,
  .place-address-form:has(input[name="payment[provider]"][value="cashapp"]:checked) .pay-only--handle,
  .place-address-form:has(input[name="payment[provider]"][value="paypal"]:checked)  .pay-only--handle,
  .place-address-form:has(input[name="payment[provider]"][value="zelle"]:checked)   .pay-only--handle,
  /* A URL: only the link option. */
  .place-address-form:has(input[name="payment[provider]"][value="link"]:checked)    .pay-only--url,
  /* The note and the proof checkbox: any method where the guest pays somewhere
     else and comes back to say so. Never Square, which charges in the app. */
  .place-address-form:has(input[name="payment[provider]"][value="venmo"]:checked)   .pay-only--offapp,
  .place-address-form:has(input[name="payment[provider]"][value="cashapp"]:checked) .pay-only--offapp,
  .place-address-form:has(input[name="payment[provider]"][value="paypal"]:checked)  .pay-only--offapp,
  .place-address-form:has(input[name="payment[provider]"][value="zelle"]:checked)   .pay-only--offapp,
  .place-address-form:has(input[name="payment[provider]"][value="link"]:checked)    .pay-only--offapp,
  .place-address-form:has(input[name="payment[provider]"][value="manual"]:checked)  .pay-only--offapp,
  /* Currency: anything that collects money at all. Not "no contributions". */
  .place-address-form:has(input[name="payment[provider]"]:checked:not([value="none"])) .pay-only--paying {
    display: block;
  }
}
