/* The hidden attribute must always win over any display rule below (grid/flex forms
   were leaking onto the page: the create form showed with empty selects when the
   visitor had no group yet, 2026-09-27). */
[hidden] {
  display: none !important;
}

/*
 * karaoke-taiwan — mobile-first styles.
 *
 * One column by default; the venue list widens into a grid only once there is
 * room for it. No framework, no build step for CSS.
 */

:root {
  --radius: 12px;
  --gap: 0.75rem;
  --density: 1;
  --pad: calc(1rem * var(--density));
  --fs: calc(1rem * (0.9 + 0.1 * var(--density)));
  --lh: 1.55;
}

/*
 * Colour tokens — two modes from the Utai icon (design/branding, batch16/17,
 * 烏龍茶と藍): U3 light = pale oolong ground + aizome indigo ink, U4 dark = the
 * same pair swapped. Every colour in this sheet is one of these tokens; the
 * only raw colours live in the three blocks below (scripts/tests/theme.test.mjs
 * holds that line).
 *
 * Light is the complete set on bare :root. Dark applies when the system asks
 * for it and the reader has not picked light in the menu (html[data-theme],
 * public/lib/theme.js), or when they picked dark. Body and dim text clear
 * 4.5:1 on the ground, the card surface and the raised surface in both modes.
 */
:root {
  --bg: #E8D7C5;               /* ground: pale oolong */
  --surface: #F4EDE2;          /* cards, inputs, menus */
  --surface-raised: #EDE1D2;   /* buttons, hovers, selected chips, popovers */
  --border: #C3B9B0;           /* ink at ~18% on the ground */
  --text: #1D324F;             /* ink: aizome indigo */
  --text-dim: #566070;         /* ink at ~72% (65% would miss 4.5:1 on the ground) */
  --primary: #1D324F;          /* primary button fill */
  --on-primary: #E8D7C5;       /* text on the primary fill */
  --accent: #2F5E91;           /* links, focus rings, emphasised figures */
  --danger: #A8332F;           /* lantern red, darkened for text */
  --success: #2F6B45;          /* 募集中 */
  --warn: #7A4F00;
  --warn-bg: #F3DDB0;
  --joysound: #1A5F87;         /* machine badges */
  --dam: #A2401A;
  --discord: #5865F2;          /* provider marks: brand colour for fills and borders */
  --discord-text: #4752C4;     /* and a readable shade for text */
  --line: #06C755;
  --line-text: #06692F;
  --shadow: rgba(29, 50, 79, 0.18);
  --shadow-strong: rgba(29, 50, 79, 0.22);
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #1D324F;
    --surface: #243F66;
    --surface-raised: #2B4870;
    --border: #425064;
    --text: #E8D7C5;
    --text-dim: #BFB6AD;
    --primary: #E8D7C5;
    --on-primary: #1D324F;
    --accent: #9DC1EA;
    --danger: #F7A197;
    --success: #86D0A0;
    --warn: #F2C46B;
    --warn-bg: #4A3F24;
    --joysound: #7ACBF0;
    --dam: #FFA27C;
    --discord: #5865F2;
    --discord-text: #B3BAFF;
    --line: #06C755;
    --line-text: #5FE09A;
    --shadow: rgba(4, 10, 20, 0.35);
    --shadow-strong: rgba(4, 10, 20, 0.45);
    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --bg: #1D324F;
  --surface: #243F66;
  --surface-raised: #2B4870;
  --border: #425064;
  --text: #E8D7C5;
  --text-dim: #BFB6AD;
  --primary: #E8D7C5;
  --on-primary: #1D324F;
  --accent: #9DC1EA;
  --danger: #F7A197;
  --success: #86D0A0;
  --warn: #F2C46B;
  --warn-bg: #4A3F24;
  --joysound: #7ACBF0;
  --dam: #FFA27C;
  --discord: #5865F2;
  --discord-text: #B3BAFF;
  --line: #06C755;
  --line-text: #5FE09A;
  --shadow: rgba(4, 10, 20, 0.35);
  --shadow-strong: rgba(4, 10, 20, 0.45);
  color-scheme: dark;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  padding: 0 0 3rem;
  background: var(--bg);
  color: var(--text);
  font: 1rem/var(--lh) system-ui, -apple-system, "Noto Sans TC", "PingFang TC",
    "Microsoft JhengHei", sans-serif;
  /* Chrome on Android otherwise inflates text in some blocks. */
  text-size-adjust: 100%;
  -webkit-text-size-adjust: 100%;
}

main {
  padding: 1rem;
  max-width: 60rem;
  margin: 0 auto;
}

/* --- filter ------------------------------------------------------------- */

.filter {
  border: 0;
  margin: 0 0 0.75rem;
  padding: 0;
}

.filter legend {
  padding: 0;
  font-size: 0.8rem;
  color: var(--text-dim);
}

.filter-options {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
  flex-wrap: wrap;
}

.chip {
  display: inline-flex;
  align-items: center;
  /* A comfortable tap target on a phone. */
  min-height: 2.5rem;
  padding: 0 0.9rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  cursor: pointer;
  font-size: 0.9rem;
  user-select: none;
}

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

