/* One stylesheet, hand-written. The app is three pages — a login form, a code
   form and a list — and a CSS framework would be more bytes than the whole of
   the rest of it. */

:root {
  color-scheme: light dark;

  --bg: #fbfaf8;
  --surface: #ffffff;
  --border: #e3ded6;
  --ink: #241f1a;
  --ink-muted: #6d655c;
  --accent: #a2432a;
  --accent-ink: #ffffff;
  --alert-bg: #fdeceb;
  --alert-ink: #8a2318;
  --notice-bg: #eaf3ec;
  --notice-ink: #1f5b32;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #17150f;
    --surface: #211e17;
    --border: #38332a;
    --ink: #f0ebe2;
    --ink-muted: #a49a8c;
    --accent: #e08a5f;
    --accent-ink: #17150f;
    --alert-bg: #3a1f1b;
    --alert-ink: #f3b5aa;
    --notice-bg: #1c3324;
    --notice-ink: #a6dcb6;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/* `wrap` is a safety valve rather than a layout: with four links beside the
   title and the picture, the row comes to about 360px, which is the whole of a
   small phone. It fits on nearly everything and drops the nav to a second line
   on what it does not, instead of pushing the account menu off the edge where
   there is nothing to scroll it back. */
.masthead {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  padding: 0.85rem 1.25rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.masthead__title {
  font-weight: 650;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-decoration: none;
}

.masthead__nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  /* Tighter than the masthead's own gap, which is buying back the width the
     fourth link costs. */
  gap: 0.6rem;
}

.masthead__link { font-size: 0.875rem; text-decoration: none; }

.masthead__user { color: var(--ink-muted); }

/* The account menu. `position: relative` on the <details> and absolute on the
   panel so the panel hangs under the name instead of pushing the masthead
   taller when it opens. */
.usermenu {
  position: relative;
}

/* The trigger is the picture itself, so the marker and the pointer live on it
   rather than on a line of text. No ::after caret: the round image reads as a
   target on its own, and a caret beside a circle is fussy. */
.usermenu > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
}

.usermenu > summary::-webkit-details-marker { display: none; }

/* object-fit so a non-square upload is cropped rather than squashed. The
   uploads are already square — AvatarImage crops them — but the generated SVG
   and anything ever stored before this rule are not guaranteed to be. */
.avatar {
  border-radius: 50%;
  object-fit: cover;
  background: var(--surface);
  display: block;
}

.avatar--sm { width: 32px; height: 32px; }
.avatar--lg { width: 72px; height: 72px; border: 1px solid var(--border); }

/* Whose account this is, at the top of the menu. It replaced the name in the
   masthead, so it has to be somewhere. */
.usermenu__whoami {
  padding: 0.45rem 0.6rem 0.5rem;
  margin-bottom: 0.2rem;
  border-bottom: 1px solid var(--border);
  color: var(--ink-muted);
  font-size: 0.8125rem;
  overflow-wrap: anywhere;
}

.usermenu__panel {
  position: absolute;
  right: 0;
  top: calc(100% + 0.5rem);
  z-index: 10;
  min-width: 9rem;
  display: grid;
  padding: 0.3rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 6px 20px rgb(0 0 0 / 12%);
}

.usermenu__item {
  width: 100%;
  padding: 0.45rem 0.6rem;
  border: none;
  border-radius: 7px;
  background: none;
  color: var(--ink);
  font-size: 0.875rem;
  font-weight: 500;
  text-align: left;
  text-decoration: none;
}

.usermenu__item:hover { background: var(--bg); }

/* How many restaurants are waiting for your answer, beside the menu item that
   lists them. The accent rather than plain text: it is the one thing in the
   menu that changes on its own, and it is there to be noticed. */
.usermenu__count {
  margin-left: 0.4rem;
  padding: 0.05rem 0.35rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 0.75rem;
  font-weight: 600;
}

/* The picture and its controls, at the top of the profile page. */
.avatarbox {
  display: flex;
  gap: 1rem;
  align-items: flex-start;
  margin-bottom: 1.5rem;
}

