/* An Evening for Goldie - winter / ice theme.
   Mobile first. Deliberately "alive": snow, ticker, pulsing live badge,
   flashing new bids. All motion is disabled under prefers-reduced-motion. */

:root {
  --ink: #04142e;
  --deep: #061c3d;
  --mid: #0d2f5e;
  --ice: #8fe4ff;
  --ice-bright: #c9f4ff;
  --frost: #eaf8ff;
  --gold: #ffd166;
  --rose: #ff9ec7;
  --violet: #a78bfa;
  --good: #58e8b0;
  --paper: rgba(255, 255, 255, 0.07);
  --paper-2: rgba(255, 255, 255, 0.12);
  --edge: rgba(180, 230, 255, 0.22);
  --shadow: 0 18px 50px rgba(0, 10, 30, 0.45);
  --radius: 20px;
  /* One spacing scale for the whole site. --pad is card padding (the lot image
     bleeds by exactly this), --stack is the gap between stacked blocks. */
  --pad: 20px;
  --stack: 18px;
  --font-display: 'Baloo 2', 'Trebuchet MS', sans-serif;
  --font-body: 'Nunito', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font-body);
  color: var(--frost);
  background:
    radial-gradient(1100px 700px at 12% -5%, #1d4b8f 0%, transparent 60%),
    radial-gradient(900px 600px at 88% 8%, #4b2d7a 0%, transparent 55%),
    radial-gradient(800px 500px at 50% 100%, #0a2b55 0%, transparent 60%),
    linear-gradient(175deg, var(--deep) 0%, var(--ink) 55%, #020b1c 100%);
  background-attachment: fixed;
  overflow-x: hidden;
  -webkit-text-size-adjust: 100%;
}

/* Aurora wash behind everything */
body::before {
  content: '';
  position: fixed;
  inset: -20% -10% auto -10%;
  height: 70vh;
  background:
    radial-gradient(60% 60% at 20% 40%, rgba(143, 228, 255, 0.16), transparent 70%),
    radial-gradient(50% 50% at 70% 30%, rgba(167, 139, 250, 0.16), transparent 70%),
    radial-gradient(40% 50% at 45% 60%, rgba(88, 232, 176, 0.1), transparent 70%);
  filter: blur(30px);
  animation: aurora 18s ease-in-out infinite alternate;
  pointer-events: none;
  z-index: 0;
}

@keyframes aurora {
  0% { transform: translate3d(-3%, 0, 0) scale(1); opacity: 0.8; }
  100% { transform: translate3d(4%, 3%, 0) scale(1.12); opacity: 1; }
}

#snow {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}

.wrap {
  position: relative;
  z-index: 2;
  width: min(1120px, 100% - 32px);
  margin: 0 auto;
  padding-bottom: 72px;
}

/* The single spacing rule for the page. Every direct child of .wrap gets the
   same gap above it, and nothing sets its own margin-top. This replaces the
   mix of per-section margins that was producing uneven gaps between boxes. */
.wrap > * + * { margin-top: var(--stack); }
.wrap > *:first-child { margin-top: 0; }

/* ------------------------------------------------------------------ ticker */

.ticker {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 46px;
  background: linear-gradient(90deg, rgba(4, 20, 46, 0.96), rgba(13, 47, 94, 0.96));
  border-bottom: 1px solid var(--edge);
  backdrop-filter: blur(10px);
  overflow: hidden;
}

.ticker__badge {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 7px;
  margin-left: 10px;
  padding: 5px 11px;
  border-radius: 999px;
  background: #e0325c;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  box-shadow: 0 0 0 0 rgba(224, 50, 92, 0.7);
  animation: livePulse 2s ease-out infinite;
}

.ticker__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #fff;
  animation: blink 1.1s steps(2, start) infinite;
}

@keyframes livePulse {
  0% { box-shadow: 0 0 0 0 rgba(224, 50, 92, 0.65); }
  70% { box-shadow: 0 0 0 14px rgba(224, 50, 92, 0); }
  100% { box-shadow: 0 0 0 0 rgba(224, 50, 92, 0); }
}

@keyframes blink {
  50% { opacity: 0.15; }
}

.ticker__track {
  flex: 1 1 auto;
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}

/* Position is driven frame by frame from app.js - deliberately no CSS
   animation here. A keyframed translateX(-50%) only loops seamlessly if the
   duplicated half is exactly half the width, which the flex `gap` broke, and
   it restarted every time the content changed. */
.ticker__inner {
  display: flex;
  align-items: center;
  white-space: nowrap;
  will-change: transform;
}

.ticker__item {
  flex: 0 0 auto;
  margin-right: 42px;   /* must match GAP in app.js */
}

.ticker__item {
  font-size: 0.92rem;
  font-weight: 700;
  color: var(--ice-bright);
}

.ticker__item b { color: var(--gold); }

.ticker__item--news { color: #fff; }

.ticker__item::before {
  content: '\2744';
  margin-right: 10px;
  color: var(--ice);
  opacity: 0.75;
}

/* ------------------------------------------------------------------ header */

header.hero {
  padding: 10px 0 0;
  text-align: center;
}

.hero__eyebrow {
  font-family: var(--font-display);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ice);
  opacity: 0.85;
}

.hero h1 {
  margin: 8px 0 6px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(2.3rem, 9vw, 4.2rem);
  line-height: 1.02;
  background: linear-gradient(180deg, #fff 10%, var(--ice-bright) 55%, #7cc8f0 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 6px 24px rgba(143, 228, 255, 0.3));
}

.hero__sub {
  margin: 0 auto;
  max-width: 44ch;
  font-size: 1.02rem;
  line-height: 1.5;
  color: #d8ecff;
  opacity: 0.95;
}

.hero__message {
  margin: 18px auto 0;
  max-width: 52ch;
  padding: 12px 18px;
  border: 1px dashed var(--edge);
  border-radius: 14px;
  background: var(--paper);
  font-weight: 700;
  color: var(--ice-bright);
}

/* ------------------------------------------------------------------ totals */

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

.card {
  position: relative;
  padding: var(--pad);
  border: 1px solid var(--edge);
  border-radius: var(--radius);
  background: linear-gradient(160deg, var(--paper-2), var(--paper));
  box-shadow: var(--shadow);
  backdrop-filter: blur(8px);
}

.total {
  text-align: center;
  overflow: hidden;
}

.total::after {
  content: '';
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.16), transparent);
  animation: sheen 5.5s ease-in-out infinite;
  pointer-events: none;
}

@keyframes sheen {
  0%, 60% { left: -60%; }
  100% { left: 120%; }
}

.total__label {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ice);
}