.chip:has(input:checked) {
  border-color: var(--accent);
  background: var(--surface-raised);
  color: var(--accent);
  font-weight: 600;
}

.chip:has(input:focus-visible) {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.filter-count {
  margin: 0 0 0.75rem;
  color: var(--text-dim);
  font-size: 0.8rem;
}

/* --- venue list --------------------------------------------------------- */

.venue-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap);
}

@media (min-width: 46rem) {
  .venue-list {
    grid-template-columns: repeat(2, 1fr);
  }
}

.venue-card {
  display: block;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
}

.venue-card:hover,
.venue-card:focus-visible {
  border-color: var(--accent);
}

.venue-card h2 {
  margin: 0;
  font-size: 1.05rem;
}

.venue-card .area {
  color: var(--text-dim);
  font-size: 0.8rem;
  margin: 0.15rem 0 0.5rem;
}

.venue-card .capacity {
  margin: 0.5rem 0 0;
  font-size: 0.85rem;
  color: var(--text-dim);
}

/* --- badges ------------------------------------------------------------- */

.badges {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.badge {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 6px;
  border: 1px solid currentColor;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
}

.badge-JOYSOUND {
  color: var(--joysound);
}

.badge-DAM {
  color: var(--dam);
}

.badge-deposit {
  color: var(--warn);
}

.badge-more {
  color: var(--text-dim);
}

/* --- stale marker ------------------------------------------------------- */

.stale {
  margin: 0.75rem 0;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius);
  background: var(--warn-bg);
  color: var(--warn);
  font-size: 0.85rem;
}

.stale strong {
  display: block;
}

.venue-card .stale {
  margin: 0.5rem 0 0;
  padding: 0.3rem 0.5rem;
  font-size: 0.75rem;
}

/* --- detail ------------------------------------------------------------- */

.back {
  display: inline-block;
  margin-bottom: 0.75rem;
  color: var(--accent);
  text-decoration: none;
  font-size: 0.9rem;
  min-height: 2.5rem;
  line-height: 2.5rem;
}

.detail-title {
  margin: 0;
  font-size: 1.3rem;
}

.detail-title .ja {
  display: block;
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--text-dim);
}

.detail-area {
  margin: 0.2rem 0 1rem;
  color: var(--text-dim);
  font-size: 0.85rem;
}

.detail-section {
  margin: 0 0 1.25rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.detail-section h3 {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--text-dim);
}

.detail-section p {
  margin: 0;
}

.room-list,
.source-list,
.hours-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.room-list li {
  padding: 0.5rem 0;
  border-top: 1px solid var(--border);
}

.room-list li:first-child {
  border-top: 0;
  padding-top: 0;
}

.room-name {
  font-weight: 600;
}

.room-capacity {
  float: right;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.room-note,
.channel-note {
  margin: 0.25rem 0 0;
  font-size: 0.8rem;
  color: var(--text-dim);
}

.hours-list li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.15rem 0;
  font-variant-numeric: tabular-nums;
}

.hours-list .day {
  color: var(--text-dim);
}

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

.detail-section a {
  display: inline-block;
  min-height: 2.5rem;
  line-height: 2.5rem;
}

.source-list li {
  overflow-wrap: anywhere;
}

.verified {
  color: var(--text-dim);
  font-size: 0.8rem;
}

.empty,
.error {
  padding: 1.5rem 0;
  color: var(--text-dim);
  text-align: center;
}

/* =========================================================================
 * The board (tasks 5.1-5.3a)
 *
 * Mobile-first throughout: one column, 2.5rem minimum tap targets, and the
 * only breakpoint widens the round-up list into two columns once a phone is
 * definitively not what is looking.
 * ===================================================================== */

.topbar-name {
  font-weight: 600;
  font-size: 0.9rem;
}

.badges-inline {
  display: inline-flex;
}

/* --- buttons ------------------------------------------------------------ */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  padding: 0 1rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text);
  font: inherit;
  font-size: 0.9rem;
  text-decoration: none;
  cursor: pointer;
}

.button:hover,
.button:focus-visible {
  border-color: var(--accent);
}

.button[disabled] {
  opacity: 0.6;
  cursor: default;
}

.button-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--on-primary);
  font-weight: 600;
}

.button-quiet {
  background: transparent;
}

.button-danger {
  color: var(--danger);
  border-color: var(--danger);
  background: transparent;
}

.button-discord {
  border-color: var(--discord);
  color: var(--discord-text);
}

.button-line {
  border-color: var(--line);
  color: var(--line-text);
}

.button-wide {
  width: 100%;
}

.button-small {
  min-height: 2.25rem;
  font-size: 0.8rem;
  padding: 0 0.75rem;
}

.button-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.text-link {
  font-size: 0.85rem;
}

.flash {
  margin: 0 0 1rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius);
  background: var(--surface-raised);
  font-size: 0.9rem;
}

.flash-error {
  background: var(--warn-bg);
  color: var(--warn);
}

.muted {
  color: var(--text-dim);
}

