/* Bodegarotten - "Flaskeglas": the page is dark bottle glass, every card is a
   cream label pasted onto it. Bricolage Grotesque carries the wordmark and the
   sign; Work Sans carries everything else, card titles included.
   Mobile first: every layout starts as one column and gains structure at
   wider viewports. */

/* ---------------------------------------------------------------- tokens - */
:root {
  /* Ink is the dark used ON a label. Text sitting directly on the glass uses
     --ink-on-glass instead, which is why the two scales exist side by side. */
  --ink: #16241b;
  --ink-70: rgba(22, 36, 27, 0.7);
  --ink-55: rgba(22, 36, 27, 0.58);
  --ink-45: rgba(22, 36, 27, 0.46);
  --ink-30: rgba(22, 36, 27, 0.3);
  --ink-12: rgba(22, 36, 27, 0.12);

  --ink-on-glass: #f0e9da;
  --glass-70: rgba(240, 233, 218, 0.68);
  --glass-45: rgba(240, 233, 218, 0.44);
  --glass-line: rgba(240, 233, 218, 0.16);

  --paper: #f4ecdc;
  --paper-warm: #e8ddc7;
  --desk: #101c15;
  --panel: #18291f;
  --white: #fffdf5;

  --amber: oklch(0.78 0.14 74);
  --amber-soft: oklch(0.93 0.05 80);
  --brown: oklch(0.34 0.045 60);
  --hop: oklch(0.8 0.13 132);
  --hop-ink: oklch(0.45 0.09 134);
  --pen: oklch(0.52 0.11 62);
  --danger: oklch(0.55 0.17 28);

  --rule: rgba(22, 36, 27, 0.18);
  --stroke: 1.5px solid rgba(22, 36, 27, 0.7);
  --stroke-soft: 1.5px solid rgba(22, 36, 27, 0.2);
  --stroke-dashed: 1.5px dashed rgba(22, 36, 27, 0.4);

  --ui: "Work Sans", system-ui, -apple-system, sans-serif;
  --brand: "Bricolage Grotesque", var(--ui);

  /* Type scale. Tracking and leading tighten as size grows, never the other
     way round: negative tracking belongs to display sizes only. Setting a
     card title at display values is what made the Danish compounds cramp. */
  --size-display: 2.4rem;
  --track-display: -0.02em;
  --leading-display: 1.02;

  --size-h1: 1.5rem;
  --track-h1: -0.005em;
  --leading-h1: 1.15;

  --size-h2: 1.125rem;
  --track-h2: 0;
  --leading-h2: 1.25;

  --gap-xs: 0.375rem;
  --gap-sm: 0.625rem;
  --gap: 1rem;
  --gap-lg: 1.5rem;
  --gap-xl: 2.25rem;

  --radius: 4px;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  --page-max: 70rem;
}

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

/* ------------------------------------------------------------------ base - */
body {
  margin: 0;
  background: var(--desk);
  color: var(--ink-on-glass);
  font-family: var(--ui);
  font-size: 100%;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  margin: 0;
  font-weight: 700;
  text-wrap: balance;
}

h1 {
  font-size: var(--size-h1);
  letter-spacing: var(--track-h1);
  line-height: var(--leading-h1);
}

h2 {
  font-size: var(--size-h2);
  letter-spacing: var(--track-h2);
  line-height: var(--leading-h2);
}

h3 {
  font-size: 1rem;
  line-height: 1.3;
}

p { margin: 0; text-wrap: pretty; }

a { color: inherit; }

img,
svg { max-width: 100%; }

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

/* ------------------------------------------------------------ typography - */
.brand-name {
  font-family: var(--brand);
  font-optical-sizing: auto;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.label {
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-45);
}

.note {
  font-family: var(--brand);
  font-size: 0.8125rem;
  letter-spacing: 0.02em;
  color: var(--pen);
}

.muted { color: var(--ink-55); }
.small { font-size: 0.6875rem; }
.numeric { font-variant-numeric: tabular-nums; }

.rule {
  height: 1.5px;
  border: 0;
  margin: 0;
  background: var(--rule);
}

/* --------------------------------------------------------------- helpers - */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

.stack--tight { gap: var(--gap-sm); }
.stack--loose { gap: var(--gap-lg); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-sm);
}

.push { margin-top: auto; }

.placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--gap-sm);
  border: 1px dashed var(--ink-30);
  background: repeating-linear-gradient(45deg, rgba(22, 36, 27, 0.07) 0 6px, transparent 6px 12px);
  font-size: 0.625rem;
  letter-spacing: 0.04em;
  color: var(--ink-55);
}

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

