/* ── Tokens ─────────────────────────────────────────────────────────── */
:root {
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f0f2f5;
  --border: #e2e5ea;
  --border-strong: #cdd2da;
  --text: #14181f;
  --text-dim: #5c6673;
  --text-faint: #8b95a3;
  --accent: #0a7c6b;
  --accent-hover: #096355;
  --accent-soft: #e3f3f0;
  --danger: #b4342c;
  --danger-soft: #fbeae9;
  --warn: #8a6410;
  --warn-soft: #fdf3dd;
  --gold: #a5791b;
  --on-accent: #ffffff;
  --on-gold: #ffffff;
  --radius: 12px;
  --radius-sm: 8px;
  --shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 4px 14px rgba(16, 24, 40, 0.06);
  --shadow-lg: 0 8px 32px rgba(16, 24, 40, 0.14);
  --safe-b: env(safe-area-inset-bottom, 0px);
  /* One family, not two: this gets loaded on hotel wifi and roaming data, and a
     second face would be a second round trip for hierarchy that weight and size
     already give. The system stack behind it is what shows if the font never
     arrives, so nothing depends on it. */
  --font: "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  /* The app is light, whatever the phone is set to. Without pinning this,
     form controls and scrollbars would still be drawn dark on a dark phone. */
  color-scheme: light;
}

/* Kept, but no longer follows the phone: the committee asked for one look.
   Add data-theme="dark" to <html> to bring it back. */
:root[data-theme="dark"] {
  --bg: #0e1116;
  --surface: #171b22;
  --surface-2: #1f242c;
  --border: #272d37;
  --border-strong: #3a424e;
  --text: #e8ecf1;
  --text-dim: #9aa5b4;
  --text-faint: #6b7685;
  --accent: #2fb39c;
  --accent-hover: #46c4ae;
  --accent-soft: #122b28;
  --danger: #f0837a;
  --danger-soft: #2c1917;
  --warn: #d9b25e;
  --warn-soft: #2a2416;
  --gold: #d9b25e;
  --on-accent: #06231f;
  --on-gold: #16202b;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 14px rgba(0, 0, 0, 0.3);
  --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.55);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overscroll-behavior-y: contain;
}

/* Jakarta sets wide by default, which reads loose at heading sizes on a phone.
   Pulling the tracking in is what makes a heading look set rather than typed. */
h1, h2, h3, h4 {
  font-weight: 700;
  letter-spacing: -0.018em;
  text-wrap: balance;
}
h1 { letter-spacing: -0.028em; }

/* Anything that lines up in a column reads as a column. */
.pill, .n, .lb-n, .lb-pos, .star-n, .codecell, td.num, th.num { font-variant-numeric: tabular-nums; }

button, input, select, textarea { font-family: inherit; }

body { padding-bottom: calc(76px + var(--safe-b)); }
body.no-nav { padding-bottom: var(--safe-b); }

/* ── Layout ─────────────────────────────────────────────────────────── */
.wrap { max-width: 720px; margin: 0 auto; padding: 0 16px; }
.stack > * + * { margin-top: 12px; }
.row { display: flex; align-items: center; gap: 10px; }
.row.between { justify-content: space-between; }
.grow { flex: 1; min-width: 0; }
.hidden { display: none !important; }

.appbar {
  position: sticky; top: 0; z-index: 30;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
  padding: calc(env(safe-area-inset-top, 0px) + 10px) 16px 10px;
}
.appbar h1 { font-size: 17px; font-weight: 700; margin: 0; letter-spacing: -0.025em; }
.appbar .sub { font-size: 12px; color: var(--text-faint); margin-top: 1px; }

section.view { padding-top: 16px; }
h2 { font-size: 15px; font-weight: 650; margin: 0 0 10px; letter-spacing: -0.01em; }
.muted { color: var(--text-dim); font-size: 13px; }
.faint { color: var(--text-faint); font-size: 12px; }