.warn {
  color: var(--warn);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- board -------------------------------------------------------------- */

.roundup-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap);
}

@media (min-width: 46rem) {
  .roundup-list {
    grid-template-columns: repeat(2, 1fr);
  }
}

.seats-full {
  color: var(--warn);
}

.chip-open,
.chip-full,
.chip-closed,
.chip-cancelled,
.chip-done {
  display: inline-block;
  padding: 0.1rem 0.6rem;
  border-radius: 999px;
  border: 1px solid currentColor;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
  min-height: 0;
}

.chip-open {
  color: var(--success);
}

.chip-full {
  color: var(--warn);
}

.chip-closed,
.chip-done {
  color: var(--text-dim);
}

.chip-cancelled {
  color: var(--danger);
}

.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
}

.tag {
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-dim);
  font-size: 0.75rem;
}

/* --- forms -------------------------------------------------------------- */

.form {
  display: grid;
  gap: 1rem;
}

.field {
  display: grid;
  gap: 0.3rem;
  border: 0;
  margin: 0;
  padding: 0;
  /* A grid/flex child defaults to min-width:auto, i.e. it refuses to shrink
     below its content — and a date input's content is wide. Without these the
     two-up rows push the page sideways on a phone. */
  min-width: 0;
}

.field > span,
.field > legend {
  font-size: 0.8rem;
  color: var(--text-dim);
  padding: 0;
}

.field input,
.field select,
.field textarea,
.target-name {
  width: 100%;
  min-width: 0;
  min-height: 2.75rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 1rem; /* 16px — anything smaller makes iOS Safari zoom on focus */
}

.field textarea {
  min-height: 4rem;
  resize: vertical;
}

.field-row {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}

.field-row > .button,
.field-row > button {
  /* Buttons sit next to inputs at their own width; only the inputs stretch. */
  flex: 0 0 auto;
}

.field-row > * {
  flex: 1 1 0;
  /* Without this a grid/flex child keeps its intrinsic width (a date input is
     wide) and the page scrolls sideways on a phone. */
  min-width: 0;
}

.hint {
  font-size: 0.75rem;
  color: var(--text-dim);
}

.field-error {
  font-size: 0.8rem;
  color: var(--danger);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

/* The tag checkboxes live inside a `fieldset.field`, so the full-width input
   rule above would otherwise stretch each hidden box to the page width — and
   since `.chip input` is absolutely positioned, that pushed the page sideways
   on a phone rather than being invisible. */
.chip input {
  width: auto;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: 0;
}

.venue-notice {
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 0.85rem;
  display: grid;
  gap: 0.3rem;
}

/* --- one round-up ------------------------------------------------------- */

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

.facts {
  margin: 0;
}

.fact {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.35rem 0;
  border-top: 1px solid var(--border);
}

.fact:first-child {
  border-top: 0;
}

.fact dt {
  color: var(--text-dim);
  font-size: 0.85rem;
  white-space: nowrap;
}

.fact dd {
  margin: 0;
  text-align: right;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: 0.4rem;
}

.note {
  white-space: pre-wrap;
  font-size: 0.9rem;
}

.note-private {
  color: var(--warn);
}

.participants {
  list-style: none;
  margin: 0;
  padding: 0;
}

.participant {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--border);
}

.participant:first-child {
  border-top: 0;
}

.participant-name {
  font-weight: 600;
}

.badge-organizer {
  color: var(--accent);
}

.joined-note {
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.join-blocked {
  color: var(--text-dim);
  font-size: 0.9rem;
}

.booking-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem;
  margin: 0.75rem 0;
}

.distribution {
  display: grid;
  gap: 0.5rem;
  margin-top: 0.75rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}

.edit-form {
  display: grid;
  gap: 0.75rem;
}

/* --- account ------------------------------------------------------------ */

.provider-list,
.target-list {
  list-style: none;
  margin: 0 0 0.75rem;
  padding: 0;
}

.provider-row,
.target-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0;
  border-top: 1px solid var(--border);
}

.provider-row:first-child,
.target-row:first-child {
  border-top: 0;
}

.target-row {
  display: grid;
  gap: 0.4rem;
}

.target-new {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--radius);
}

.target-revoked .target-name {
  opacity: 0.6;
}

.paste-form {
  margin-top: 1rem;
  font-size: 0.9rem;
}

.paste-form summary {
  min-height: 2.5rem;
  line-height: 2.5rem;
  cursor: pointer;
  color: var(--accent);
}

.paste-form form {
  display: grid;
  gap: 0.6rem;
  margin-top: 0.5rem;
}

.danger-zone {
  border-color: var(--danger);
}

/* --- groups (8.6) -------------------------------------------------------- */

/*
 * A group is the audience of a round-up, so its name is a badge in the same
 * family as the machine badges rather than a heading of its own: on a card it
 * sits under the facts, and on a phone it wraps instead of pushing anything out
 * of the 390px viewport.
 */
.badge-group {
  color: var(--accent);
}

.badges-group {
  margin-top: 0.3rem;
}

.badge-role {
  color: var(--text-dim);
}

.badge-admin {
  color: var(--accent);
}

