/* ============================================================
   Bellyful — Potluck Invite (RSVP placeholder)
   Mobile-first static page. No external assets. System fonts.
   ============================================================ */

:root {
  /* Warm food-oriented palette */
  --bg:           #F4F0E8;
  --surface:      #FFFFFF;
  --ink:          #14110F;
  --ink-2:        #5C544C;
  --ink-3:        #8E867D;
  --ink-4:        #B5ADA3;
  --rule:         #ECE5D7;
  --rule-2:       #E2D9C7;

  /* Brand green — confident forest, not spring */
  --green:        #1B7A3D;
  --green-2:      #2A8D4A;
  --green-tint:   #E5F1EA;
  --green-edge:   #B6D8C2;
  --green-deep:   #135B2D;

  /* Info banner blue (subtle, not stocky) */
  --info-bg:      #E9F0F8;
  --info-edge:    #C6D6E8;
  --info-ink:     #1F4F86;

  /* Shadows — warm-toned */
  --sh-card:      0 1px 0 rgba(20,17,15,.03), 0 8px 22px -10px rgba(80,60,30,.10);
  --sh-card-hi:   0 1px 0 rgba(20,17,15,.04), 0 14px 30px -12px rgba(80,60,30,.14);
  --sh-button:    0 6px 14px -4px rgba(27,122,61,.36);

  --radius-card:  16px;
  --radius-field: 12px;
  --radius-chip:  999px;

  /* Menu dietary labels — MONOCHROME BY DESIGN. No semantic hue.
     A green "GF" badge reads as a safety clearance, and these
     labels are not one: the filled tier means the server matched
     the ingredient list, the outline tier means the recipe simply
     said so. Neither is a guarantee, so neither gets to borrow the
     colour of one. The two tiers are told apart by fill vs border,
     which survives greyscale, colour-blindness, and the aggressive
     recolouring some in-app browsers apply. */
  --label-filled-bg:   #14110F;
  --label-filled-ink:  #FFFFFF;   /* 19.0:1 on --label-filled-bg */
  --label-filled-edge: #14110F;
  --label-outline-ink:  #5C544C;  /* 7.4:1 on --surface */
  --label-outline-edge: #8E867D;  /* 3.6:1 on --surface (1.4.11) */

  /* Tells the UA we render both themes, so it themes form controls,
     scrollbars and the caret to match — and so Android Chrome's
     auto-dark stops guessing at our colours and uses the dark block
     at the foot of this file instead. */
  color-scheme: light dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Soft cream radial — subtle texture, no images */
  background-image:
    radial-gradient(1200px 600px at 50% -10%, #FBF8F1 0%, transparent 60%),
    radial-gradient(800px 600px at 100% 100%, #EFE9DA 0%, transparent 60%);
  background-attachment: fixed;
  min-height: 100dvh;
}

/* Mobile-first phone column */
.page {
  max-width: 420px;
  margin: 0 auto;
  padding: 0 16px 36px;
  position: relative;
}

/* iOS-style status bar (cosmetic only) */
.statusbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 6px 4px;
  color: var(--ink);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.statusbar .indicators {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.statusbar .indicators svg { display: block; }

/* App header */
.header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 4px 6px;
}
.header-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 15.5px;
  font-weight: 600;
  letter-spacing: -0.012em;
  color: var(--ink);
  min-width: 0;
  flex: 1;
}
.header-title .dot {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--green);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 0 rgba(0,0,0,.04), inset 0 -1px 0 rgba(0,0,0,.08);
}
.more-btn {
  border: 0;
  background: transparent;
  color: var(--ink-3);
  padding: 8px;
  border-radius: 8px;
  cursor: pointer;
}
.more-btn:hover { color: var(--ink); background: rgba(0,0,0,.04); }

/* Invite tag */
.invite-tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 4px 4px 16px;
  padding: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--green);
  text-transform: none;
}
.invite-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 3px rgba(27,122,61,.14);
}

/* Form root */
.form { display: block; }