/* ---------------------------------------------------------------- header - */
.site-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm);
  padding: var(--gap-sm) var(--gap);
  border-bottom: 1px solid var(--glass-line);
  background: var(--panel);
  color: var(--ink-on-glass);
}

.site-header__brand {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  text-decoration: none;
}

.site-header__mark {
  width: 2rem;
  height: 2rem;
  flex: none;
}

.site-header__name { font-size: 1.125rem; }

.site-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap);
}

/* The nav carries .label, which is scaled for dark ink on a label. Up here it
   sits on the glass, so it takes the light end of the scale instead. */
.site-header .label {
  color: var(--glass-45);
}

.site-nav a:hover { color: var(--ink-on-glass); }

.site-nav a { text-decoration: none; }
.site-nav a:hover { text-decoration: underline; }

/* Divides the sections of the site from the account links. */
.site-nav__sep {
  width: 1.5px;
  align-self: stretch;
  min-height: 0.9rem;
  background: var(--glass-line);
}

/* ------------------------------------------------------------------ page - */
.page {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0;
}

/* A panel is a label pasted onto the bottle: it carries its own dark ink,
   because the page around it is dark. */
.panel {
  background: var(--paper);
  color: var(--ink);
  border-bottom: 1px solid rgba(0, 0, 0, 0.25);
}

.panel__body {
  padding: var(--gap-lg) var(--gap);
}

.panel__aside {
  padding: var(--gap-lg) var(--gap);
  border-top: var(--stroke-soft);
  background: rgba(22, 36, 27, 0.05);
}

@media (min-width: 48em) {
  .page { padding: var(--gap-lg) var(--gap); }

  .panel {
    border: 1px solid rgba(0, 0, 0, 0.14);
    border-radius: 6px;
    box-shadow: var(--shadow);
    overflow: hidden;
  }

  .panel__body { padding: var(--gap-xl) var(--gap-lg); }

  .panel__aside {
    border-top: 0;
    border-left: var(--stroke-soft);
    padding: var(--gap-xl) var(--gap-lg);
  }

  /* Main column plus a narrower rail, once there is room for both. */
  .panel--split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 20rem;
  }
}

/* ----------------------------------------------------------------- forms - */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
}

.field__label {
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-45);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="file"],
select,
textarea {
  width: 100%;
  padding: 0.6rem 0.7rem;
  border: 1.5px solid rgba(22, 36, 27, 0.55);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  font-family: var(--ui);
  font-size: 1rem; /* keeps iOS from zooming on focus */
}

textarea { resize: vertical; }

input::placeholder,
textarea::placeholder { color: rgba(22, 36, 27, 0.42); }

.form-grid {
  display: grid;
  gap: var(--gap);
}

@media (min-width: 34em) {
  .form-grid--halves { grid-template-columns: 1fr 1fr; }
  .form-grid--main-aside { grid-template-columns: minmax(0, 1fr) 7rem; }
}

.fieldset {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  margin: 0;
  padding: var(--gap);
  border: var(--stroke);
  background: var(--white);
}

.fieldset legend {
  padding: 0 var(--gap-xs);
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-45);
}

.errorlist {
  margin: 0;
  padding-left: 1.1rem;
  color: var(--danger);
  font-size: 0.6875rem;
}

/* Buttons and anything that must look like one. */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-xs);
  min-height: 2.75rem; /* comfortable touch target */
  padding: 0.6rem 0.9rem;
  border: var(--stroke);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font-family: var(--ui);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
}

.button:hover:not(:disabled) { box-shadow: var(--shadow); }

.button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.button--primary {
  background: var(--amber);
  font-weight: 700;
}

.button--block { width: 100%; }

.button--small {
  min-height: 2rem;
  padding: 0.3rem 0.6rem;
  font-size: 0.625rem;
}

.button--icon {
  min-height: 2rem;
  width: 2rem;
  padding: 0;
}

/* Toggle: a real checkbox wearing the wireframe's pill. */
.toggle {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  font-size: 0.75rem;
  cursor: pointer;
}

.toggle__input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.toggle__pill {
  flex: none;
  display: flex;
  justify-content: flex-start;
  width: 2.375rem;
  height: 1.25rem;
  padding: 2px;
  border: var(--stroke);
  border-radius: 0.625rem;
  background: var(--white);
}

.toggle__pill::after {
  content: "";
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--ink-30);
}

.toggle__input:checked + .toggle__pill {
  justify-content: flex-end;
  background: var(--amber);
}

.toggle__input:checked + .toggle__pill::after { background: var(--ink); }

.toggle__input:focus-visible + .toggle__pill {
  outline: 2px solid var(--pen);
  outline-offset: 2px;
}