/*
 * `display: grid` beats the `hidden` ATTRIBUTE (there is no global
 * `[hidden] { display: none }` in this sheet), so every grid block that a page
 * toggles has to say so explicitly — otherwise the signed-out prompt stays on
 * screen for a signed-in reader, which is exactly what happened the first time.
 */
.signed-out[hidden],
.invite-card[hidden],
.group-card[hidden] {
  display: none;
}

.signed-out {
  display: grid;
  gap: 0.75rem;
  justify-items: start;
  padding: 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

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

.group-card {
  display: grid;
  gap: 0.6rem;
  padding: 0.85rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}

.group-card h3,
.group-card h4 {
  margin: 0;
  font-size: 0.95rem;
}

.group-name-input,
.invite-url {
  flex: 1;
  min-width: 0;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font: inherit;
}

/* The token is long; it must scroll inside the field, never widen the page. */
.invite-url {
  font-size: 0.8rem;
  overflow-x: auto;
}

.invite-box {
  display: grid;
  gap: 0.4rem;
  padding: 0.6rem;
  border-radius: var(--radius);
  background: var(--bg);
}

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

.member-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.member-name {
  font-weight: 600;
}

.group-targets {
  display: grid;
  gap: 0.4rem;
}

/* The register button is a link styled as a button; it must not stretch the
   whole grid row on a phone, nor overflow it. */
.group-targets .button-discord {
  justify-self: start;
  max-width: 100%;
}

/* The push picker on a round-up: one fieldset per group, its channels as chips. */
.push-groups {
  display: grid;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}

.push-group {
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}

.push-group legend {
  padding: 0;
  margin-bottom: 0.3rem;
  font-size: 0.85rem;
  color: var(--text-dim);
}

/* --- the invite landing page --------------------------------------------- */

.invite-card {
  display: grid;
  gap: 0.75rem;
  padding: 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  text-align: center;
  justify-items: center;
}

.invite-group {
  margin: 0;
  font-size: 1.3rem;
}

.headline-group {
  margin: 0 0 0.5rem;
  font-weight: 600;
  color: var(--accent);
}

.share-block {
  display: inline-flex;
  gap: 0.4rem;
  align-items: center;
  flex-wrap: wrap;
}

.share-group,
.target-group {
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  max-width: 100%;
}

.field-inline {
  flex-direction: row;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
}

/* Legend text collapsed into an ⓘ beside the label; the popover is the old hint. */
.info-wrap {
  position: relative;
  display: inline-block;
  margin-left: 0.35rem;
  vertical-align: middle;
}
.info {
  width: 1.15rem;
  height: 1.15rem;
  padding: 0;
  border: 1px solid var(--text-dim);
  border-radius: 999px;
  background: transparent;
  color: var(--text-dim);
  font: 700 0.7rem/1 ui-serif, Georgia, serif;
  font-style: italic;
  cursor: pointer;
}
.info[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent);
}
.popover {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.4rem);
  left: 0;
  min-width: 14rem;
  max-width: min(22rem, 80vw);
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--surface-raised);
  border-radius: 0.6rem;
  background: var(--surface-raised);
  color: var(--text);
  font-size: 0.8rem;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;
  box-shadow: 0 8px 24px var(--shadow-strong);
}

/* =========================================================================
 * Layout density: tight / normal / wide (howish 2026-09-27).
 *
 * One multiplier (--density) feeds the paddings (--pad), the base font size
 * (--fs), the line height (--lh) and the gaps (--gap); components read those
 * tokens. Tight is meant to be TIGHT — a phone should show a screenful of
 * round-ups under a one-line bar — without taking body text below 15px.
 * ===================================================================== */

:root { --bar: 3rem; }
:root[data-density="tight"] { --density: 0.6; --gap: 0.4rem; --lh: 1.4; --bar: 2.75rem; }
:root[data-density="normal"] { --density: 1; --gap: 0.6rem; --lh: 1.5; --bar: 3rem; }
:root[data-density="wide"] { --density: 1.35; --gap: 1rem; --lh: 1.6; --bar: 3.25rem; }
html { font-size: var(--fs); }
main { padding: calc(var(--pad) * 0.75) var(--pad) 1rem; }
.card, .detail-section, .group-card { padding: calc(var(--pad) * 0.75); }
.detail-section { margin-bottom: calc(var(--gap) * 1.5); }
.chip { min-height: calc(2rem + 0.5rem * var(--density)); }

/* --- the app bar: one line, every page ------------------------------------ */

