/* Campoff — night camp palette
   night #000000, smoke #141414, ember #FF7A3D, moss #7FA98C, bone #EDE7DC, ash #8B948F */

:root {
  --night: #000000;
  --smoke: #141414;
  --smoke-2: #1F1F1F;
  --ember: #FF7A3D;
  --ember-deep: #C24A1A;
  --moss: #7FA98C;
  --bone: #EDE7DC;
  --ash: #8B948F;
  --danger: #E0604C;
  --radius: 14px;
}

* { box-sizing: border-box; }
/* The page itself is pinned to the screen and never scrolls or bounces.
 * Only #app (the screens) scrolls. iPhone home-screen apps (iOS 26) misplace
 * fixed bottom bars on pages that scroll the body, so nothing does. */
/* --app-h: app.js, the real screen height on an installed iPhone app */
html, body { height: var(--app-h, 100%); overflow: hidden; }
html { background: var(--night); overscroll-behavior: none; }
body {
  margin: 0;
  display: flex; flex-direction: column;
  background: var(--night);
  color: var(--bone);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

/* A black strip over the status bar, so content scrolling under the pinned
 * header never shows behind the clock and battery. */
body::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; z-index: 35;
  height: env(safe-area-inset-top); background: var(--night);
}

/* The scroll box: all the room between the notch and the tab bar
 * (or the home bar when there is no tab bar). */
#app { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
/* Home and the running Campoff are fixed like an app screen: no scrolling,
 * no bounce, even if you drag. Only the long screens (Stats, League...) scroll. */
body[data-screen="home"] #app, body[data-screen="session"] #app { overflow: hidden; touch-action: none; }
/* Exactly as tall as the scroll box, so short screens fit and cannot scroll. */
.screen { min-height: 100%; display: flex; flex-direction: column; max-width: 480px; margin: 0 auto; padding: 0 20px; }
[hidden] { display: none !important; }

.brand {
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
  font-weight: 800; font-size: 2.6rem; letter-spacing: -0.02em; margin: 0.2em 0 0;
}
.brand.small { font-size: 1.2rem; }
.tagline { color: var(--ash); margin-top: 4px; margin-bottom: 32px; }

.ember-mark {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--ember);
  box-shadow: 0 0 22px var(--ember), 0 0 44px rgba(255,122,61,.35);
  animation: breathe 3.2s ease-in-out infinite;
}
@keyframes breathe { 50% { box-shadow: 0 0 10px var(--ember), 0 0 20px rgba(255,122,61,.2); opacity: .8; } }
@media (prefers-reduced-motion: reduce) { .ember-mark { animation: none; } }

.auth-wrap { margin: auto 0; padding: 48px 0; display: flex; flex-direction: column; gap: 12px; }
.auth-wrap h2 { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; }

.field { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.field span { font-size: .85rem; color: var(--ash); }
.field input {
  background: var(--smoke); color: var(--bone);
  border: 1px solid var(--smoke-2); border-radius: var(--radius);
  padding: 14px 16px; font-size: 1.05rem; outline: none;
}
.field input:focus-visible { border-color: var(--ember); }
#auth-code, #modal-input { letter-spacing: .25em; font-variant-numeric: tabular-nums; text-transform: uppercase; }

.btn {
  border: 1px solid var(--smoke-2); background: var(--smoke); color: var(--bone);
  border-radius: var(--radius); padding: 14px 18px; font-size: 1rem; cursor: pointer;
  transition: transform .06s ease, background .2s;
}
.btn:active { transform: scale(.98); }
.btn.primary { background: var(--ember); border-color: var(--ember); color: #1A0E06; font-weight: 700; }
.btn.ghost { background: transparent; }
.btn.danger { color: var(--danger); border-color: rgba(224,96,76,.35); }
.btn.tiny { padding: 8px 14px; font-size: .85rem; border-radius: 10px; }
.btn:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }

.error { color: var(--danger); min-height: 1.2em; font-size: .9rem; }
.hint { color: var(--ash); font-size: .9rem; line-height: 1.5; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 0 8px;
  position: sticky; top: 0; z-index: 30; background: var(--night);
}
/* Header and switch pinned together; only what is under them scrolls. */
.screen-head { position: sticky; top: 0; z-index: 30; background: var(--night); padding-bottom: 8px; }
.screen-head .topbar { position: static; }
.iconbtn { background: none; border: none; color: var(--ash); font-size: 1.3rem; cursor: pointer; padding: 6px 10px; }
.iconbtn:focus-visible { outline: 2px solid var(--ember); border-radius: 8px; }

/* -------- home -------- */
.home-main { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px 0 48px; }
.start-ring {
  width: 240px; height: 240px; border-radius: 50%;
  background: radial-gradient(circle at 50% 42%, #241812 0%, var(--smoke) 62%);
  border: 2px solid var(--ember-deep);
  color: var(--bone); cursor: pointer;
  box-shadow: 0 0 40px rgba(255,122,61,.16), inset 0 0 30px rgba(255,122,61,.08);
  transition: box-shadow .3s, transform .06s;
}
.start-ring:active { transform: scale(.97); }
.start-ring:focus-visible { outline: 3px solid var(--ember); outline-offset: 4px; }
.start-label { font-family: "Bricolage Grotesque", sans-serif; font-weight: 800; font-size: 1.75rem; line-height: 1.15; }
.ritual { color: var(--ash); font-size: .85rem; letter-spacing: .04em; margin-top: 14px; }
.ritual:empty { display: none; }
/* phone only: on a computer or tablet Start cannot be pressed */
.start-ring:disabled { cursor: default; opacity: .4; box-shadow: none; }
.start-ring:disabled:active { transform: none; }
.ritual.phone-only { color: var(--bone); max-width: 260px; text-align: center; line-height: 1.4; }
/* the invitation: two ember rings ripple out from Start, one after the other,
   and the label breathes. Only transform and opacity move, so the phone's
   graphics chip does the work and the battery barely notices. */
.start-ring { position: relative; }
.start-ring::before, .start-ring::after {
  content: ""; position: absolute; inset: -2px; border-radius: 50%;
  border: 2px solid var(--ember); opacity: 0; pointer-events: none;
  animation: start-ripple 3.6s cubic-bezier(.2,.6,.3,1) infinite;
}
.start-ring::after { animation-delay: 1.8s; }
.start-label { display: inline-block; animation: start-breathe 3.6s ease-in-out infinite; }
@keyframes start-ripple {
  0%   { transform: scale(1);   opacity: .55; }
  70%  { opacity: 0; }
  100% { transform: scale(1.3); opacity: 0; }
}
@keyframes start-breathe {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.05); }
}
.start-ring:disabled::before, .start-ring:disabled::after, .start-ring:disabled .start-label { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .start-ring::before, .start-ring::after, .start-label { animation: none; }
}
/* the same ring, small, in every camp. Same ripple, same breathing label. */
.go-ring { flex: none; width: 92px; height: 92px; padding: 0; margin: 4px 6px 0 0; box-shadow: 0 0 22px rgba(255,122,61,.16), inset 0 0 16px rgba(255,122,61,.08); }
.go-ring .start-label { font-size: .85rem; }

/* -------- live embers on Home --------
   One green dot per person at the fire right now: the same moss green and
   glow as .presence.on, so a dot here means exactly what a green light in
   the Friends list means. The sky sits behind Start and never takes a tap.
   Each dot only fades (opacity), so the battery barely notices. */