/* Event card */
.event-card {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius-card);
  padding: 18px 18px 16px;
  box-shadow: var(--sh-card);
  position: relative;
  overflow: hidden;
}
.event-card::before {
  /* hairline accent on the left, food-warm gold-green */
  content: "";
  position: absolute;
  left: 0; top: 14px; bottom: 14px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--green-2), var(--green-deep));
  opacity: .9;
}
.event-card h2 {
  margin: 0 0 12px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.018em;
  color: var(--ink);
}
.event-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.event-date {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-2);
}
.event-date svg { color: var(--ink-3); }
.going-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px 4px 8px;
  background: var(--green-tint);
  color: var(--green-deep);
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  border: 1px solid var(--green-edge);
}
.event-loc {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  font-size: 13px;
  color: var(--ink-2);
}
.event-loc svg { color: var(--ink-3); }

/* Generic field block */
.field {
  margin-top: 18px;
  position: relative;
}
.field label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 7px;
  letter-spacing: -0.005em;
}
.field .optional {
  color: var(--ink-3);
  font-weight: 500;
}
.field input[type="text"],
.field textarea {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--rule-2);
  border-radius: var(--radius-field);
  padding: 12px 14px;
  font: inherit;
  font-size: 15px;
  color: var(--ink);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
  box-shadow: 0 1px 0 rgba(20,17,15,.02);
  -webkit-appearance: none;
  appearance: none;
}
.field input::placeholder,
.field textarea::placeholder {
  color: var(--ink-4);
}
.field input:focus,
.field textarea:focus {
  border-color: var(--green);
  box-shadow: 0 0 0 4px rgba(27,122,61,.14);
  background: #FFFFFF;
}
.field textarea {
  resize: vertical;
  min-height: 78px;
  line-height: 1.5;
}
.char-count {
  position: absolute;
  right: 12px;
  bottom: 10px;
  font-size: 11.5px;
  color: var(--ink-4);
  background: rgba(255,255,255,.85);
  padding: 0 4px;
  border-radius: 6px;
  pointer-events: none;
}
.field-hint {
  display: block;
  margin-top: 6px;
  font-size: 12px;
  color: var(--ink-3);
}

/* Section block (allergy / diet / bringing) */
.block {
  margin-top: 22px;
}
.block-title {
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--ink);
}

/* Where card: address and the host's arrival note. No fixed heights;
   the note keeps the host's line breaks and wraps unbroken strings
   (URLs, door codes) so nothing truncates at 320px or 200% zoom. */
.where-address {
  margin: 0;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.where-note {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}
.where-note-label {
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
}
.where-note-hint {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--ink-2);
}
.where-note-text {
  margin: 0;
  color: var(--ink);
  white-space: pre-line;
  overflow-wrap: anywhere;
}

/* Chips */
.chips {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.chip {
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  padding: 11px 14px;
  background: var(--surface);
  border: 1px solid var(--rule-2);
  border-radius: var(--radius-chip);
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
  transition: border-color .14s ease, background-color .14s ease, transform .14s ease, box-shadow .14s ease;
  text-align: left;
  box-shadow: 0 1px 0 rgba(20,17,15,.02);
  -webkit-tap-highlight-color: transparent;
}
.chip:hover { border-color: var(--ink-4); }
.chip:active { transform: translateY(1px); }
.chip[aria-pressed="true"] {
  background: var(--green-tint);
  border-color: var(--green);
  color: var(--green-deep);
  box-shadow:
    0 1px 0 rgba(20,17,15,.02),
    inset 0 0 0 1px rgba(27,122,61,.12);
}
.chip-emoji {
  font-size: 16px;
  line-height: 1;
  filter: saturate(1.05);
  flex: 0 0 auto;
}

/* Info banner */
.info {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 16px;
  padding: 12px 14px;
  background: var(--info-bg);
  border: 1px solid var(--info-edge);
  border-radius: 12px;
  color: var(--info-ink);
}
.info p {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
}
.info .info-icon {
  color: var(--info-ink);
  flex: 0 0 auto;
  margin-top: 1px;
}
.info a {
  color: var(--info-ink);
  text-decoration: underline;
  text-underline-offset: 2px;
  font-weight: 600;
}
.info-sub {
  display: inline-block;
  margin-top: 2px;
  color: rgba(31, 79, 134, .75);
}

/* Bringing — steppers */
.stepper-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--rule-2);
  border-radius: 12px;
  margin-bottom: 8px;
  box-shadow: 0 1px 0 rgba(20,17,15,.02);
}
.stepper-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.stepper {
  display: inline-flex;
  align-items: center;
  gap: 14px;
}
.step {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--rule-2);
  background: var(--surface);
  color: var(--ink-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: border-color .14s ease, color .14s ease, background-color .14s ease, transform .1s ease;
  -webkit-tap-highlight-color: transparent;
  padding: 0;
}
.step:hover { border-color: var(--green); color: var(--green); background: var(--green-tint); }
.step:active { transform: scale(0.94); }
.stepper output {
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  min-width: 22px;
  text-align: center;
}
.bringing-hint {
  margin: 8px 4px 0;
  font-size: 12px;
  color: var(--ink-3);
}