/* Axis list on the create screen. Each row is a tickbox: the host chooses
   which scales the table rates on, and may switch them all off. */
.axis-row {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  padding: 0.7rem 0.8rem;
  border: var(--stroke);
  background: var(--white);
  font-size: 0.75rem;
  cursor: pointer;
}

.axis-row input[type="checkbox"] {
  width: 0.875rem;
  height: 0.875rem;
  flex: none;
  margin: 0;
  accent-color: var(--hop-ink);
}

.axis-row__name { font-weight: 600; }

/* A switched-off axis reads as an offer declined, not as a disabled control. */
.axis-row:has(input:not(:checked)) {
  background: transparent;
  border: var(--stroke-soft);
  color: var(--ink-45);
}

.axis-row--muted {
  border: var(--stroke-dashed);
  background: transparent;
  color: var(--ink-45);
}

.axis-row__scale {
  flex: 1;
  min-width: 4rem;
  height: 1rem;
}

/* ----------------------------------------------------------------- lobby - */
.lobby { display: block; }

.poster {
  display: flex;
  flex-direction: column;
  gap: var(--gap-lg);
  padding: var(--gap-lg) var(--gap);
  background: var(--ink);
  color: var(--paper);
}

.poster .label { color: rgba(255, 253, 248, 0.5); }

.poster__code {
  font-size: clamp(3.5rem, 18vw, 5.25rem);
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: 0.1em;
}

.poster__qr {
  width: 8rem;
  height: 8rem;
  border-color: rgba(255, 253, 248, 0.35);
  color: rgba(255, 253, 248, 0.55);
  background: repeating-linear-gradient(45deg, rgba(255, 253, 248, 0.12) 0 6px, transparent 6px 12px);
}

.poster__tally {
  font-size: 2rem;
  font-weight: 700;
}

.room {
  display: flex;
  flex-direction: column;
  gap: var(--gap-lg);
  padding: var(--gap-lg) var(--gap);
}

@media (min-width: 62em) {
  .lobby {
    display: grid;
    grid-template-columns: 24rem minmax(0, 1fr);
    min-height: 38rem;
  }

  .poster {
    justify-content: space-between;
    padding: var(--gap-xl) var(--gap-lg);
  }

  .room { padding: var(--gap-xl) var(--gap-lg); }
}

/* Who is in the room. */
.roster {
  display: grid;
  gap: var(--gap-sm);
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
}

.roster__card {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
  min-height: 6rem;
  padding: 0.8rem;
  border: var(--stroke);
  background: var(--white);
}

.roster__card--empty {
  align-items: center;
  justify-content: center;
  border: var(--stroke-dashed);
  background: transparent;
  color: var(--ink-45);
  font-size: 0.6875rem;
  text-align: center;
}

.roster__who {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
}

.roster__avatar {
  width: 1.75rem;
  height: 1.75rem;
  flex: none;
  border-radius: 50%;
}

.roster__name {
  font-size: 0.8125rem;
  font-weight: 700;
}

.roster__beer { font-size: 0.6875rem; }

/* The draw: bottle caps, flipped one at a time. */
.caps {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-sm);
}

.cap {
  position: relative;
  width: 2.125rem;
  height: 2.125rem;
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1.6px solid var(--ink);
  background: var(--paper);
  color: var(--ink-45);
  font-size: 0.75rem;
  font-weight: 700;
  /* The dashes are the crimped edge of the cap. */
  box-shadow: inset 0 0 0 3px transparent;
}

.cap::before {
  content: "";
  position: absolute;
  inset: 1px;
  border-radius: 50%;
  border: 3px dashed rgba(22, 36, 27, 0.55);
  opacity: 0.55;
}

.cap::after {
  content: "";
  position: absolute;
  inset: 0.45rem;
  border-radius: 50%;
  border: 1.2px solid rgba(22, 36, 27, 0.4);
}

.cap--flipped {
  background: var(--hop);
  color: oklch(0.3 0.06 128);
  animation: cap-flip 0.45s ease-out;
}

@keyframes cap-flip {
  from { transform: rotateY(-180deg) scale(0.85); }
  to { transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .cap--flipped { animation: none; }
}

/* The drawn order. */
.order {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

.order__row {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
  padding: 0.6rem 0.7rem;
  border: var(--stroke);
  background: var(--white);
}

.order__row--drawn { background: var(--amber-soft); }

.order__row--pending {
  border: var(--stroke-dashed);
  background: transparent;
  color: var(--ink-45);
}

.order__pos {
  min-width: 1.75rem;
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--ink-45);
}

.order__what {
  flex: 1;
  min-width: 0;
}

.order__name {
  font-size: 0.75rem;
  font-weight: 700;
}

.order__meta {
  font-size: 0.625rem;
  color: var(--ink-55);
}

.order__moves {
  display: flex;
  gap: 0.25rem;
}

/* Host-only controls, folded into the same screen. */
.host-panel {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding: var(--gap);
  border: var(--stroke-dashed);
  background: rgba(22, 36, 27, 0.03);
}

.host-panel__title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--gap-sm);
}