.avatarbox__controls { display: grid; gap: 0.5rem; }
.avatarbox__controls .muted { margin: 0; max-width: 26rem; }

/* A form that is one control and a button, sitting on a line rather than in a
   .stack column. */
.inline { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }

.telegramtest { margin-top: 1.5rem; }
.telegramtest .muted { margin: 0.35rem 0 0; max-width: 26rem; }

.users { list-style: none; margin: 1rem 0 2rem; padding: 0; display: grid; gap: 0.6rem; }

.user {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

.user__who { flex: 1; min-width: 0; }
.user__name { font-weight: 650; }
.user__identities { color: var(--ink-muted); font-size: 0.875rem; word-break: break-word; }

.user__badge {
  margin-left: 0.4rem;
  font-size: 0.75rem;
  color: var(--ink-muted);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.05rem 0.4rem;
}

.page {
  max-width: 44rem;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 4rem;
}

h1 {
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  margin: 0 0 0.5rem;
}

.lede { color: var(--ink-muted); margin: 0 0 1.5rem; }
.muted { color: var(--ink-muted); font-size: 0.875rem; }
.empty { color: var(--ink-muted); padding: 2rem 0; }

code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.875em;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 0.1em 0.35em;
}

/* Forms ------------------------------------------------------------------ */

.stack { display: flex; flex-direction: column; gap: 0.5rem; max-width: 22rem; }
.stack label { font-weight: 600; font-size: 0.875rem; }

input[type="text"],
input[type="email"] {
  width: 100%;
  padding: 0.6rem 0.7rem;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 7px;
}

input:focus-visible,
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Wide tracking and a monospace face so six digits read as six digits — at the
   default spacing 111111 and 11111 are hard to tell apart at a glance. */
.code-input {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 1.5rem;
  letter-spacing: 0.4em;
  text-align: center;
}

input[type="submit"],
button {
  font: inherit;
  font-weight: 600;
  padding: 0.6rem 1rem;
  color: var(--accent-ink);
  background: var(--accent);
  border: 1px solid transparent;
  border-radius: 7px;
  cursor: pointer;
}

/* A button that has to sit in a line of prose — "Sign out", "Clear". They are
   real form submissions, so they cannot be anchors. */
.linkish,
.linkish button {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-weight: 500;
  text-decoration: underline;
  cursor: pointer;
}

.searchbar {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.75rem;
}

.searchbar input[type="text"] { flex: 1; }

/* The location pull-down, which sits on all three modes. A flex row rather than
   prose, because each control in it is a form and a form is a block wherever
   you put it. It wraps rather than shrinking the select: on a phone the place
   names are the part that must stay readable. */
.origin {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}

.origin__pick, .origin__share { display: flex; gap: 0.4rem; align-items: baseline; }
.origin__label { color: var(--ink-muted); font-size: 0.875rem; }
.origin__select { font-size: 0.875rem; padding: 0.2rem 0.3rem; }
.origin__note { margin: 0; }

/* An author `display` beats the UA stylesheet's rule for [hidden] whatever the
   specificity, so saying it here is what keeps the button hidden until the
   script reveals it — and the Use button hidden once the script has made the
   select submit itself. */
.origin [hidden] { display: none; }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Adding ----------------------------------------------------------------- */

/* The box and its three choices are one form, so the choices sit under the box
   rather than beside it: they are read once, when you are deciding what to
   type, and they must not narrow the box on a phone. */
.addform { margin-bottom: 1rem; }

.addopts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  align-items: baseline;
  color: var(--ink-muted);
  font-size: 0.875rem;
}

.addopts select { font-size: 0.875rem; padding: 0.2rem 0.3rem; }

/* How adding works. A bordered aside rather than more grey prose: it is read
   once and then skipped forever, and it should be as easy to skip as it is to
   find. */
.addnote {
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 0.75rem 0.9rem;
  font-size: 0.875rem;
}