/* Privacy */
.privacy {
  margin-top: 22px;
  padding: 14px 16px;
  background: rgba(255,255,255,.55);
  border: 1px dashed var(--rule-2);
  border-radius: 12px;
  color: var(--ink-2);
}
.privacy p {
  margin: 0;
  font-size: 12px;
  line-height: 1.55;
}
.privacy strong { color: var(--ink); font-weight: 600; }
.privacy a {
  color: var(--green-deep);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Bottom action bar */
.action-bar {
  margin-top: 22px;
  text-align: center;
}
.totals {
  margin: 0 0 12px;
  font-size: 13.5px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.totals strong {
  color: var(--ink);
  font-weight: 700;
}
.totals .sep {
  margin: 0 8px;
  color: var(--ink-4);
}

.confirm-btn {
  display: block;
  width: 100%;
  background: var(--green);
  color: #fff;
  border: 0;
  border-radius: 14px;
  padding: 15px 20px;
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: 0.005em;
  cursor: pointer;
  box-shadow: var(--sh-button);
  transition: background-color .15s ease, transform .12s ease, box-shadow .15s ease;
  -webkit-tap-highlight-color: transparent;
}
.confirm-btn:hover { background: var(--green-2); }
.confirm-btn:active { transform: translateY(1px); box-shadow: 0 4px 10px -4px rgba(27,122,61,.36); }
.confirm-btn:focus-visible {
  outline: 3px solid rgba(27,122,61,.38);
  outline-offset: 2px;
}

.change-mind {
  display: inline-block;
  margin-top: 14px;
  font-size: 13px;
  color: var(--green-deep);
  text-decoration: none;
  font-weight: 600;
  border-bottom: 1px solid rgba(27,122,61,.25);
  padding-bottom: 1px;
}
.change-mind:hover {
  color: var(--green);
  border-bottom-color: var(--green);
}

/* Focus visibility — universal */
:focus-visible {
  outline: 3px solid rgba(27,122,61,.35);
  outline-offset: 2px;
}
.chip:focus-visible {
  outline-offset: 1px;
  border-color: var(--green);
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* Larger viewport — center the phone column nicely */
@media (min-width: 480px) {
  .page {
    margin-top: 16px;
    margin-bottom: 16px;
    padding-bottom: 28px;
    background: var(--surface);
    border-radius: 24px;
    box-shadow: 0 10px 40px -10px rgba(60,40,10,.18);
    overflow: hidden;
    padding-left: 18px;
    padding-right: 18px;
  }
}

/* ============================================================
   Functional SPA additions — state-machine screens, drawer,
   fatal/loading states, dietary notice, plus-one rows, legal
   footer. Builds on the design tokens already defined above.
   ============================================================ */

.screen[hidden] { display: none !important; }
.screen { padding-top: 18px; }

.screen-header { margin-bottom: 12px; }
.screen-title {
  font-size: 22px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 4px 0 6px;
}
.screen-body {
  color: var(--ink-2);
  margin: 4px 0 16px;
}
.screen-body.muted { color: var(--ink-3); }

.back-btn {
  background: transparent;
  border: 0;
  color: var(--ink-2);
  font-size: 22px;
  padding: 6px 0;
  cursor: pointer;
}

.event-meta {
  color: var(--ink-2);
  margin: 2px 0 8px;
  font-size: 14px;
}
.event-row {
  margin: 4px 0;
  color: var(--ink-2);
}

.splash {
  text-align: center;
  padding: 80px 0;
}
.loading-pulse {
  color: var(--ink-3);
  font-size: 15px;
}

.fatal-card {
  background: var(--surface);
  border-radius: var(--radius-card);
  padding: 24px;
  box-shadow: var(--sh-card);
  margin: 24px 0;
  text-align: center;
}

/* Note: .event-card is intentionally NOT included here — its
   original definition (with the ::before accent bar, padding,
   border) lives earlier in this file and is what the State-3
   markup expects. The cards below are siblings introduced for
   the functional flow. */
.host-message-card,
.dietary-summary-card,
.full-menu-card {
  background: var(--surface);
  border-radius: var(--radius-card);
  padding: 14px 14px;
  box-shadow: var(--sh-card);
  margin: 12px 0;
}

.host-message {
  margin: 8px 0 0;
  color: var(--ink);
  white-space: pre-wrap;
}

.pill-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.pill {
  background: var(--green-tint);
  color: var(--green-deep);
  border: 1px solid var(--green-edge);
  border-radius: var(--radius-chip);
  padding: 4px 10px;
  font-size: 13px;
}

.menu-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;
}
.menu-item {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 14px;
}
.menu-item:last-child { border-bottom: 0; }
.menu-name { color: var(--ink); }
.menu-assignee {
  color: var(--ink-3);
  font-size: 12px;
  background: var(--rule);
  border-radius: var(--radius-chip);
  padding: 2px 8px;
}
/*
 * Dietary-flag pills inside a menu row. Breaks to its own line
 * so the pills don't crowd the assignee badge on narrow phones.
 * Inherits base .pill-list (gap, list-reset). flex-basis 100%
 * forces the wrap.
 */
.menu-item-flags {
  flex-basis: 100%;
  margin-top: 4px;
}

.landing-actions {
  display: grid;
  gap: 10px;
  margin-top: 16px;
}

.ghost-btn {
  background: var(--surface);
  color: var(--green);
  border: 1px solid var(--green-edge);
  border-radius: var(--radius-field);
  padding: 12px 14px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.ghost-btn:hover { background: var(--green-tint); }

.link-btn {
  background: transparent;
  border: 0;
  color: var(--green);
  text-decoration: underline;
  cursor: pointer;
  font-size: 14px;
  padding: 4px 0;
}

.app-link-row {
  margin: 12px 0 0;
  text-align: center;
}
.app-link-row[hidden] { display: none; }
.app-link {
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
  padding: 0 16px;
  color: var(--green);
  font-size: 15px;
  font-weight: 600;
  text-decoration: underline;
}

.form-error {
  color: #B23A2E;
  background: #FCEAE6;
  border: 1px solid #F1C7BF;
  border-radius: var(--radius-field);
  padding: 8px 12px;
  margin: 8px 0;
  font-size: 14px;
}

.dietary-notice {
  background: var(--info-bg);
  border: 1px solid var(--info-edge);
  color: var(--info-ink);
  border-radius: var(--radius-field);
  padding: 10px 12px;
  margin-top: 10px;
  font-size: 13px;
}

.consent-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 8px;
  font-size: 13px;
  color: var(--ink-2);
}
.consent-row input[type="checkbox"] {
  margin-top: 3px;
  flex-shrink: 0;
}

.bringing-helper {
  color: var(--ink-3);
  font-size: 13px;
  margin: 4px 0 8px;
}

.plusone-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  margin: 6px 0;
  align-items: center;
}
.plusone-name,
.plusone-age {
  border: 1px solid var(--rule-2);
  border-radius: var(--radius-field);
  padding: 8px 10px;
  font-size: 14px;
  font-family: inherit;
}
.plusone-name { min-width: 0; }
.plusone-remove { font-size: 13px; }

.confirm-hero {
  text-align: center;
  padding: 32px 0 16px;
}
.confirm-check {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border-radius: 999px;
  background: var(--green-tint);
  color: var(--green-deep);
  font-size: 32px;
  font-weight: 600;
  margin-bottom: 12px;
}
.confirm-check.muted {
  background: var(--rule);
  color: var(--ink-3);
}
.confirm-title {
  font-size: 26px;
  margin: 0 0 4px;
}
.confirm-footer {
  margin-top: 24px;
  font-size: 13px;
  color: var(--ink-3);
  text-align: center;
}

.legal-footer {
  margin-top: 32px;
  padding: 16px 0;
  border-top: 1px solid var(--rule);
  text-align: center;
  font-size: 12px;
  color: var(--ink-3);
}
.legal-footer a { color: var(--ink-2); }

/* Defense in depth for browsers/WebViews without <dialog> support
   (or stripped UA stylesheet). Native <dialog> hides itself when
   not [open]; this rule restates the contract explicitly so the
   drawer never renders accidentally. */
.drawer:not([open]) { display: none; }

.drawer {
  border: 0;
  padding: 0;
  border-radius: 16px 16px 0 0;
  width: 100%;
  max-width: 420px;
  margin: auto auto 0;
  background: var(--surface);
  box-shadow: 0 -10px 40px -10px rgba(20,17,15,.30);
}
.drawer::backdrop {
  background: rgba(20,17,15,.45);
}
.drawer-inner {
  padding: 16px 18px 20px;
}
.cal-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 16px;
}
.cal-btn {
  display: block;
  text-align: center;
  padding: 12px 14px;
  margin: 6px 0;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius-field);
  color: var(--ink);
  text-decoration: none;
  font-size: 15px;
}
.cal-btn:hover {
  background: var(--green-tint);
  border-color: var(--green-edge);
}