#screen-home { position: relative; }
#screen-home .topbar, #screen-home .ib-banner, #screen-home .cl-banner, #screen-home .nh-card, #screen-home .home-main { position: relative; z-index: 1; }
.live-sky { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 0; }
.live-dot { position: absolute; display: flex; flex-direction: column; align-items: center; gap: 4px; transform: translate(-50%, -4px); }
.live-dot i {
  width: 7px; height: 7px; border-radius: 50%; background: var(--moss);
  box-shadow: 0 0 8px var(--moss), 0 0 16px rgba(127,169,140,.4);
  animation: live-flicker 2.8s ease-in-out infinite;
}
.live-dot span { font-size: .7rem; color: var(--bone); white-space: nowrap; max-width: 96px; overflow: hidden; text-overflow: ellipsis; }
.live-count {
  position: absolute; right: 20px; bottom: 16px; z-index: 1; margin: 0;
  display: flex; align-items: center; gap: 6px; color: var(--ash); font-size: .8rem;
}
.live-count i { width: 7px; height: 7px; border-radius: 50%; background: var(--moss); box-shadow: 0 0 8px var(--moss); }
.live-count b { color: var(--bone); font-weight: 600; font-variant-numeric: tabular-nums; }
@keyframes live-flicker { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .live-dot i { animation: none; } }

.link-btn { background: none; border: 0; color: var(--bone); opacity: .7; text-decoration: underline; font-size: .95rem; padding: 10px; cursor: pointer; }
.groups-head { display: flex; align-items: center; justify-content: space-between; }
.groups-head h3 { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; margin: 12px 0; }
.group-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.group-item {
  background: var(--smoke); border-radius: var(--radius); padding: 14px 16px;
  display: flex; justify-content: space-between; align-items: center; cursor: pointer;
}
.group-item small { color: var(--ash); }

/* -------- streak flame --------
   Amber, right of the name, with a number. Never green (that is presence,
   left of the name). Dimmed at 40% until today has burned: own view only. */
.topbar-right { display: flex; align-items: center; gap: 10px; }
.flame { display: inline-flex; align-items: center; gap: 4px; flex: none; }
.flame svg { width: 16px; height: 16px; fill: var(--ember); display: block; }
.flame b { font-size: .9rem; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--bone); }
.flame.dim svg { opacity: .4; }
.flame.small svg { width: 14px; height: 14px; }
.flame.small b { font-size: .82rem; }
.streak-note { margin-top: 10px; text-align: center; }

/* The flame on the home screen is a button: it opens the rules. Big enough to
   tap on a phone, quiet enough not to compete with Start Campoff. */
button.flame {
  background: none; border: none; cursor: pointer;
  padding: 6px 8px; margin: -6px -4px -6px 0; border-radius: 10px;
}
button.flame:focus-visible { outline: 2px solid var(--ember); }
/* Zero state, own screen only: grey flame, grey zero, no amber at all. It is a
   door into the feature, never a mark of failure. The board never shows this. */
.flame.zero svg { fill: var(--ash); opacity: .55; }
.flame.zero b { color: var(--ash); }