.addnote p { margin: 0 0 0.4rem; }
.addnote ul { margin: 0; padding-left: 1.1rem; }
.addnote li + li { margin-top: 0.3rem; }

.added__title { margin: 1.5rem 0 0.5rem; font-size: 1.1rem; }

/* Flashes ---------------------------------------------------------------- */

.flash {
  padding: 0.7rem 0.9rem;
  border-radius: 7px;
  margin: 0 0 1rem;
  font-size: 0.9375rem;
}

.flash--alert { background: var(--alert-bg); color: var(--alert-ink); }
.flash--notice { background: var(--notice-bg); color: var(--notice-ink); }

/* The last meal, at the top of Pick. A line rather than a card: it is one fact
   whose answer is a link, and anything boxed would compete with the heading
   directly above it. Ruled on the left rather than filled — a filled block on
   this page reads as a flash, and this is neither a notice nor an alert. */
.lastmeal {
  margin: 0 0 1rem;
  padding: 0.1rem 0 0.1rem 0.7rem;
  border-left: 2px solid var(--border);
  font-size: 0.9375rem;
  color: var(--ink-muted);
}

/* The name is the target and the only part of the line worth reading first, so
   it keeps the body colour the rest of the sentence gives up. */
.lastmeal a { color: var(--ink); font-weight: 600; }

/* Listing ---------------------------------------------------------------- */

/* The list and the party control. One column on a phone, with the party first
   — it is the smaller of the two and the thing you set before you read the
   list — and two columns once there is room for a sidebar beside the cards. */
.listing { display: grid; gap: 1.25rem; }

@media (min-width: 48rem) {
  .listing { grid-template-columns: 1fr 12rem; align-items: start; }
  .party { order: 2; }
}

.restaurants { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: 0.6rem; }

.restaurant {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 0.85rem 1rem;

  /* Answering a picker comes back anchored at this card (see ModeReturn), and
     an anchor with nothing to say puts its element's top edge flush against the
     top of the window — which reads as the top of the page rather than as a
     place in a list. The gap is what shows there is more above. */
  scroll-margin-top: 1rem;
}