/* ============================================================
   MENU DIETARY LABEL SYSTEM
   Claim line + guest disclaimer + per-item badges + legend.
   Lives only inside #rsvp-menu-card (post-OTP, ADR-0056 Tier 2).
   ============================================================ */

/* Screen-reader-only text. Badges show two letters; the accessible
   name has to say the whole thing, including which tier it is. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  /* Comma form, not `rect(0 0 0 0)`. The space-separated syntax is a CSS
     Masking Level 1 relaxation; the deprecated `clip` property's own CSS 2.1
     grammar requires commas, and the browsers old enough to still need this
     fallback are exactly the ones that reject the comma-less form. Paired
     with clip-path below, which covers everything modern. */
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Header block above the menu list. */
.menu-labels-head {
  margin: 0 0 12px;
}
.menu-labels-claim {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.menu-labels-disclaimer {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-2);
}

/*
 * The badge itself. Squared (4px), not a pill — the pill shape is
 * already spoken for on this screen by .pill / .going-pill /
 * .menu-assignee, all of which carry unrelated meanings. A distinct
 * silhouette is what stops a guest reading a dietary label as an
 * assignee chip.
 *
 * min-width 22px keeps the one-letter badges (V, P, H, K) the same
 * optical weight as the two-letter ones (GF, DF, NF, VG) so a row of
 * mixed badges lines up instead of looking ragged.
 */