.appbar {
  position: sticky;
  top: 0;
  z-index: 30;
  background: color-mix(in srgb, var(--bg) 90%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.appbar-inner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 60rem;
  min-height: var(--bar);
  margin: 0 auto;
  padding: 0 var(--pad);
}

.appbar-brand {
  flex: 0 1 auto;
  min-width: 0;
  margin: 0;
  font-size: 1.1rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.appbar-brand a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 2.5rem;
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

.brand-machines {
  display: inline-flex;
  gap: 0.2rem;
  letter-spacing: 0.03em;
}

.brand-machines .badge {
  padding: 0 0.3rem;
  font-size: 0.6rem;
  line-height: 1.6;
  border-radius: 4px;
}

@media (max-width: 22rem) {
  .brand-machines { display: none; }
}

.appbar-back {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  margin-left: -0.6rem;
  border-radius: 999px;
  color: var(--text);
  font-size: 1.15rem;
  text-decoration: none;
  transition: background-color 0.15s;
}

.appbar-back:hover,
.appbar-back:focus-visible { background: var(--surface-raised); }

.appbar-title {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  font-size: 1.05rem;
  font-weight: 700;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
}

.topbar .button-small { min-height: 2.25rem; }

.button { transition: border-color 0.15s, background-color 0.15s, transform 0.1s; }
.button:active { transform: translateY(1px); }

/* --- the account menu (avatar → name, pages, density) -------------------- */

.menu { position: relative; }

.menu > summary {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  min-height: 2.5rem;
  padding: 0.2rem;
  border-radius: 999px;
  list-style: none;
  cursor: pointer;
  transition: background-color 0.15s;
}

.menu > summary::-webkit-details-marker { display: none; }
.menu[open] > summary,
.menu > summary:hover { background: var(--surface-raised); }
.menu > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.menu-name {
  display: none;
  max-width: 10rem;
  overflow: hidden;
  font-size: 0.9rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (min-width: 46rem) {
  .menu-name { display: inline; padding-right: 0.5rem; }
}

.avatar {
  position: relative;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--border);
  border-radius: 0.6rem;
  background: var(--surface-raised);
}

.avatar-img {
  width: 100%;
  height: 100%;
  border-radius: inherit;
  object-fit: cover;
}

.avatar-initial {
  color: var(--accent);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1;
}

.avatar-dot {
  position: absolute;
  right: -3px;
  bottom: -3px;
  width: 0.65rem;
  height: 0.65rem;
  border: 2px solid var(--bg);
  border-radius: 999px;
}

.avatar-dot-discord { background: var(--discord); }
.avatar-dot-line { background: var(--line); }

.menu-panel {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 40;
  display: grid;
  gap: 0.1rem;
  width: max-content;
  min-width: 14rem;
  max-width: calc(100vw - 2rem);
  padding: 0.35rem;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 14px 36px var(--shadow);
}

.menu-who {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.2rem;
  padding: 0.45rem 0.6rem 0.55rem;
  border-bottom: 1px solid var(--border);
}

.topbar-name {
  font-size: 0.9rem;
  font-weight: 600;
}

.menu-item {
  display: flex;
  align-items: center;
  min-height: 2.5rem;
  padding: 0 0.6rem;
  border-radius: 0.5rem;
  color: var(--text);
  font-size: 0.9rem;
  text-decoration: none;
}

.menu-item:hover,
.menu-item:focus-visible { background: var(--surface-raised); }

.menu-density {
  display: grid;
  gap: 0.35rem;
  margin-top: 0.2rem;
  padding: 0.5rem 0.6rem 0.35rem;
  border-top: 1px solid var(--border);
  font-size: 0.8rem;
}

.density {
  display: flex;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 999px;
}

.density-option {
  flex: 1;
  min-height: 2.25rem;
  padding: 0 0.6rem;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.8rem;
  white-space: nowrap; /* 「跟隨系統」 must not wrap inside its segment */
  cursor: pointer;
}

.density-option[aria-pressed="true"] {
  background: var(--primary);
  color: var(--on-primary);
  font-weight: 600;
}

/* --- the board's filter row: one line of chips --------------------------- */

.filterbar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  /* Bleed to the screen edge so a long row scrolls under the gutter, not the page. */
  /* The block padding leaves room for the focus ring, which overflow would clip. */
  margin: -4px calc(var(--pad) * -1) calc(var(--gap) + 0.1rem - 4px);
  padding: 5px var(--pad);
  overflow-x: auto;
  scrollbar-width: none;
}

.filterbar::-webkit-scrollbar { display: none; }

.fchip {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  height: calc(1.9rem + 0.3rem * var(--density));
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.85rem;
  transition: border-color 0.15s, color 0.15s;
}

/* The caret on select / date chips. */
.fchip:not(.fchip-reset)::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 0.75rem;
  width: 0.32rem;
  height: 0.32rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  opacity: 0.6;
  pointer-events: none;
  transform: translateY(-70%) rotate(45deg);
}

.fchip select {
  height: 100%;
  max-width: 8rem;
  padding: 0 1.7rem 0 0.8rem;
  field-sizing: content; /* as wide as the chosen option, where supported */
  border: 0;
  border-radius: inherit;
  background: transparent;
  color: inherit;
  font: inherit;
  text-overflow: ellipsis;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.fchip select option { color: var(--text); background: var(--surface); }

.fchip-date { padding: 0 1.7rem 0 0.8rem; }

/* The date input is the chip's full-size, transparent hit area; the label text
   underneath shows 「日期」 or the chosen day. */
.fchip-date input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  opacity: 0;
  cursor: pointer;
}