.total__value {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(3rem, 15vw, 5.6rem);
  line-height: 1;
  margin: 6px 0 4px;
  color: #fff;
  text-shadow: 0 0 34px rgba(255, 209, 102, 0.45);
  font-variant-numeric: tabular-nums;
}

.total__value.bump { animation: bump 0.7s cubic-bezier(.3, 1.6, .5, 1); }

@keyframes bump {
  0% { transform: scale(1); }
  35% { transform: scale(1.14); color: var(--gold); }
  100% { transform: scale(1); }
}

.total__split {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin-top: 12px;
  font-size: 0.86rem;
  color: #cfe7ff;
}

.total__split span b { color: #fff; }

/* Soft, rounded, no hard diagonal edges - the old barber-pole stripes read as
   saw teeth, which is not the feeling we want at a children's film night. */
/* Four layers, all soft-edged, no sawtooth. The bright sweep shares the card's
   5.5s sheen timing, so the light that crosses the total card carries on
   across the bar as one movement rather than two unrelated animations. */

/* The GoFundMe figure. Kept visually separate from tonight's total, and NOT
   added into it - they are different pots and adding them would double count
   in people's heads. */
.gfm {
  display: flex;
  align-items: baseline;
  justify-content: center;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px dashed var(--edge);
}

.gfm[hidden] { display: none; }

.gfm__label {
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--rose);
}