.restaurant__head { display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.restaurant__name { font-weight: 650; }
.restaurant__price { color: var(--ink-muted); font-size: 0.875rem; }

.restaurant__meta {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: var(--ink-muted);
  font-size: 0.875rem;
  margin-top: 0.15rem;
}

.restaurant__address { color: var(--ink-muted); font-size: 0.875rem; margin-top: 0.15rem; }

.restaurant__stars {
  display: flex;
  gap: 1rem;
  margin-top: 0.5rem;
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
}

/* Map and website, in the distance's row rather than on one of their own.

   The accent rather than the muted grey the rest of the row is set in: they are
   the only two things on that line you can click, and a grey pin beside grey
   text reads as decoration. It is the colour every other link in the app is.

   The padding with a matching negative margin is the tap target: the box a
   thumb has to hit is bigger than the icon it looks like, and the row does not
   grow to fit it. */
.restaurant__link {
  display: inline-flex;
  color: var(--accent);
  padding: 0.3rem;
  margin: -0.3rem;
}

.restaurant__link:hover { color: var(--ink); }
.restaurant__link svg { display: block; width: 1.05rem; height: 1.05rem; }

.restaurant__phone { margin-top: 0.5rem; font-size: 0.875rem; }

/* The Fam number when one of the party rated it a 1. Coloured like an alert
   rather than merely greyed: it is not a low score, it is a place this group
   cannot go, and it has already been sorted to the bottom of the list. */
.restaurant__veto { color: var(--alert-ink); }

/* "Bob doesn't want to try" — one very small line, the same alert colour as a
   veto because it means the same thing to the evening. Small deliberately: it
   is the footnote explaining why the card sank, not a headline. */
.restaurant__unwilling {
  color: var(--alert-ink);
  font-size: 0.8125rem;
  margin-top: 0.4rem;
}

/* "Ada wants to try" — the same line the other way round, and the only thing on
   a card that explains an unrated restaurant sitting in the top tier. Set in
   the notice green rather than the alert red for exactly that reason: the two
   sink and lift the same card, so they must not read alike. */
.restaurant__eager {
  color: var(--notice-ink);
  font-size: 0.8125rem;
  margin-top: 0.4rem;
}

/* The tiers --------------------------------------------------------------- */

/* Pick's three groups. The heading and the sentence under it are the whole
   point — an order nobody can account for is one nobody trusts — so they are
   given real room rather than being tucked in as a label. */
.tiers { display: grid; gap: 1.5rem; margin-top: 1rem; }

.tier__heading {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin: 0;
  font-size: 1rem;
}

.tier__count {
  color: var(--ink-muted);
  font-size: 0.8125rem;
  font-variant-numeric: tabular-nums;
}

.tier__why { margin: 0.2rem 0 0; }

/* The ruled-out group, greyed as a whole. These are on screen so you can see
   they were considered, not so you can choose one — and a tier that looked the
   same as the others would be offering them. */
.tier--ruled_out .tier__heading { color: var(--ink-muted); }
.tier--ruled_out .restaurants { opacity: 0.72; }

/* Saved locations --------------------------------------------------------- */

.locations { list-style: none; margin: 1rem 0 2rem; padding: 0; display: grid; gap: 0.6rem; }

.location {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  flex-wrap: wrap;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 0.7rem 1rem;
}

.location__name { font-weight: 650; }

.location__where {
  color: var(--ink-muted);
  font-size: 0.875rem;
  font-family: ui-monospace, monospace;
  font-variant-numeric: tabular-nums;
}

.locationform { display: flex; gap: 0.75rem; align-items: flex-end; flex-wrap: wrap; }
.locationform label { display: grid; gap: 0.25rem; font-weight: 600; font-size: 0.875rem; }
.locationform input[type="text"] { width: 11rem; }

/* One restaurant ---------------------------------------------------------- */

.backlink { font-size: 0.875rem; margin: 0 0 0.75rem; }

/* The name on the restaurant's own page. An h1 rather than the card's span, so
   the page has a heading — but sitting on the same baseline row as the price,
   which is why it needs the margin off. */
.restaurant__title { font-size: 1.5rem; letter-spacing: -0.02em; margin: 0; }

/* The id, last line of the restaurant's page. Small, muted and monospaced: it
   is a key you copy into the bot, not something the page is about. */
.restaurant__ref {
  margin-top: 2rem;
  color: var(--ink-muted);
  font-size: 0.8125rem;
  font-family: ui-monospace, monospace;
}

/* Taking the restaurant out altogether, last on its page and the administrator's
   alone. Styled as the visit delete is, because it is the same act one size
   larger — a disclosure whose summary is a link and whose contents are the
   counts of what would go with it and the button.

   With nothing recorded here there is no disclosure and no warning, so the
   button stands on its own — and without the indent that only made sense under
   a summary. */
.restaurant__remove { font-size: 0.8125rem; margin-top: 1.25rem; }
.restaurant__remove summary { cursor: pointer; color: var(--accent); }
.restaurant__remove-counts {
  margin: 0.35rem 0 0;
  padding-left: 2rem;
  color: var(--ink-muted);
}
.restaurant__remove-form { margin: 0.35rem 0 0.25rem 0.9rem; }
.restaurant__remove-form--bare { margin-left: 0; }

/* The same control on the add page, under the row you have just saved and did
   not want. Same shape as the two deletes above it, so a disclosure whose
   summary is a link reads the same wherever it appears. */
.added__remove { font-size: 0.8125rem; margin-top: 0.4rem; }
.added__remove summary { cursor: pointer; color: var(--accent); }
.added__remove-form { margin: 0.35rem 0 0.25rem 0.9rem; }

/* The dates somebody has eaten here, and who was with them. Tighter than the
   notes below it, and with no card around each one: a line here is a date and a
   list of names, not something somebody wrote that you have to read. */
.visits { margin-top: 2rem; }
.visits__title { font-size: 1.125rem; margin: 0 0 0.5rem; }
.visits__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.45rem; }