.status-list {
  margin: 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.2rem var(--gap-sm);
  font-size: 0.75rem;
}

.status-list dt { font-weight: 700; }
.status-list dd { margin: 0; color: var(--ink-55); }

/* ---------------------------------------------------------------- rating - */
.beer-head {
  display: flex;
  align-items: flex-start;
  gap: var(--gap);
}

.beer-head__photo {
  width: 4rem;
  height: 5.5rem;
  flex: none;
  object-fit: cover;
  border: var(--stroke);
}

.beer-head__name {
  font-size: 1.3rem;
  font-weight: 700;
}

.tag {
  display: inline-block;
  align-self: flex-start;
  padding: 0.25rem 0.5rem;
  border: var(--stroke-dashed);
  font-size: 0.625rem;
  color: var(--ink-55);
}

.slider {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
}

.slider__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm);
}

.slider__name {
  font-size: 0.875rem;
  font-weight: 700;
}

.slider__readout {
  display: flex;
  align-items: baseline;
  gap: var(--gap-xs);
}

.slider__value {
  min-width: 4.5rem;
  padding: 0.35rem 0.6rem;
  border: var(--stroke);
  background: var(--white);
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* Range input styled to match the drawn track: flat bar, square handle. */
.slider__input {
  width: 100%;
  height: 2.75rem;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  appearance: none;
  cursor: pointer;
}

.slider__input::-webkit-slider-runnable-track {
  height: 0.5rem;
  border: 1.5px solid rgba(22, 36, 27, 0.55);
  background: var(--white);
}

.slider__input::-moz-range-track {
  height: 0.5rem;
  border: 1.5px solid rgba(22, 36, 27, 0.55);
  background: var(--white);
}

.slider__input::-moz-range-progress {
  height: 0.5rem;
  background: var(--amber);
}

.slider__input::-webkit-slider-thumb {
  appearance: none;
  width: 1.6rem;
  height: 2.4rem;
  margin-top: -0.95rem;
  border: 1.5px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
}

.slider__input::-moz-range-thumb {
  width: 1.6rem;
  height: 2.4rem;
  border: 1.5px solid var(--ink);
  border-radius: 2px;
  background: var(--ink);
}

/* Ten hop cones under the track: filled up to the current score. */
.slider__scale {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 0.25rem;
  padding: 0 0.4rem;
}

/* Ten cones sharing the row: flexible so they never overflow a narrow card,
   capped so they do not balloon on a wide one. */
.hop {
  flex: 1 1 0;
  min-width: 0;
  max-width: 1.25rem;
  height: auto;
  aspect-ratio: 18 / 24;
}

/* The unlit drawing, always painted. */
.hop__base {
  color: var(--ink-30);
  opacity: 0.55;
}

/* The lit drawing sits on top of it: a light cone with dark linework, so the
   shape still reads instead of going flat green. Hidden on a cone the score
   has not reached, and clipped down the middle on a half. */
.hop__fill {
  display: none;
  color: var(--hop);
  --hop-stroke: var(--ink);
  --hop-detail-opacity: 0.8;
  --hop-stem-opacity: 1;
}

.hop--on .hop__fill,
.hop--half .hop__fill {
  display: inline;
}

/* Percentages in inset() resolve against the fill box on an SVG element, so
   this is half the cone rather than half the viewBox. */
.hop--half .hop__fill {
  clip-path: inset(0 50% 0 0);
}

.slider__ends {
  display: flex;
  justify-content: space-between;
  gap: var(--gap-sm);
  font-size: 0.6rem;
  color: var(--ink-45);
}

/* Your earlier beers: a rail on desktop, a swipeable strip on phones. */
.history {
  display: flex;
  gap: var(--gap-sm);
  overflow-x: auto;
  padding-bottom: var(--gap-xs);
  scroll-snap-type: x proximity;
}

.history__card {
  flex: none;
  min-width: 8rem;
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
  padding: 0.7rem;
  border: var(--stroke);
  background: var(--white);
  scroll-snap-align: start;
}

.history__score {
  font-size: 1.0625rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

@media (min-width: 48em) {
  .history {
    flex-direction: column;
    overflow: visible;
  }

  .history__card { min-width: 0; }
}

/* Host banner that rides along on the rating screen. */
/* The bar and the waiting line beneath it. The inset lives here, once, so the
   two cannot end up at different distances from the edge. */
.host-strip {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  margin: var(--gap) var(--gap) 0;
}

.host-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm);
  padding: 0.6rem 0.8rem;
  border: var(--stroke-dashed);
  background: rgba(22, 36, 27, 0.04);
  font-size: 0.6875rem;
}