.fchip-reset {
  justify-content: center;
  width: calc(1.9rem + 0.3rem * var(--density));
  padding: 0;
  color: var(--text-dim);
  font: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.fchip.is-set {
  border-color: var(--accent);
  background: var(--surface-raised);
  color: var(--accent);
  font-weight: 600;
}

.fchip:focus-within,
.fchip-reset:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fchip:hover { border-color: var(--accent); }

/* A select under 16px makes iOS Safari zoom the page on focus. */
@media (pointer: coarse) {
  .fchip select { font-size: 16px; }
}

.board-count {
  flex: none;
  margin: 0 0 0 auto;
  padding-left: 0.25rem;
  color: var(--text-dim);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- round-up cards: one rendering per density ---------------------------- */

.roundup-card {
  display: block;
  padding: calc(0.8rem * var(--density)) calc(var(--pad) * 0.9);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: inherit;
  text-decoration: none;
  transition: border-color 0.15s, background-color 0.15s;
}

.roundup-card:hover,
.roundup-card:focus-visible { border-color: var(--accent); }
.roundup-card:active { background: var(--surface-raised); }
.roundup-card.state-cancelled,
.roundup-card.state-done { opacity: 0.7; }

/* tight: one row — brand · venue · when · seats · state */
.rc-line { display: none; }

:root[data-density="tight"] .rc-full { display: none; }
:root[data-density="tight"] .rc-line {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: 0.55rem;
  min-height: 2.1rem;
}
:root[data-density="tight"] .roundup-card { padding: 0.3rem 0.7rem; border-radius: 10px; }

.rc-brands { display: flex; gap: 0.2rem; }
.rc-brands .badge { padding: 0 0.3rem; font-size: 0.65rem; line-height: 1.6; border-radius: 4px; }

.rc-venue {
  overflow: hidden;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rc-when,
.roundup-when {
  color: var(--accent);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rc-seats {
  font-size: 0.9rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* normal / wide */
.roundup-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
}

.roundup-title {
  margin: calc(0.4rem * var(--density)) 0 0.1rem;
  overflow: hidden;
  font-size: 1.05rem;
  line-height: 1.35;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rc-whenwhere,
.roundup-seats,
.rc-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 0.55rem;
  row-gap: 0.2rem;
  margin: 0;
}

.rc-whenwhere { flex-wrap: nowrap; font-size: 0.95rem; }
.roundup-where {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rc-full .roundup-card-top .badges { gap: 0.25rem; }
.rc-full .roundup-card-top .badge { padding: 0.05rem 0.4rem; font-size: 0.68rem; }
.roundup-seats { margin-top: 0.1rem; font-size: 0.85rem; }
.rc-foot { margin-top: calc(0.45rem * var(--density)); gap: 0.3rem; font-size: 0.8rem; }
.rc-foot .roundup-organizer { margin-right: 0.2rem; }

/* wide: the old airy card — each fact on its own line, title may wrap */
:root[data-density="wide"] .roundup-title { white-space: normal; }
:root[data-density="wide"] .rc-whenwhere { display: grid; row-gap: 0.1rem; }
:root[data-density="wide"] .roundup-where { white-space: normal; }

/* --- forms: compact rows, no card around every field ---------------------- */

.form { gap: calc(var(--gap) * 1.5); }
.field { gap: 0.2rem; }

.field input,
.field select,
.field textarea,
.target-name {
  min-height: calc(2.25rem + 0.5rem * var(--density));
  padding: calc(0.3rem + 0.2rem * var(--density)) 0.7rem;
  font-size: max(16px, 1rem); /* anything smaller makes iOS Safari zoom on focus */
}

.field-row-top { align-items: flex-start; }
.field-row > .field-grow { flex-grow: 2; }

/* --- venues: filter chips and the count share one row --------------------- */

.filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: calc(var(--gap) + 0.1rem);
}

.filter-row .filter { margin: 0; }
.filter-row .filter-options { margin-top: 0; gap: 0.4rem; }
.filter-row .chip { min-height: calc(1.9rem + 0.3rem * var(--density)); padding: 0 0.8rem; font-size: 0.85rem; }
.filter-row .filter-count { margin: 0 0 0 auto; }

.venue-card { padding: calc(0.8rem * var(--density)) calc(var(--pad) * 0.9); }

/* State chips are labels, not tap targets: they must not inherit the filter
   chip's tap-target height (which turned them into tall pills). */
.chip.chip-open,
.chip.chip-full,
.chip.chip-closed,
.chip.chip-cancelled,
.chip.chip-done {
  min-height: 0;
  padding: 0.05rem 0.55rem;
  font-size: 0.75rem;
  line-height: 1.5;
  cursor: inherit;
}

/* A grid item defaults to min-width:auto and would widen to its longest
   no-wrap line (a long room name pushed the page sideways at 390px). */
.roundup-list > li { display: grid; min-width: 0; }
.roundup-list > li > a { min-width: 0; }

/* Machine badges on a card: one + count in normal, two + count in wide. */
.rc-full .badge-extra,
.rc-full .more-wide { display: none; }
:root[data-density="wide"] .rc-full .badge-extra,
:root[data-density="wide"] .rc-full .more-wide { display: inline-block; }
:root[data-density="wide"] .rc-full .more-normal { display: none; }
.rc-foot .badge { padding: 0 0.4rem; font-size: 0.7rem; }
.rc-foot .tag { padding: 0 0.45rem; font-size: 0.7rem; }

/* The venue notice on /new: its lines are <p>s, which carried 1em margins each. */
.venue-notice { gap: 0.15rem; padding: calc(0.35rem + 0.25rem * var(--density)) 0.75rem; }
.venue-notice p { margin: 0; }
.detail .badges-group { margin-bottom: var(--gap); }
/* A page legend collapsed onto the title (the ⓘ on /groups) must not be
   clipped by the title's ellipsis. */
.appbar-title:has(.info-wrap) { overflow: visible; }

/* Tight card: the title on a second, quieter line (hidden in normal / wide, where .rc-full carries it). */
.rc-line-title { display: none; }
:root[data-density="tight"] .rc-line-title {
  display: block;
  margin-top: 0.1rem;
  font-size: 0.82rem;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- public groups (task 11.3, design D12) ------------------------------- */

/* 公開: a round-up or group reached through a public group. Dashed, so it reads
   as "about visibility", not as another group name. */
.badge-public {
  border-style: dashed;
  color: var(--accent);
}
.rc-line-title .badge-public {
  margin-right: 0.35rem;
  padding: 0 0.3rem;
  font-size: 0.65rem;
  line-height: 1.5;
  vertical-align: 0.05em;
}

/* The admin's switches on a group card: checkbox + label, the ⓘ beside it. */
.group-public { display: grid; gap: calc(var(--gap) * 0.5); }
.toggle-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; }
.toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.9rem;
  cursor: pointer;
}
.toggle input {
  width: 1.1rem;
  height: 1.1rem;
  min-height: 0;
  margin: 0;
  accent-color: var(--accent);
}

/* The directory: one row per group — name, counts, the one action. */
.directory-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--gap);
}
.directory-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--gap) * 0.75);
  padding: calc(var(--pad) * 0.75);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.directory-name {
  flex: 1 1 8rem;
  min-width: 0;
  overflow: hidden;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.directory-meta {
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.directory-signin { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 0.35rem; font-size: 0.8rem; }

/* --- privacy page -------------------------------------------------------- */

.privacy-intro {
  margin: 0 0 1rem;
}

.privacy-list {
  margin: 0;
  padding-left: 1.2rem;
  display: grid;
  gap: 0.35rem;
  line-height: 1.55;
}

.privacy-updated {
  font-size: 0.8rem;
}

/* The one-line 「隱私權政策」 link under the sign-in block and the account page. */
.privacy-footer {
  margin: 1rem 0 0;
  font-size: 0.8rem;
}

/* The landing's footer line: 使用說明 · 隱私權政策. */
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
}
.footer-links .text-link { font-size: inherit; }

/* --- guide page (使用說明) ---------------------------------------------- */

.guide-intro {
  margin: 0 0 var(--gap);
}

/* Three jump cards; one column on a phone, side by side when there is room. */
.guide-personas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  gap: var(--gap);
  margin-bottom: calc(var(--gap) * 1.5);
}