/* Wrapping rather than truncating: on a phone the names go under the date, and
   a household of five is a line worth two. */
.visit {
  color: var(--ink-muted);
  font-size: 0.875rem;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem;
}

.visit__date { font-weight: 650; color: var(--ink); }
.visit__who { color: var(--ink); }
.visit__logger { font-size: 0.8125rem; }

/* Where the meal was, on the "Where we ate" page only — the restaurant's page
   knows its own name. As prominent as the date beside it: on that page the two
   together are what a line says. */
.visit__where { font-weight: 650; }

.visit__edit,
.visit__remove { font-size: 0.8125rem; }
.visit__edit summary,
.visit__remove summary { cursor: pointer; color: var(--accent); }

/* The revealed delete, indented under its own summary so it reads as belonging
   to the disclosure rather than to the next line down. */
.visit__remove-form { margin: 0.35rem 0 0.25rem 0.9rem; }

.visit__form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0.4rem 0 0.5rem;
}

.visit__attendee { display: flex; align-items: center; gap: 0.3rem; color: var(--ink); }

/* Small, like the party control's own save button: it sits at the end of a row
   of checkboxes rather than at the bottom of a form. */
.visit__form input[type="submit"] { font-size: 0.8125rem; padding: 0.2rem 0.5rem; }

/* The page's one picture: the most recent thing anybody photographed here.
   Capped by height rather than width, so that a portrait photo off a phone does
   not push the whole page down before you reach what it says. */
.restaurant__photo { margin: 0.9rem 0 0; }
.restaurant__photo img {
  display: block;
  max-width: 100%;
  max-height: 320px;
  border-radius: 10px;
  border: 1px solid var(--border);
}
.restaurant__photo figcaption {
  color: var(--ink-muted);
  font-size: 0.8125rem;
  margin-top: 0.3rem;
}

/* The Street View that stands in until somebody photographs a meal. A fixed
   height rather than an aspect ratio: a panorama has no natural shape, and this
   is the same 320px cap the photo above gets so the two do not shift the page
   about as one replaces the other. */
.restaurant__streetview { margin: 0.9rem 0 0; }
.restaurant__streetview iframe {
  display: block;
  width: 100%;
  height: 320px;
  border: 1px solid var(--border);
  border-radius: 10px;
}
.restaurant__streetview figcaption {
  color: var(--ink-muted);
  font-size: 0.8125rem;
  margin-top: 0.3rem;
}

/* Every picture of a place, in a row that wraps. Square thumbnails of photos
   that are not square: object-fit crops the tile rather than letterboxing it,
   which keeps the row even without distorting anything. The full shape is one
   click away. */