@media (min-width: 48em) {
  .host-strip { margin: var(--gap) var(--gap-lg) 0; }
}

/* --------------------------------------------------------------- results - */
/* Table on wide screens; the same rows become stacked cards on phones. */
.results { width: 100%; border-collapse: collapse; }

.results thead { display: none; }

.results tr {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr) auto;
  gap: 0.2rem var(--gap-sm);
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--ink-12);
}

.results td { padding: 0; }

.results__pos {
  grid-row: span 2;
  font-weight: 700;
  color: var(--ink-45);
}

.results__avg {
  grid-row: span 2;
  align-self: center;
  font-size: 1.0625rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.results__axes {
  grid-column: 2;
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-sm);
  font-size: 0.625rem;
  color: var(--ink-55);
}

.results tr.is-winner { background: var(--amber-soft); }

@media (min-width: 48em) {
  .results thead { display: table-header-group; }

  .results tr {
    display: table-row;
    padding: 0;
  }

  .results th,
  .results td {
    padding: 0.65rem 0.5rem;
    text-align: left;
    vertical-align: middle;
  }

  .results th {
    font-size: 0.6rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ink-45);
    border-bottom: 1.5px solid var(--ink-30);
  }

  .results__axes { display: table-cell; }
  .results__axis { display: table-cell; }
}

/* Progress list while scores are still sealed. */
.progress-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm);
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--ink-12);
  font-size: 0.75rem;
}

.progress-row__state { color: var(--ink-55); }

.sealed {
  letter-spacing: 0.1em;
  color: var(--ink-30);
}

/* ------------------------------------------------------------------ chips - */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap-xs);
}

.chip {
  padding: 0.35rem 0.6rem;
  border: var(--stroke-dashed);
  border-radius: 0.875rem;
  font-size: 0.6875rem;
}

.chip--self {
  border-style: solid;
  background: var(--amber-soft);
}

/* ----------------------------------------------------------- front door - */
/* The front page is not a panel: the sign carries its own frame, and the
   doors below are separate cards rather than one sheet of paper. */
.front {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding: var(--gap);
}

/* The sign. Thicker rule than anything else on the site, on purpose: it is
   the one piece of furniture rather than paperwork. */
.sign {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--gap);
  padding: var(--gap-xl) var(--gap-lg);
  border: 1px solid var(--amber);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--ink-on-glass);
  text-align: center;
}

.sign__figure {
  width: 6.5rem;
}

.sign__kicker { color: var(--glass-45); }

.sign__title {
  margin: 0;
  font-family: var(--brand);
  font-optical-sizing: auto;
  font-size: var(--size-display);
  font-weight: 800;
  line-height: var(--leading-display);
  letter-spacing: var(--track-display);
  color: var(--amber);
}

.sign__lead {
  max-width: 24ch;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--glass-70);
}

/* One card per section of the site. A third drops into the grid untouched. */
/* Cards stretch to match each other, so a short one does not leave a ragged
   edge next to a long one. */
.doors {
  display: grid;
  gap: var(--gap);
}