/* ── Cards ──────────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  box-shadow: var(--shadow);
}
.card + .card { margin-top: 12px; }
.card h3 { margin: 0 0 4px; font-size: 15px; font-weight: 650; }

/* ── Controls ───────────────────────────────────────────────────────── */
button, .btn {
  font: inherit; font-weight: 600; font-size: 15px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
  padding: 11px 16px;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  text-decoration: none;
  transition: background 0.12s, border-color 0.12s, opacity 0.12s;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
button:active, .btn:active { transform: translateY(0.5px); }
button:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); }
.btn-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, var(--border)); }
.btn-block { width: 100%; }
.btn-lg { padding: 15px 20px; font-size: 16px; }
.btn-sm { padding: 7px 11px; font-size: 13px; border-radius: 6px; }

label { display: block; font-size: 13px; font-weight: 600; color: var(--text-dim); margin-bottom: 5px; }
input[type="text"], input[type="password"], input[type="number"], select, textarea {
  font: inherit; font-size: 16px; /* 16px stops iOS zooming the page on focus */
  width: 100%;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--text);
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: 1px;
  border-color: var(--accent);
}
.field + .field { margin-top: 12px; }

/* display:none can stop a file input opening on some mobile browsers, so hide
   it without removing it from the layout tree. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
label.btn { margin-bottom: 0; font-size: 15px; color: var(--text); }
label.btn.btn-lg { font-size: 16px; }

/* ── Notices ────────────────────────────────────────────────────────── */
.notice { padding: 11px 13px; border-radius: var(--radius-sm); font-size: 13.5px; line-height: 1.45; border: 1px solid transparent; }
.notice-info { background: var(--accent-soft); color: var(--text); border-color: color-mix(in srgb, var(--accent) 25%, transparent); }
.notice-warn { background: var(--warn-soft); color: var(--text); border-color: color-mix(in srgb, var(--warn) 30%, transparent); }
.notice-error { background: var(--danger-soft); color: var(--text); border-color: color-mix(in srgb, var(--danger) 30%, transparent); }

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 650; letter-spacing: 0.02em;
  padding: 3px 9px; border-radius: 999px;
  background: var(--surface-2); color: var(--text-dim);
  border: 1px solid var(--border);
}
.pill-ok { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
.pill-warn { background: var(--warn-soft); color: var(--warn); border-color: transparent; }
.pill-err { background: var(--danger-soft); color: var(--danger); border-color: transparent; }

/* ── Bottom nav ─────────────────────────────────────────────────────── */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  /* Was repeat(4, 1fr), left over from the Contest tab. Removing that tab left
     a quarter of the bar empty on the right. Auto columns track however many
     buttons are actually there. */
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-top: 1px solid var(--border);
  padding-bottom: var(--safe-b);
}
.tabbar button {
  border: 0; background: none; border-radius: 0;
  flex-direction: column; gap: 3px;
  padding: 9px 4px 8px;
  font-size: 10.5px; font-weight: 600; color: var(--text-faint);
}
.tabbar button svg { width: 22px; height: 22px; stroke-width: 1.7; }
.tabbar button[aria-current="page"] { color: var(--accent); }

/* ── Photo grid ─────────────────────────────────────────────────────── */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 6px; }
.grid.lg { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.tile {
  position: relative; aspect-ratio: 1; overflow: hidden;
  border-radius: var(--radius-sm); background: var(--surface-2);
  border: 1px solid var(--border); cursor: pointer; padding: 0;
}
.tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tile .cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 14px 6px 4px;
  font-size: 10.5px; font-weight: 600; color: #fff; text-align: left;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.72));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tile.selected { border-color: var(--accent); box-shadow: 0 0 0 2.5px var(--accent); }
.tile .mark {
  position: absolute; top: 6px; right: 6px;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent); color: var(--on-accent);
  display: grid; place-items: center; font-size: 12px; font-weight: 700;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}
/* A tile holds the photo and its vote control, so the photo itself is the
   button rather than the whole tile — a button inside a button is invalid. */
.tile-open {
  display: block; width: 100%; height: 100%;
  padding: 0; border: 0; background: none; cursor: pointer;
}
.tile-open:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }

/* Vote control. Sits above the caption gradient, thumb-sized on a phone. */
.tile .star {
  position: absolute; right: 5px; bottom: 5px;
  display: flex; align-items: center; gap: 3px;
  min-height: 30px; padding: 4px 8px;
  border: 0; border-radius: 999px;
  background: rgba(0, 0, 0, 0.5); color: #fff;
  font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums;
  cursor: pointer; backdrop-filter: blur(3px);
}
.tile .star:disabled { cursor: default; opacity: .85; }
/* While the captain is choosing the final five the heart stops being a
   control, but the number is exactly what they are choosing on — so it stays,
   dimmed and unpressable rather than hidden. */