.photos { margin-top: 2rem; }
.photos__title { font-size: 1.125rem; margin: 0 0 0.5rem; }
.photos__list {
  list-style: none;
  margin: 0 0 0.9rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.photo { display: grid; gap: 0.15rem; justify-items: start; max-width: 120px; }
.photo img {
  display: block;
  width: 120px;
  height: 120px;
  object-fit: cover;
  border-radius: 7px;
  border: 1px solid var(--border);
}
.photo__caption {
  font-size: 0.75rem;
  color: var(--ink-muted);
  overflow-wrap: anywhere;
}
.photo__when { font-size: 0.75rem; color: var(--ink-muted); }
.photo__delete button { font-size: 0.75rem; }

/* The upload, open on the page rather than behind a disclosure — it is the
   control the page was missing, and hiding it is how it stayed unreachable. */
.photobox {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.photobox__caption { font-size: 0.875rem; }

.notes { margin-top: 2rem; }
.notes__title { font-size: 1.125rem; margin: 0 0 0.75rem; }
.notes__list { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid; gap: 0.6rem; }

.note {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 0.7rem 0.9rem;
}

.note__who { display: flex; align-items: baseline; gap: 0.5rem; }
.note__name { font-weight: 650; }
.note__date { color: var(--ink-muted); font-size: 0.8125rem; }

/* Pushed to the far end, so the destructive control is nowhere near the name
   and the date you are reading. The class is on the form rather than the
   button, because `button_to` wraps the button in one and the form is what the
   flex row actually lays out. */
.note__delete { margin-left: auto; }
.note__delete button { font-size: 0.8125rem; }

/* `pre-wrap` so the line breaks somebody typed are the line breaks they get.
   The alternative is turning newlines into <br> on the way out, which means
   building markup out of what a person typed — and this is a note, not HTML. */
.note__text { margin: 0.3rem 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }

.notebox { display: grid; gap: 0.5rem; justify-items: start; margin-bottom: 1.25rem; }
.notebox__label { font-weight: 600; font-size: 0.875rem; }

textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  font: inherit;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 7px;
  resize: vertical;
}

textarea:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* How everyone votes ------------------------------------------------------ */

.voters { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: 1rem; }

.voter {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.75rem 0.9rem;
}

.voter__who { margin: 0 0 0.5rem; display: flex; gap: 0.5rem; align-items: baseline; flex-wrap: wrap; }
.voter__name { font-weight: 650; }
.voter__summary { color: var(--ink-muted); font-size: 0.875rem; }

/* The histogram is a table because it is five labelled numbers — the bar is
   what the number looks like, not a second thing to read. `fixed` and the two
   column widths below so that every person's bars start and end in the same
   place: they are meant to be compared down the page, and a column sized to
   its own contents would put each row's baseline somewhere else. */
.histogram { width: 100%; border-collapse: collapse; table-layout: fixed; }

.histogram__col--score { width: 3.6rem; }
.histogram__col--count { width: 3rem; }

.histogram__row { line-height: 1.3; }

.histogram__score {
  text-align: left;
  font-weight: 400;
  font-size: 0.875rem;
  color: var(--ink-muted);
  padding: 0.12rem 0.4rem 0.12rem 0;
  white-space: nowrap;
}

/* The track the bar is drawn in. A background so that a zero — which draws no
   fill at all — still reads as a row with nothing in it rather than as a row
   that is not there. */
.histogram__bar {
  padding: 0.12rem 0;
  background: linear-gradient(var(--bg), var(--bg));
  background-clip: content-box;
}

/* Always drawn, at nought wide for a score nobody has given — it is what gives
   the track above its height, so an empty row is an empty track rather than a
   row that is not there. */
.histogram__fill {
  display: block;
  height: 0.7rem;
  border-radius: 3px;
  background: var(--accent);
}

.histogram__count {
  text-align: right;
  font-size: 0.875rem;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  padding: 0.12rem 0 0.12rem 0.5rem;
}

/* Who's going ------------------------------------------------------------ */

.party {
  margin-top: 1rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--surface);
}

.party__title { font-size: 0.9375rem; margin: 0 0 0.6rem; }

.party__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.4rem; }

.party__who {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  min-width: 0;
}

.party__name { overflow-wrap: anywhere; }

/* Big enough to hit with a thumb; the row's whole width is a <label>, so the
   name and the picture are targets too. */
.party__box { width: 1.05rem; height: 1.05rem; accent-color: var(--accent); flex: none; }

/* The per-row fallback submit, for a browser that ran no script. Hidden the
   moment the script marks the control as its own, because from then on ticking
   the box submits the form by itself. */
.party--scripted .party__save { display: none; }

.party__save { margin-top: 0.3rem; font-size: 0.8125rem; padding: 0.2rem 0.5rem; }

.party__note { margin: 0.7rem 0 0; }

/* Type of food ----------------------------------------------------------- */

.filter {
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--surface);
}

.filter__title { font-size: 0.9375rem; margin: 0 0 0.6rem; }

.filter__pills { display: flex; flex-wrap: wrap; gap: 0.35rem; }