.door {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.85rem;
  padding: var(--gap-lg);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.door__title {
  margin: 0;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  line-height: 1.25;
  text-wrap: balance;
}

/* Takes up the slack, so the actions sit at the foot of every card. */
.door__text {
  flex-grow: 1;
  font-size: 1rem;
  line-height: 1.6;
  max-width: 55ch;
  color: var(--ink-70);
}

/* Encouragement belongs to the door it is cheering for, not to the page. */
.door__cheer {
  font-family: var(--brand);
  font-size: 0.9375rem;
  line-height: 1.4;
  color: var(--pen);
}

@media (min-width: 34em) {
  .sign__title { font-size: 3rem; letter-spacing: -0.025em; }
}

@media (min-width: 48em) {
  .front {
    gap: var(--gap-lg);
    padding: var(--gap-lg) var(--gap);
  }

  /* Wide enough for the figure to stand beside the wordmark instead of on
     top of it, which is how a real sign would be laid out. */
  .sign {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 16rem;
    align-items: center;
    gap: var(--gap-xl);
    padding: var(--gap-xl) var(--gap-lg);
    text-align: left;
  }

  .sign__figure {
    grid-column: 2;
    grid-row: 1 / span 3;
    width: 100%;
  }

  .sign__kicker { grid-column: 1; }
  .sign__title { grid-column: 1; font-size: 3.5rem; letter-spacing: -0.025em; }

  .sign__lead {
    grid-column: 1;
    max-width: 46ch;
    font-size: 1.15rem;
  }

  /* Flows to as many columns as fit, so a fourth door needs no CSS change.
     The four rows are the four parts of a door: title, text, action, cheer.
     Each card spans them as a subgrid, so every part lines up with the same
     part in its neighbours no matter how many lines it runs to. Without this
     the buttons sit at whatever height the text above them happens to end,
     and a two-line cheer in one card pushes its button out of step with the
     rest. */
  .doors {
    grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
    grid-template-rows: auto 1fr auto auto;
    gap: var(--gap-lg);
  }

  .door {
    display: grid;
    grid-row: span 4;
    grid-template-rows: subgrid;
    row-gap: 0.85rem;
    justify-items: start;
  }

  /* The 1fr row does the stretching now, so the text no longer has to. */
  .door__text { flex-grow: 0; }

  .door { padding: var(--gap-lg); }
}

/* --------------------------------------------------------------- listings - */
.tasting-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap);
  padding: 0.8rem;
  border: var(--stroke);
  background: var(--white);
  text-decoration: none;
}

.tasting-link__code {
  font-size: 1.25rem;
  font-weight: 700;
  letter-spacing: 0.14em;
}

/* ----------------------------------------------------------- account UI - */
/* A form nobody needs to read across: keep the measure short on a laptop. */
.panel--narrow { max-width: 30rem; }

@media (min-width: 48em) {
  .panel--narrow { margin: 0 auto; }
}

.or-rule {
  display: flex;
  align-items: center;
  gap: var(--gap-sm);
}

.or-rule .rule {
  flex-grow: 1;
}

.button--google {
  background: var(--white);
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 0.8125rem;
}

.button__mark {
  width: 1rem;
  height: 1rem;
  flex: none;
}

.callout {
  padding: var(--gap);
  border: var(--stroke);
  background: var(--amber-soft);
}

.cluster--between { justify-content: space-between; }

.ticks {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  margin: 0;
  padding-left: 1.1rem;
  font-size: 0.75rem;
}

/* The guest offer. Never a wall: every use leaves a way to carry on. */
.offer {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  padding: var(--gap);
  border: var(--stroke);
  background: var(--amber-soft);
}

.offer__text {
  font-size: 0.8125rem;
  line-height: 1.45;
  text-wrap: pretty;
}

.offer__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--gap-sm);
}

.tag--host {
  border-style: solid;
  background: var(--amber-soft);
  color: var(--ink);
}

/* ------------------------------------------------------------- history - */
.history {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8125rem;
}

.history th {
  padding: 0 var(--gap-sm) var(--gap-xs) 0;
  text-align: left;
  font-size: 0.6rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-45);
  white-space: nowrap;
}

.history td {
  padding: 0.7rem var(--gap-sm) 0.7rem 0;
  border-top: 1.5px solid var(--rule);
  vertical-align: baseline;
}

.history__num { text-align: right; }
.history__avg { font-weight: 700; }

/* The table has more columns than a phone can hold, so it scrolls on its own
   rather than squeezing the whole page. */
@media (max-width: 47.99em) {
  .history { display: block; overflow-x: auto; white-space: nowrap; }
}

/* ------------------------------------------------------------ game rules - */
/* A rules page answers three questions in the order a newcomer asks them:
   what are we doing, what do we need, and how does a turn go. The layout keeps
   them apart so none of them has to be read to reach the others. */
.rules {
  display: flex;
  flex-direction: column;
  gap: var(--gap-lg);
  max-width: 44rem;
  margin: 0 auto;
  padding: var(--gap-lg) var(--gap);
}

.rules__head {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
}

.rules__title {
  margin: 0;
  font-family: var(--brand);
  font-optical-sizing: auto;
  font-size: var(--size-display);
  font-weight: 800;
  letter-spacing: var(--track-display);
  line-height: var(--leading-display);
  color: var(--amber);
}

.rules__lead {
  font-size: 1.125rem;
  line-height: 1.55;
  color: var(--glass-70);
  max-width: 46ch;
}

/* Each section is a label on the bottle, like every other card on the site. */
.rules__section {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding: var(--gap-lg);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  box-shadow: var(--shadow);
}

.rules__heading {
  margin: 0;
  font-size: 1.375rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  line-height: 1.25;
}

.rules__body {
  font-size: 1rem;
  line-height: 1.65;
  color: var(--ink-70);
  max-width: 60ch;
}

.rules__aside {
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--ink-55);
}