.guide-persona {
  display: grid;
  gap: 0.2rem;
  padding: calc(var(--pad) * 0.75);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  color: var(--text);
  text-decoration: none;
}
.guide-persona strong { color: var(--accent); }
.guide-persona span { font-size: 0.85rem; }

.guide-section { scroll-margin-top: calc(var(--bar, 3rem) + 0.5rem); }
.guide-section h2 { margin: 0 0 0.25rem; font-size: 1.1rem; }
.guide-lead { margin: 0 0 0.5rem; font-size: 0.85rem; }

.guide-steps,
.guide-sub {
  margin: 0;
  padding-left: 1.3rem;
  display: grid;
  gap: calc(var(--gap) * 0.6);
  line-height: var(--lh);
  overflow-wrap: anywhere;
}
.guide-sub { margin-top: 0.3rem; gap: 0.2rem; }
.guide-link { white-space: nowrap; }

.guide-faq { margin: 0; display: grid; gap: var(--gap); }
.guide-faq dt { font-weight: 600; }
.guide-faq dd { margin: 0.15rem 0 0; line-height: var(--lh); overflow-wrap: anywhere; }

.export-block {
  display: grid;
  gap: 0.4rem;
  justify-items: start;
}

/* The register button plus the ⓘ that explains Discord's webhook.incoming consent. */
.target-register {
  display: inline-flex;
  align-items: center;
  justify-self: start;
  max-width: 100%;
}

/* --- one-row fields (howish 2026-09-27) -------------------------------------
 * "We tend to put the info line different from the actual handle ... the UI
 * becomes sparse. Let's not do it." A control and the words that describe it
 * share ONE row: label left, control right (a checkbox: box first, words
 * after); a short live hint sits inline after the control in dim type; any
 * longer explanation is an ⓘ beside the label (`infoTip` / `.hint[data-i18n]`).
 * The row only breaks for an error line (`.field-error`, `.frow-full`), or —
 * inside `.frow-pair` — between whole label+control pairs, never between a
 * label and its control. */