.gfm__value {
  font-family: var(--font-display);
  font-size: 1.7rem;
  line-height: 1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.gfm__meta { font-size: 0.76rem; color: #92b4d8; width: 100%; }

body.screen .gfm__label { font-size: 1rem; }
body.screen .gfm__value { font-size: clamp(2rem, 4vh, 3.2rem); }
body.screen .gfm__meta { font-size: 0.95rem; }

.bar {
  position: relative;
  height: 22px;
  margin-top: 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid var(--edge);
  overflow: hidden;
}

/* Layer 1: faint snow drifting along the whole track, behind the fill. */
.bar::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(circle at 30% 45%, rgba(255, 255, 255, 0.5) 0 1.4px, transparent 1.9px),
    radial-gradient(circle at 70% 70%, rgba(255, 255, 255, 0.32) 0 1.1px, transparent 1.6px);
  background-size: 34px 100%, 52px 100%;
  animation: barSnow 7s linear infinite;
  pointer-events: none;
}

@keyframes barSnow {
  to { background-position: 34px 0, 52px 0; }
}

/* Layer 2: the fill, with its colours flowing left to right. */
.bar__fill {
  position: relative;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background-image: linear-gradient(100deg,
    #7ad4ff 0%, var(--ice) 18%, var(--good) 38%, var(--gold) 58%,
    var(--ice-bright) 78%, #7ad4ff 100%);
  background-size: 260% 100%;
  transition: width 1.2s cubic-bezier(.2, .8, .2, 1);
  animation: barFlow 7s linear infinite, barGlow 3.4s ease-in-out infinite;
}

@keyframes barFlow {
  from { background-position: 0 0; }
  to { background-position: -260% 0; }
}

@keyframes barGlow {
  0%, 100% { box-shadow: 0 0 14px rgba(143, 228, 255, 0.45); }
  50% { box-shadow: 0 0 26px rgba(255, 209, 102, 0.6); }
}

/* Layer 3: the bright sweep - same 5.5s cadence as the card's sheen. */
.bar__fill::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg,
    transparent 14%, rgba(255, 255, 255, 0.3) 38%,
    rgba(255, 255, 255, 0.75) 50%, rgba(255, 255, 255, 0.3) 62%, transparent 86%);
  animation: glide 5.5s ease-in-out infinite;
}

@keyframes glide {
  0%, 8% { transform: translateX(-110%); }
  100% { transform: translateX(110%); }
}

/* Layer 4: a snowflake riding the leading edge, turning and twinkling. */
.bar__fill::before {
  content: '\2744';
  position: absolute;
  right: 4px;
  top: 50%;
  font-size: 13px;
  line-height: 1;
  color: #fff;
  animation: driftFlake 7s linear infinite, twinkle 2.1s ease-in-out infinite;
}

@keyframes driftFlake {
  from { transform: translateY(-50%) rotate(0deg); }
  to { transform: translateY(-50%) rotate(360deg); }
}

@keyframes twinkle {
  0%, 100% { text-shadow: 0 0 6px rgba(255, 255, 255, 0.85); opacity: 0.85; }
  50% { text-shadow: 0 0 16px #fff, 0 0 26px var(--gold); opacity: 1; }
}

.bar__caption {
  margin-top: 8px;
  font-size: 0.82rem;
  color: #bcd9f5;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  margin-top: 18px;
}

.btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 20px;
  border: 0;
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 800;
  cursor: pointer;
  text-decoration: none;
  transition: transform 0.14s ease, box-shadow 0.2s ease, filter 0.2s ease;
  min-height: 46px;
}

.btn:active { transform: translateY(1px) scale(0.99); }

.btn--primary {
  background: linear-gradient(135deg, #fff 0%, var(--ice-bright) 50%, var(--ice) 100%);
  color: #06284d;
  box-shadow: 0 10px 28px rgba(143, 228, 255, 0.35);
}

.btn--primary:hover { filter: brightness(1.06); box-shadow: 0 14px 34px rgba(143, 228, 255, 0.5); }

.btn--gold {
  background: linear-gradient(135deg, #ffe9a8, var(--gold) 60%, #f0a93c);
  color: #3a2200;
  box-shadow: 0 10px 28px rgba(255, 209, 102, 0.34);
}

.btn--ghost {
  background: rgba(255, 255, 255, 0.08);
  color: var(--frost);
  border: 1px solid var(--edge);
}

.btn[disabled] { opacity: 0.45; cursor: not-allowed; }

/* ------------------------------------------------------------- live feed */

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 12px;
}

.section-head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.45rem, 5vw, 2rem);
  color: #fff;
}

.section-head p {
  margin: 0;
  font-size: 0.86rem;
  color: #a9c9ea;
}

.layout {
  display: grid;
  gap: 16px;
}

@media (min-width: 900px) {
  .layout { grid-template-columns: 1.55fr 1fr; align-items: start; }
  .layout .feed-card { position: sticky; top: 62px; }
}

.feed {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 460px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.feed li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 4px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.1);
  font-size: 0.94rem;
}

.feed li:last-child { border-bottom: 0; }

.feed li.is-new {
  animation: slideFlash 1.5s ease-out;
  border-radius: 12px;
}

@keyframes slideFlash {
  0% { transform: translateX(-18px); background: rgba(255, 209, 102, 0.55); }
  40% { background: rgba(255, 209, 102, 0.3); }
  100% { transform: translateX(0); background: transparent; }
}

.feed__amount {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}