.rules__cheer {
  font-family: var(--brand);
  font-size: 1.0625rem;
  color: var(--amber);
  text-align: center;
}

/* What you need, as objects rather than a sentence: it is the one part people
   scan before deciding whether they can play tonight. */
/* Fixed column counts rather than auto-fit. Left to itself the grid packed
   five items into four columns and left one on its own; two then three reads
   as a choice instead of a leftover. */
.kit {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: auto auto 1fr;
  gap: var(--gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* The three rows are icon, name, note. Each card takes them from the grid, so
   the drawings sit on one line and the names on another even when one of them
   wraps and its neighbours do not. */
.kit__item {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  row-gap: var(--gap-xs);
  justify-items: center;
  padding: var(--gap);
  border: var(--stroke-dashed);
  border-radius: var(--radius);
  text-align: center;
}

@media (min-width: 34em) {
  .kit { grid-template-columns: repeat(3, minmax(0, 1fr)); }

  /* Two items in three columns leave a hole in the third, and the pair drifts
     to the left of the section above and below it. A kit of exactly two keeps
     the two-up layout it already has on a phone: full width, equal halves,
     centred under everything else. Driven by the count rather than a modifier
     class, so adding a third item is enough on its own. */
  .kit:has(.kit__item:nth-child(2):last-child) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.kit__icon {
  width: 2.25rem;
  height: 2.25rem;
  color: var(--ink);
}

.kit__name {
  font-weight: 700;
  font-size: 0.9375rem;
}

.kit__note {
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--ink-55);
  text-wrap: pretty;
}

/* The turn, step by step. Numbers are drawn from the list itself, so steps can
   be added or reordered without renumbering anything by hand. */
.play {
  display: flex;
  flex-direction: column;
  gap: var(--gap-lg);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: play;
}

.play__step {
  display: grid;
  grid-template-columns: 2.25rem minmax(0, 1fr);
  gap: var(--gap-xs) var(--gap);
  align-items: baseline;
  counter-increment: play;
}

.play__step::before {
  content: counter(play);
  grid-row: span 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border: var(--stroke);
  border-radius: 50%;
  background: var(--amber-soft);
  font-size: 0.9375rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.play__title {
  margin: 0;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.3;
}

.play__text {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ink-70);
  max-width: 60ch;
}

@media (min-width: 48em) {
  .rules { padding: var(--gap-xl) var(--gap); }
  .rules__title { font-size: 3.25rem; letter-spacing: -0.025em; }
}

/* The named rules: what the players call a thing, and what it means. A
   description list rather than paragraphs, because that is what it is, and it
   lets the term hang above its explanation instead of running into it. */
.ruleset {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  margin: 0;
}

.ruleset__term {
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink);
}

.ruleset__what {
  margin: 0 0 var(--gap-sm) 0;
  font-size: 1rem;
  line-height: 1.65;
  color: var(--ink-70);
  max-width: 60ch;
}

.ruleset__what:last-child { margin-bottom: 0; }

/* The parenthetical warnings, set apart so they read as a nudge from the side
   rather than as part of the rule itself. */
.ruleset__aside {
  display: block;
  margin-top: var(--gap-xs);
  font-size: 0.875rem;
  color: var(--pen);
}

.choices {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  margin: 0;
  padding-left: 1.15rem;
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink-70);
}

.choices li::marker { color: var(--ink-45); }

@media (min-width: 34em) {
  /* Wide enough for the term to sit beside what it means, which is how a rule
     sheet is read: run your eye down the left, stop at the one you need. */
  .ruleset {
    display: grid;
    grid-template-columns: minmax(7rem, auto) minmax(0, 1fr);
    gap: var(--gap-sm) var(--gap);
    align-items: baseline;
  }

  .ruleset__what { margin: 0; }
}

/* ------------------------------------------------------- style picker - */
.stylepick {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
}

.stylepick__filter {
  width: 100%;
  padding: 0.55rem 0.7rem;
  border: var(--stroke-soft);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  font-family: var(--ui);
  font-size: 1rem; /* keeps iOS from zooming on focus */
}

.stylepick__count {
  min-height: 1.1rem; /* reserved, so the field does not jump while typing */
}

/* An open listbox rather than a dropdown, on screens wide enough to spare
   the room. Set by the script, so without it the field stays a plain select. */
.stylepick__list {
  padding: 0;
  overflow-y: auto;
}

.stylepick__list option {
  padding: 0.4rem 0.7rem;
}

.stylepick__list optgroup {
  font-size: 0.6875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-45);
}

/* -------------------------------------------------------- style note - */
/* The evening's theme, explained. Amber-soft rather than a card, so it reads
   as a note pinned to the screen and not as another thing to fill in. */
