/* WineNight — mobile first: most sheets are filled in with a glass in the other hand. */

:root {
  --bg: #faf6f1;
  --surface: #ffffff;
  --surface-2: #f3ece4;
  --ink: #2a1d1f;
  --muted: #7a6a6c;
  --line: #e6dcd2;
  --wine: #6b1a36;
  --wine-strong: #521127;
  --wine-soft: #f3e1e6;
  --wine-faded: #e9cdd6;
  --wine-faded-ink: #8a4a5f;
  --on-wine: #fff8f2;
  --gold: #b88a2e;
  --ok: #2f6b45;
  --ok-soft: #e3f1e7;
  --danger: #a3242d;
  --danger-soft: #fbe6e6;
  --red-wine: #7d1631;
  --white-wine: #e8d58a;
  --rose-wine: #f0a1a8;
  --glass: #b4c3d0;
  --radius: 14px;
  --radius-small: 9px;
  --shadow: 0 1px 2px rgb(60 20 30 / 6%), 0 6px 20px rgb(60 20 30 / 6%);
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #171113;
    --surface: #211a1c;
    --surface-2: #2b2225;
    --ink: #f1e8e3;
    --muted: #a8989a;
    --line: #3a2f32;
    --wine: #c2466d;
    --wine-strong: #d85c83;
    --wine-soft: #3a1f29;
    --wine-faded: #4a2433;
    --wine-faded-ink: #d9a3b5;
    --on-wine: #fff8f2;
    --ok: #7ccf98;
    --ok-soft: #1f3327;
    --danger: #f07a82;
    --danger-soft: #3a1c1f;
    --glass: #6d8193;
    --shadow: 0 1px 2px rgb(0 0 0 / 30%), 0 6px 20px rgb(0 0 0 / 25%);
    color-scheme: dark;
  }
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.5 var(--sans);
}

h1, h2, h3 { font-family: var(--serif); font-weight: 600; line-height: 1.2; margin: 0 0 .4em; }
h1 { font-size: clamp(1.6rem, 5vw, 2.2rem); }
h2 { font-size: 1.3rem; }
h3 { font-size: 1.1rem; }
p { margin: 0 0 .8em; }
a { color: var(--wine); }
img { max-width: 100%; }

.muted { color: var(--muted); }
.small { font-size: .875rem; }
[hidden] { display: none !important; }
/* For screen readers only. */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* Top bar */
.topbar {
  position: relative; z-index: 10;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 16px; padding-top: max(10px, env(safe-area-inset-top));
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.brand { display: flex; align-items: center; gap: 8px; color: var(--wine); text-decoration: none; font: 600 1.2rem var(--serif); }
.brand-mark { width: 22px; height: 22px; }
.topbar-actions { display: flex; align-items: center; gap: 10px; }
.nav-link { color: var(--ink); text-decoration: none; font-size: .95rem; }
.nav-link:hover { color: var(--wine); }
@media (max-width: 420px) { .nav-link { display: none; } }

.locale-switch { display: flex; border: 1px solid var(--line); border-radius: 999px; overflow: hidden; }
.locale-switch button {
  border: 0; background: transparent; color: var(--muted); font: 600 .75rem var(--sans);
  padding: 5px 9px; cursor: pointer;
}
.locale-switch button[aria-current="true"] { background: var(--wine); color: var(--on-wine); }

.avatar { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; display: inline-flex; flex: none; }
.avatar-initials {
  align-items: center; justify-content: center;
  background: var(--wine-soft); color: var(--wine); font: 600 .8rem var(--sans);
}
.user-menu { position: relative; }
.user-menu summary { list-style: none; cursor: pointer; display: flex; }
.user-menu summary::-webkit-details-marker { display: none; }
.user-menu-panel {
  position: absolute; right: 0; top: calc(100% + 8px); min-width: 200px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-small);
  box-shadow: var(--shadow); padding: 12px;
}
.user-menu-name { font-weight: 600; margin-bottom: 8px; }
.user-menu-link { display: block; margin-bottom: 8px; color: var(--ink); }
.link-button { border: 0; background: none; padding: 0; color: var(--danger); font: inherit; cursor: pointer; }
/* A button of the menu that reads as one of its links. */
.menu-button { color: var(--ink); text-decoration: underline; text-align: left; }

/* Flash */
.flash {
  margin: 12px auto 0; max-width: 760px; width: calc(100% - 32px);
  padding: 10px 14px; border-radius: var(--radius-small); font-weight: 500;
  transition: opacity .4s ease;
}
.flash.is-leaving { opacity: 0; }
.flash-notice { background: var(--ok-soft); color: var(--ok); }
.flash-alert { background: var(--danger-soft); color: var(--danger); }

/* Layout */
.page { max-width: 760px; margin: 0 auto; padding: 20px 16px 64px; }
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.page-header h1 { margin: 0; }
.crumb { margin-bottom: 10px; font-size: .9rem; }
.crumb a { text-decoration: none; color: var(--muted); }
.crumb a:hover { color: var(--wine); }
/* The way back, with what can be done to the page across from it. */
.crumb-bar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 20px; }
.crumb-bar .crumb { margin: 0; min-width: 0; }

.card {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); padding: 20px;
}
.panel { margin-bottom: 24px; }
.panel-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
.panel-header h2 { margin: 0; }
.narrow { max-width: 460px; margin: 0 auto; }
.count { color: var(--muted); font: 500 .95rem var(--sans); }
.description { color: var(--muted); margin-bottom: 16px; }