.feed__who { font-weight: 700; color: #fff; }
.feed__lot { color: #a9c9ea; font-size: 0.86rem; }
.feed__time { margin-left: auto; flex: 0 0 auto; font-size: 0.76rem; color: #87a8cc; }
.feed__anon { font-size: 0.78rem; opacity: 0.8; }

.empty {
  padding: 26px 10px;
  text-align: center;
  color: #a9c9ea;
}

/* ---------------------------------------------------------------- lots */

.lots { display: grid; gap: 16px; }

@media (min-width: 680px) {
  .lots { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
}

.lot {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.lot:hover { transform: translateY(-3px); }

.lot.just-bid { animation: lotFlash 1.6s ease-out; }

@keyframes lotFlash {
  0% { box-shadow: 0 0 0 3px var(--gold), 0 0 50px rgba(255, 209, 102, 0.6); }
  100% { box-shadow: var(--shadow); }
}

.lot__media {
  margin: calc(var(--pad) * -1) calc(var(--pad) * -1) 14px;
  aspect-ratio: 16 / 10;
  background: linear-gradient(135deg, #15386b, #2a1e55);
  display: grid;
  place-items: center;
  font-size: 3rem;
  overflow: hidden;
}

.lot__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.lot__title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.3rem;
  color: #fff;
}

.lot__blurb {
  margin: 0 0 12px;
  font-size: 0.92rem;
  line-height: 1.5;
  color: #cfe3fa;
}

.lot__donor {
  font-size: 0.8rem;
  color: var(--ice);
  margin-bottom: 12px;
}

.lot__price {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  margin-top: auto;
  border-radius: 14px;
  background: rgba(4, 20, 46, 0.5);
  border: 1px solid var(--edge);
}

.lot__price small {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ice);
}

.lot__amount {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.8rem;
  line-height: 1.1;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.lot__leader { font-size: 0.84rem; color: #cfe3fa; }
.lot__count { font-size: 0.78rem; color: #87a8cc; text-align: right; }

.lot__actions { margin-top: 12px; display: flex; gap: 8px; }
.lot__actions .btn { flex: 1 1 auto; }

.pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.pill--closed { background: rgba(255, 255, 255, 0.16); color: #dbe9fa; }
.pill--winning { background: var(--good); color: #052e21; }
.pill--outbid { background: #e0325c; color: #fff; }

.lot__status { margin-bottom: 10px; min-height: 22px; }

/* ------------------------------------------------------------ bid dialog */

dialog.sheet {
  width: min(520px, calc(100% - 24px));
  padding: 0;
  border: 1px solid var(--edge);
  border-radius: 22px;
  background: linear-gradient(165deg, #0e2f5c, #061c3d 70%);
  color: var(--frost);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}

dialog.sheet::backdrop {
  background: rgba(2, 10, 24, 0.72);
  backdrop-filter: blur(4px);
}

.sheet__body { padding: 22px; }

.sheet h3 {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: #fff;
}

.sheet__hint { margin: 0 0 16px; font-size: 0.88rem; color: #a9c9ea; }

.field { margin-bottom: 14px; }

.field label {
  display: block;
  margin-bottom: 6px;
  font-size: 0.82rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ice);
}

.field input[type='text'],
.field input[type='number'],
.field textarea,
.field select {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
  font-family: var(--font-body);
  font-size: 1.05rem;
}

.field input:focus, .field textarea:focus, .field select:focus {
  outline: 2px solid var(--ice);
  outline-offset: 1px;
}

.field small { display: block; margin-top: 6px; font-size: 0.78rem; color: #92b4d8; }

.amount-row { display: flex; gap: 8px; align-items: center; }
.amount-row .prefix { font-size: 1.4rem; font-weight: 800; color: var(--gold); }

.quick { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }

.quick button {
  padding: 9px 14px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  font-weight: 800;
  font-family: var(--font-display);
  cursor: pointer;
  min-height: 40px;
}

.quick button:hover { background: var(--ice); color: #06284d; }

.check {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 13px;
  border: 1px solid var(--edge);
  border-radius: 14px;
  background: rgba(167, 139, 250, 0.12);
  cursor: pointer;
}

.check input { width: 22px; height: 22px; margin: 2px 0 0; flex: 0 0 auto; accent-color: var(--violet); }
.check span { font-size: 0.9rem; line-height: 1.45; }
.check b { color: #fff; }

.sheet__error {
  display: none;
  margin: 0 0 14px;
  padding: 12px 14px;
  border-radius: 12px;
  background: rgba(224, 50, 92, 0.25);
  border: 1px solid rgba(255, 140, 170, 0.5);
  font-weight: 700;
  font-size: 0.92rem;
}

.sheet__error.show { display: block; }

.sheet__actions { display: flex; gap: 10px; margin-top: 18px; }
.sheet__actions .btn { flex: 1 1 auto; }

.privacy {
  margin: 14px 0 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: #92b4d8;
}

.linkish {
  display: inline;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ice);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

.step-pane[hidden] { display: none; }

.field input[type='email'],
.field input[type='password'],
.field input[type='tel'] {
  width: 100%;
  padding: 13px 14px;
  border: 1px solid var(--edge);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.07);
  color: #fff;
  font-family: var(--font-body);
  font-size: 1.05rem;
}

/* ------------------------------------------------------------------ toast */

#toasts {
  position: fixed;
  left: 50%;
  bottom: 22px;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: min(460px, calc(100% - 24px));
  pointer-events: none;
}

.toast {
  width: 100%;
  padding: 14px 18px;
  border-radius: 16px;
  border: 1px solid rgba(255, 209, 102, 0.6);
  background: linear-gradient(135deg, rgba(14, 47, 92, 0.97), rgba(70, 40, 110, 0.97));
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
  animation: toastIn 0.5s cubic-bezier(.2, 1.5, .4, 1), toastOut 0.5s ease-in 5.2s forwards;
  text-align: center;
}

.toast strong {
  display: block;
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--gold);
}

.toast span { font-size: 0.9rem; color: #dcebff; }

@keyframes toastIn {
  from { transform: translateY(40px) scale(0.9); opacity: 0; }
  to { transform: none; opacity: 1; }
}

@keyframes toastOut {
  to { transform: translateY(-14px); opacity: 0; }
}

/* ------------------------------------------------------------------ misc */

.story {
  line-height: 1.65;
}

.story p { margin: 0 0 12px; }
.story p:last-child { margin-bottom: 0; }

.howto { margin: 12px 0 0; padding-left: 22px; line-height: 1.7; }
.howto li::marker { color: var(--ice); font-weight: 800; }

footer.foot {
  padding-top: 20px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  text-align: center;
  font-size: 0.82rem;
  color: #8fb0d4;
}

footer.foot a { color: var(--ice); }

.foot__tools {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}

.foot__tools button {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: rgba(255, 255, 255, 0.06);
  color: #cfe3fa;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
}

.conn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
  padding: 5px 12px;
  border-radius: 999px;
  background: rgba(88, 232, 176, 0.14);
  border: 1px solid rgba(88, 232, 176, 0.4);
  font-size: 0.76rem;
  font-weight: 800;
  color: var(--good);
}

.conn.bad {
  background: rgba(255, 180, 80, 0.14);
  border-color: rgba(255, 180, 80, 0.45);
  color: var(--gold);
}

.conn__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  animation: blink 1.6s ease-in-out infinite;
}

.countdown-wrap { text-align: center; }
.countdown-wrap:empty { display: none; }

.countdown {
  display: inline-flex;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 800;
  transition: box-shadow 0.2s ease;
}

/* Once the countdown has scrolled off the top, it docks to the bottom of the
   screen so the time left is always visible. Driven by an IntersectionObserver
   in app.js rather than position:sticky, so the docked look can differ. */
.countdown.is-docked {
  position: fixed;
  left: 50%;
  bottom: 12px;
  transform: translateX(-50%);
  z-index: 55;
  gap: 6px;
  padding: 9px 12px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: rgba(4, 20, 46, 0.94);
  box-shadow: var(--shadow);
  backdrop-filter: blur(8px);
  animation: dockIn 0.3s ease-out;
}

.countdown.is-docked::before {
  content: 'Bidding closes in';
  align-self: center;
  margin-right: 4px;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ice);
  white-space: nowrap;
}

.countdown.is-docked span { min-width: 46px; padding: 4px 5px; font-size: 1rem; }
.countdown.is-docked small { font-size: 0.52rem; }

@keyframes dockIn {
  from { transform: translate(-50%, 20px); opacity: 0; }
  to { transform: translate(-50%, 0); opacity: 1; }
}

/* Keep the bid toasts clear of the docked bar. */
body.has-dock #toasts { bottom: 80px; }
body.has-dock.screen .qr { bottom: 86px; }

.countdown span {
  min-width: 56px;
  padding: 8px 6px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid var(--edge);
  text-align: center;
  font-size: 1.2rem;
  font-variant-numeric: tabular-nums;
}

.countdown small {
  display: block;
  font-size: 0.6rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ice);
  font-weight: 700;
  white-space: nowrap;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* -------------------------------------------------------- big screen mode */

/* Big screen mode is a fixed dashboard, not the normal page scaled up. Every
   piece of live information is on screen at once and the page never scrolls.
   Everything explanatory is removed. */

body.screen { overflow: hidden; height: 100%; }
html:has(body.screen) { overflow: hidden; }

body.screen .wrap {
  position: fixed;
  inset: 68px 18px 18px;      /* clears the 60px ticker */
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: minmax(260px, 1fr) minmax(0, 1.85fr) minmax(220px, 0.85fr);
  /* The bottom row must be tall enough for a projectable QR code. */
  grid-template-rows: auto minmax(0, 1fr) minmax(clamp(210px, 25vh, 390px), auto);
  grid-template-areas:
    "title title count"
    "total lots  feed"
    "wall  wall  .";
  gap: 16px;
  overflow: hidden;
}

/* The stacking margin rule must not apply inside a grid. */
body.screen .wrap > * + * { margin-top: 0; }

/* Nothing explanatory, nothing that needs scrolling to reach. */
body.screen .hero__sub,
body.screen .hero__eyebrow,
body.screen .hero__message,
body.screen .section-head,
body.screen .story,
body.screen .howto,
body.screen #howCard,
body.screen .lot__actions,
body.screen .lot__blurb,
body.screen .lot__donor,
body.screen footer.foot > p { display: none; }

body.screen header.hero { grid-area: title; padding: 0; align-self: center; }
body.screen .countdown-wrap { grid-area: count; align-self: center; text-align: right; }

/* Readable from the back of a hall. */
body.screen .countdown { gap: 10px; }

body.screen .countdown::before {
  content: 'Closes in';
  align-self: center;
  margin-right: 6px;
  font-size: clamp(0.7rem, 1.2vh, 0.95rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ice);
  white-space: nowrap;
}

body.screen .countdown span {
  min-width: clamp(70px, 7vw, 110px);
  padding: 10px 8px;
  font-size: clamp(1.7rem, 3.6vh, 2.9rem);
}

body.screen .countdown small {
  font-size: clamp(0.5rem, 1vh, 0.72rem);
  margin-top: 2px;
}
body.screen .board { grid-area: total; min-height: 0; }
body.screen #wallCard { grid-area: wall; min-height: 0; }

/* Dissolve .layout so the lots card and the feed card become grid items. */
body.screen .layout { display: contents; }
body.screen #lotsCard { grid-area: lots; min-height: 0; }
body.screen .feed-card { grid-area: feed; min-height: 0; position: static; }

/* Cards fill their cell and clip rather than scroll. */
body.screen .board > .card,
body.screen #lotsCard,
body.screen .feed-card,
body.screen #wallCard {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

body.screen .board { display: flex; }
body.screen .total { flex: 1 1 auto; justify-content: center; display: flex; flex-direction: column; }

body.screen .lots {
  grid-template-columns: repeat(auto-fit, minmax(185px, 1fr));
  align-content: start;
  overflow: hidden;
  flex: 1 1 auto;
  min-height: 0;
}

body.screen .lot { padding: 14px; }
body.screen .lot__title { font-size: 1.15rem; }
body.screen .lot__status { min-height: 0; margin-bottom: 6px; }

/* Lot photos stay on the big screen - people need to see what they are
   bidding on. Kept shallow so several lots still fit without scrolling. */
body.screen .lot__media {
  margin: -14px -14px 10px;
  aspect-ratio: 16 / 7;
}

body.screen .feed { flex: 1 1 auto; min-height: 0; overflow: hidden; }
body.screen .wall__grid {
  grid-template-columns: none;
  grid-auto-flow: column;
  grid-auto-columns: minmax(200px, 1fr);
  overflow: hidden;
  flex: 1 1 auto;
  min-height: 0;
}
body.screen .note { font-size: 1.05rem; }
body.screen .note__body { font-size: 1.1rem; }

/* Operator controls: exit, and the chime. They used to sit top-right, directly
   on top of the countdown and each other. Now they stack in the bottom-LEFT,
   clear of the countdown (top-right) and the QR (bottom-right), and they fade
   away like video player controls so they never cover live information. Any
   mouse move, tap or key press brings them back for a few seconds. */

body.screen .exit-screen,
body.screen footer.foot {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}

body.screen.controls-on .exit-screen,
body.screen.controls-on footer.foot {
  opacity: 1;
  pointer-events: auto;
}

body.screen .exit-screen {
  top: auto;
  right: auto;
  bottom: 18px;
  left: 18px;
  font-size: 1rem;
  padding: 12px 20px;
}

body.screen footer.foot {
  position: fixed;
  top: auto;
  bottom: 74px;
  left: 18px;
  right: auto;
  z-index: 80;
  margin: 0;
  padding: 0;
  border: 0;
  width: auto;
  text-align: left;
}

body.screen .foot__tools { margin: 0; justify-content: flex-start; }
body.screen #calmToggle,
body.screen #screenToggle { display: none; }
body.screen #soundToggle { padding: 12px 18px; font-size: 0.95rem; }
/* NOTE: .foot__tools stays visible on purpose. It holds the button that leaves
   big screen mode, and hiding it trapped people in here with no way back. */
body.screen .lot__actions,
body.screen .story,
body.screen .howto,
body.screen .hero__message { display: none; }

/* Always-reachable way out, so you never have to scroll to the footer. */
.exit-screen {
  position: fixed;
  top: 54px;
  right: 14px;
  z-index: 80;
  padding: 12px 18px;
  border-radius: 999px;
  border: 1px solid var(--edge);
  background: rgba(4, 20, 46, 0.92);
  color: var(--frost);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.95rem;
  cursor: pointer;
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow);
}

.exit-screen:hover { background: var(--ice); color: #06284d; }
.exit-screen[hidden] { display: none; }
body.screen .exit-screen { top: 70px; font-size: 1.1rem; padding: 14px 22px; }
body.screen .total__value { font-size: clamp(4rem, 13vw, 11rem); }
body.screen .hero h1 { font-size: clamp(3rem, 8vw, 6.5rem); }
body.screen .feed li { font-size: 1.3rem; padding: 16px 6px; }
body.screen .feed__amount { font-size: 1.7rem; }
body.screen .feed { max-height: 70vh; }
body.screen .lot__amount { font-size: 2.4rem; }
body.screen .ticker { height: 60px; }
body.screen .ticker__item { font-size: 1.3rem; }
body.screen .toast strong { font-size: 2.4rem; }

/* ------------------------------------------------- full screen bid moment */

.blast {
  position: fixed;
  inset: 0;
  z-index: 85;
  display: grid;
  place-items: center;
  pointer-events: none;            /* never swallows a tap */
  background:
    radial-gradient(60% 60% at 50% 45%, rgba(13, 47, 94, 0.92), rgba(4, 20, 46, 0.86) 70%),
    rgba(2, 10, 24, 0.72);
  backdrop-filter: blur(6px);
  animation: blastIn 0.45s cubic-bezier(.2, 1.5, .4, 1);
  text-align: center;
  padding: 24px;
}

.blast[hidden] { display: none; }
.blast.is-out { animation: blastOut 0.5s ease-in forwards; }

@keyframes blastIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes blastOut {
  to { opacity: 0; }
}

.blast__inner { animation: blastPop 0.6s cubic-bezier(.2, 1.6, .4, 1); }

@keyframes blastPop {
  0% { transform: scale(0.6) rotate(-4deg); }
  70% { transform: scale(1.06) rotate(1deg); }
  100% { transform: scale(1) rotate(0); }
}

.blast__eyebrow {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.1rem, 4vw, 1.8rem);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ice);
  animation: blink 0.8s steps(2, start) 4;
}

.blast__amount {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(4.5rem, 24vw, 13rem);
  line-height: 0.95;
  margin: 6px 0 10px;
  background: linear-gradient(180deg, #fff 5%, var(--gold) 55%, #f0a93c 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 10px 40px rgba(255, 209, 102, 0.55));
  font-variant-numeric: tabular-nums;
}

.blast__who {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.4rem, 6vw, 3rem);
  color: #fff;
}

.blast__lot {
  margin-top: 6px;
  font-size: clamp(0.95rem, 3.4vw, 1.5rem);
  color: var(--ice-bright);
}

body.screen .blast__amount { font-size: clamp(7rem, 26vw, 18rem); }
body.screen .blast__who { font-size: clamp(2rem, 7vw, 4.5rem); }

/* ------------------------------------------------------- messages of support */

.wall__grid { display: grid; gap: 12px; }

@media (min-width: 680px) {
  .wall__grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
}

.note {
  position: relative;
  padding: 16px 16px 14px;
  border-radius: 16px;
  border: 1px solid var(--edge);
  background: linear-gradient(160deg, rgba(167, 139, 250, 0.16), rgba(255, 255, 255, 0.06));
  line-height: 1.5;
}

.note.is-new { animation: noteIn 1.4s ease-out; }

@keyframes noteIn {
  0% { transform: scale(.92); box-shadow: 0 0 0 3px var(--rose); }
  100% { transform: scale(1); }
}

.note__body { font-size: 1rem; color: #fff; }

.note__who {
  display: block;
  margin-top: 10px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.9rem;
  color: var(--rose);
}

.note__who::before { content: '\2014 '; }

/* ---------------------------------------------------------- QR, big screen */

.qr {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 75;
  display: none;
  align-items: center;
  gap: 16px;
  padding: 16px 20px 16px 16px;
  border-radius: 20px;
  background: rgba(255, 255, 255, 0.97);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
}

body.screen .qr { display: flex; }
.qr[hidden] { display: none; }

.qr__code {
  width: 150px;
  height: 150px;
  display: grid;
  place-items: center;
  background: #fff;
}

/* Projected, the QR has to be far bigger than it looks on a laptop. The image
   itself is generated at 560px (see app.js) so scaling it down stays crisp -
   scaling a small one up would blur the modules and break scanning. */
body.screen .qr__code {
  width: clamp(200px, 22vh, 340px);
  height: clamp(200px, 22vh, 340px);
}

.qr__code img, .qr__code canvas { display: block; width: 100%; height: 100%; }

.qr__text { max-width: 230px; color: #06284d; }

body.screen .qr { gap: 22px; padding: 22px 26px 22px 22px; }
body.screen .qr__text { max-width: 300px; }
body.screen .qr__text b { font-size: clamp(1.8rem, 3.2vh, 2.6rem); }
body.screen .qr__text span { font-size: clamp(1rem, 1.7vh, 1.35rem); }

.qr__text b {
  display: block;
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1.1;
  margin-bottom: 4px;
}

.qr__text span {
  font-size: 1rem;
  font-weight: 700;
  color: #1d4b8f;
  word-break: break-all;
}

/* ----------------------------------------------------- phones: the fold
   On a phone the headline number is the whole point, so everything above it
   gets out of the way. The decorative eyebrow goes, the title and sub-heading
   shrink, and the welcome banner and countdown move BELOW the total card via
   flex ordering - so "Raised so far tonight" lands in the first screenful. */

@media (max-width: 720px) {
  :root { --pad: 16px; --stack: 14px; }

  .hero__eyebrow { display: none; }

  header.hero { padding: 12px 0 0; }

  .hero h1 { font-size: clamp(1.75rem, 8.5vw, 2.4rem); }

  .hero__sub { font-size: 0.9rem; line-height: 1.4; max-width: 34ch; }

  .hero__message { padding: 10px 14px; font-size: 0.88rem; }

  .countdown span { min-width: 50px; padding: 6px 5px; font-size: 1.05rem; }

  /* Docked, on a phone: a full-width bar rather than a centred pill. The pill
     was narrower than its own contents once the label was added, so flex
     squashed the digits and the hours/mins/secs labels wrapped. */
  .countdown.is-docked {
    left: 10px;
    right: 10px;
    bottom: 10px;
    transform: none;
    justify-content: center;
    border-radius: 16px;
    padding: 8px 10px;
    gap: 6px;
    animation: dockInFlat 0.3s ease-out;
  }

  .countdown.is-docked::before {
    content: 'Closes in';
    margin-right: 2px;
    font-size: 0.64rem;
  }

  .countdown.is-docked span {
    min-width: 0;
    flex: 0 1 auto;
    padding: 3px 7px;
    font-size: 0.98rem;
  }

  .countdown.is-docked small { font-size: 0.48rem; letter-spacing: 0.06em; }

  @keyframes dockInFlat {
    from { transform: translateY(18px); opacity: 0; }
    to { transform: translateY(0); opacity: 1; }
  }

  .total__label { font-size: 0.68rem; letter-spacing: 0.16em; }
  .total__value { font-size: clamp(2.8rem, 16vw, 4rem); margin: 2px 0; }
  .total__split { font-size: 0.8rem; gap: 4px 14px; margin-top: 8px; }
  .bar { margin-top: 12px; }
  .bar__caption { font-size: 0.78rem; }

  /* The two primary actions get a full line each; the two secondary ones share
     a line, so adding "How it works" does not push the total below the fold. */
  .cta-row { margin-top: 14px; gap: 8px; }
  .cta-row .btn { flex: 1 1 100%; padding: 14px 16px; }
  .cta-row .btn--ghost { flex: 1 1 calc(50% - 4px); padding: 13px 10px; font-size: 0.92rem; }

  .section-head { margin: 24px 0 10px; }
}

/* ------------------------------------------------------------ motion off */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  #snow { display: none; }
}

body.calm #snow { display: none; }

body.calm .total::after,
body.calm .bar__fill::after { display: none; }
body.calm .bar__fill::before { animation: none; }
