/* ============================================================
   Open House 2026 — Soft 3D Mission Badge
   Needs tokens.css. Markup comes from assets/js/badge.js.

   Sizes: sm 72 / md 88 / lg 108, driven by --bdg-size.
   ============================================================ */
.bdg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

.bdg {
  --bdg-size: 88px;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: var(--bdg-size);
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: center;
  -webkit-tap-highlight-color: transparent;
}
.bdg--sm { --bdg-size: 72px; }
.bdg--md { --bdg-size: 88px; }
.bdg--lg { --bdg-size: 108px; }

.bdg-art {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1;
  min-width: 44px;
  min-height: 44px;
}
.bdg-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

/* soft ambient shadow under the token, light from the upper left */
.bdg-token { filter: drop-shadow(2px 5px 6px rgba(18, 61, 45, .22)); }
.bdg.is-locked .bdg-token { filter: drop-shadow(1px 3px 4px rgba(18, 61, 45, .12)); }
.bdg.is-completed .bdg-token,
.bdg.is-special .bdg-token { filter: drop-shadow(2px 5px 7px rgba(18, 61, 45, .26)) drop-shadow(0 0 7px rgba(246, 200, 78, .42)); }
/* Nothing at this event is actually locked: a family registered for the early
   years is welcome at the primary stations too, so a padlock on those badges
   told a lie.

   An uncollected badge used to keep half its colour (saturate .5, opacity .72).
   Half-desaturated pastel is the worst of both: too dull to look won, too tinted
   to look empty, and it turned the case into eleven dusty smudges. Now it goes
   fully grey — stone waiting to be filled — and colour is the entire reward for
   collecting it. The four silhouettes and the glyph still say which is which.
   Greyscale sits on the whole svg so the leaves go grey with the token; the
   glyph is HTML on top and has to be dimmed on its own. */