.frow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: calc(var(--gap) * 0.8);
  row-gap: 0.2rem;
  min-width: 0;
}
.frow > .flabel,
.frow > span:first-child {
  flex: none;
  white-space: nowrap;
  font-size: 0.85rem;
  color: var(--text-dim);
}
.frow > :is(input, select, textarea, .chips, .fctl) {
  flex: 1 1 0;
  width: auto;
  min-width: 0;
}
.frow > :is(button, .button, .hint-inline, .info-wrap, .badge) { flex: none; }
.frow > .field-error,
.frow > .frow-full,
.frow-pair > .frow-full { flex-basis: 100%; }
/* A multi-line control (textarea, wrapping chips): the label sits level with
   its first line instead of its middle. */
.frow-top { align-items: flex-start; }
.frow-top > .flabel,
.frow-top > span:first-child { padding-top: calc(0.3rem + 0.2rem * var(--density)); }
.hint-inline {
  font-size: 0.8rem;
  color: var(--text-dim);
  white-space: nowrap;
}
/* Two controls in one field (date + time): side by side, never stacked. */
.fctl { display: flex; gap: 0.4rem; min-width: 0; }
.fctl > * { flex: 1 1 0; min-width: 0; }
/* Two or three short fields on one line; a whole pair wraps when they do not fit. */
.frow-pair {
  display: flex;
  flex-wrap: wrap;
  column-gap: calc(var(--gap) * 1.5);
  row-gap: calc(var(--gap) * 1.5);
  min-width: 0;
}
.frow-pair > .frow { flex: 1 1 0; min-width: max-content; }
.frow input[type="date"] { min-width: 8.6em; }
.frow input[type="time"] { min-width: 6.2em; }
.frow input[type="number"] { min-width: 3.5em; }
/* Inside a pair each field's natural width is label + its control's minimum,
   so a pair wraps only when both truly cannot share the line. */
.frow-pair input[type="date"] { width: 8.6em; }
.frow-pair input[type="time"] { width: 6.2em; }
.frow-pair input[type="number"] { width: 3.5em; }
.frow-pair select { width: 6em; }
/* An error or continuation line takes the row's width, never sets it. */
.frow > .field-error,
.frow > .frow-full,
.frow-pair > .frow-full { contain: inline-size; }
/* Checkbox rows: the box first, the words after, the ⓘ beside them. */
.frow-check { display: flex; align-items: center; gap: 0.45rem; cursor: pointer; }
.frow-check input { flex: none; width: 1.1rem; height: 1.1rem; min-height: 0; margin: 0; accent-color: var(--accent); }
/* An ⓘ on a row opens its popover under the whole row, from the row's left
   edge — wherever the ⓘ sits on the row, the popover stays on screen. */
.frow,
.frow-pair { position: relative; }
.frow .info-wrap,
.frow-pair > .frow { position: static; }
/* The /new venue notice: one compact line under the venue select. */
.venue-line { display: flex; flex-wrap: wrap; align-items: center; gap: 0.2rem 0.6rem; font-size: 0.8rem; color: var(--text-dim); }
.venue-line .badge { color: var(--warn); }

/* /groups: an action pushed to the end of its row (a member's 設為管理員). */
.row-end { margin-left: auto; }
.target-row > .target-name { flex: 1 1 0; min-width: 5em; }
.target-meta { max-width: 9em; overflow: hidden; text-overflow: ellipsis; }
.target-actions { column-gap: 0.4rem; }
.paste-form { margin-top: 0; font-size: 0.9rem; }
.paste-form input { min-width: 8em; }

/* /r: 推送到 Discord — group name, its channel chips and the button, one wrapping row. */
.push-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
/* Long names must never widen the page (the server allows 60-char names). Flex
   items default to min-width:auto, i.e. their content width, so max-width alone
   is circular; min-width:0 is what lets them shrink and truncate. */
.push-row, .share-block { min-width: 0; max-width: 100%; }
.share-block { display: flex; }
.push-group-name { font-size: 0.85rem; color: var(--text-dim); flex: 0 1 auto; min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.push-row .chip { flex: 0 1 auto; min-width: 0; max-width: 100%; }
.push-row .chip span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
select.share-group { flex: 1 1 8rem; min-width: 0; max-width: 100%; }
.badge-group { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: bottom; }
.booking-row { align-items: center; margin: calc(var(--gap) * 0.75) 0; }
.edit-form { gap: var(--gap); }

/* The board's empty state: its ways out share one line under the message. */
.empty-links { justify-content: center; }

/* /venues detail: a short fact's name and value on one row. */
.fact-row > h3.flabel { margin: 0; font-weight: 600; }
.fact-row > p { margin: 0; }
.fact-row > .fact-value { flex: 1 1 0; min-width: 0; }
.fact-row > .badges { margin: 0; }
/* /g: the prompt beside the two sign-in buttons it describes. */
.sign-in-row { align-items: center; }
.invite-group .hint-inline { font-weight: 400; margin-left: 0.5em; }