/* Buttons */
.button {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 10px 18px; border-radius: 999px; border: 1px solid transparent;
  background: var(--wine); color: var(--on-wine); font: 600 .95rem var(--sans);
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background .15s ease, transform .1s ease;
}
.button:hover { background: var(--wine-strong); }
.button:active { transform: scale(.98); }
.button-small { min-height: 36px; padding: 6px 14px; font-size: .875rem; }
.button-secondary { background: transparent; color: var(--ink); border-color: var(--line); }
.button-secondary:hover { background: var(--surface-2); }
.button-danger { background: transparent; color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.button-danger:hover { background: var(--danger-soft); }
.button-google { background: var(--surface); color: var(--ink); border-color: var(--line); box-shadow: var(--shadow); }
.button-google:hover { background: var(--surface-2); }
.button-block { width: 100%; }
.icon-link { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex: none; color: var(--muted); border-radius: 50%; }
.icon-link:hover { color: var(--ink); background: var(--surface-2); }
.icon-link svg { width: 24px; height: 24px; }
.panel-actions { justify-content: flex-end; margin-top: 12px; }
.event-menu summary { list-style: none; cursor: pointer; }
.event-menu summary::-webkit-details-marker { display: none; }
.event-menu-panel, .event-summary {
  display: flex; flex-direction: column; gap: 14px; margin: -12px 0 24px;
}
.event-menu[open] + .event-summary { display: none; }
.event-summary .description { margin: 0; }
.event-invite { display: flex; flex-direction: column; gap: 10px; }
.event-menu-panel .button + .event-invite { border-top: 1px solid var(--line); padding-top: 14px; }
.invite-qr { align-self: center; width: 200px; max-width: 100%; padding: 8px; background: #fff; border-radius: var(--radius-small); }
.invite-qr svg { display: block; width: 100%; height: auto; }
.button-group { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.button-icon { width: 1.25em; height: 1.25em; flex: none; }
.google-mark { width: 20px; height: 20px; }

/* Forms */
.stack { display: flex; flex-direction: column; gap: 14px; }
.row { display: grid; gap: 14px; grid-template-columns: 1fr; }
@media (min-width: 560px) {
  .row { grid-template-columns: 1fr 1fr; }
  .row-4 { grid-template-columns: repeat(4, 1fr); }
}
label { display: flex; flex-direction: column; gap: 6px; font-weight: 500; font-size: .9rem; }
input[type="text"], input[type="email"], input[type="date"], input[type="number"], input[type="search"], textarea {
  width: 100%; padding: 11px 12px; border-radius: var(--radius-small);
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  font: 16px/1.4 var(--sans);
}
input:focus, textarea:focus, button:focus-visible, a:focus-visible {
  outline: 2px solid var(--wine); outline-offset: 2px;
}
textarea { resize: vertical; }
.checkbox { flex-direction: row; align-items: flex-start; gap: 10px; font-weight: 400; }
.checkbox input { width: 20px; height: 20px; margin-top: 2px; accent-color: var(--wine); flex: none; }
.form-actions { display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.form-error { background: var(--danger-soft); color: var(--danger); padding: 10px 14px; border-radius: var(--radius-small); }
.form-section { margin-top: 8px; font-size: 1.1rem; }
/* A question answered with one of a few choices, one to a line. */
.radio-choices { border: 0; padding: 0; margin: 0; display: grid; gap: 16px; }
.radio-choices legend { font-weight: 700; margin-bottom: 14px; padding: 0; }
.radio-choice { flex-direction: row; align-items: center; gap: 10px; font-weight: 400; cursor: pointer; }
.radio-choice input { width: 20px; height: 20px; margin: 0; accent-color: var(--wine); flex: none; }
.radio-choice-label { flex: 1; }
/* How an event's wines are tasted: each choice is its name and, under it, a
   few words on what it means. */
.pace-choices .radio-choice { align-items: flex-start; }
.pace-choices .radio-choice input { margin-top: 2px; }
.pace-choices .radio-choice-label { display: flex; flex-direction: column; gap: 2px; }
.pace-name { font-weight: 600; }
/* The two ways are a switch, and under it is the panel of the one picked:
   its few words, its picture and the settings that only go with it. */
.pace-switch { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 3px; padding: 3px; border-radius: var(--radius); background: var(--surface-2); }
.pace-switch .chip-radio > span { width: 100%; justify-content: center; min-height: 44px; padding: 8px; border: 0; border-radius: calc(var(--radius) - 3px); color: var(--muted); font-size: .9rem; font-weight: 600; line-height: 1.2; text-align: center; }
.pace-switch .chip-radio input:checked + span { background: var(--wine); color: var(--on-wine); }
.pace-panel { display: none; flex-direction: column; gap: 14px; margin-top: 12px; padding: 14px; border: 1px solid var(--line); border-radius: var(--radius); }
.pace-switcher:has(input[name="pace"][value="together"]:checked) .pace-panel[data-pace="together"],
.pace-switcher:has(input[name="pace"][value="own"]:checked) .pace-panel[data-pace="own"] { display: flex; }
.pace-panel .pace-example { margin-top: 0; }
.sharing-choices.radio-choices { gap: 12px; }
.sharing-choices legend { margin-bottom: 10px; font-size: .9rem; }
.pace-blurb { color: var(--muted); font-size: .875rem; }
/* And a small picture of it: three wines one under the other, as on the
   event's page, with the people tasting each beside its name and,
   when they are tasted together, the organizer's player over them (back,
   stop, forward) with everyone on the wine being tasted. */
.pace-example { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; padding: 8px; border-radius: var(--radius-small); background: var(--surface-2); }
.pace-deck { display: flex; align-items: center; gap: 6px; padding: 5px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); }
.pace-round { flex: none; width: 22px; height: 22px; border: 1px solid var(--line); border-radius: 50%; background: var(--surface); color: var(--ink); display: inline-flex; align-items: center; justify-content: center; }
.pace-round.is-main { background: var(--wine); border-color: var(--wine); color: var(--on-wine); }
.pace-round svg { width: 11px; height: 11px; }
.pace-deck-text { flex: 1; display: flex; align-items: center; justify-content: center; color: var(--wine); }
.pace-bar { display: block; width: 46px; height: 6px; border-radius: 3px; background: color-mix(in srgb, var(--ink) 22%, transparent); }
.pace-wines { display: flex; flex-direction: column; gap: 4px; }
.pace-wine { position: relative; overflow: hidden; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px 6px 12px; border: 1px solid var(--line); border-radius: 7px; background: var(--surface); }
.pace-wine::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 4px; background: var(--stripe); }
.pace-wine .pace-bar { width: 40%; }
.pace-wine.is-now { border-color: var(--wine); }
.pace-wine.is-done { opacity: .55; }
.pace-people { display: flex; gap: 2px; height: 12px; }
.pace-people i { width: 12px; height: 12px; border-radius: 50%; background: var(--wine-faded-ink); }
/* The example pill next to a choice: a set size, so its loop can be drawn ahead. */
.highlight-example { width: 88px; height: 42px; justify-content: center; }
.scanner { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.scanner-view { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; width: 100%; }
.scanner-frame { position: relative; width: 100%; }
.scanner-frame::after {
  content: ""; position: absolute; left: 8%; right: 8%; top: 50%; height: 2px; transform: translateY(-50%);
  background: #ff3b30; border-radius: 2px; box-shadow: 0 0 8px rgba(255, 59, 48, .8); pointer-events: none;
}
.scanner-view video { display: block; width: 100%; aspect-ratio: 4 / 3; max-height: 50vh; object-fit: cover; border-radius: var(--radius); background: #000; }
.scanner-view p { margin: 0; }
.scanner-status { margin: 0; color: var(--muted); }
.scanner-status:empty { display: none; }
.scanner-status.is-error { color: var(--danger); }
.scanner-status.is-busy { display: flex; align-items: center; gap: 8px; }
.scanner-status.is-busy::before {
  content: ""; flex: none; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent;
  border-radius: 50%; animation: scanner-spin .7s linear infinite;
}
@keyframes scanner-spin { to { rotate: 360deg; } }
@media (prefers-reduced-motion: reduce) { .scanner-status.is-busy::before { animation-duration: 2s; } }
.scan-result h2 { margin: 0 0 2px; font-size: 1.25rem; }
.scan-result .wine-details { margin: 0; background: var(--surface-2); }
.danger-zone { border-top: 1px solid var(--line); margin-top: 24px; padding-top: 16px; }
.dev-login { border-top: 1px dashed var(--line); margin-top: 24px; padding-top: 16px; display: flex; flex-direction: column; gap: 12px; }
.dev-login h2 { font-size: 1rem; margin: 0; }

.color-picker { border: 0; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.color-picker legend { font-weight: 500; font-size: .9rem; margin-bottom: 6px; }
.chip-radio { flex-direction: row; }
.chip-radio input { position: absolute; opacity: 0; pointer-events: none; }
.chip-radio > span {
  display: inline-flex; align-items: center; gap: 8px; padding: 9px 14px; min-height: 42px;
  border: 1px solid var(--line); border-radius: 999px; cursor: pointer; font-weight: 500;
}
.chip-radio input:checked + span { background: var(--wine); border-color: var(--wine); color: var(--on-wine); }
.chip-radio input:focus-visible + span { outline: 2px solid var(--wine); outline-offset: 2px; }
/* The kind of wine, picked by the glass it is served in (wines/_glass.html):
   the three colours still, and under them the three sparkling. */
.glass-picker { border: 0; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.glass-picker legend { font-weight: 500; font-size: .9rem; margin-bottom: 6px; }
.glass-choice > span, .tile-choice > span { flex-direction: column; justify-content: flex-end; gap: 6px; width: 100%; padding: 10px 4px 8px; border-radius: var(--radius-small); font-size: .85rem; text-align: center; }
.glass-choice input:checked + span, .tile-choice input:checked + span { background: var(--wine-soft); border-color: var(--wine); color: var(--ink); box-shadow: inset 0 0 0 1px var(--wine); }
/* Room for a name on two lines ("Sparkling white"), so that every glass of a
   row stands at the same height whatever is written under it. */
.glass-choice-name { min-height: 2.4em; display: flex; align-items: center; line-height: 1.2; }
.glass-icon { display: block; height: 72px; width: auto; overflow: visible; }
.glass-icon-body { fill: color-mix(in srgb, var(--glass) 65%, transparent); }
.glass-icon-line { fill: none; stroke: var(--ink); stroke-width: 1.6; stroke-linejoin: round; }
.glass-icon-rim { stroke: color-mix(in srgb, var(--ink) 45%, transparent); stroke-width: 1.1; stroke-linecap: round; }
.glass-icon-wine { fill: var(--pour); }
.glass-icon-bubble { fill: #fff; opacity: .85; }
.glass-icon.is-red { --pour: var(--red-wine); }
.glass-icon.is-white { --pour: var(--white-wine); }
.glass-icon.is-rose { --pour: var(--rose-wine); }
/* A flute holds the wine of its tile: pale gold for a sparkling white. */
.glass-icon.is-sparkling { --pour: #f1dc9a; }
.glass-choice[data-pour="red"] .glass-icon.is-sparkling { --pour: var(--red-wine); }
.glass-choice[data-pour="rose"] .glass-icon.is-sparkling { --pour: var(--rose-wine); }

.copy-field { display: flex; gap: 8px; }
.copy-field input { flex: 1; min-width: 0; font-size: .9rem; color: var(--muted); }

/* Home */
.hero { text-align: center; padding: 32px 0 24px; }
.hero h1 { font-size: clamp(2rem, 7vw, 3rem); }
.eyebrow { color: var(--gold); font-weight: 600; letter-spacing: .04em; text-transform: uppercase; font-size: .8rem; }
.lead { color: var(--muted); font-size: 1.1rem; max-width: 560px; margin: 0 auto 24px; }
.hero .button-google { margin-bottom: 10px; }
.home-cta-note { margin: 0; color: var(--muted); font-size: .85rem; }
/* The steps of an evening: each said, with the piece of the app it is about
   drawn beside it (under it on a phone), on alternate sides. */
.home-steps { margin-top: 56px; }
.home-steps h2 { font-size: 1.75rem; margin-bottom: 32px; text-align: center; }
.home-steps ol:not(.wine-cards) { list-style: none; padding: 0; margin: 0; display: grid; gap: 36px; }
.home-step { display: grid; gap: 16px; align-items: center; }
.home-step-text { display: flex; gap: 14px; align-items: flex-start; }
.home-step h3 { font-size: 1.35rem; margin-bottom: 4px; }
.home-step-text p { margin: 0; color: var(--muted); }
.step-number {
  display: inline-flex; flex: none; width: 36px; height: 36px; border-radius: 50%; font-size: 1.1rem;
  align-items: center; justify-content: center; background: var(--wine-soft); color: var(--wine); font-weight: 700;
}
@media (min-width: 640px) {
  .home-step { grid-template-columns: 1fr 1fr; gap: 28px; }
  .home-step:nth-child(even) .home-visual { order: -1; }
}
/* A picture of the app, not the app: nothing in it answers a tap. */
.home-visual { padding: 14px; border-radius: 22px; background: var(--surface-2); border: 1px solid var(--line); pointer-events: none; }
.home-visual .wine-card { height: auto; }
/* A sheet's card keeps its edges here, on a phone too. */
.home-visual .sheet-section { margin-left: 0; margin-right: 0; border: 1px solid var(--line); border-radius: var(--radius); box-shadow: none; }
.home-invite { display: flex; align-items: center; gap: 16px; padding: 14px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.home-invite strong { display: block; font: 600 1.2rem var(--serif); margin-bottom: 6px; }
.home-qr { flex: none; width: 84px; height: 84px; padding: 4px; border-radius: 6px; background: #fff; fill: #2a1d1f; }
.home-people { display: flex; gap: 6px; }
.home-people .avatar { position: relative; overflow: hidden; width: 30px; height: 30px; font-size: .7rem; }
.home-people img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.home-joined { margin: 10px 4px 0; color: var(--ok); font-size: .875rem; font-weight: 600; }
.home-scan { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 12px; color: var(--muted); }
.home-barcode { width: 96px; height: 44px; padding: 6px 8px; border-radius: 6px; background: #fff; fill: #2a1d1f; }
.home-arrow { width: 22px; height: 22px; }
.home-close { margin-top: 64px; padding: 28px 20px; border-radius: var(--radius); background: var(--wine-soft); text-align: center; }
.home-close h2 { font-size: 1.5rem; margin-bottom: 16px; }

/* Events */
.event-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
.event-card {
  display: flex; flex-direction: column; gap: 4px; padding: 16px 18px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  text-decoration: none; color: var(--ink); box-shadow: var(--shadow);
}
.event-card:hover { border-color: var(--wine); }
/* An event with something to do to it beside it, on the right. */
.event-row { display: flex; align-items: center; gap: 10px; }
.event-row .event-card { flex: 1; min-width: 0; }
.event-card-name { font: 600 1.15rem var(--serif); }
.event-card-meta, .event-meta { display: flex; flex-wrap: wrap; gap: 4px 12px; color: var(--muted); font-size: .9rem; align-items: center; margin: 0; }
.badges { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 4px; }
.badge { font-size: .75rem; font-weight: 600; padding: 2px 9px; border-radius: 999px; background: var(--surface-2); color: var(--muted); }
.badge-blind { background: var(--wine-soft); color: var(--wine); }
.badge-revealed { background: var(--ok-soft); color: var(--ok); }
.empty { text-align: center; padding: 40px 0; color: var(--muted); }

.wine-cards { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
.wine-card {
  display: flex; align-items: center; gap: 10px; height: 100%;
  padding: 12px 12px 12px 18px; position: relative; overflow: hidden;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  text-decoration: none; color: var(--ink);
}
/* The organizer's cards are also what the wines are reordered by (app.js):
   the cursor says so, and a card lifts a little once it is picked up. */
.wine-cards[data-sortable] { position: relative; }
.wine-cards[data-sortable] .wine-card { cursor: grab; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; transition: transform .12s, box-shadow .12s; }
.wine-cards li.is-dragging { z-index: 2; }
.wine-cards li.is-dragging .wine-card { cursor: grabbing; transform: scale(1.02); box-shadow: var(--shadow); border-color: var(--wine); }
.wine-card::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 6px; background: var(--stripe); }
.is-red { --stripe: var(--red-wine); }
.is-white { --stripe: var(--white-wine); }
.is-rose { --stripe: var(--rose-wine); }
.wine-card-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wine-card-meta { font-size: .75rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.wine-card .badge { flex: none; }
/* What is said of a blind wine at the end of that line: "Blind", "Revealed". */
.wine-card-tag { color: var(--wine); font-weight: 700; }
.wine-vintage { flex: none; font: 600 .9rem var(--sans); color: var(--muted); font-variant-numeric: tabular-nums; }
.wine-chevron { width: 18px; height: 18px; flex: none; color: var(--line); }
.wine-card:hover .wine-row-title, .wine-card:hover .wine-chevron { color: var(--wine); }
.wine-row-title { font-weight: 600; }
.wine-row-subtitle { color: var(--muted); font-size: .85rem; }

.wine-dot { width: 14px; height: 14px; border-radius: 50%; flex: none; display: inline-block; border: 1px solid rgb(0 0 0 / 12%); }
.wine-red { background: var(--red-wine); }
.wine-white { background: var(--white-wine); }
.wine-rose { background: var(--rose-wine); }
.wine-sparkling { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3px var(--gold); }

/* The attendees: pictures side by side; tap for one per row with names. */
.attendees { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 6px; cursor: pointer; border-radius: var(--radius-small); }
.attendees:focus-visible { outline: 2px solid var(--wine); outline-offset: 4px; }
.attendees li { display: flex; align-items: center; gap: 10px; }
.attendees .is-extra, .attendee-name { display: none; }
.attendees.is-expanded { flex-direction: column; flex-wrap: nowrap; gap: 8px; }
.attendees.is-expanded .is-extra { display: flex; }
.attendees.is-expanded .attendees-more { display: none; }
.attendees.is-expanded .attendee-name { display: block; font-weight: 500; animation: attendee-name-in .3s ease-out both; }
@keyframes attendee-name-in { from { opacity: 0; transform: translateX(-8px); } }
.avatar-more {
  align-items: center; justify-content: center;
  background: var(--surface-2); color: var(--muted); border: 1px solid var(--line); font: 600 .75rem var(--sans);
}

/* Wine page */
.wine-header { display: flex; align-items: flex-start; gap: 14px; margin-bottom: 12px; }
.wine-header-text { flex: 1; min-width: 0; }
.wine-header h1 { margin-bottom: 2px; }
.wine-header p { margin: 0; }
/* A wine's page is in that wine's colour: headings, links, buttons, the "+"
   and the rest of what the app colours in its own wine red take it instead,
   by standing in for the app's wine colours inside the page. The accent has to
   work as type on the page as well as a fill under type, so on a light page a
   white wine's is a dark gold and a rosé's a deep rose; on a dark page they
   are the pale colours themselves, with dark type on them. The shades that go
   with the accent are mixed from it. */
.wine-page {
  --wine-strong: color-mix(in srgb, var(--wine) 82%, var(--ink));
  --wine-soft: color-mix(in srgb, var(--wine) 13%, var(--surface));
  --wine-faded: color-mix(in srgb, var(--wine) 24%, var(--surface));
  --wine-faded-ink: color-mix(in srgb, var(--wine) 72%, var(--ink));
}
.wine-page[data-pour="red"] { --wine: #7d1631; --on-wine: #fff8f2; }
.wine-page[data-pour="white"] { --wine: #7c6212; --on-wine: #fffaf0; }
.wine-page[data-pour="rose"] { --wine: #b03456; --on-wine: #fff8f2; }
@media (prefers-color-scheme: dark) {
  .wine-page[data-pour="red"] { --wine: #cf4767; --on-wine: #fff8f2; }
  .wine-page[data-pour="white"] { --wine: #e8d58a; --on-wine: #3a2c10; }
  .wine-page[data-pour="rose"] { --wine: #f0a1a8; --on-wine: #4a1420; }
}

/* A wine's page opens with where it is from, its name set large, and what
   kind it is as a row of tags. */
.wine-header h1 { font-size: clamp(1.9rem, 6.5vw, 3.2rem); line-height: 1.05; letter-spacing: -.02em; margin: 0; }
.wine-eyebrow { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 0 0 10px; color: var(--wine); font-size: .8rem; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.wine-eyebrow span + span::before { content: ""; display: inline-block; width: 4px; height: 4px; margin-right: 10px; border-radius: 50%; background: currentColor; opacity: .5; vertical-align: middle; }
.wine-tags { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 16px 0 0; padding: 0; }
.wine-header { margin-bottom: 20px; }
.wine-tag { display: inline-flex; align-items: center; gap: 8px; min-height: 32px; padding: 4px 14px; border-radius: 999px; background: var(--surface-2); font-size: .92rem; font-weight: 500; }
/* What SAQ says is special about a wine (organic, orange wine…), as a wax
   seal: a blob of sealing wax in the feature's colour (--tag), never quite
   round, with its picture pressed into it. --seal is its size, so the same
   seal is worn large on the wine's page and small on its card. */
[data-feature="organic"] { --tag: #3d8b4a; }
[data-feature="biodynamic"] { --tag: #5a5fc0; }
[data-feature="natural"] { --tag: #7d8a2e; }
[data-feature="orange"] { --tag: #d9772b; }
[data-feature="kosher"], [data-feature="kosher_mevushal"] { --tag: #2f72b8; }
[data-feature="fair_trade"] { --tag: #1f8f8a; }
.seal-wax { --seal: 62px; position: relative; display: block; flex: none; width: var(--seal); height: var(--seal); border-radius: 58% 42% 47% 53% / 46% 55% 45% 54%; background: radial-gradient(circle at 34% 28%, color-mix(in srgb, var(--tag) 68%, #fff), var(--tag) 46%, color-mix(in srgb, var(--tag) 60%, #000)); box-shadow: inset 0 calc(var(--seal) * -.05) calc(var(--seal) * .08) rgb(0 0 0 / 28%), inset 0 calc(var(--seal) * .03) calc(var(--seal) * .05) rgb(255 255 255 / 30%); filter: drop-shadow(0 calc(var(--seal) * .03) calc(var(--seal) * .05) rgb(0 0 0 / 28%)); }
:nth-child(even) > .seal-wax, li:nth-child(even) .seal-wax { border-radius: 45% 55% 52% 48% / 55% 44% 56% 45%; }
.seal-wax i { position: absolute; inset: 17.7%; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: color-mix(in srgb, var(--tag) 80%, #000); box-shadow: inset 0 calc(var(--seal) * .03) calc(var(--seal) * .065) rgb(0 0 0 / 50%), 0 1px 0 rgb(255 255 255 / 28%); color: color-mix(in srgb, var(--tag) 40%, #fff); }
.seal-wax svg { width: 55%; height: 55%; filter: drop-shadow(0 1px 0 rgb(0 0 0 / 45%)); }
/* On the wine's page they have a row of their own, centred under the
   pills, a little askew. More than fit take a second row. */
.wine-seals { position: relative; list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 10px 14px; margin: 0 0 20px; padding: 0; }
.seal { display: block; padding: 0; border: 0; border-radius: 50%; background: none; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: transform .18s ease; }
.wine-seals li:nth-child(odd) .seal { --tilt: rotate(-6deg); }
.wine-seals li:nth-child(even) .seal { --tilt: rotate(5deg) translateY(3px); }
.wine-seals .seal { transform: var(--tilt); }
.seal:focus-visible { outline: 2px solid var(--tag); outline-offset: 3px; }
/* Tapped, a seal comes forward and straightens, and what it means is said
   in a note centred under the row, over what follows, in the seal's colour,
   with an arrow up to the seal (app.js says where: --arrow, from the note's
   right, and puts the note over the row when it wouldn't be in sight under
   it). */
.wine-seals .seal[aria-expanded="true"] { transform: scale(1.16); }
.seal-about { position: absolute; z-index: 3; top: calc(100% + 12px); left: 0; right: 0; width: max-content; max-width: min(340px, 100%); margin-inline: auto; padding: 10px 14px 12px; border: 1px solid var(--line); border-top: 3px solid var(--tag); border-radius: var(--radius-small); background: var(--surface); box-shadow: var(--shadow); color: var(--ink); font-size: .9rem; line-height: 1.4; text-align: left; animation: seal-about-in .16s ease-out; }
.seal-about::before { content: ""; position: absolute; bottom: 100%; right: calc(var(--arrow, 45px) - 8px); margin-bottom: 3px; border: 8px solid transparent; border-top: 0; border-bottom-color: var(--tag); }
.seal-about strong { display: block; margin-bottom: 2px; font: 600 1.05rem var(--serif); color: color-mix(in srgb, var(--tag) 72%, var(--ink)); }
@keyframes seal-about-in { from { opacity: 0; transform: translateY(-4px); } }
/* Over the row, when there isn't room in sight under it: its coloured edge
   and its arrow are then at its foot. */
.seal-about.is-above { top: auto; bottom: calc(100% + 12px); border-top: 1px solid var(--line); border-bottom: 3px solid var(--tag); animation-name: seal-about-in-above; }
.seal-about.is-above::before { top: 100%; bottom: auto; margin: 3px 0 0; border: 8px solid transparent; border-bottom: 0; border-top-color: var(--tag); }
@keyframes seal-about-in-above { from { opacity: 0; transform: translateY(4px); } }
@media (prefers-reduced-motion: reduce) { .seal { transition: none; } .seal-about { animation: none; } }
/* On a wine's card in the event's list: small, lapping over one another,
   floating at the card's top right, over its edge and above its title. */
.wine-cards li { position: relative; }
.wine-card-seals { position: absolute; z-index: 1; top: -9px; right: 14px; display: flex; pointer-events: none; }
.wine-card-seals .seal-wax { --seal: 26px; }
.wine-card-seals .seal-wax + .seal-wax { margin-left: -6px; }
/* On the card a scan fills in: each with its name beside it. */
.scan-seals { list-style: none; display: flex; flex-wrap: wrap; gap: 8px 16px; margin: 0 0 16px; padding: 0; }
.scan-seals li { display: flex; align-items: center; gap: 8px; font-size: .92rem; font-weight: 500; }
.scan-seals .seal-wax { --seal: 34px; }
/* Its figures, side by side in one box, ruled apart. */
.wine-stats { display: flex; flex-wrap: wrap; gap: 1px; margin: 0 0 20px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
/* A card: its name in the top corner, its figure in the very middle, and
   what goes with the figure (the sugar's scale) along the bottom. The name
   and the scale are laid over the card, so the figure is centred in the whole
   of it; the cards of a row are one height, so their figures line up. */
/* The cards of a row share its width, whatever their number: as many to a
   row as fit, and the last row's stretch to fill it, so the box is never
   left with an empty corner. */
.stat { flex: 1 1 140px; position: relative; display: flex; align-items: center; justify-content: center; min-height: 118px; padding: 0 20px; background: var(--surface); }
.wine-stats:has([data-sugar]:not([hidden])) .stat { min-height: 148px; }
.stat > .stat-label, .stat > .stat-head { position: absolute; top: 12px; left: 20px; right: 20px; }
}
.stat-label { font-size: .875rem; color: var(--muted); }
.stat-value { font: 600 2.1rem/1 var(--serif); text-align: center; }
.stat-unit { font-size: 1.15rem; font-weight: 500; color: var(--muted); }
/* A figure that leads somewhere: the price, to the wine at the SAQ. */
.stat-link { color: inherit; text-decoration: none; }
.stat-link:hover { background: var(--wine-soft); }
.stat-link .stat-level { display: inline-flex; align-items: center; gap: 3px; }
.stat-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.stat-level { font-size: .875rem; font-weight: 600; color: var(--wine); }
/* With nothing in it yet to show, the box isn't there. */
.wine-stats:not(:has(.stat:not([hidden]))) { display: none; }
/* Where the sugar falls among the four choices of the sheet's sweetness
   line: the segments up to it are filled, and a ring marks the spot. */
.gauge { display: flex; flex-direction: column; gap: 6px; }
/* In its card it sits along the bottom edge. */
.stat .gauge { position: absolute; left: 20px; right: 20px; bottom: 8px; }
.gauge-track { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 3px; height: 6px; }
.gauge-track i { background: var(--surface-2); }
.gauge-track i:first-child { border-radius: 3px 0 0 3px; }
.gauge-track i:nth-child(4) { border-radius: 0 3px 3px 0; }
.gauge[data-segment="0"] i:nth-child(-n+1), .gauge[data-segment="1"] i:nth-child(-n+2), .gauge[data-segment="2"] i:nth-child(-n+3), .gauge[data-segment="3"] i { background: var(--wine); }
.gauge-track b { position: absolute; left: var(--at, 0%); top: -4px; width: 14px; height: 14px; margin-left: -7px; border-radius: 50%; background: var(--surface); border: 3px solid var(--wine); }
.gauge-ends { display: flex; justify-content: space-between; font-size: .75rem; color: var(--muted); }
/* The rest (producer, appellation, grapes), as pills under the figures. They
   grow to share the row, so they always fill its width, and wrap into rows
   of their own on a phone. Each leads with a small picture on a disc of the
   wine's colour: dark on the pale ones, so that the picture still shows. */
.wine-facts { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 24px; padding: 0; --disc: var(--red-wine); --on-disc: #fff8f2; }
.wine-facts.is-white { --disc: var(--white-wine); --on-disc: #3a2c10; }
.wine-facts.is-rose { --disc: var(--rose-wine); --on-disc: #4a1420; }
.wine-fact { flex: 1 1 auto; display: flex; align-items: center; gap: 10px; min-width: 0; padding: 6px 16px 6px 6px; border-radius: 999px; background: var(--surface-2); font-size: .92rem; font-weight: 500; }
.wine-fact svg { width: 32px; height: 32px; padding: 7px; border-radius: 50%; background: var(--disc); color: var(--on-disc); flex: none; }
.wine-fact-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.wine-fact-name { font-size: .62rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.wine-glass { width: 40px; height: 40px; border-radius: 50% 50% 45% 45%; flex: none; margin-top: 4px; border: 1px solid rgb(0 0 0 / 12%); }
.wine-details { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px 16px; margin: 0 0 16px; padding: 14px 16px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.wine-details dt { font-size: .75rem; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.wine-details dd { margin: 0; font-weight: 500; }

.reveal-bar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin: 0 0 16px; padding: 10px 14px; border-radius: var(--radius-small); background: var(--wine-soft);
}
.reveal-bar span { flex: 1; min-width: 180px; }
.blind-notice { margin: 0 0 16px; padding: 10px 14px; border-radius: var(--radius-small); background: var(--surface-2); color: var(--muted); }
.wine-row-title .badge { vertical-align: 2px; margin-left: 4px; }

/* The tasting sheet */
/* Each of its parts (eye, nose, mouth…) is a card of its own, with the page
   showing between them. */
.sheet { display: flex; flex-direction: column; gap: 16px; }
/* The wine's colour runs along the top of its figures, as it runs down the
   side of its row in the event, or of its sheet's first card when it has no
   figures. */
:is(.wine-stats:is(.is-red, .is-white, .is-rose), .sheet:is(.is-red, .is-white, .is-rose) > .sheet-section:first-of-type) { position: relative; overflow: hidden; padding-top: 12px; }
:is(.wine-stats:is(.is-red, .is-white, .is-rose), .sheet:is(.is-red, .is-white, .is-rose) > .sheet-section:first-of-type)::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 12px; background: var(--stripe); }
/* Says "Saved" (or that saving failed) from the corner, wherever you've scrolled to. */
.save-status {
  position: fixed; right: 12px; bottom: max(12px, env(safe-area-inset-bottom)); z-index: 5; margin: 0;
  padding: 4px 12px; border-radius: 999px; background: var(--surface-2); color: var(--muted); box-shadow: var(--shadow);
}
.save-status:empty { display: none; }
.save-status.is-error { color: var(--danger); }

.sheet-section { padding: 6px 16px 12px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }
/* On a phone, the sheet's cards and the wine's figures run edge to edge: the room at
   their sides is better spent on what is inside them. */
@media (max-width: 560px) {
  .sheet-section, .wine-stats { margin-left: -16px; margin-right: -16px; border-left: 0; border-right: 0; border-radius: 0; }
}
.sheet-section h3 { display: flex; align-items: center; gap: 8px; color: var(--wine); margin: 14px 0 4px; }
.sheet-section h3 svg { flex: none; width: 1.25em; height: 1.25em; }

.line { padding: 10px 0; }
.line + .line { border-top: 1px dashed var(--line); }
/* A line that is the second step of the one before it (which grapes, after
   one grape or a blend) is part of it: nothing is drawn between them, it is
   set in under it, and its question is said lower than a line's own. */
.line[data-follows] { margin: 0 0 10px 4px; padding: 2px 0 2px 12px; border-top: 0; border-left: 2px solid var(--line); }
.line[data-follows] .line-head { margin-bottom: 6px; }
.line[data-follows] .line-label { font-weight: 500; font-size: .88rem; color: var(--muted); }
.line-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 8px; }
.line-label { font-weight: 600; }
/* What a line is answered against, beside its name: the wine's price, on the
   line that weighs it against the pleasure. */
.line-aside { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* The rows sit a little apart: each option's dots go in the gap under it. */
.chips { display: flex; flex-wrap: wrap; gap: 14px 8px; }
.chip {
  position: relative; display: inline-flex; align-items: center; gap: 6px;
  min-height: 42px; padding: 8px 14px; border-radius: 999px;
  border: 1px solid var(--line); background: var(--bg); color: var(--ink);
  font: 500 .92rem var(--sans); cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.chip:hover { border-color: var(--wine); }
/* How a line shows its votes is each person's choice (profile settings).
   Counts: a number on each option, toned down so your own choice stays the loudest. */
.shows-counts .chip.has-total:not(.is-selected) { background: var(--wine-faded); border-color: var(--wine-faded); color: var(--wine-faded-ink); }
.chip.is-selected { background: var(--wine); border-color: var(--wine); color: var(--on-wine); }
.total-count {
  min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: .72rem; font-weight: 700; background: var(--surface); color: var(--wine-faded-ink);
}
.chip.is-selected .total-count { background: rgb(255 255 255 / 22%); color: var(--on-wine); }
/* On a wine's sheet, your picks take the colour of the wine being tasted, as
   the pictures in its details do: dark type on the pale ones. Aromas keep
   their own colours. */
.sheet[data-wine-color="red"] { --pick: var(--red-wine); --on-pick: #fff8f2; }
.sheet[data-wine-color="white"] { --pick: var(--white-wine); --on-pick: #3a2c10; }
.sheet[data-wine-color="rose"] { --pick: var(--rose-wine); --on-pick: #4a1420; }
.sheet[data-wine-color] .chip.is-selected:not(.is-aroma) { background: var(--pick); border-color: var(--pick); color: var(--on-pick); }
.sheet[data-wine-color] .chip.is-selected:not(.is-aroma) .total-count { background: color-mix(in srgb, var(--on-pick) 18%, transparent); color: var(--on-pick); }
.sheet:not(.shows-counts) .total-count, .dots-below .total-count, .dots-inside .total-count { display: none; }
/* Or dots, one per other person who chose the option: under it, or inside it
   under its name. Only whole dots are drawn, as many as fit. With the number,
   there are none. */
.vote-dots {
  position: absolute; left: 50%; top: calc(100% + 4px); translate: -50% 0; pointer-events: none;
  width: calc(var(--votes, 0) * 9px); max-width: 100%; height: 5px;
  background: radial-gradient(circle, var(--ink) 2px, transparent 2.5px) 0 0 / 9px 5px space no-repeat;
}
/* Your own pick is told by the option itself, filled or circled: it gets no
   dot, so the dots under it are the others who chose as you did. */
.chip.is-selected .vote-dots { width: calc(max(var(--votes, 0) - 1, 0) * 9px); }
.shows-counts .vote-dots { display: none; }
/* Inside, they sit along the bottom edge of the option, under its name,
   which stays in the middle as it is with the other ways of counting. They
   take the name's colour, so that they show on a filled option as well as
   on a plain one. */
.dots-inside .vote-dots {
  top: auto; bottom: 3px; max-width: calc(100% - 14px);
  background-image: radial-gradient(circle, currentColor 2px, transparent 2.5px);
}
.dots-inside .chip.is-aroma .vote-dots { bottom: 2px; }
/* A question answered by picking a picture, the choices side by side as the
   kinds of wine are on the wine form. */
.tile-choices { border: 0; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.tile-choices legend { font-weight: 700; margin-bottom: 14px; padding: 0; }
/* Room at the top for the tick, clear of the picture. */
.tile-choice > span { position: relative; justify-content: flex-end; gap: 14px; padding: 24px 4px 10px; }
.tile-choice-name { font-size: .8rem; line-height: 1.2; }
/* A hand-drawn loop reaches past its pill: a little smaller, it keeps inside its tile. */
.tile-choice .highlight-example { scale: .86; }
/* The one picked is ticked in its corner. */
.tile-check { position: absolute; top: 6px; right: 6px; width: 18px; height: 18px; display: none; }
.tile-check circle { fill: var(--wine); }
.tile-check path { fill: none; stroke: var(--on-wine); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.tile-choice input:checked + span .tile-check { display: block; }
/* The example of each way of counting, on the settings page. */
.vote-example { flex: none; }
/* The dots under the example need the room the caption would take. */
.vote-example.dots-below { margin-bottom: 8px; }
.vote-example:not(.dots-below) { margin-bottom: 0; translate: 0 -4px; }
.vote-example .chip { cursor: inherit; }
/* By hand: a loop drawn round your own pick as well as its colour (by
   sheet.js, in the pill's own pixels), in pencil or in pen. The pills sit further apart to leave it room. */
.hand-picks .chips { gap: 18px 14px; }
/* The loop is drawn outside its own box, which is kept to a point: left to
   itself an SVG is 300 pixels wide, enough to push the page past the screen. */
.pick-loop { position: absolute; left: -1px; top: -1px; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.pick-loop path { fill: none; stroke: var(--ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.hand-pencil .pick-loop path { opacity: .9; filter: url(#soft-pencil); }
.pick-loop.is-drawing path { stroke-dasharray: var(--length); animation: draw-loop .45s ease-out both; }
@keyframes draw-loop { from { stroke-dashoffset: var(--length); } to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) { .pick-loop.is-drawing path { stroke-dasharray: none; animation: none; } }

/* An aroma is a pill in its own colour, the one it has in the picker, not a
   box to tick: filled when it is yours, outlined when only others picked it. */
.chip.is-aroma, .shows-counts .chip.is-aroma.has-total:not(.is-selected) {
  min-height: 36px; padding: 6px 13px; background: transparent; color: var(--ink);
  border: 1px dashed color-mix(in srgb, var(--tint) 70%, var(--surface));
}
.chip.is-aroma.is-selected { background: color-mix(in srgb, var(--tint) 34%, #fff); border: 1px solid transparent; color: #2a1d1f; }
.chip.is-aroma:hover { border-color: var(--tint); }
.chip.is-aroma .total-count { background: rgb(255 255 255 / 65%); color: #2a1d1f; }
/* When someone else picks one of your aromas (aroma-match.js): sparks from
   behind its pill, a band of light across it, and two glasses clinking over
   it. The sparks go behind the pills, so the line is a layer of its own. */
.line[data-kind="aromas"] .chips { position: relative; isolation: isolate; }
.match-spark { position: absolute; z-index: -1; width: 7px; height: 7px; border-radius: 50%; translate: -50% -50%; pointer-events: none; }
.match-spark.is-streak { width: 3px; height: 12px; border-radius: 2px; }
.match-shine { position: absolute; inset: 0; border-radius: inherit; overflow: hidden; pointer-events: none; }
.match-shine::before { content: ""; position: absolute; top: -20%; bottom: -20%; left: 0; width: 45%; translate: -160% 0; rotate: 18deg; background: linear-gradient(90deg, transparent, rgb(255 255 255 / 85%), transparent); animation: match-sweep .8s ease-in-out; }
.chip.is-shining { animation: match-swell .8s ease-out; }
@keyframes match-sweep { to { translate: 320% 0; } }
@keyframes match-swell { 0%, 100% { scale: 1; } 35% { scale: 1.07; } }
.match-toast { position: absolute; left: 50%; bottom: 100%; width: 56px; pointer-events: none; z-index: 2; }
/* The glasses: a clear bowl drawn in the theme's ink, the rim in a lighter
   line, filled with the wine. Each leans in from its foot and slides until
   the bowls meet (--tilt and --slide are worked out from its shape), bounces
   off and settles; the wine turns the other way to stay level, and slops a
   little after the knock. */
.clink { display: block; width: 100%; height: auto; overflow: visible; }
/* The glass itself hides what is behind it; the wine goes over that, and the
   outline over the wine. */
.clink-glass { fill: color-mix(in srgb, var(--glass) 65%, var(--surface)); }
.clink-outline { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linejoin: round; }
.clink-rim { stroke: color-mix(in srgb, var(--ink) 45%, transparent); stroke-width: 2; stroke-linecap: round; }
.clink-wine { fill: var(--pour); }
.clink-bubble { fill: #fff; opacity: .8; animation: clink-rise .9s linear infinite; }
.clink-spark { opacity: 0; animation: clink-spark 1.4s ease-out; }
.clink-spark line { stroke: var(--gold); stroke-width: 1.8; stroke-linecap: round; }
.clink-lean { animation: clink-lean 1.4s ease-in-out; }
.clink-level { animation: clink-level 1.4s ease-in-out; }
@keyframes clink-lean {
  0%, 8%, 74%, 100% { transform: none; }
  20% { transform: translateX(-2px) rotate(-3deg); }
  38% { transform: translateX(var(--slide)) rotate(var(--tilt)); }
  45% { transform: translateX(calc(var(--slide) - 3.5px)) rotate(calc(var(--tilt) - 3deg)); }
  53% { transform: translateX(calc(var(--slide) - 1.5px)) rotate(calc(var(--tilt) - 1deg)); }
}
@keyframes clink-level {
  0%, 8%, 86%, 100% { transform: none; }
  20% { transform: rotate(3deg); }
  38% { transform: rotate(calc(var(--tilt) * -1)); }
  45% { transform: rotate(calc(var(--tilt) * -1 + 7deg)); }
  53% { transform: rotate(calc(var(--tilt) * -1 - 3deg)); }
  66% { transform: rotate(-3deg); }
  76% { transform: rotate(2deg); }
}
@keyframes clink-spark {
  0%, 37% { opacity: 0; transform: scale(.2); }
  39% { opacity: 1; transform: scale(1); }
  50%, 100% { opacity: 0; transform: scale(1.7); }
}
@keyframes clink-rise {
  from { transform: translateY(0); opacity: 0; }
  15% { opacity: .8; }
  to { transform: translateY(var(--climb)); opacity: 0; }
}
/* A question asked before something is taken away. */
.confirm { border: 0; padding: 20px; width: min(340px, calc(100vw - 32px)); border-radius: var(--radius); background: var(--surface); color: var(--ink); box-shadow: 0 20px 60px rgb(0 0 0 / 35%); }
.confirm::backdrop { background: rgb(0 0 0 / 45%); }
.confirm p { margin: 0 0 6px; }
.confirm-title { font: 600 1.15rem var(--serif); }
.confirm .form-actions { margin-top: 16px; }
/* An aromas line: what has been picked, then the "+" that opens the picker. */
.add-aroma {
  width: 42px; height: 42px; border-radius: 50%; flex: none; cursor: pointer;
  border: 1px dashed var(--wine); background: var(--wine-soft); color: var(--wine);
  font: 400 1.5rem/1 var(--sans); display: inline-flex; align-items: center; justify-content: center;
}
.add-aroma:hover { border-style: solid; }

/* The aroma picker (aroma-picker.js): centred on a wide screen; on a phone,
   the whole screen, however it is turned or resized, with the bubbles taking
   all the room the search box and the explanation leave them. */
.picker { border: 0; padding: 0; width: min(430px, calc(100vw - 24px)); max-height: 92dvh; border-radius: var(--radius); background: var(--surface); color: var(--ink); box-shadow: 0 20px 60px rgb(0 0 0 / 35%); overflow: hidden; }
.picker[open] { display: flex; flex-direction: column; }
.picker::backdrop { background: rgb(0 0 0 / 45%); }
/* A phone held either way: narrow when upright, short when on its side. */
@media (max-width: 560px), (max-height: 560px) {
  .picker { width: 100%; max-width: 100%; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
  .picker-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  /* Never so short that the bubbles can't be told apart: the picker scrolls first. */
  .picker .depth { flex: 1 0 280px; max-width: none; aspect-ratio: auto; }
}
/* On its side there is width to spare and little height: the bubbles take the
   whole height, and what is said of them goes beside them. */
@media (max-height: 560px) and (orientation: landscape) {
  .picker-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(200px, 34%); grid-template-rows: auto minmax(0, 1fr); gap: 0 14px; overflow: hidden; }
  .picker .depth { grid-row: 1 / 3; height: 100%; }
  .picker-about { margin-top: 0; }
  .picker-about, .picker-hint { grid-column: 2; overflow-y: auto; }
  .picker-body .picker-hint { align-self: start; margin-top: 0; text-align: left; }
}
.picker-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--line); }
.picker-head button { width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--line); background: var(--bg); color: var(--ink); font: 500 1.1rem/1 var(--sans); cursor: pointer; flex: none; }
.picker-body { overflow-y: auto; padding: 12px; }
.picker-hint { text-align: center; color: var(--muted); font-size: .8rem; margin: 8px 0 0; }
/* Bubbles: flat discs, all one size, in a space that can be dragged about.
   What is in focus is sharp and in front; the rest is dim and blurred behind. */
.depth { position: relative; width: 100%; max-width: 400px; margin: 0 auto; aspect-ratio: 360 / 440; overflow: hidden; border-radius: var(--radius-small); background: radial-gradient(ellipse at 50% 38%, var(--surface) 0%, var(--surface-2) 100%); touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none; }
.depth.is-dragging { cursor: grabbing; }
.depth-world { position: absolute; left: 0; top: 0; width: 0; height: 0; transform-origin: 0 0; will-change: transform; }
.depth-lines { position: absolute; left: 0; top: 0; width: 1px; height: 1px; overflow: visible; pointer-events: none; }
.depth-lines line { stroke-width: 1.6; stroke-linecap: round; opacity: .55; transition: opacity .34s ease; }
.depth-lines line.is-blur { opacity: .16; }
.orb {
  position: absolute; left: 0; top: 0; border: 0; border-radius: 50%; padding: 5px; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; text-align: center;
  color: #2a1d1f; font: 600 12px/1.12 var(--sans); -webkit-tap-highlight-color: transparent;
  background: color-mix(in srgb, var(--tint) 34%, #fff);
  transition: filter .34s ease, opacity .34s ease;
}
.orb:not(.is-blur) { z-index: 1; }
.orb.is-blur { filter: blur(2.6px) saturate(.65); opacity: .5; }
.orb.is-leaving { opacity: 0; pointer-events: none; }
.orb.is-open { box-shadow: 0 0 0 2px color-mix(in srgb, var(--tint) 60%, #fff); }
.orb.is-current { outline: 2.5px solid var(--tint); outline-offset: 3px; }
.orb-hint { font-size: .72em; font-weight: 500; opacity: .75; }
/* An aroma that is already yours on this line: hollow, an outline in its
   colour, among the ones still to pick. It is filled with the colour of what
   the bubbles sit on, and a little of its own, not left clear: the line that
   joins a bubble to its cluster runs to its middle, and would show through. */
.orb.is-mine, .found-orb.is-mine {
  background: color-mix(in srgb, var(--tint) 16%, var(--surface-2)); color: var(--ink);
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--tint) 60%, var(--surface));
}
/* The search box at the top of the picker, beside the way out: rounded, with
   a magnifying glass. */
input.search-input {
  flex: 1; min-width: 0; margin: 0; border-radius: 999px; padding-left: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23857a7c' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='8.5' cy='8.5' r='5.5'/%3E%3Cpath d='M13 13l4.5 4.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 14px center; background-size: 16px;
}
/* A bubble that was added, on its way from where the picker showed it to the
   line, where it turns into its pill (aroma-picker.js moves and reshapes it). */
.picked-bubble { position: fixed; z-index: 1000; box-sizing: border-box; padding: 0 6px; overflow: hidden; pointer-events: none; display: flex; align-items: center; justify-content: center; text-align: center; color: #2a1d1f; font: 600 12px/1.12 var(--sans); }
/* What the box finds: laid out flat over the bubbles, each one in its colour
   with its cluster's name, scrolling when there are many. */
.found { position: absolute; inset: 0; z-index: 5; overflow-y: auto; overscroll-behavior: contain; touch-action: pan-y; cursor: default; display: flex; flex-wrap: wrap; align-content: center; justify-content: center; gap: 9px; padding: 14px; background: radial-gradient(ellipse at 50% 38%, var(--surface) 0%, var(--surface-2) 100%); }
.found-orb { flex: none; width: 78px; height: 78px; border: 0; border-radius: 50%; padding: 5px; cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px; text-align: center; color: #2a1d1f; font: 600 12px/1.12 var(--sans); background: color-mix(in srgb, var(--tint) 34%, #fff); -webkit-tap-highlight-color: transparent; }
.found-orb small { font-size: .72em; font-weight: 500; opacity: .75; }
.found p { color: var(--muted); font-size: .85rem; }
/* Under the bubbles: what the one you are on is, and why it is where it is.
   It keeps its room, so that the picker doesn't grow and shrink at each tap. */
.picker-about { min-height: 5.6em; margin: 10px 2px 0; font-size: .82rem; line-height: 1.4; }
.picker-about:empty { display: none; }
.picker-about strong { display: block; font-size: .9rem; }
.picker-about strong small { font-size: 1em; font-weight: 400; color: var(--muted); }
.picker-about p { margin: 0; color: var(--muted); }
/* Or it is said over the foot of the bubbles, smaller, where it takes no
   room from them: a press goes through it to the bubbles. */
.picker-about.is-inside {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2; min-height: 0; margin: 0; padding: 22px 12px 8px;
  font-size: .72rem; line-height: 1.3; pointer-events: none; overflow: visible;
  background: linear-gradient(to top, var(--surface-2) 60%, transparent);
}
.picker-about.is-inside strong { font-size: .78rem; }
.picker-about b { margin-right: 6px; font-size: .68rem; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--wine); }
.picker-hint:empty { display: none; }

/* The guess at a blind wine's country: pills as an aromas line has them,
   each in the colour of its part of the world. They open the map, so they
   aren't crossed out or dimmed by a tap. Once the wine is revealed, the line
   says what it was and who had it; the pill that was right is ticked, and
   nothing more is picked. */
.line.is-closed [data-option] { cursor: default; }
/* Nothing goes round the pill, where the voting dots are: the pill that
   was right has a green edge of its own and a tick. The viewer's own, when
   it was right, is filled with that green, and swells once; the line that
   says what the wine was is ticked and green too. */
.chip.is-aroma.is-right { border: 1px solid var(--ok); }
.chip.is-right::after { content: "✓"; font-weight: 700; color: var(--ok); }
.chip.is-aroma.is-selected.is-right { background: var(--ok); color: var(--surface); animation: match-swell .8s ease-out; }
.chip.is-selected.is-right::after { color: inherit; }
.line.is-won .guess-answer strong { color: var(--ok); }
.line.is-won .guess-answer strong::before { content: "✓ "; }
@media (prefers-reduced-motion: reduce) { .chip.is-aroma.is-selected.is-right { animation: none; } }
.guess-answer { margin: 12px 0 0; font-size: .9rem; }
.guess-answer strong { display: block; }
.guess-answer span { color: var(--muted); }

/* The country picker (country-picker.js): the picker's frame round a map of
   the world. From afar, each part of the world is named on the map, and its
   countries are in its colour; a tap on a name flies to it. Near, the names
   go, no two countries that touch are alike, and those of that part of the
   world are brighter than the others. A country picked is in its
   full colour; the one being looked at is outlined. Any country of the
   world can be picked. */
.country-picker .picker-body { display: block; overflow-y: auto; }
.picker-title { flex: 1; padding-left: 4px; font: 600 1.1rem var(--serif); color: var(--wine); }
.world { position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-small); background: var(--surface-2); touch-action: none; cursor: grab; user-select: none; -webkit-user-select: none; }
@media (max-width: 520px) { .world { aspect-ratio: 1; } }
.world svg { display: block; width: 100%; height: 100%; }
.world path { vector-effect: non-scaling-stroke; stroke: var(--surface-2); stroke-width: .75; stroke-linejoin: round; }
.world-land { fill: color-mix(in srgb, var(--muted) 32%, var(--surface-2)); pointer-events: none; }
.world-country { fill: var(--own); cursor: pointer; transition: fill .3s ease; }
.world.is-far .world-country { fill: color-mix(in srgb, var(--tint) 45%, #fff); }
/* Near, the countries of the part of the world gone to are bright; the
   others are dimmed towards the land round them. */
.world:not(.is-far) .world-country.is-dim { fill: color-mix(in srgb, var(--own) 28%, color-mix(in srgb, var(--muted) 32%, var(--surface-2))); }
.world .world-country.is-picked, .world:not(.is-far) .world-country.is-picked { fill: var(--own-strong); }
.world .world-country.is-on { stroke: var(--ink); stroke-width: 1.75; }
/* The names of the parts of the world, put on the map by country-picker.js,
   which also brings the name of the part gone to into the map's corner. A
   name that is beside its part of the world is tied to it by a line. */
.world-lead { vector-effect: non-scaling-stroke; stroke: var(--ink); stroke-width: 1; opacity: 0; pointer-events: none; transition: opacity .25s ease; }
.world.is-far .world-lead { opacity: .55; }
.world-part { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); padding: 3px 8px; border: 0; border-radius: 999px; background: color-mix(in srgb, var(--tint) 34%, #fff); color: #2a1d1f; font: 700 .68rem/1.2 var(--sans); white-space: nowrap; cursor: pointer; box-shadow: 0 1px 4px rgb(0 0 0 / 30%); opacity: 0; pointer-events: none; transition: opacity .25s ease; }
/* The way back out to the whole world, beside the picker's title while the
   map is nearer than that: a magnifying glass with a minus in it. */
.picker-head [data-picker-out] { display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.picker-head [data-picker-out][hidden] { display: none; }
.picker-head [data-picker-out] svg { width: 18px; height: 18px; }
/* The country being looked at wears a "+" in its middle while it can be
   added to the guess (country-picker.js keeps it there as the map moves). */
.country-plus { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); width: 44px; height: 44px; padding: 0; border: 2px solid #fff; border-radius: 50%; background: var(--wine); color: var(--on-wine); font: 500 1.7rem/1 var(--sans); box-shadow: 0 2px 8px rgb(0 0 0 / 45%); cursor: pointer; }
/* From afar there is no room for it: it is for a country seen near. */
.country-plus[hidden], .world.is-far .country-plus { display: none; }
/* A country of the guess wears a tick there instead: a tap goes through it
   to the country. */
.country-ticks { position: absolute; inset: 0; pointer-events: none; }
.country-tick { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); display: grid; place-items: center; width: var(--size, 36px); height: var(--size, 36px); border: max(1px, calc(var(--size, 36px) / 18)) solid #fff; border-radius: 50%; background: var(--ok); color: #fff; font: 700 calc(var(--size, 36px) / 2) / 1 var(--sans); box-shadow: 0 1px 5px rgb(0 0 0 / 45%); }
/* Under the map: the country being looked at and what it is known for, in
   two lines that keep their room so that nothing under them moves. */
.country-about { min-height: 2.9em; margin: 8px 0 0; display: grid; gap: 1px; align-content: center; justify-items: center; text-align: center; }
.country-about strong { font: 600 1.1rem var(--serif); }
.country-about small { color: var(--muted); font-size: .78rem; line-height: 1.3; }
/* Under that, always in view: the guess, a line for each choice. Its
   number, the country as a pill that goes to it on the map (the one being
   looked at is ringed), and the "×" that takes it off; a choice not made
   yet is its number and an empty place. */
.country-mine { list-style: none; counter-reset: choice; width: min(100%, 330px); margin: 8px auto 0; padding: 0; display: grid; gap: 6px; }
.country-mine li { counter-increment: choice; display: grid; grid-template-columns: 1.6em minmax(0, 1fr) 40px; align-items: center; justify-items: start; gap: 6px; min-height: 42px; }
.country-mine li::before { content: counter(choice) "."; font-weight: 700; color: var(--muted); }
.country-mine li.is-empty::after { content: ""; grid-column: 2 / 4; justify-self: stretch; height: 40px; border: 1px dashed var(--line); border-radius: 999px; }
.country-mine .chip { min-height: 42px; max-width: 100%; padding: 8px 16px; font-size: 1rem; }
.country-mine .chip.is-on { box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--tint); }
/* A line is dragged up or down to make it another choice. */
.country-mine li[data-code] { cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; }
.country-mine li[data-code] .chip { cursor: inherit; }
.country-mine li.is-carried { position: relative; z-index: 1; cursor: grabbing; }
.country-mine li.is-carried .chip { box-shadow: 0 6px 18px rgb(0 0 0 / 35%); }
/* At the foot of the picker: the button that closes it on the guess made.
   On a phone the map takes what room the rest leaves, so that all of it,
   the button too, is in view without scrolling. */
.country-confirm { width: 100%; margin-top: 12px; }
@media (max-width: 560px), (max-height: 560px) {
  .country-picker .picker-body { display: flex; flex-direction: column; }
  .country-picker .world { flex: 1 1 0; min-height: 220px; aspect-ratio: auto; }
  .country-picker .picker-body > :not(.world) { flex: none; }
}
.country-off { justify-self: end; width: 40px; height: 40px; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: var(--bg); color: var(--ink); font: 500 1.3rem/1 var(--sans); cursor: pointer; }
/* Which choice a country of the guess is, the first, second or third: its
   number, on its pill on the sheet. */
.chip[data-choice]::before { content: attr(data-choice); font-weight: 700; opacity: .65; }
/* The "×" that takes a country or a grape off one's guess, at the end of its
   pill: there while the pill is one's own and the guess is open. */
.sheet .chip-off { display: none; }
.sheet .line:not(.is-closed) .chip.is-selected .chip-off {
  display: grid; place-items: center; width: 24px; height: 24px; margin-right: -8px;
  border-radius: 50%; background: rgb(255 255 255 / 60%); font-size: 1rem; line-height: 1;
}
@media (prefers-reduced-motion: reduce) { .world-country { transition: none; } }

/* The guess at a blind wine's grapes. Its first step, one grape or a blend,
   is boxes to tick: the one that was right has the green edge and the tick
   of any guess that was, and is filled with that green when it is the
   viewer's own. Its second, which grapes, is pills in the colour of their
   skin, picked and taken off as aromas are. */
.chip.is-right { border-color: var(--ok); }
.sheet .chip.is-selected.is-right:not(.is-aroma), .sheet[data-wine-color] .chip.is-selected.is-right:not(.is-aroma) { background: var(--ok); border-color: var(--ok); color: var(--surface); }
/* The grape picker is the aroma picker with the grapes in it
   (aroma-picker.js), and tabs under its search box: the three trees the
   grapes are in. What the search finds nothing for is offered as a pill,
   to be added as it was typed. */
.picker-tabs { display: flex; gap: 6px; padding: 8px 12px; border-bottom: 1px solid var(--line); }
.picker-tabs button { flex: 1; min-height: 36px; padding: 6px 10px; border-radius: 999px; border: 1px solid var(--line); background: var(--bg); color: var(--ink); font: 600 .85rem var(--sans); cursor: pointer; }
.picker-tabs button[aria-selected="true"] { background: var(--wine); border-color: var(--wine); color: var(--on-wine); }
.found p { flex-basis: 100%; margin: 0; text-align: center; }
/* Under what is said of the bubble one is on, the guess: a pill for each
   grape, as on the line, which goes to it among the bubbles, with a "×"
   that takes it off. A long guess scrolls there, and leaves the bubbles
   their room. */
.picker-mine { display: flex; flex-wrap: wrap; gap: 6px; max-height: 5.6rem; overflow-y: auto; margin: 10px 2px 0; }
.picker-mine:empty { display: none; }
.picker-mine .chip { min-height: 32px; padding: 3px 5px 3px 12px; gap: 4px; font-size: .85rem; cursor: default; }
.picker-mine .chip button { border: 0; padding: 0; background: none; color: inherit; font: inherit; cursor: pointer; }
.picker-mine .chip .chip-off { width: 24px; height: 24px; border-radius: 50%; background: rgb(255 255 255 / 60%); font-size: 1rem; line-height: 1; }
@media (max-height: 560px) and (orientation: landscape) { .picker-mine { grid-column: 2; margin-top: 8px; } }
/* At its foot, the button that closes it on the guess made. */
.picker-foot { padding: 10px 12px; border-top: 1px solid var(--line); }
.picker-foot .button { width: 100%; }

/* How long the wine can be kept (aging-picker.js): the years as numbers with
   no box of their own, ten to a line at any width, so on a phone a year is
   some 32 pixels wide: enough to read beside a finger and to hit without
   aiming. What is picked is one pill, in one colour from its first year to
   its last. */
.aging { font-variant-numeric: tabular-nums; user-select: none; -webkit-user-select: none; }
.aging [hidden] { display: none; }
.aging-box { padding: 6px 10px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg); }
/* A finger on the years sweeps, down as well as along: the page is scrolled
   from anywhere else on the line. */
.aging-years { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); row-gap: 2px; touch-action: none; }
.aging-years button { height: 38px; min-width: 0; padding: 0; border: 0; background: none; color: var(--ink); font: 500 1rem var(--sans); cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* Columns a fraction of a pixel wide can leave a hair between two years. */
.aging-years .is-picked { background: var(--wine); color: var(--on-wine); box-shadow: 1px 0 0 var(--wine); }
.aging-years :is(.is-last, :nth-child(10n)) { box-shadow: none; }
.aging-years .is-first { border-radius: 999px 0 0 999px; }
.aging-years .is-last { border-radius: 0 999px 999px 0; }
.aging-years .is-first.is-last { border-radius: 999px; }
/* The handle under the years, which opens all of them and shuts them again. */
.aging-more { display: block; width: 100%; margin-top: 2px; padding: 4px 0 2px; border: 0; border-top: 1px dashed var(--line); background: none; color: var(--muted); font: 500 .78rem var(--sans); cursor: pointer; }
/* While a finger is on the years, the bubble over it that says the year it is
   on, or the range it has swept so far: the finger hides them. */
.aging-bubble { position: fixed; z-index: 10; translate: -50% -100%; padding: 5px 14px; border-radius: 999px; background: var(--ink); color: var(--bg); font: 700 1.3rem/1.2 var(--sans); white-space: nowrap; box-shadow: 0 6px 18px rgb(0 0 0 / 30%); pointer-events: none; }
/* Its tail is long: the bubble is over the line above, and the tail comes
   down past that line's year to the one it is about. */
.aging-bubble::after { content: ""; position: absolute; left: calc(50% + var(--tail, 0px)); top: 100%; translate: -50% -1px; border: 7px solid transparent; border-top: var(--reach, 7px) solid var(--ink); border-bottom: 0; }
/* Once the others' answers may be seen: the table's answers on one line of
   years, from the first anyone said to the last, written out as small
   numbers. A year is never wider than a pill is tall and a little more, so a
   table that agrees to the year has a short line, not a stretched one. The others' are
   see-through pills under the numbers, none hiding another, so that the years
   are the deeper the more pills lie on them; the viewer's own is over those,
   full, as what is picked is among the years, and opens them. */
.aging-table { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.aging-line, .aging-dots { display: grid; grid-template-columns: repeat(var(--years), minmax(0, 2.25rem)); }
/* The viewer's own is as tall as what is picked on the sheet's other lines;
   the others' are lower, and all of them share its middle. */
.aging-line { align-items: center; }
.aging-line > * { grid-row: 1; height: 42px; }
.aging-line i { height: 28px; border-radius: 999px; background: color-mix(in srgb, var(--wine) 28%, transparent); }
.aging-line button { z-index: 1; min-width: 0; padding: 0; border: 0; border-radius: 999px; background: var(--wine); color: var(--on-wine); font: 500 clamp(.7rem, 3.4vw, .92rem) var(--sans); white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* The numbers are over the pills, and let a tap through to the viewer's.
   Where three pills or more lie under one it is on a colour deep enough to
   want the light ink, as on the viewer's own. */
.aging-line span { z-index: 2; display: flex; align-items: center; justify-content: center; pointer-events: none; color: var(--ink); font: 500 clamp(.58rem, 2.7vw, .85rem) var(--sans); letter-spacing: -.03em; }
.aging-line span:is(.is-mine, .is-deep) { color: var(--on-wine); }
/* Under each year, a dot for each person whose answer holds it: the viewer's
   own first and in the wine's colour, so that theirs make a line under
   their pill and the others' hang from it. */
.aging-dots { margin-top: 6px; align-items: start; }
.aging-dots div { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.aging-dots i { width: 5px; height: 5px; border-radius: 50%; background: var(--ink); }
.aging-dots .is-mine { background: var(--wine); }
/* Where the table settled, in words. */
.aging-says { margin: 8px 0 0; font-size: .88rem; color: var(--muted); }
.aging-says strong { color: var(--ink); }
/* The years opened wide, in a pop-up shaped as the aroma picker is: what is
   picked in words at the top, then every year from 0 to 100, ten to a line,
   the lines sharing all the height there is so that on a phone a year is a
   good fingertip in size. A finger on them sweeps, any way it goes. */
.aging-picker .picker-body { display: flex; flex-direction: column; }
.aging-wide-reading { min-height: 1.4em; margin: 2px 0 10px; text-align: center; font: 600 1.35rem/1.4 var(--sans); font-variant-numeric: tabular-nums; color: var(--wine); }
.aging-wide { flex: 1; display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); grid-auto-rows: minmax(40px, 1fr); row-gap: 2px; touch-action: none; user-select: none; -webkit-user-select: none; font-variant-numeric: tabular-nums; }
.aging-wide button { min-width: 0; padding: 0; border: 0; background: none; color: var(--ink); font: 500 1.05rem var(--sans); cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* Under the years, the others' answers as on the line: see-through pills,
   lower than a year is tall and in the middle of it, the deeper the more of
   them lie on a year. Where three or more do, the year takes the light ink. */
.aging-wide button { position: relative; z-index: 1; }
.aging-wide i { align-self: center; height: 28px; background: color-mix(in srgb, var(--wine) 28%, transparent); pointer-events: none; }
.aging-wide .is-deep { color: var(--on-wine); }
.aging-wide .is-picked { background: var(--wine); color: var(--on-wine); box-shadow: 1px 0 0 var(--wine); }
.aging-wide :is(.is-last, :nth-child(10n)) { box-shadow: none; }
.aging-wide .is-first { border-radius: 999px 0 0 999px; }
.aging-wide .is-last { border-radius: 0 999px 999px 0; }
.aging-wide .is-first.is-last { border-radius: 999px; }
/* What flies from the years to the pill as they fold. */
.aging-ghost { position: fixed; z-index: 10; display: flex; align-items: center; justify-content: center; overflow: hidden; border-radius: 999px; background: var(--wine); color: var(--on-wine); font: 500 .92rem var(--sans); white-space: nowrap; pointer-events: none; }
.others-text { margin-top: 8px; padding: 8px 12px; border-radius: var(--radius-small); background: var(--wine-soft); color: var(--wine-faded-ink); font-size: .9rem; }
.others-text-title { font-size: .72rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700; margin: 0 0 4px; }
.others-text ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 3px; }
.others-text strong { color: var(--ink); opacity: .75; font-weight: 600; }

/* Where the tasting is, in an event tasted together: each wine's card holds,
   after its stripe, a circle on a hairline. The circle is empty once the
   wine has been tasted and pulses while it is being tasted; a wine still to
   come has neither circle nor line, only their place, so that the names stay
   in line. The line runs through the card from edge to edge (through its 12
   pixels of padding), in two halves so that it can end at a circle. */
.tasting-rail { --node: 14px; flex: none; align-self: stretch; position: relative; width: 16px; display: flex; align-items: center; justify-content: center; color: var(--muted); }
.tasting-rail::before, .tasting-rail::after { content: ""; position: absolute; left: 50%; width: 1px; margin-left: -.5px; }
.tasting-rail::before { top: -12px; bottom: calc(50% + var(--node) / 2); }
.tasting-rail::after { top: calc(50% + var(--node) / 2); bottom: -12px; }
.tasting-rail.has-up::before, .tasting-rail.has-down::after { background: var(--muted); }
.tasting-rail i { position: relative; z-index: 1; width: var(--node); height: var(--node); border-radius: 50%; }
.is-tasted > .wine-card .tasting-rail i { border: 1.5px solid currentColor; }
/* The pulse: the circle swells a little with each beat, and a ring of its
   colour spreads from behind it and fades. */
.is-on > .wine-card .tasting-rail i { background: var(--wine); animation: rail-beat 1.6s ease-in-out infinite; }
.is-on > .wine-card .tasting-rail i::after { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: 50%; background: var(--wine); animation: rail-ring 1.6s ease-out infinite; }
@keyframes rail-beat { 0%, 100% { transform: scale(1); } 30% { transform: scale(1.2); } }
@keyframes rail-ring { from { transform: scale(1); opacity: .55; } to { transform: scale(2.8); opacity: 0; } }
/* A card cuts off what leaves it, so the stretch of line between two cards
   belongs to the row: from the bottom edge of one card to the top edge of
   the next, over their borders, under the rail (which is 27 pixels in: the
   card's border, its padding, half the rail). */
.wine-cards li.joins-next { position: relative; }
.wine-cards li.joins-next::after { content: ""; position: absolute; z-index: 1; left: 26.5px; top: calc(100% - 1px); width: 1px; height: 12px; background: var(--muted); }
.wine-cards li.is-dragging::after { display: none; }
/* On that line every row is the same height, whatever its wine and wherever
   the tasting is: three lines, each cut short rather than wrapped. */
/* A line that isn't wrapped would otherwise make its row, and with it the
   whole list, as wide as its words: the list's one column is held to the
   width of the page. */
.wine-cards.has-line { grid-template-columns: minmax(0, 1fr); }
.wine-cards.has-line .wine-card { min-height: 5.8rem; }
.wine-cards.has-line .wine-card-text > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (prefers-reduced-motion: reduce) {
  .is-on > .wine-card .tasting-rail i { animation: none; }
  .is-on > .wine-card .tasting-rail i::after { display: none; }
}
/* The wine the event is on says so at the top of its own page, and its card
   in the event is outlined. */
.live-dot { display: inline-block; width: 8px; height: 8px; margin-right: 6px; border-radius: 50%; background: currentColor; vertical-align: 1px; animation: live-pulse 1.6s ease-out infinite; }
@keyframes live-pulse { from { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 55%, transparent); } to { box-shadow: 0 0 0 7px transparent; } }
.now-tag { display: block; margin: 0 0 2px; color: var(--wine); font-size: .72rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.wine-header .now-tag { margin-bottom: 8px; }
.wine-card.is-now { border-color: var(--wine); }
/* The organizer runs the tasting with round buttons: a step back or forward,
   play, stop. The one that goes on is filled. */
.round-button { flex: none; width: 44px; height: 44px; padding: 0; border: 1px solid var(--line); border-radius: 50%; background: var(--surface); color: var(--ink); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; }
.round-button:hover:not(:disabled) { border-color: var(--wine); color: var(--wine); }
.round-button:disabled { opacity: .35; cursor: default; }
.round-button.is-main, .round-button.is-main:hover:not(:disabled) { background: var(--wine); border-color: var(--wine); color: var(--on-wine); }
.round-button svg { width: 20px; height: 20px; }
/* Their player, above the event's wines (events/_player.html): back, what is
   being tasted, stop, forward. The buttons keep their place from wine to wine. */
.tasting-deck { display: flex; align-items: center; gap: 10px; min-height: 66px; margin-bottom: 16px; padding: 10px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); text-align: left; }
.tasting-deck form { display: flex; flex: none; }
/* With nothing being tasted, and on the first wine, there is nowhere to go
   back to and no button for it; its place is kept, so that the words don't
   move when it turns up on the second wine. */
.tasting-deck:is(.is-idle, .is-first)::before { content: ""; flex: none; width: 44px; }
/* Before the tasting starts, between two wines and once it is over, what
   takes the player's place is the size of the player: nothing below moves. */
.tasting-over { min-height: 66px; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; margin: 0 0 16px; padding: 10px 14px; border-radius: var(--radius-small); background: var(--surface-2); color: var(--muted); font-size: .9rem; }
.tasting-over > span { flex: 1 1 200px; }
.tasting-over form, .tasting-over .button { min-width: 0; max-width: 100%; }
.tasting-over .button { background: var(--surface); }
.tasting-over .button span { overflow: hidden; text-overflow: ellipsis; }
/* What floats at the bottom of an event's pages for a guest who is somewhere
   else than the wine being tasted (events/_tasting.html): a card that leads
   to it, in that wine's colour. */
.tasting-dock { position: fixed; left: 0; right: 0; bottom: max(12px, env(safe-area-inset-bottom)); z-index: 6; display: flex; justify-content: center; padding: 0 12px; pointer-events: none; }
.tasting-dock > * { pointer-events: auto; }
.tasting-text strong, .tasting-chip span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tasting-call {
  position: relative; display: flex; align-items: center; gap: 8px; width: 100%; max-width: 520px;
  padding: 10px 6px 10px 20px; overflow: hidden; background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radius); box-shadow: 0 8px 28px rgb(40 10 20 / 28%);
  animation: tasting-rise .28s ease-out both;
}
.tasting-call::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 6px; background: var(--stripe); }
@keyframes tasting-rise { from { opacity: 0; transform: translateY(18px); } }
.tasting-text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.tasting-eyebrow { color: var(--wine); font-size: .72rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.tasting-close { flex: none; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 50%; background: none; color: var(--muted); font: 400 1.4rem/1 var(--sans); cursor: pointer; }
.tasting-close:hover { background: var(--surface-2); color: var(--ink); }
/* Turned down, the card leaves a way to the wine in the corner. */
.tasting-chip { max-width: 100%; margin-left: auto; display: inline-flex; align-items: center; gap: 4px; padding: 6px 12px; border-radius: 999px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow); color: var(--wine); font-size: .85rem; font-weight: 600; text-decoration: none; }
.tasting-dock:not(.is-declined) .tasting-chip, .tasting-dock.is-declined .tasting-call { display: none; }
/* The page ends clear of what floats, and "Saved" sits above it. */
body:has(.tasting-dock > *) .page { padding-bottom: 120px; }
body:has(.tasting-dock > *) .save-status { bottom: calc(max(12px, env(safe-area-inset-bottom)) + 76px); }
@media (prefers-reduced-motion: reduce) { .live-dot, .tasting-call { animation: none; } }

.wine-pager { display: flex; justify-content: space-between; align-items: center; gap: 8px; margin-top: 20px; }
/* Where the page ends for the organizer: their button for this wine's
   tasting, then the way to the next wine. */
.wine-pager-end { display: flex; align-items: center; gap: 8px; min-width: 0; }
.wine-pager-end form { display: flex; }
.wine-pager-end .button-icon { width: 1em; height: 1em; }
.wine-pager .button { min-width: 0; padding-left: 14px; padding-right: 14px; }