.dlabel,
.dlabel-swatch {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  height: 18px;
  min-width: 22px;
  padding: 0 5px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  white-space: nowrap;
  flex: 0 0 auto;
}
/* Empty legend swatch — carries no text, so it must not collapse. */
.dlabel-swatch {
  width: 22px;
  padding: 0;
}

/* Tier 1 — the server matched the ingredient list. */
.dlabel--checked {
  background: var(--label-filled-bg);
  color: var(--label-filled-ink);
  border-color: var(--label-filled-edge);
}
/* Tier 2 — the recipe's own description, unverified. */
.dlabel--described {
  background: transparent;
  color: var(--label-outline-ink);
  border-color: var(--label-outline-edge);
}

/*
 * Badge row inside a menu item. Mirrors .menu-item-flags: breaks to
 * its own line so badges never crowd the assignee chip on a 320px
 * phone.
 */
.menu-item-labels {
  list-style: none;
  padding: 0;
  margin: 4px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  flex-basis: 100%;
}

/* Legend — always open, never collapsed. See index.html for why. */
.menu-legend {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
}
.menu-legend-title {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.menu-legend-key,
.menu-legend-tiers {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
}
.menu-legend-key {
  gap: 7px 12px;
  margin-bottom: 10px;
}
.menu-legend-tiers {
  flex-direction: column;
  gap: 6px;
}
/*
 * `white-space: nowrap` on the PAIR, not on the badge, is the whole
 * point: without it a wrap can leave the badge at the end of one
 * line and its word at the start of the next, so the guest reads a
 * naked "P" and then an orphaned "Pescatarian". The badge and the
 * word it defines wrap as one unit or not at all.
 */
.menu-legend-key li,
.menu-legend-tier {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  font-size: 12px;
  line-height: 1.4;
  color: var(--ink-2);
}
/* The tier rows carry a full sentence, so they may wrap internally —
   only the swatch must stay welded to the start of its text. */
.menu-legend-tier {
  white-space: normal;
  align-items: flex-start;
}
.menu-legend-tier .dlabel-swatch {
  margin-top: 1px;
}

/* The absence rule — the legend's conclusion, not a fourth item. */
.menu-legend-rule {
  margin: 10px 0 0;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
  font-size: 12.5px;
  line-height: 1.45;
  font-weight: 600;
  color: var(--ink);
}

/* ============================================================
   DARK THEME
   Additive only — every rule here sits inside the media query, so
   the light rendering is byte-for-byte what it was before.

   This exists because the label system has to clear WCAG AA in
   dark as well as light, and there is no honest way to ship dark
   badge colours onto a page that is permanently light: a
   dark-tuned badge on a white card is a contrast failure, not a
   feature. Both halves of every contrast pair have to move
   together, so the page tokens move with them.

   The palette is a re-tone of the light one, not a new design:
   same warm hue family, inverted lightness. Contrast ratios noted
   per token were computed against --surface.
   ============================================================ */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:           #12100E;
    --surface:      #1E1A17;
    --ink:          #F5F1EA;  /* 15.4:1 */
    --ink-2:        #C6BEB4;  /*  9.4:1 */
    --ink-3:        #9C948A;  /*  5.8:1 */
    --ink-4:        #6E665E;  /*  3.1:1 — placeholders / hairlines */
    --rule:         #2C2622;
    --rule-2:       #3A332D;

    /* Brand green lifted for legibility on dark; #1B7A3D as TEXT on
       a dark surface is ~2.4:1 and unreadable. Kept as the button
       FILL colour below, where white sits on top of it. */
    --green:        #4FBF77;
    --green-2:      #6BD08E;
    --green-tint:   #16301F;
    --green-edge:   #2C5C3C;
    --green-deep:   #8FE0AC;

    --info-bg:      #17242F;
    --info-edge:    #2A3E52;
    --info-ink:     #A9C9EA;

    --sh-card:      0 1px 0 rgba(0,0,0,.25), 0 8px 22px -10px rgba(0,0,0,.55);
    --sh-card-hi:   0 1px 0 rgba(0,0,0,.30), 0 14px 30px -12px rgba(0,0,0,.60);
    --sh-button:    0 6px 14px -4px rgba(0,0,0,.55);

    /* Label tiers invert with the page. Filled stays the maximum
       available contrast against the card; outline stays a hairline
       box with body-copy ink. */
    --label-filled-bg:   #EDE7DC;
    --label-filled-ink:  #14110F;  /* 15.3:1 on --label-filled-bg */
    --label-filled-edge: #EDE7DC;
    --label-outline-ink:  #C6BEB4; /*  9.4:1 on --surface */
    --label-outline-edge: #9C948A; /*  5.8:1 on --surface (1.4.11) */
  }

  /* The warm cream radial has no dark equivalent — a dark radial
     just reads as a smudge on OLED. Flat background instead. */
  body {
    background-image: none;
  }

  /* Rules below are the light-mode hardcodes that the token
     overrides above cannot reach. Each one assumed a white page. */
  .more-btn:hover { background: rgba(255,255,255,.06); }
  .field input:focus,
  .field textarea:focus { background: var(--surface); }
  .char-count { background: rgba(30,26,23,.85); }
  .privacy { background: rgba(255,255,255,.03); }
  .info-sub { color: rgba(169, 201, 234, .75); }

  /* Error state: light palette was ink-on-tint; dark is tint-on-ink.
     #F0A79C on #2A1714 is 7.9:1. */
  .form-error {
    color: #F0A79C;
    background: #2A1714;
    border-color: #5A2E27;
  }

  /* Primary CTA inverts: a bright mint fill with near-black text
     (12.0:1). Keeping the light-mode #1B7A3D fill under white text
     would technically pass, but a dark-green slab on a dark card
     loses its edge and stops reading as the primary action. */
  .confirm-btn { background: var(--green-deep); color: #14110F; }
  .confirm-btn:hover { background: var(--green-2); }

  /* The focus ring is a 35%-alpha forest green — on a near-black
     page it disappears. Retint it to the lifted green. */
  :focus-visible { outline-color: rgba(79,191,119,.55); }
  .confirm-btn:focus-visible { outline-color: rgba(143,224,172,.60); }
}