/* -------- streak rules sheet -------- */
.sheet {
  position: fixed; inset: 0; background: rgba(0,0,0,.7);
  display: flex; align-items: flex-end; justify-content: center; z-index: 55;
  padding: 16px;
}
.sheet-card {
  background: var(--smoke); border-radius: 20px; padding: 24px 22px;
  width: 100%; max-width: 440px; max-height: 88dvh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  margin-bottom: env(safe-area-inset-bottom);
}
.sheet-flame svg { width: 34px; height: 34px; fill: var(--ember); display: block; }
.sheet-card h3 { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; font-size: 1.35rem; margin: 0; }
.sheet-lead { color: var(--bone); font-size: .95rem; line-height: 1.55; margin: 0; }
.sheet-rules { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.sheet-rules li { color: var(--ash); font-size: .9rem; line-height: 1.6; padding-left: 14px; border-left: 2px solid var(--smoke-2); }
.sheet-rules b { color: var(--bone); font-weight: 600; }
.sheet-close-note { color: var(--ash); font-size: .88rem; font-style: italic; margin: 6px 0 2px; }

/* -------- session: near-black, one dim timer -------- */
.session-screen { background: #000; justify-content: center; }
.session-inner { display: flex; flex-direction: column; align-items: center; gap: 18px; padding: 40px 0; }
/* 268 viewBox units around a 200 unit ring: the ring stays 230px on screen
 * and the +xp labels fit outside it. Turned by its inner <g>, not by CSS. */
.session-ring { width: 308px; max-width: 100%; height: auto; aspect-ratio: 1; overflow: visible; }
.ring-bg { fill: none; stroke: #101010; stroke-width: 3; }
.ring-fg {
  fill: none; stroke: var(--ember-deep); stroke-width: 3; stroke-linecap: round;
  stroke-dasharray: 565.5; stroke-dashoffset: 565.5; opacity: .55;
  /* no transition on purpose: the ring steps at 30 s and then every 2
     minutes, and each step is an instant jump (battery list, question A) */
}
.session-time {
  position: absolute; font-variant-numeric: tabular-nums;
  font-size: 2.2rem; color: #5A5148; letter-spacing: .06em;
}
/* The time sits in the middle of the ring itself, not of the whole column,
 * so a note line under the ring never pushes it down. */
.session-dial { position: relative; width: 308px; max-width: 100%; }
.session-dial .session-ring { display: block; width: 100%; }
.session-time { top: 50%; left: 50%; transform: translate(-50%, -50%); }
.session-hint { color: #33302B; font-size: .8rem; text-align: center; max-width: 300px; }
.session-hint.mt-note { color: #6B655D; } /* readable, still grey: never red */
/* End: drag the knob from left to right. The word fades as the knob covers it. */
.end-slide {
  position: relative; width: 260px; max-width: 100%; height: 58px; padding: 4px;
  border: 1px solid #262626; border-radius: 29px;
  display: flex; align-items: center; justify-content: center;
  -webkit-user-select: none; user-select: none;
}
.end-slide-label { color: #6B655D; font-size: 1rem; opacity: calc(1 - var(--end-p, 0)); }
.end-slide-knob {
  position: absolute; left: 4px; top: 4px; width: 48px; height: 48px; padding: 0 0 4px;
  border-radius: 50%; border: 1px solid #333; background: #1A1A1A; color: #8A8277;
  font-size: 1.6rem; line-height: 1; cursor: grab; touch-action: none;
  transition: transform .2s; -webkit-tap-highlight-color: transparent;
}
.end-slide-knob.dragging { transition: none; cursor: grabbing; }
.end-slide-knob:focus-visible { outline: 2px solid var(--ember-deep); outline-offset: 2px; }

.done-time { font-size: 2.4rem; font-variant-numeric: tabular-nums; font-family: "Bricolage Grotesque", sans-serif; margin: 0; }

/* -------- group board -------- */
.group-title { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; }
.tabs { display: flex; gap: 6px; padding: 8px 0 16px; }
.tabs button {
  flex: 1; background: transparent; border: 1px solid var(--smoke-2); color: var(--ash);
  border-radius: 10px; padding: 9px 0; cursor: pointer; font-size: .85rem;
}
.tabs button.active { background: var(--smoke); color: var(--bone); border-color: var(--ember-deep); }
.board { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.board-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--smoke); border-radius: var(--radius); padding: 13px 16px;
}
.board-row.me { border: 1px solid var(--ember-deep); }
.presence {
  width: 11px; height: 11px; border-radius: 50%; flex: none;
  background: #3A3A3A;
}
.presence.on {
  background: var(--moss);
  box-shadow: 0 0 10px var(--moss), 0 0 20px rgba(127,169,140,.4);
}
.board-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-time { font-variant-numeric: tabular-nums; color: var(--bone); }
.board-rank { color: var(--ash); width: 1.4em; font-size: .85rem; }

/* Friends / Camps toggle. A filled two segment control, so it reads as a
 * switch between two views rather than as the period tabs below it. */
.seg {
  display: flex; gap: 4px; background: var(--smoke); border-radius: 12px;
  padding: 4px; margin: 12px 0 4px;
}
.seg button {
  flex: 1; background: transparent; border: 0; color: var(--ash);
  border-radius: 9px; padding: 9px 0; cursor: pointer;
  font-family: inherit; font-size: .9rem; -webkit-user-select: none; user-select: none;
}
.seg button.active { background: var(--smoke-2); color: var(--bone); }

/* The quiet "You" marker on your own row. Never a badge, never a colour:
 * it says which row is yours and nothing more. */
.you-mark { color: var(--ash); font-size: .78rem; font-weight: 600; letter-spacing: .02em; }

/* The friends list reuses .board and .board-row exactly, so a row here and a
 * row on a camp board are the same object. The only difference is that no
 * .board-rank is ever drawn: this list is ordered, but it has no positions. */
#friends-list { padding-bottom: 8px; }

/* ---- choosing your friends ---- */
.board-row.tappable { cursor: pointer; }
.board-row.tappable:active { background: var(--smoke-2); }
.section-head { color: var(--ash); font-size: .82rem; font-weight: 600; letter-spacing: .04em; margin: 18px 0 8px; }
#from-camps-list { flex: none; }
/* The plus: round, quiet, the ember only as an outline. Big enough for a thumb. */
.add-plus {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--ember-deep); color: var(--ember);
  font-size: 1.1rem; line-height: 1; padding: 0; cursor: pointer; font-family: inherit;
}
.add-plus:disabled { opacity: .5; cursor: default; }
.add-plus:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.add-plus.done { border-color: transparent; color: var(--moss); cursor: default; }
.plus-slot:empty { display: none; }
.show-all {
  background: none; border: 0; color: var(--ash); font-family: inherit; font-size: .88rem;
  padding: 10px 0; cursor: pointer; text-align: left;
}
.toast-action {
  background: none; border: 0; color: var(--ember); font-weight: 700; font-family: inherit;
  font-size: .9rem; margin-left: 14px; padding: 4px 2px; cursor: pointer;
}

.camp-top { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 8px; }
.camp-top-text { flex: 1; min-width: 0; }
.invite-box { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.invite-box p { margin: 0; }
.invite-box b { color: var(--ember); letter-spacing: .2em; }
/* the room at the end keeps your pinned row off this button */
.camp-leave { padding: 16px 0 64px; }

.settings-wrap { display: flex; flex-direction: column; gap: 10px; padding: 12px 0 32px; }
.settings-wrap hr { border: none; border-top: 1px solid var(--smoke-2); width: 100%; margin: 16px 0; }

/* -------- modal + toast -------- */
.modal {
  position: fixed; inset: 0; background: rgba(0,0,0,.65);
  display: flex; align-items: center; justify-content: center; padding: 24px; z-index: 50;
}
.modal-card { background: var(--smoke); border-radius: 18px; padding: 22px; width: 100%; max-width: 380px; }
.modal-card h3 { margin: 0 0 8px; font-family: "Bricolage Grotesque", sans-serif; }
.modal-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 8px; }

.toast {
  position: fixed; bottom: 28px; left: 50%; transform: translateX(-50%);
  background: var(--smoke-2); color: var(--bone); border-radius: 12px;
  padding: 12px 20px; z-index: 60; font-size: .9rem; max-width: 90vw;
}

/* ---------------- camp description and counting window ---------------- */
.field textarea, .field select {
  background: var(--smoke); color: var(--bone);
  border: 1px solid var(--smoke-2); border-radius: var(--radius);
  padding: 14px 16px; font-size: 1.05rem; outline: none;
  font-family: inherit; resize: vertical;
}
.field textarea:focus-visible, .field select:focus-visible { border-color: var(--ember); }
.window-row { display: flex; gap: 10px; }
.window-row .field { flex: 1; min-width: 0; }
.field input[type="date"] { width: 100%; min-width: 0; min-height: 52px; padding: 14px 10px; font-size: 1rem; font-family: inherit; color-scheme: dark; }
.camp-desc { margin: 4px 0 0; color: var(--bone); white-space: pre-wrap; overflow-wrap: anywhere; }

/* -------- camp screen: period, hours, your days, you pinned -------- */
.camp-facts { margin: 4px 0 8px; display: flex; flex-direction: column; gap: 4px; }
.camp-facts > div { display: flex; gap: 10px; align-items: baseline; }
.camp-facts dt { color: var(--ash); font-size: .85rem; width: 4.2em; flex: none; }
.camp-facts dd { margin: 0; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

.days-chart { background: var(--smoke); border-radius: var(--radius); padding: 14px 16px 10px; margin: 14px 0 6px; }
.days-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.days-title { margin: 0; font-size: .95rem; font-weight: 600; }
.days-total { color: var(--ash); font-size: .85rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
.days-plot { display: flex; gap: 6px; margin-top: 12px; }
/* the one scale label: the top of the plot, a clean whole hour */
.days-scale { color: var(--ash); font-size: .72rem; font-variant-numeric: tabular-nums; flex: none; line-height: 1; }
.days-scroll { flex: 1; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.days-scroll::-webkit-scrollbar { display: none; }
.days-bars { display: flex; gap: 2px; min-width: 100%; }
.day-col {
  flex: 1 0 14px; max-width: 44px; display: flex; flex-direction: column; align-items: center;
  background: transparent; border: 0; padding: 0; margin: 0; cursor: pointer;
  font-family: inherit; color: var(--ash); -webkit-tap-highlight-color: transparent;
}
/* the plot area: 96px tall, one hairline baseline, the bar grows up from it */
.day-plot { width: 100%; height: 96px; display: flex; align-items: flex-end; justify-content: center; border-bottom: 1px solid var(--smoke-2); }
.day-bar { width: 100%; max-width: 24px; background: var(--ember); border-radius: 4px 4px 0 0; }
.day-col.future .day-plot { border-bottom-style: dotted; }
.day-col.picked .day-plot { background: rgba(237, 231, 220, .05); border-radius: 4px 4px 0 0; }
.day-col:focus-visible { outline: 2px solid var(--ember); outline-offset: 1px; border-radius: 4px; }
.day-label { font-size: .68rem; line-height: 1; padding-top: 5px; height: 1.3em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.day-col.today .day-label { color: var(--bone); font-weight: 700; }
.day-col.future .day-label { opacity: .5; }
.days-tip { margin: 8px 0 0; font-size: .85rem; min-height: 1.3em; }

/* You, at the bottom of the scroll box, while your row is out of sight. Height
 * 0: it floats over the list, so showing it never moves anything. */
.board-pinned { flex: none; position: sticky; bottom: 0; z-index: 5; height: 0; }
.board-pinned .board-row {
  position: absolute; left: 0; right: 0; bottom: 6px;
  background: #1A1A1A; box-shadow: 0 0 0 6px var(--night);
}

/* -------- camp goal: one bar everyone fills together -------- */
.goal-card {
  background: var(--smoke); border: 1px solid #3a2416; border-radius: 16px;
  padding: 14px 16px 12px; margin: 12px 0 4px;
}
.goal-head { display: flex; justify-content: space-between; align-items: baseline; }
.goal-label { color: var(--ash); font-size: .8rem; }
.goal-pct { color: var(--ember); font-size: .85rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.goal-num {
  margin: 2px 0 10px; font-family: "Bricolage Grotesque", sans-serif; font-weight: 600;
  font-size: 1.6rem; font-variant-numeric: tabular-nums;
}
.goal-of { color: var(--ash); font-family: system-ui, -apple-system, sans-serif; font-weight: 400; font-size: 1rem; }
.goal-bar { height: 12px; background: var(--smoke-2); border-radius: 6px; overflow: hidden; }
.goal-fill { height: 100%; background: var(--ember); border-radius: 6px; transition: width .6s ease; }
.goal-left { margin: 8px 0 0; color: var(--ash); font-size: .8rem; text-align: right; font-variant-numeric: tabular-nums; }
.goal-card.reached { border-color: var(--ember-deep); }
.goal-card.reached .goal-left { color: var(--ember); }
.goal-reward { margin: 10px 0 0; padding-top: 10px; border-top: 1px solid var(--smoke-2); font-size: .9rem; overflow-wrap: anywhere; }
.goal-reward .goal-label { margin-right: 6px; }

.goal-party {
  background: var(--smoke); border: 1px solid var(--ember-deep); border-radius: 16px;
  padding: 18px 16px 16px; margin: 12px 0 4px; text-align: center;
}
.goal-party .ember-mark { margin: 0 auto 6px; }
.goal-party h3 { margin: 0 0 4px; font-family: "Bricolage Grotesque", sans-serif; }
.goal-party .hint { margin: 0; }
.goal-party-reward { margin: 8px 0 0; color: #FFB58F; overflow-wrap: anywhere; }
.goal-party .btn { margin-top: 12px; }

/* session end: what this fire did for each camp goal */
.done-goals { display: flex; flex-direction: column; gap: 8px; width: 100%; margin: 6px 0 4px; }
.done-goal { background: var(--smoke); border-radius: 12px; padding: 10px 12px; text-align: left; }
.done-goal-line { margin: 0 0 6px; font-size: .9rem; overflow-wrap: anywhere; }
.done-goal .goal-bar { height: 8px; }
.done-goal-pct { margin: 6px 0 0; color: var(--ember); font-size: .8rem; font-variant-numeric: tabular-nums; }

/* ---------------- notifications panel (Paziņojumi), rendered by push.js ----
 * Same smoke card, same hint colour and same checkbox rows as the rest of
 * the settings screen, so it reads as part of the app and not as a new tab. */
.np-panel { display: flex; flex-direction: column; gap: 10px; }
.np-h { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; font-size: 1.1rem; margin: 0; }
.np-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  background: var(--smoke); border-radius: var(--radius); padding: 13px 16px; cursor: pointer;
}
.np-label { display: flex; flex-direction: column; gap: 3px; flex: 1; }
.np-label small { color: var(--ash); font-size: .82rem; line-height: 1.45; }
.np-row input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; flex: none;
  width: 46px; height: 28px; border-radius: 14px; background: var(--smoke-2);
  border: 1px solid var(--smoke-2); position: relative; cursor: pointer; margin: 0;
  transition: background .2s;
}
.np-row input[type="checkbox"]::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
  border-radius: 50%; background: var(--ash); transition: transform .2s, background .2s;
}
.np-row input[type="checkbox"]:checked { background: var(--ember-deep); border-color: var(--ember-deep); }
.np-row input[type="checkbox"]:checked::after { transform: translateX(18px); background: var(--bone); }
.np-row input[type="checkbox"]:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.np-select {
  flex: none; font: inherit; font-size: .9rem; color: var(--bone);
  background: var(--smoke-2); border: 1px solid var(--smoke-2); border-radius: 10px;
  padding: 6px 10px; cursor: pointer;
}
.np-select:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.np-trust { margin: 2px 0 0; font-style: italic; }

/* -------- notifications: the switches on the home screen (nh-) --------
   One quiet card, one line per switch: this is an offer, not the main event,
   and Start Campoff stays the biggest thing on the screen. The switch is the
   same shape as the np-row one in Settings, only smaller. */
.nh-card {
  background: var(--smoke); border-radius: var(--radius);
  padding: 4px 14px; margin: 12px 0 4px;
  display: flex; flex-direction: column;
}
.nh-h {
  display: flex; align-items: center; gap: 7px;
  color: var(--ash); font-size: .78rem; letter-spacing: .03em; text-transform: uppercase;
  margin: 0; padding: 10px 0 8px; border-bottom: 1px solid var(--smoke-2);
}
.nh-bell { width: 14px; height: 14px; fill: var(--ember); flex: none; display: block; }
.nh-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 0; cursor: pointer; font-size: .9rem;
  transition: opacity .25s, transform .25s;
}
.nh-row + .nh-row { border-top: 1px solid var(--smoke-2); }
.nh-label { flex: 1; }
.nh-row input[type="checkbox"] {
  appearance: none; -webkit-appearance: none; flex: none;
  width: 38px; height: 22px; border-radius: 11px; background: var(--smoke-2);
  border: 1px solid var(--smoke-2); position: relative; cursor: pointer; margin: 0;
  transition: background .2s;
}
.nh-row input[type="checkbox"]::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 50%; background: var(--ash); transition: transform .2s, background .2s;
}
.nh-row input[type="checkbox"]:checked { background: var(--ember-deep); border-color: var(--ember-deep); }
.nh-row input[type="checkbox"]:checked::after { transform: translateX(16px); background: var(--bone); }
.nh-row input[type="checkbox"]:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.nh-row input[type="checkbox"]:disabled { cursor: default; opacity: .7; }
.nh-row.nh-leaving { opacity: 0; transform: translateY(-4px); }
.nh-foot { color: var(--ash); font-size: .75rem; margin: 0 0 8px; }
#nh-error { margin: 0 0 6px; }
#nh-error:empty { display: none; }
@media (prefers-reduced-motion: reduce) { .nh-row { transition: none; } }

/* -------- install banner and its steps sheet (ib-) --------
   A quiet row on the home screen, like the nh- card, with one ember icon:
   an offer, not the main event. It cannot be closed; tapping opens the sheet. */
.ib-banner {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--smoke); border: 1px solid var(--ember-deep); border-radius: var(--radius);
  color: var(--bone); font: inherit; font-size: .9rem; text-align: left;
  padding: 11px 14px; margin: 12px 0 4px; cursor: pointer;
}
.ib-banner:active { transform: scale(.99); }
.ib-banner:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.ib-icon svg { width: 20px; height: 20px; fill: var(--ember); display: block; }
.ib-label { flex: 1; }
.ib-chev { color: var(--ash); font-size: 1.3rem; line-height: 1; }
.ib-wrap {
  position: fixed; inset: 0; background: rgba(0,0,0,.72);
  display: flex; align-items: flex-end; justify-content: center;
  z-index: 61; padding: 16px;
  opacity: 1; transition: opacity .26s ease;
}
.ib-wrap.ib-fade { opacity: 0; }
.ib-wrap.ib-hidden { display: none; }
.ib-card {
  background: var(--smoke); border-radius: 20px; padding: 24px 22px;
  width: 100%; max-width: 440px; max-height: 88dvh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  margin-bottom: env(safe-area-inset-bottom);
  animation: nb-rise .34s cubic-bezier(.22,.7,.3,1) both;
}
.ib-title {
  font-family: "Bricolage Grotesque", sans-serif; font-weight: 600;
  font-size: 1.3rem; line-height: 1.25; margin: 0;
}
.ib-text { color: var(--bone); font-size: .95rem; line-height: 1.55; margin: 0; }
#ib-body { display: flex; flex-direction: column; gap: 12px; }
.ib-sub { color: var(--ash); font-size: .78rem; letter-spacing: .03em; text-transform: uppercase; margin: 6px 0 0; }
.ib-steps { margin: 0; padding-left: 1.3em; display: flex; flex-direction: column; gap: 10px; font-size: .95rem; line-height: 1.5; }
.ib-steps li::marker { color: var(--ember); font-weight: 600; }
.ib-steps b { font-weight: 600; }
.ib-glyph { width: 18px; height: 18px; fill: var(--ember); vertical-align: -3px; }
.ib-key { color: var(--ember); font-weight: 700; padding: 0 2px; }
.ib-note { color: var(--ash); font-size: .85rem; line-height: 1.45; margin: 0; }
@media (prefers-reduced-motion: reduce) {
  .ib-card { animation: none; }
  .ib-wrap { transition: none; }
}

/* -------- notifications: the one card that offers them (nb-) --------
   The same bottom sheet shape as the streak rules, with its own class names,
   so nothing here can move that sheet. It appears once when the app opens,
   for people who have not answered yet, and never during a session. */
.nb-wrap {
  position: fixed; inset: 0; background: rgba(0,0,0,.72);
  display: flex; align-items: flex-end; justify-content: center;
  z-index: 60; padding: 16px;
  opacity: 1; transition: opacity .26s ease;
}
.nb-wrap.nb-fade { opacity: 0; }
.nb-wrap.nb-hidden { display: none; }
.nb-card {
  background: var(--smoke); border-radius: 20px; padding: 24px 22px;
  width: 100%; max-width: 440px; max-height: 88dvh; overflow-y: auto;
  display: flex; flex-direction: column; gap: 12px;
  margin-bottom: env(safe-area-inset-bottom);
  animation: nb-rise .34s cubic-bezier(.22,.7,.3,1) both;
}
@keyframes nb-rise { from { transform: translateY(20px); opacity: 0; } }
.nb-bell svg { width: 32px; height: 32px; fill: var(--ember); display: block; }
.nb-title {
  font-family: "Bricolage Grotesque", sans-serif; font-weight: 600;
  font-size: 1.3rem; line-height: 1.25; margin: 0;
}
.nb-text { color: var(--bone); font-size: .95rem; line-height: 1.55; margin: 0; }
.nb-text b { font-weight: 600; }
/* An empty error line must not push the buttons down the card. */
#nb-error:empty { display: none; }
.nb-actions { display: flex; flex-direction: column; gap: 10px; }
.nb-never {
  background: none; border: none; color: var(--ash); cursor: pointer;
  font-size: .82rem; padding: 6px 2px; text-decoration: underline;
  text-underline-offset: 3px; align-self: center;
}
.nb-never:hover { color: var(--bone); }
.nb-never:focus-visible { outline: 2px solid var(--ember); border-radius: 6px; }
@media (prefers-reduced-motion: reduce) {
  .nb-card { animation: none; }
  .nb-wrap { transition: none; }
}

/* ---------------- quick start (Ātrais starts) in settings ----------------
 * Same look as the notifications panel above it. */
.qs-panel { display: flex; flex-direction: column; gap: 10px; }
.qs-steps { margin: 0; padding-left: 1.3em; }
.qs-steps li { margin: 4px 0; }
.qs-steps b, #qs-open { color: var(--bone); overflow-wrap: anywhere; }

/* ---------------- wallet (wl-) ----------------
   Same night palette as everything else. The balance card is the one warm
   surface on the screen, so the eye finds the hours first. */
.wl-home {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: var(--smoke); border: 1px solid var(--smoke-2); border-radius: var(--radius);
  padding: 14px 16px; margin: 0 0 8px; color: var(--bone); font: inherit; text-align: left; cursor: pointer;
}
.wl-home:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.wl-home-label { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; }
.wl-home-hours { flex: 1; color: var(--ash); font-size: .9rem; }
.wl-home-hours b { color: var(--ember); font-variant-numeric: tabular-nums; }
.wl-home-go { color: var(--ash); font-size: 1.4rem; line-height: 1; }

.wl-balance {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  margin: 8px 0 4px; padding: 22px 16px; border-radius: 20px; text-align: center;
  background: linear-gradient(135deg, var(--ember) 0%, var(--ember-deep) 100%);
  color: #1A0E06;
}
.wl-balance-label { font-size: .95rem; font-weight: 600; opacity: .8; }
.wl-balance-hours {
  font-family: "Bricolage Grotesque", sans-serif; font-weight: 800;
  font-size: 3rem; line-height: 1.1; font-variant-numeric: tabular-nums;
}
.wl-balance-sub { font-size: .85rem; opacity: .75; }

.wl-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 14px 12px; padding-bottom: 24px; }
.wl-tile {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  background: none; border: 0; padding: 0; color: var(--bone); font: inherit; cursor: pointer; min-width: 0;
}
.wl-tile:focus-visible { outline: 2px solid var(--ember); outline-offset: 4px; border-radius: var(--radius); }
.wl-logo {
  width: 100%; aspect-ratio: 1; border-radius: var(--radius); overflow: hidden;
  background: var(--smoke); border: 1px solid var(--smoke-2);
  display: flex; align-items: center; justify-content: center;
  font-family: "Bricolage Grotesque", sans-serif; font-weight: 800; font-size: 2rem; color: var(--ash);
}
.wl-logo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.wl-logo-plus { color: var(--ember); font-weight: 400; font-size: 2.6rem; border-style: dashed; }
.wl-tile-name { font-size: .88rem; text-align: center; line-height: 1.3; overflow-wrap: anywhere; }

.wl-title { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; font-size: 1.6rem; margin: 4px 0 2px; overflow-wrap: anywhere; }
.wl-have { color: var(--ember); margin: 0 0 12px; font-variant-numeric: tabular-nums; }
.wl-list { list-style: none; margin: 0; padding: 0 0 32px; display: flex; flex-direction: column; }
.wl-row {
  display: flex; align-items: center; gap: 12px; padding: 14px 0;
  border-bottom: 1px solid var(--smoke-2); cursor: pointer;
}
.wl-thumb {
  width: 64px; height: 64px; flex: none; border-radius: 12px; object-fit: cover;
  background: var(--smoke); border: 1px solid var(--smoke-2);
}
.wl-row-words { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wl-row-words b { font-weight: 600; overflow-wrap: anywhere; }
.wl-row-words span { color: var(--ash); font-size: .9rem; }
.wl-row-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; flex: none; }
.wl-price { color: var(--ember); font-variant-numeric: tabular-nums; }
.wl-get {
  border: 1px solid var(--ember); color: var(--ember); border-radius: 999px;
  padding: 4px 14px; font-size: .85rem; font-weight: 600;
}
.wl-get.off { border-color: var(--smoke-2); color: var(--ash); }

.wl-hero {
  width: calc(100% + 40px); margin: 0 -20px 12px; aspect-ratio: 4 / 3; object-fit: cover;
  background: var(--smoke); display: block;
}
.wl-reward-meta { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; color: var(--ash); }
.wl-reward-meta b { color: var(--ember); font-size: 1.15rem; font-variant-numeric: tabular-nums; flex: none; }
.wl-company-line { color: var(--ash); margin: 0 0 8px; }
.wl-desc { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.6; margin: 0 0 12px; }
.wl-link { color: var(--ember); font-weight: 600; text-decoration: underline; overflow-wrap: anywhere; }
.wl-action {
  position: sticky; bottom: 0; margin-top: auto; padding: 16px 0 calc(16px + env(safe-area-inset-bottom));
  background: linear-gradient(to bottom, transparent, var(--night) 30%);
  display: flex; flex-direction: column; gap: 4px;
}
.wl-action .btn:disabled { opacity: .45; cursor: default; }
.wl-action .hint { text-align: center; margin: 4px 0 0; }

.wl-code-box {
  display: flex; flex-direction: column; gap: 8px; margin: 12px 0;
  background: var(--smoke); border: 1px solid rgba(255,122,61,.38); border-radius: var(--radius); padding: 14px 16px;
}
.wl-code-box .hint { margin: 0; font-size: .82rem; }
.wl-code-label { color: var(--ash); font-size: .85rem; }
.wl-code-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.wl-code {
  color: var(--ember); font-size: 1.25rem; letter-spacing: .04em; font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere; user-select: all; -webkit-user-select: all;
}
.wl-mine-item { border-bottom: 1px solid var(--smoke-2); padding-bottom: 6px; }
.wl-mine-item .wl-row { border-bottom: 0; cursor: default; padding-bottom: 0; }

.wl-claim-item { display: flex; align-items: center; gap: 12px; background: var(--night); border-radius: var(--radius); padding: 12px; }
.wl-claim-item div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wl-claim-item span { color: var(--ash); font-size: .9rem; }
.wl-center { text-align: center; margin: 4px 0 0; }
.wl-trap { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
#screen-wallet .topbar, #screen-myrewards .topbar { gap: 8px; }
#wl-biz-sheet .field input { background: var(--night); }
#wl-biz-form, #wl-biz-done { display: flex; flex-direction: column; gap: 10px; }

/* ---------------- leagues and xp (leagues brief 4, 5, 7) ---------------- */
.session-screen { position: relative; }
/* milestone marks on the ring: as quiet as the hints until reached */
.xp-dot { fill: #2A2622; }
.xp-label { fill: #3A352F; font-size: 10.5px; font-family: system-ui, -apple-system, sans-serif; letter-spacing: .02em; }
.xp-mark.on .xp-dot { fill: var(--ember-deep); }
.xp-mark.on .xp-label { fill: var(--ember-deep); }
.xp-mark .xp-dot { transform-box: fill-box; transform-origin: center; }
.xp-mark.pulse .xp-dot { animation: xp-pulse .6s ease-out 1; }
@keyframes xp-pulse { 50% { transform: scale(1.6); } }
@media (prefers-reduced-motion: reduce) { .xp-mark.pulse .xp-dot { animation: none; } }

/* the i in the top right of the session screen */
.xp-info {
  position: absolute; top: 12px; right: 4px; z-index: 2;
  width: 32px; height: 32px; border-radius: 50%;
  background: transparent; border: 1px solid #2A2622; color: #5A5148;
  font: italic 600 .95rem Georgia, serif; line-height: 1; cursor: pointer;
}
.xp-info:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }

/* the bar chart: extra xp by session length */
.xp-chart { display: flex; align-items: flex-end; gap: 10px; height: 168px; padding: 6px 2px 0; }
.xp-col { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; gap: 6px; }
.xp-col b { font-size: .8rem; font-weight: 600; color: var(--ash); font-variant-numeric: tabular-nums; white-space: nowrap; }
.xp-bar { width: 100%; max-width: 44px; border-radius: 6px 6px 2px 2px; background: var(--smoke-2); min-height: 4px; }
.xp-col span { font-size: .78rem; color: var(--ash); white-space: nowrap; }
.xp-col.on .xp-bar { background: var(--ember); }
.xp-col.on b { color: var(--ember); }
.xp-totals { font-size: .8rem; margin: 0; }

/* done screen */
.done-xp { color: var(--ember); font-size: 1.3rem; font-weight: 700; margin: 4px 0 0; font-variant-numeric: tabular-nums; }
.done-xp-note { margin: 0; }
.done-flame { height: 20px; width: auto; vertical-align: -5px; margin-right: 6px; }

/* home: league card and the Monday result card */
.lg-home-icon svg { width: 16px; height: 16px; fill: var(--ember); display: block; }
.lg-home-line b { color: var(--ember); font-variant-numeric: tabular-nums; }
.lg-result {
  position: relative; display: grid; grid-template-columns: auto 1fr; column-gap: 14px; row-gap: 4px; align-content: center;
  background: var(--smoke); border: 1px solid var(--ember-deep); border-radius: var(--radius);
  padding: 14px 44px 14px 16px; margin: 8px 0;
}
.lg-result-flame { grid-row: span 2; align-self: center; height: 56px; width: auto; }
.lg-result-title { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; font-size: 1.05rem; }
.lg-result-line { color: var(--ash); font-size: .9rem; line-height: 1.45; }
.lg-result-x { position: absolute; top: 6px; right: 6px; background: none; border: 0; color: var(--ash); font-size: 1.4rem; width: 36px; height: 36px; cursor: pointer; }

/* league screen */
/* all leagues in one row, scrolled sideways by finger; runs to the screen edges */
.lg-ladder {
  position: relative; /* so a flame's offsetLeft is measured from this row */
  display: flex; align-items: flex-end; gap: 6px; margin: 10px -20px 6px; padding: 4px 20px 2px;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.lg-ladder::-webkit-scrollbar { display: none; }
.lg-step { flex: 0 0 64px; display: flex; flex-direction: column; align-items: center; gap: 6px; color: var(--ash); font-size: .78rem; scroll-snap-align: center; }
.lg-flame { display: block; height: 44px; width: auto; opacity: .6; }
.lg-step.me { flex-basis: 92px; color: var(--ember); font-weight: 600; }
.lg-step.me .lg-flame { height: 80px; opacity: 1; filter: drop-shadow(0 0 10px rgba(255, 122, 61, .35)); }
/* not reached yet: the shape only, no material, no name */
.lg-step.locked .lg-flame { opacity: .13; filter: brightness(0) invert(1); }
.lg-week { text-align: center; margin: 4px 0 12px; font-size: .85rem; }
.lg-week b { color: var(--bone); font-weight: 600; font-variant-numeric: tabular-nums; }
.lg-room { padding-bottom: 16px; }
/* My league / All campers, above the flames */
.lg-scope { margin-top: 4px; }
/* All campers: all ten flames, one size, side by side, no names */
.lg-ladder.even { justify-content: space-between; gap: 2px; margin: 14px 0 12px; padding: 0; overflow: visible; }
.lg-ladder.even .lg-step { flex: 1 1 0; min-width: 0; }
.lg-ladder.even .lg-flame { height: 30px; opacity: 1; max-width: 100%; object-fit: contain; }
.board-flame { height: 22px; width: 22px; object-fit: contain; flex: none; }
.lg-gap { list-style: none; text-align: center; color: var(--ash); letter-spacing: .2em; font-size: .8rem; }
.lg-none { text-align: center; margin-top: 8px; }
.lg-room .board-row.lg-up { box-shadow: inset 3px 0 0 var(--ember); }
.lg-room .board-row.me { position: sticky; top: calc(var(--head-h, 0px) + 8px); bottom: 8px; z-index: 1; background: #1A1A1A; }
.lg-divider { list-style: none; color: var(--ash); font-size: .78rem; letter-spacing: .04em; padding: 2px 4px; display: flex; align-items: center; gap: 8px; }
.lg-divider::after { content: ""; flex: 1; height: 1px; background: var(--smoke-2); }
.lg-divider.up { color: var(--ember); }
.lg-friend { color: var(--moss); font-size: .75rem; margin-left: 6px; }
.lg-empty { display: flex; flex-direction: column; gap: 12px; align-items: stretch; margin-top: 16px; }

/* ---------------- tab bar ----------------
 * Five thin ember icons, no words. The open tab gets a thin ember ring,
 * like the logo. Hidden while Campoff runs (and before sign in). */
/* A plain row under the scroll box, not position: fixed, so it can never float. */
.tabbar {
  position: relative; flex-shrink: 0; z-index: 40;
  display: flex; justify-content: space-around; align-items: center;
  /* the icons sit low, just clear of the home bar line, not a whole safe area above it */
  --tab-foot: max(6px, calc(env(safe-area-inset-bottom) - 14px));
  height: calc(52px + var(--tab-foot));
  padding: 0 max(12px, calc((100vw - 480px) / 2 + 12px)) var(--tab-foot);
  background: var(--smoke); border-top: 1px solid var(--smoke-2);
}
.tab {
  width: 44px; height: 44px; border-radius: 50%; padding: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 1px solid transparent;
  -webkit-tap-highlight-color: transparent;
}
.tab svg {
  width: 23px; height: 23px; fill: none; stroke: var(--ember);
  stroke-width: 1.2; stroke-linecap: round; stroke-linejoin: round;
}
.tab.on { border-color: var(--ember); }
.tab:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
/* the bar keeps the home bar space itself, so the screens above it need no extra room */
body.with-tabbar { padding-bottom: 0; }
body.with-tabbar .screen { padding-bottom: 16px; }
body.with-tabbar .wl-action { padding-bottom: 16px; }
body.with-tabbar .toast { bottom: calc(84px + env(safe-area-inset-bottom)); }
.tab-title { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; font-size: 1.2rem; }
#lg-help { margin-left: auto; }

/* ---------------- stats ---------------- */
.st-head { display: flex; flex-direction: column; gap: 2px; margin: 14px 0 12px; }
.st-total { font-family: "Bricolage Grotesque", sans-serif; font-weight: 600; font-size: 1.8rem; font-variant-numeric: tabular-nums; }
.st-delta { color: var(--ash); font-size: .85rem; }
.st-delta.up { color: var(--moss); }
.st-chart { margin-bottom: 4px; }
.st-plot { display: flex; align-items: flex-end; gap: 3px; height: 110px; }
.st-hours .st-plot, #st-weekdays .st-plot { height: 70px; }
/* the whole slot is the tap target; the drawn bar is a slim stick in its middle */
.st-bar {
  flex: 1; min-width: 0; height: 100%; padding: 0; border: 0; cursor: pointer;
  background: none; position: relative; -webkit-tap-highlight-color: transparent;
}
.st-bar::before {
  content: ""; position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
  width: min(55%, 14px); min-width: 3px; height: var(--h);
  background: var(--ember); border-radius: 3px 3px 1px 1px;
}
.st-bar.zero::before { background: var(--smoke-2); }
.st-bar.future::before { opacity: .35; }
.st-labels { display: flex; gap: 3px; margin-top: 4px; }
.st-labels span { flex: 1; min-width: 0; text-align: center; color: var(--ash); font-size: .7rem; white-space: nowrap; overflow: visible; }
.st-tip { min-height: 1.4em; margin: 4px 0 0; font-size: .82rem; }
.st-kpis { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 10px 0 4px; }
.st-kpis div { background: var(--smoke); border-radius: var(--radius); padding: 12px 14px; display: flex; flex-direction: column; gap: 2px; }
.st-kpis span { color: var(--ash); font-size: .78rem; }
.st-kpis b { font-size: 1.1rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.st-lengths { display: flex; flex-direction: column; gap: 8px; }
.st-len { display: grid; grid-template-columns: 96px 1fr 28px; align-items: center; gap: 10px; font-size: .85rem; }
.st-len span { color: var(--ash); }
.st-len i { display: block; height: 4px; border-radius: 3px; background: linear-gradient(to right, var(--ember) var(--w), var(--smoke-2) var(--w)); }
.st-len b { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }

/* ---------------- new flame unlock ----------------
 * Full screen moment when someone reaches a league for the first time.
 * Charge (grey silhouette shakes, light gathers) → burst (flash, shock ring,
 * the real flame opens from its middle, sparks) → shine → name. app.js
 * playFlameUnlock() drives it by adding classes; --fc is the league colour. */
.fu {
  position: fixed; inset: 0; z-index: 80; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 18px; overflow: hidden;
  background: radial-gradient(ellipse at 50% 42%, color-mix(in srgb, var(--fc) 16%, #000) 0%, #000 62%);
  opacity: 0; transition: opacity .35s ease;
  padding: env(safe-area-inset-top) 16px env(safe-area-inset-bottom);
}
.fu.in { opacity: 1; }
.fu.out { opacity: 0; transition-duration: .3s; }
.fu canvas { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.fu-stage { position: relative; width: 240px; height: 300px; display: grid; place-items: center; }
.fu-rays {
  position: absolute; width: 640px; height: 640px; left: 50%; top: 50%; margin: -320px 0 0 -320px;
  background: repeating-conic-gradient(from 0deg, color-mix(in srgb, var(--fc) 30%, transparent) 0deg 5deg, transparent 5deg 18deg);
  -webkit-mask: radial-gradient(circle, #000 0%, transparent 62%); mask: radial-gradient(circle, #000 0%, transparent 62%);
  opacity: 0; transform: scale(.4); transition: opacity .9s ease, transform 1.2s cubic-bezier(.2, .8, .2, 1);
  animation: fu-spin 26s linear infinite;
}
.fu.charge .fu-rays { opacity: .35; transform: scale(.7); }
.fu.burst .fu-rays { opacity: .9; transform: scale(1); }
.fu-glow {
  position: absolute; width: 220px; height: 220px; border-radius: 50%;
  background: radial-gradient(circle, var(--fc) 0%, transparent 68%);
  opacity: 0; transform: scale(.3); filter: blur(10px);
  transition: opacity 1.2s ease, transform 1.3s ease;
}
.fu.charge .fu-glow { opacity: .55; transform: scale(.8); }
.fu.burst .fu-glow { opacity: .75; transform: scale(1.35); animation: fu-breathe 2.6s ease-in-out .6s infinite; }
.fu-ring {
  position: absolute; width: 120px; height: 120px; border-radius: 50%;
  border: 3px solid var(--fc); box-shadow: 0 0 24px var(--fc), inset 0 0 24px var(--fc);
  opacity: 0; transform: scale(.2);
}
.fu.burst .fu-ring { animation: fu-ring .9s cubic-bezier(.1, .7, .3, 1) forwards; }
.fu.burst .fu-ring.r2 { animation-delay: .14s; border-width: 1.5px; }
.fu-flame { position: absolute; height: 240px; width: auto; }
.fu-sil {
  filter: brightness(0) invert(1); opacity: 0; transform: scale(.7);
  transition: opacity .4s ease, transform .5s cubic-bezier(.3, 1.6, .5, 1);
}
.fu.show .fu-sil { opacity: .16; transform: scale(1); }
.fu.charge .fu-sil { animation: fu-shake 1.3s ease-in forwards; }
.fu.burst .fu-sil { opacity: 0; transition: opacity .15s; animation: none; }
.fu-real {
  opacity: 0; clip-path: circle(0% at 50% 58%); -webkit-clip-path: circle(0% at 50% 58%);
  filter: brightness(3) saturate(.4);
}
.fu.burst .fu-real {
  opacity: 1; animation: fu-open .75s cubic-bezier(.2, .9, .25, 1) forwards, fu-pop .9s cubic-bezier(.3, 1.7, .45, 1) forwards,
    fu-float 3.4s ease-in-out 1.1s infinite;
  filter: brightness(1) saturate(1) drop-shadow(0 0 22px color-mix(in srgb, var(--fc) 70%, transparent));
  transition: filter 1s ease .1s;
}
/* a band of light across the flame, cut to its shape */
.fu-shine {
  position: absolute; height: 240px; width: 180px; pointer-events: none; opacity: 0;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 255, 255, .85) 50%, transparent 65%) no-repeat;
  background-size: 250% 100%; background-position: 150% 0;
  -webkit-mask: var(--fm) center / contain no-repeat; mask: var(--fm) center / contain no-repeat;
  mix-blend-mode: overlay;
}
.fu.shine .fu-shine { opacity: 1; animation: fu-sweep 1s ease-in-out forwards; }
.fu-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; }
.fu.burst .fu-flash { animation: fu-flash .6s ease-out forwards; }
.fu-kicker {
  position: relative; font-size: .78rem; letter-spacing: .32em; text-transform: uppercase;
  color: var(--fc); opacity: 0; transform: translateY(10px); transition: all .5s ease;
}
.fu-name {
  position: relative; font-family: "Bricolage Grotesque", system-ui, sans-serif; font-weight: 700;
  font-size: 2.6rem; line-height: 1; color: var(--bone); display: flex; margin-top: -8px;
  text-shadow: 0 0 24px color-mix(in srgb, var(--fc) 60%, transparent);
}
.fu-name span { display: inline-block; white-space: pre; opacity: 0; transform: translateY(18px) scale(.6); filter: blur(6px);
  transition: opacity .45s ease, transform .55s cubic-bezier(.3, 1.6, .5, 1), filter .45s ease; }
.fu.named .fu-kicker { opacity: 1; transform: none; }
.fu.named .fu-name span { opacity: 1; transform: none; filter: none; }
.fu-btn { position: relative; min-width: 200px; opacity: 0; transform: translateY(12px); transition: all .5s ease; pointer-events: none; }
.fu.done .fu-btn { opacity: 1; transform: none; pointer-events: auto; }

@keyframes fu-spin { to { rotate: 360deg; } }
@keyframes fu-breathe { 50% { transform: scale(1.5); opacity: .55; } }
@keyframes fu-shake {
  0% { transform: scale(1); } 20% { transform: scale(1.02) rotate(-1deg); } 40% { transform: scale(1.03) rotate(1.5deg); }
  60% { transform: scale(1.05) translateX(-2px) rotate(-2deg); } 75% { transform: scale(1.06) translateX(3px) rotate(2.5deg); }
  88% { transform: scale(1.08) translateX(-3px) rotate(-3deg); } 100% { transform: scale(.92); }
}
@keyframes fu-ring { 0% { opacity: 1; transform: scale(.2); } 100% { opacity: 0; transform: scale(4.2); } }
@keyframes fu-open { to { clip-path: circle(80% at 50% 58%); -webkit-clip-path: circle(80% at 50% 58%); } }
@keyframes fu-pop { 0% { transform: scale(.6); } 60% { transform: scale(1.14); } 100% { transform: scale(1); } }
@keyframes fu-float { 50% { translate: 0 -8px; } }
@keyframes fu-sweep { to { background-position: -150% 0; } }
@keyframes fu-flash { 0% { opacity: 0; } 15% { opacity: .85; } 100% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .fu *, .fu { animation: none !important; transition: opacity .3s ease !important; }
  .fu .fu-real { clip-path: none; -webkit-clip-path: none; filter: none; }
  .fu .fu-name span, .fu .fu-kicker, .fu .fu-btn { transform: none; filter: none; }
}

/* ---------------- first steps on Home (cl-) ----------------
 * checklist.js. One line above Start: "1/4 Get app ›". Same size and place
 * as the old install banner, so Start stays the biggest thing on Home. */
.cl-banner {
  display: flex; align-items: center; gap: 11px; width: 100%;
  background: var(--smoke); border: 1px solid var(--ember-deep); border-radius: var(--radius);
  color: var(--bone); font: inherit; font-size: .95rem; text-align: left;
  padding: 11px 14px; margin: 12px 0 4px; cursor: pointer;
}
.cl-banner:active { transform: scale(.99); }
.cl-banner:focus-visible { outline: 2px solid var(--ember); outline-offset: 2px; }
.cl-num {
  flex: none; font-weight: 800; font-size: .8rem; font-variant-numeric: tabular-nums;
  color: #1A0E06; background: var(--ember); border-radius: 999px; padding: 3px 8px;
}
.cl-label { flex: 1; font-weight: 600; }
.cl-label b { color: var(--ember); }
.cl-chev { color: var(--ash); font-size: 1.3rem; line-height: 1; }
.cl-pic { flex: none; width: 34px; height: 34px; margin: -4px 0; object-fit: contain;
  filter: drop-shadow(0 0 8px rgba(255, 122, 61, .45)); }
.cl-show { color: var(--ember); font-weight: 700; font-size: .9rem; }
.cl-new { animation: cl-glow 2.4s ease-in-out infinite; }
@keyframes cl-glow { 50% { box-shadow: 0 0 18px rgba(255, 122, 61, .35); } }

@media (prefers-reduced-motion: reduce) { .cl-new { animation: none; } }
/* Friends, right after tapping "Invite 1 friend": the invite card lights up once */
.invite-card.cl-flash { animation: cl-flash 1.6s ease; }
@keyframes cl-flash { 20% { box-shadow: 0 0 0 2px var(--ember); } 100% { box-shadow: 0 0 0 2px transparent; } }

/* Stats | Badges: one row per kind of badge. Title and amount, a bar to the
 * next badge, then small badges the finger scrolls, like the league flames.
 * Locked badges stay grey but their hours stay readable. */
.cl-views { margin-bottom: 0; }
.cl-row { margin-top: 22px; }
.cl-row-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.cl-row-head b { color: var(--bone); font-weight: 600; font-size: .95rem; }
.cl-row-head span { color: var(--ash); font-size: .85rem; font-variant-numeric: tabular-nums; }
.cl-row-title { display: flex; align-items: center; gap: 8px; }
/* small on screen, a full finger to tap */
.cl-help {
  position: relative; flex: none; width: 18px; height: 18px; padding: 0; border-radius: 50%;
  border: 1px solid var(--ash); background: none; color: var(--ash);
  font-family: inherit; font-size: .7rem; font-weight: 600; line-height: 1; cursor: pointer;
}
.cl-help::after { content: ""; position: absolute; inset: -13px; }
.cl-help:active { color: var(--bone); border-color: var(--bone); }
.cl-row-bar { height: 5px; border-radius: 3px; background: var(--smoke-2); margin-top: 8px; overflow: hidden; }
.cl-row-bar i { display: block; height: 100%; width: 0; background: var(--ember); border-radius: 3px; }
.cl-badges {
  display: flex; gap: 10px; margin-top: 12px; padding: 2px 0 4px;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity; scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.cl-badges::-webkit-scrollbar { display: none; }
.cl-badge { flex: 0 0 72px; background: none; border: 0; padding: 0; cursor: pointer; scroll-snap-align: center; }
.cl-badge img { display: block; width: 72px; height: 72px; object-fit: contain; }
.cl-badge.cl-locked img { filter: grayscale(1) brightness(.7); opacity: .6; }

/* the unlock moment for a badge picture (playFlameUnlock opts.src) */
.fu-pic .fu-flame { height: 230px; }
.fu-pic .fu-shine { width: 230px; height: 230px; }

/* ---------------- terms and privacy ----------------
 * The tick box at sign in and on the Terms sheet: a big square, easy to hit
 * with a thumb (the whole line is the label). The checkbox itself stays in
 * the page for screen readers and the keyboard, only visually hidden. */
.tick { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; padding: 6px 0; text-align: left; }
.tick input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.tick-box {
  flex: none; width: 26px; height: 26px; border-radius: 8px; margin-top: 1px;
  border: 2px solid var(--ash); background: var(--smoke); position: relative; transition: background .15s, border-color .15s;
}
.tick input:checked + .tick-box { background: var(--ember); border-color: var(--ember); }
.tick input:checked + .tick-box::after {
  content: ""; position: absolute; left: 8px; top: 3px; width: 6px; height: 12px;
  border: solid #000; border-width: 0 3px 3px 0; transform: rotate(45deg);
}
.tick input:focus-visible + .tick-box { outline: 2px solid var(--ember); outline-offset: 2px; }
.tick-text { color: var(--ash); font-size: .9rem; line-height: 1.5; }
.legal-link { color: var(--ember); }
.legal-links { text-align: center; margin: 0; }
.terms-links { margin: 0; font-size: .95rem; }
.terms-sheet { z-index: 100; background: rgba(0,0,0,.92); }
.terms-sheet .btn.tiny { align-self: center; }

/* Invite card at the bottom of Friends: your own link and a Share button */
.invite-card {
  display: flex; align-items: center; gap: 12px; margin: 22px 0 8px;
  padding: 14px 16px; background: var(--smoke); border-radius: var(--radius);
}
.invite-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.invite-url { color: var(--ash); font-size: .85rem; overflow-wrap: anywhere; }
.invite-joined { color: var(--ember); font-size: .85rem; }
.invite-card .btn { flex: none; }