.bdg.is-available .bdg-svg { filter: grayscale(1) brightness(1.02) opacity(.72); }
.bdg.is-available .bdg-ic { color: #FBFDFB; opacity: .82; }
.bdg.is-available .bdg-label b { color: #5E6E64; }

/* shown as an emblem, not as a slot to fill — keeps its colour */
.bdg.is-available.bdg--full .bdg-svg { filter: none; }
.bdg.is-available.bdg--full .bdg-ic { opacity: 1; }
.bdg.is-available.bdg--full .bdg-label b { color: #123D2D; }

.bdg-leaves { opacity: 1; filter: drop-shadow(0 2px 2px rgba(18,61,45,.18)); }

/* ---- the case ----
   A grid of badges is a cabinet, so each one sits in a socket. Empty sockets
   read as slots to fill; a won badge lights its own up. Opt in with .bdg-grid
   or .bdg-case so badges used inline in a list row stay flat. */
.bdg-grid .bdg-art::before,
.bdg-case .bdg-art::before {
  content: "";
  position: absolute;
  left: 7%; top: 3%;
  width: 86%; height: 86%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, #EDF2EE 0%, #E0E8E2 66%, #D2DCD5 100%);
  box-shadow: inset 0 2px 5px rgba(19, 55, 38, .16), inset 0 -1px 0 rgba(255, 255, 255, .92);
  z-index: 0;
}
/* A won badge lights its plate. The centre stays pale so the token's own warm
   rim keeps a hard edge against it — a plate as gold as the rim just blurs the
   two into one lump. The inset ring is what gives the plate an edge of its own. */
.bdg-grid .bdg.is-completed .bdg-art::before,
.bdg-grid .bdg.is-special .bdg-art::before,
.bdg-case .bdg.is-completed .bdg-art::before,
.bdg-case .bdg.is-special .bdg-art::before {
  background: radial-gradient(circle at 50% 40%, #FFFCF2 0%, #FEF3D6 60%, #F9E4AC 100%);
  box-shadow: inset 0 0 0 1.5px rgba(226, 176, 62, .55), inset 0 1px 3px rgba(150, 104, 20, .12), 0 0 14px rgba(242, 178, 26, .38);
}

/* the light crossing a won badge, twice and then still */
.bdg.is-completed .bdg-shine,
.bdg.is-special .bdg-shine { animation: bdgSweep 3.6s cubic-bezier(.42, 0, .58, 1) .7s 2; }
@keyframes bdgSweep {
  0%        { transform: translateX(0); }
  42%, 100% { transform: translateX(152px); }
}

/* the glyph rides on the face; the token centre is 54/120 */
.bdg-ic {
  position: absolute;
  left: 50%;
  top: 45%;
  transform: translate(-50%, -50%);
  z-index: 2;
  font-size: calc(var(--bdg-size) * .33);
  color: #fff;
  line-height: 1;
}
.bdg.is-locked .bdg-ic { color: #FBFDFB; opacity: .65; }

/* a small points chip, kept out of the icon and away from the check mark */
.bdg-chip {
  position: absolute;
  top: 2%;
  left: 0;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--oh-cream, #FFF9EE);
  color: var(--oh-forest, #075B3B);
  font-size: calc(var(--bdg-size) * .125);
  font-weight: 700;
  line-height: 1.35;
  box-shadow: 0 1px 3px rgba(18, 61, 45, .2);
}
.bdg-chip i { font-size: .9em; color: #E6AC33; }

/* the label is HTML so Thai shapes and truncates properly */
.bdg-label { display: block; line-height: 1.25; max-width: 118%; }
.bdg-label b {
  display: block;
  font-size: clamp(12.5px, calc(var(--bdg-size) * .16), 15px);
  font-weight: 700;
  color: #123D2D;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bdg-label small {
  display: block;
  margin-top: 1px;
  font-size: clamp(10px, calc(var(--bdg-size) * .125), 12px);
  color: #718077;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bdg.is-locked .bdg-label b { color: #5E6E64; }

/* interaction */
button.bdg { cursor: pointer; transition: transform .2s cubic-bezier(.34, 1.2, .64, 1); }
button.bdg:hover, button.bdg:focus-visible { transform: translateY(-2px) scale(1.025); }
button.bdg:active { transform: translateY(0) scale(.99); }
button.bdg:focus-visible { outline: 2px solid var(--oh-gold, #E6AC33); outline-offset: 4px; border-radius: 12px; }
button.bdg.is-locked:hover, button.bdg.is-locked:focus-visible { transform: none; }

/* the moment a mission completes */
.bdg.is-slam .bdg-art { animation: bdgPop .5s cubic-bezier(.34, 1.4, .5, 1); }
@keyframes bdgPop {
  0%   { transform: scale(.85); }
  55%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}
.bdg-spark { opacity: 0; animation: bdgSpark .7s ease-out .18s forwards; }
.bdg-spark2 { animation-delay: .34s; }
@keyframes bdgSpark {
  0%   { opacity: 0; transform: scale(.4); transform-origin: center; }
  60%  { opacity: 1; }
  100% { opacity: .9; transform: scale(1); }
}

/* A badge worth walking to next. Six breaths, not forever: parents keep this
   app open for hours and an endless animation is a background battery drain
   that carries no extra information after the first few pulses. */
.bdg.is-next .bdg-token { animation: bdgBreathe 2.6s ease-in-out 6; }
@keyframes bdgBreathe {
  0%, 100% { filter: drop-shadow(2px 5px 6px rgba(18, 61, 45, .2)) drop-shadow(0 0 5px rgba(255, 255, 255, .8)); }
  50%      { filter: drop-shadow(2px 5px 6px rgba(18, 61, 45, .2)) drop-shadow(0 0 12px rgba(246, 200, 78, .75)); }
}

/* mobile first: three across on a narrow phone, more when there is room */
.bdg-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 20px 8px;
  justify-items: center;
}
@media (min-width: 560px) { .bdg-grid { grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); } }

@media (prefers-reduced-motion: reduce) {
  .bdg.is-slam .bdg-art,
  .bdg-spark,
  .bdg-shine,
  .bdg.is-next .bdg-token { animation: none; }
  .bdg-spark { opacity: .9; }
  button.bdg { transition: none; }
  button.bdg:hover, button.bdg:focus-visible { transform: none; }
}