.stylenote {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs);
  padding: var(--gap);
  border: var(--stroke-soft);
  border-radius: var(--radius);
  background: var(--amber-soft);
  color: var(--ink);
}

.stylenote__name {
  font-family: var(--brand);
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.2;
}

.stylenote__text {
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ink-70);
  max-width: 62ch;
}

/* Folded on the rating screen: the sliders are what people came for. */
.stylenote--folded { padding: 0; }

.stylenote__summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--gap-sm);
  padding: var(--gap-sm) var(--gap);
  cursor: pointer;
}

.stylenote--folded .stylenote__text {
  padding: 0 var(--gap) var(--gap);
}

.stylenote__summary::marker { color: var(--ink-45); }

@media (min-width: 48em) {
  .lobby .stylenote { margin: var(--gap-lg) var(--gap) 0; }
}

/* ------------------------------------------------------- your own beer - */
/* The round where your bottle is on the table. No sliders, so the space they
   left has to say why rather than just sit empty. */
.own-beer {
  display: flex;
  flex-direction: column;
  gap: var(--gap-sm);
  padding: var(--gap);
  border: var(--stroke-dashed);
  background: var(--amber-soft);
}

.own-beer__title {
  font-family: var(--brand);
  font-size: var(--size-h2);
  letter-spacing: var(--track-h2);
  line-height: var(--leading-h2);
  margin: 0;
}

.own-beer__text {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.45;
  text-wrap: pretty;
}

/* ----------------------------------------------------------- the awards - */
/* Joke prizes. Set like the little medals on a bottle: small, gold, slightly
   too pleased with themselves. */
.awards {
  display: grid;
  gap: var(--gap-sm);
  grid-template-columns: 1fr;
}

.award {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.7rem 0.8rem;
  border: var(--stroke);
  background: var(--white);
  border-left: 4px solid var(--amber);
}

.award__title {
  font-size: 0.625rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-55);
}

.award__name {
  font-family: var(--brand);
  font-size: 1.0625rem;
  line-height: 1.15;
}

.award__detail {
  font-size: 0.75rem;
  color: var(--ink-70);
  text-wrap: pretty;
}

@media (min-width: 40em) {
  .awards { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 60em) {
  .awards { grid-template-columns: repeat(3, 1fr); }
}

/* ------------------------------------------------------ the quote wall - */
/* Every note written during the evening, pasted up as the scraps they are:
   torn label paper, a biro hand, and the score stamped in the corner. The
   rotation is decoration and stays tiny - a wall you cannot read is a joke
   that only works once. */
.wall {
  display: grid;
  gap: var(--gap);
  grid-template-columns: 1fr;
  padding: var(--gap-sm) 0;
}

.scrap {
  position: relative;
  margin: 0;
  padding: 1rem 2.6rem 0.9rem 1rem;
  background: var(--paper);
  border: var(--stroke-soft);
  box-shadow: 2px 3px 0 rgba(22, 36, 27, 0.14);
}

.scrap:nth-child(3n) { background: var(--paper-warm); }
.scrap:nth-child(4n) { background: var(--white); }

.scrap__quote {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--pen);
  text-wrap: pretty;
}

.scrap__quote::before { content: "»"; }
.scrap__quote::after { content: "«"; }

.scrap__by {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: var(--gap-sm);
  font-size: 0.6875rem;
  color: var(--ink-55);
}

.scrap__author {
  font-weight: 700;
  color: var(--ink);
}

/* The score, stamped rather than typed: it belongs to the paper, not the
   note. Tabular numerals so a column of stamps lines up down the wall. */
.scrap__stamp {
  position: absolute;
  top: 0.55rem;
  right: 0.5rem;
  padding: 0.15rem 0.35rem;
  border: 1.5px solid var(--hop-ink);
  color: var(--hop-ink);
  font-size: 0.6875rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  transform: rotate(-6deg);
}

@media (min-width: 48em) {
  .wall {
    grid-template-columns: repeat(2, 1fr);
    align-items: start;
  }

  .scrap--wide { grid-column: span 2; }

  /* Alternating tilt, kept under a degree and a half. Enough to read as
     pinned up by hand, not enough to fight the baseline of the page. */
  .scrap:nth-child(odd) { transform: rotate(-0.7deg); }
  .scrap:nth-child(even) { transform: rotate(0.6deg); }
}

@media (min-width: 64em) {
  .wall { grid-template-columns: repeat(3, 1fr); }
  .scrap--wide { grid-column: span 2; }
}

@media (prefers-reduced-motion: reduce) {
  .scrap,
  .scrap__stamp { transform: none; }
}