.filter__note { margin: 0.7rem 0 0; }

/* All and None. Square and quiet, so that they read as two things you do to
   the pills rather than as two more types among them. */
.filter__bulk { display: flex; gap: 0.35rem; margin-bottom: 0.5rem; }

.filter__every {
  font-size: 0.8125rem;
  padding: 0.15rem 0.6rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--ink-muted);
}

.filter__every:hover { border-color: var(--accent); color: var(--ink); }

/* The pill itself, worn by the type of food on a card and by every option in
   the filter. One class for both so that the thing you are picking looks like
   the thing you will then see on the cards. */
.pill {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink-muted);
  font-size: 0.8125rem;
  line-height: 1.4;
  white-space: nowrap;
}

/* Both kinds of pill are pressable, and they do different things: the filter's
   turn a type of food off, and a card's goes to Find for everywhere else of
   that type. The filter's are buttons, so the filled-accent button style above
   has to be undone — they are a row of little switches, not a row of calls to
   action. A card's is an anchor and needs none of that.

   They share the hover, because what it says is the same either way: this is a
   thing you can press. */
.pill--button {
  cursor: pointer;
  font-family: inherit;
  font-weight: 400;
}

.pill--link { text-decoration: none; }

.pill--button:hover,
.pill--link:hover { border-color: var(--accent); color: var(--ink); }

/* On means you will see this type. Every pill starts here, and turning one off
   drains it to the same grey a card's label wears — so what is left coloured is
   exactly what the list below is showing. */
.pill--on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}

.pill--on:hover { color: var(--accent-ink); }

/* The 1-5 picker: one button per level in Rating::SCALE. Unchosen faces are
   drained of colour so that the one you picked is the only thing on the card
   with any, which is what makes a screen of them scannable. Overrides the
   filled-accent button style above — these are a row of little targets, not
   five calls to action.

   Two forms on one row: the picker, and the Clear beside it, which has to be a
   form of its own because it is a DELETE. So `.rate` is the row and
   `.rate__picker` is the faces — same split on `.willing` below. */
.rate { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin-top: 0.5rem; }

.rate__picker { display: flex; gap: 0.3rem; }

.rate__level {
  font-size: 1.15rem;
  line-height: 1;
  padding: 0.3rem 0.5rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px;
  filter: grayscale(1);
  opacity: 0.5;
}

.rate__level:hover { filter: none; opacity: 1; }

.rate__level--chosen {
  filter: none;
  opacity: 1;
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* The willingness picker, shown only on somewhere you have not rated. Its
   buttons carry words rather than a bare face: three statuses have no scale to
   read them off, and "🤔" alone says nothing. */
.willing { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin-top: 0.5rem; }

.willing__picker { display: flex; flex-wrap: wrap; gap: 0.3rem; }

/* Shared with the "I'm eating here" button below, and with the two Clears: the same
   quiet outline, so the controls under a card read as one row of small answers
   rather than as one picker and something louder next to it. */
.willing__level,
.rate__clear,
.willing__clear,
.ate__button {
  font-size: 0.8125rem;
  line-height: 1;
  padding: 0.35rem 0.5rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--ink-muted);
}

.willing__level { opacity: 0.75; }

.willing__level:hover { opacity: 1; }

.willing__level--chosen {
  opacity: 1;
  color: var(--ink);
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* Clearing an answer. Quieter still than the picker it sits next to — it is the
   way out of a mistake rather than one of the answers, so it must not read as
   another button to press. */
.rate__clear,
.willing__clear { opacity: 0.6; }

.rate__clear:hover,
.willing__clear:hover { opacity: 1; color: var(--ink); border-color: var(--accent); }

/* "I'm eating here". One button rather than a picker, because it has one answer,
   and quieter than the faces above it: it records what you are doing tonight
   rather than answering the question the page is on screen to ask. */
.ate { margin-top: 0.5rem; }

.ate__button:hover { color: var(--ink); border-color: var(--accent); }

a { color: var(--accent); }