.tile .star.readonly { pointer-events: none; background: rgba(0, 0, 0, 0.62); }
.tile .star.readonly.on { background: color-mix(in srgb, var(--accent) 88%, #000); }
.tile .star.on { background: var(--accent); color: var(--on-accent); }
.tile .star .star-i { font-size: 14px; line-height: 1; }
.tile .star.hidden { display: none; }

/* Already in the group's contest entry. */
.tile.selected .entered { display: none; }
.tile .entered {
  position: absolute; top: 5px; right: 5px;
  width: 22px; height: 22px; border-radius: 50%;
  background: var(--gold, #c9a227); color: var(--on-gold, #24201a);
  display: grid; place-items: center; font-size: 12px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}

/* The like count on a chosen photo, in the final-five list. */
.pick-votes {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  padding: 3px 8px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 12px; font-weight: 700; color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.pick-votes.top { background: var(--accent-soft); border-color: transparent; color: var(--accent); }

/* How many of your votes are spent, at a glance. */
.votebar { display: flex; gap: 5px; margin-top: 12px; }
.votebar > i {
  flex: 1; height: 7px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
}
.votebar > i.on { background: var(--accent); border-color: var(--accent); }

.tile.video::after {
  content: "\25B6"; position: absolute; top: 6px; left: 7px;
  font-size: 11px; color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}

/* ── Upload queue ───────────────────────────────────────────────────── */
.qitem { display: flex; gap: 10px; align-items: center; padding: 9px 0; border-bottom: 1px solid var(--border); }
.qitem:last-child { border-bottom: 0; }
.qthumb { width: 42px; height: 42px; border-radius: 6px; object-fit: cover; background: var(--surface-2); flex: none; }
.qname { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar { height: 4px; border-radius: 999px; background: var(--surface-2); overflow: hidden; margin-top: 5px; }
.bar > i { display: block; height: 100%; background: var(--accent); border-radius: 999px; transition: width 0.25s ease-out; }

/* ── Camera ─────────────────────────────────────────────────────────── */
/* The preview always fills the whole surface and the controls float on top of
   it, so nothing reserves space from the image. That keeps the frame as large
   as the screen allows and centred, on any phone and either orientation. */
.camera {
  position: fixed; inset: 0; z-index: 100; background: #000;
  /* Stop the browser interpreting a pinch as page zoom, which used to scale the
     whole app and push the shutter off screen. */
  touch-action: none;
  overscroll-behavior: none;
  -webkit-user-select: none; user-select: none;
}
.camera video {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;          /* what you see is what gets captured */
  background: #000;
  touch-action: none; pointer-events: none;
}

.camera .cam-top {
  position: absolute; top: 0; left: 0; right: 0; z-index: 2;
  padding: calc(env(safe-area-inset-top, 0px) + 14px) 14px 24px;
  display: flex; justify-content: space-between; align-items: flex-start; gap: 10px;
  background: linear-gradient(rgba(0, 0, 0, 0.65), transparent);
  pointer-events: none;
}
.camera .cam-top > * { pointer-events: auto; }

.cam-pill {
  display: inline-flex; align-items: center;
  font-size: 12px; font-weight: 650; color: #fff;
  padding: 6px 12px; border-radius: 999px;
  background: rgba(0, 0, 0, 0.55); backdrop-filter: blur(8px);
  max-width: 60vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Finish is a filled button — the conventional place for it, and far enough
   from the edge to miss the notch and the swipe-back gesture. */
.cam-done {
  font-size: 14px; font-weight: 650;
  padding: 9px 18px; border-radius: 999px;
  background: rgba(255, 255, 255, 0.95); color: #000; border: 0;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.4);
  flex: none;
}

.camera .cam-bottom {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  padding: 40px 24px calc(20px + var(--safe-b));
  display: flex; align-items: center; justify-content: space-between;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.7) 45%);
  pointer-events: none;
}
.camera .cam-bottom > * { pointer-events: auto; }

.shutter {
  width: 72px; height: 72px; border-radius: 50%;
  background: #fff; border: 4px solid rgba(255, 255, 255, 0.35);
  box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 2px 12px rgba(0, 0, 0, 0.5);
  padding: 0; flex: none;
}
.shutter:active { transform: scale(0.93); }
.cam-side {
  width: 52px; height: 52px; border-radius: 50%; flex: none;
  background: rgba(255, 255, 255, 0.18); border: 0; color: #fff;
  padding: 0; overflow: hidden; font-size: 21px;
  display: grid; place-items: center;
  backdrop-filter: blur(8px);
}
.cam-thumb { background: rgba(255, 255, 255, 0.1); }
.cam-side img { width: 100%; height: 100%; object-fit: cover; }

.flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; z-index: 3; }
.flash.fire { animation: flash 0.28s ease-out; }
@keyframes flash { 0% { opacity: 0.85; } 100% { opacity: 0; } }

/* Landscape: the wasted space is at the sides, so the controls move there —
   still overlaid, so the preview keeps the full width and stays centred. */
@media (orientation: landscape) and (max-height: 600px) {
  .camera .cam-top {
    right: auto; bottom: 0; width: auto;
    flex-direction: column; align-items: flex-start; justify-content: flex-start;
    padding: calc(env(safe-area-inset-top, 0px) + 12px) 28px 12px
             calc(env(safe-area-inset-left, 0px) + 12px);
    background: linear-gradient(to right, rgba(0, 0, 0, 0.65), transparent);
  }
  .camera .cam-bottom {
    top: 0; left: auto; bottom: 0; width: auto;
    flex-direction: column-reverse;
    padding: 12px calc(env(safe-area-inset-right, 0px) + 14px) 12px 32px;
    background: linear-gradient(to left, rgba(0, 0, 0, 0.7) 45%, transparent);
  }
  .shutter { width: 62px; height: 62px; }
  .cam-side { width: 44px; height: 44px; font-size: 18px; }
  .cam-pill { max-width: 34vw; }
}

/* Review: the shot just taken, held until it is accepted or discarded. */
.cam-review { position: absolute; inset: 0; z-index: 4; background: #000; display: flex; flex-direction: column; }
.cam-review-stage { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
.cam-review-stage img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }
.cam-review .cam-top { position: absolute; }
.cam-review-actions {
  display: flex; gap: 12px; flex: none;
  padding: 16px 16px calc(20px + var(--safe-b));
  background: #000;
}
@media (orientation: landscape) and (max-height: 600px) {
  .cam-review { flex-direction: row; }
  .cam-review-actions {
    flex-direction: column; width: 160px; justify-content: center;
    padding: 12px calc(env(safe-area-inset-right, 0px) + 12px);
  }
  .cam-review .cam-top { flex-direction: row; padding-bottom: 12px; }
}

/* ── Lightbox ───────────────────────────────────────────────────────── */
.lightbox { position: fixed; inset: 0; z-index: 90; background: rgba(0, 0, 0, 0.96); display: flex; flex-direction: column; }
.lightbox .lb-bar {
  padding: calc(env(safe-area-inset-top, 0px) + 12px) 16px 12px;
  display: flex; justify-content: space-between; align-items: center;
  /* Stated rather than inherited: this bar is white-on-dark whatever the app
     theme is, and a stray background here is invisible text. */
  background: transparent;
  color: #fff; font-size: 13px; font-weight: 600; flex: none;
}
.lightbox .lb-bar button { background: rgba(255, 255, 255, 0.18); border: 0; color: #fff; font-weight: 600; }
.lightbox .lb-bar > span { color: rgba(255, 255, 255, 0.75); letter-spacing: 0.01em; }
.lightbox .lb-bar .btn-danger { color: #ff9a91; }

.lb-stage { position: relative; flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; }
.lb-stage video {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  display: block; background: #000;
}
.lb-stage img {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  object-fit: contain; display: block;
  transition: transform 0.18s ease-out, opacity 0.15s;
  user-select: none; -webkit-user-select: none; -webkit-touch-callout: none;
}

/* Arrows sit clear of the photo edges and stay thumb-reachable on a phone. */
.lb-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(0, 0, 0, 0.45); color: #fff;
  font-size: 26px; line-height: 1; font-weight: 400;
  display: grid; place-items: center;
  backdrop-filter: blur(6px);
}
.lb-nav:first-of-type { left: 10px; }
.lb-nav:last-of-type { right: 10px; }
@media (hover: none) { .lb-nav { opacity: 0.55; } }

.lightbox .lb-foot {
  padding: 12px 16px calc(16px + var(--safe-b));
  color: #d6dbe2; font-size: 12.5px; text-align: center; flex: none;
}

/* ── Tables / results ───────────────────────────────────────────────── */
.tablewrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.tablewrap > table { width: auto; min-width: 100%; }
.tablewrap th, .tablewrap td { white-space: nowrap; }
.tablewrap td:first-child { white-space: normal; min-width: 9em; }
th { text-align: left; font-size: 11.5px; font-weight: 650; text-transform: uppercase; letter-spacing: 0.045em; color: var(--text-faint); padding: 0 10px 7px 0; white-space: nowrap; }
td { padding: 9px 10px 9px 0; border-top: 1px solid var(--border); vertical-align: middle; }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; padding-right: 0; }
.rank { display: inline-grid; place-items: center; width: 24px; height: 24px; border-radius: 6px; background: var(--surface-2); font-size: 12px; font-weight: 700; }
.rank.r1 { background: var(--gold); color: var(--on-gold); }
.rank.r2 { background: var(--border-strong); color: var(--text); }
.rank.r3 { background: color-mix(in srgb, var(--gold) 40%, var(--surface-2)); }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.stat { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 13px; }
.stat .v { font-size: 24px; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.stat .k { font-size: 11.5px; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.04em; margin-top: 1px; }

/* ── Ballot ─────────────────────────────────────────────────────────── */
.album { border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.album + .album { margin-top: 12px; }
.album.picked { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.album-head { display: flex; align-items: center; gap: 10px; padding: 12px 14px; }
.album-strip { display: grid; grid-template-columns: repeat(5, 1fr); gap: 2px; background: var(--border); }
.album-strip button { border: 0; padding: 0; border-radius: 0; aspect-ratio: 1; overflow: hidden; background: var(--surface-2); }
.album-strip img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rankbtn { min-width: 76px; }
.rankbtn.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

.spinner { width: 17px; height: 17px; border: 2px solid var(--border-strong); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.7s linear infinite; flex: none; }
@keyframes spin { to { transform: rotate(360deg); } }

.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(90px + var(--safe-b)); z-index: 200;
  background: var(--text); color: var(--bg);
  padding: 11px 17px; border-radius: 999px;
  font-size: 13.5px; font-weight: 600; box-shadow: var(--shadow-lg);
  max-width: calc(100vw - 32px); text-align: center;
  animation: rise 0.2s ease-out;
}
@keyframes rise { from { opacity: 0; transform: translate(-50%, 10px); } }

.empty { text-align: center; padding: 40px 20px; color: var(--text-faint); font-size: 14px; }

/* ── Filter chips ───────────────────────────────────────────────────── */
.chips { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px; -webkit-overflow-scrolling: touch; }
.chips::-webkit-scrollbar { display: none; }
.chip {
  flex: none; white-space: nowrap;
  font-size: 13px; font-weight: 600;
  padding: 7px 13px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  cursor: pointer;
}
.chip.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.chip .n { opacity: .65; margin-left: 5px; font-variant-numeric: tabular-nums; }

.day-head {
  font-size: 12px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text-faint); margin: 18px 0 8px; grid-column: 1 / -1;
}
.day-head:first-child { margin-top: 0; }

/* ── Leaderboard ────────────────────────────────────────────────────── */
.lb-row { display: grid; grid-template-columns: 22px 1fr auto; gap: 10px; align-items: center; padding: 9px 0; border-bottom: 1px solid var(--border); }
.lb-row:last-child { border-bottom: 0; }
.lb-pos { font-weight: 700; color: var(--text-faint); font-size: 13px; font-variant-numeric: tabular-nums; }
/* Was .lb-bar, which the lightbox's own top bar also answered to. Being later
   in the file this rule won, and painted that bar --surface-2 — invisible under
   its white text once the app went light. */
.lb-meter { height: 6px; border-radius: 999px; background: var(--surface-2); overflow: hidden; margin-top: 5px; }
.lb-meter > i { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.lb-n { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ── Notices ────────────────────────────────────────────────────────── */
.notice-board { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
