/* The shared kit's looks: the round avatar (avatar.js), the road of the class (journey.js) and the celebrations (celebrate.js).
   One file for all three, so every page that uses any of them loads just this one next to board.css.
   Fonts come from board.css (--font, Vazirmatn); no letter-spacing on Persian text; weights 400 text, 500 labels, 600-700 headings.
   Positions that depend on the data are set by the scripts through the DOM (the page's security policy forbids style attributes),
   everything else is a class. */

/* ====================================================================== avatar */

.av {
  --av: 40px;
  display: inline-grid; place-items: center; flex: none; vertical-align: middle;
  width: var(--av); height: var(--av); border-radius: 50%; overflow: hidden;
  background: var(--av-bg, #e8ecfb);
  box-shadow: 0 0 0 2px #fff, 0 1px 5px rgba(23, 32, 58, .28);
  font-size: calc(var(--av) * .6); line-height: 1; user-select: none;
}
.av-sm { --av: 28px; }
.av-md { --av: 40px; }
.av-lg { --av: 64px; }
.av-xl { --av: 112px; }
.av img { display: block; width: 100%; height: 100%; object-fit: cover; }
.av-emoji { display: block; line-height: 1; }
.av-generic { --av-bg: #e4e8f2; filter: grayscale(.5); opacity: .9; }
/* the initial: a white letter on a two-colour disc; the disc colour follows the person (the same 8 tones) */
.av-initial { color: #fff; font-weight: 700; font-size: calc(var(--av) * .48); text-shadow: 0 1px 2px rgba(0, 0, 0, .18); }
.av-initial.av-t0 { background: linear-gradient(145deg, #ff8a5b, #e0452f); }
.av-initial.av-t1 { background: linear-gradient(145deg, #ffc84a, #e08a00); }
.av-initial.av-t2 { background: linear-gradient(145deg, #7fd36b, #2f9a4a); }
.av-initial.av-t3 { background: linear-gradient(145deg, #4fd1b8, #138a7a); }
.av-initial.av-t4 { background: linear-gradient(145deg, #5fb4ff, #1f6fd1); }
.av-initial.av-t5 { background: linear-gradient(145deg, #8f8bff, #4e3fd6); }
.av-initial.av-t6 { background: linear-gradient(145deg, #d98bff, #8f3fd1); }
.av-initial.av-t7 { background: linear-gradient(145deg, #ff86b8, #d1336f); }
.av-letter { display: block; line-height: 1; transform: translateY(.04em); }
.av-t0 { --av-bg: #ffe0d2; }
.av-t1 { --av-bg: #ffefb8; }
.av-t2 { --av-bg: #d9f3c8; }
.av-t3 { --av-bg: #c9f1e4; }
.av-t4 { --av-bg: #cfe9ff; }
.av-t5 { --av-bg: #dcd9ff; }
.av-t6 { --av-bg: #f3d6ff; }
.av-t7 { --av-bg: #ffd3e6; }

/* ====================================================================== the road */

.jr {
  --jr-ink: var(--ink, #17203a);
  --jr-ink-2: var(--ink-2, #4b5675);
  --jr-accent: var(--accent, #2740c9);
  --jr-gold: #ffb400;
  /* the size class chooses these. xl is the projector (names 28 px on a 1920 px wide screen); journey.js sets --jr-s, the width of the
     road divided by 1860, so a smaller picture (1366 px: names 20 px) is the same layout scaled down, never below 18 px for a name. */
  --jr-s: 1;
  --jr-av: 40px; --jr-name: 20px; --jr-place: 23px; --jr-title: 20px; --jr-node: 68px; --jr-emoji: 38px; --jr-lv: 24px;
  --jr-road: 34px; --jr-turn: 42px; --jr-stub: 48px; --jr-padx: 70px; --jr-pady: 18px; --jr-gapx: 10px; --jr-gapy: 16px; --jr-wobble: 16px;
  --jr-basis: 168px; --jr-gutter: 84px;
  position: relative; isolation: isolate; box-sizing: border-box; overflow: hidden;
  direction: rtl; text-align: center; color: var(--jr-ink); font-family: var(--font);
  padding: var(--jr-pady) var(--jr-padx);
  border: 2px solid #d6e0fb; border-radius: 30px;
  background:
    radial-gradient(rgba(39, 64, 201, .07) 1.6px, transparent 1.8px) 0 0 / 24px 24px,
    linear-gradient(180deg, #e8f2ff 0%, #f5f8ff 55%, #fff4dc 100%);
}
.jr * { box-sizing: border-box; }
.jr-xl {
  --jr-node: max(58px, calc(96px * var(--jr-s)));
  --jr-av: max(30px, calc(44px * var(--jr-s)));
  --jr-name: max(20px, calc(28px * var(--jr-s)));
  --jr-place: max(20px, calc(32px * var(--jr-s)));
  --jr-title: max(20px, calc(28px * var(--jr-s)));
  --jr-emoji: calc(var(--jr-node) * .54); --jr-lv: calc(var(--jr-node) * .31); --jr-road: calc(var(--jr-node) * .48);
  --jr-turn: calc(var(--jr-node) * .58); --jr-stub: calc(var(--jr-node) * .66); --jr-padx: calc(var(--jr-node) * 1.14);
  --jr-pady: calc(var(--jr-node) * .27); --jr-gapx: calc(var(--jr-node) * .17); --jr-gapy: calc(var(--jr-node) * .23);
  --jr-wobble: calc(var(--jr-node) * .27); --jr-basis: calc(var(--jr-node) * 2.46);
}
.jr-md { --jr-av: 32px; --jr-name: 18px; --jr-place: 20px; --jr-title: 17px; --jr-node: 60px; --jr-emoji: 32px; --jr-lv: 21px; --jr-road: 28px; --jr-turn: 36px; --jr-stub: 40px; --jr-padx: 56px; --jr-pady: 20px; --jr-gapx: 8px; --jr-gapy: 18px; --jr-wobble: 18px; --jr-basis: 128px; }
.jr-sm { --jr-av: 30px; --jr-name: 16px; --jr-place: 18px; --jr-title: 15px; --jr-node: 56px; --jr-emoji: 30px; --jr-lv: 20px; --jr-road: 22px; --jr-turn: 30px; --jr-stub: 30px; --jr-padx: 12px; --jr-pady: 20px; --jr-gapx: 8px; --jr-gapy: 14px; --jr-wobble: 0px; --jr-gutter: 84px; border-radius: 24px; }

/* the road itself: an SVG behind the stops, drawn by journey.js through the middle of every stop */
.jr-road { position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; overflow: visible; filter: drop-shadow(0 8px 10px rgba(33, 44, 105, .22)); }
.jr-road path { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.jr-road-edge { stroke: #ffffff; stroke-width: calc(var(--jr-road) + 14px); }
.jr-road-bed { stroke: #5d6590; stroke-width: var(--jr-road); }
.jr-road-lit { stroke: #3340b5; stroke-width: var(--jr-road); }
.jr-road-dash { stroke: rgba(255, 255, 255, .8); stroke-width: 4px; stroke-dasharray: 14 20; stroke-linecap: butt; animation: jr-march 3s linear infinite; }
@keyframes jr-march { to { stroke-dashoffset: -34; } }

/* the stops are in rows: on the snake the stops of a row share the width in proportion to how many people stand there */
.jr-stops { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--jr-gapy); }
.jr-row { display: flex; align-items: flex-start; gap: var(--jr-gapx); list-style: none; margin: 0; padding: 0; }
.jr-stop { --h: 210; position: relative; display: flex; flex-direction: column; align-items: center; min-width: 0; }
.jr-stop[data-level="1"] { --h: 28; }
.jr-stop[data-level="2"] { --h: 46; }
.jr-stop[data-level="3"] { --h: 92; }
.jr-stop[data-level="4"] { --h: 150; }
.jr-stop[data-level="5"] { --h: 178; }
.jr-stop[data-level="6"] { --h: 205; }
.jr-stop[data-level="7"] { --h: 232; }
.jr-stop[data-level="8"] { --h: 262; }
.jr-stop[data-level="9"] { --h: 296; }
.jr-stop[data-level="10"] { --h: 334; }

/* the stop on the road: a round milestone with the icon, the number of the stop, and the flag when the class has got this far */
.jr-node {
  position: relative; z-index: 2; flex: none; display: grid; place-items: center;
  width: var(--jr-node); height: var(--jr-node); border-radius: 50%;
  background: #fff; border: 6px solid hsl(var(--h), 78%, 54%);
  box-shadow: 0 8px 18px rgba(24, 32, 80, .26), inset 0 -6px 12px hsla(var(--h), 70%, 50%, .12);
}
.jr-emoji { font-size: var(--jr-emoji); line-height: 1; display: inline-grid; place-items: center; color: var(--accent-dark, #2a2ca3); }
.jr-emoji .ic { width: 1em; height: 1em; }
.jr-flag .ic { width: 1em; height: 1em; color: #d63a2f; }
.jr-lv {
  position: absolute; top: -8px; inset-inline-start: -10px; display: grid; place-items: center;
  min-width: var(--jr-lv); height: var(--jr-lv); padding: 0 6px; border-radius: 999px;
  background: hsl(var(--h), 70%, 28%); color: #fff; border: 3px solid #fff;
  font-size: calc(var(--jr-lv) * .62); font-weight: 700; line-height: 1;
}
.jr-flag {
  position: absolute; top: -20px; inset-inline-end: -12px; font-size: calc(var(--jr-node) * .36); line-height: 1;
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, .3)); transform-origin: 20% 90%; animation: jr-wave 3.2s ease-in-out infinite;
}
@keyframes jr-wave { 0%, 100% { transform: rotate(-4deg); } 50% { transform: rotate(7deg); } }
.jr-xl .jr-lv { display: none; }                  /* too small to read from the back row: the stop is known by its icon and its name */

/* the sign that hangs under the stop: its name, the title one gets there, and the people who are standing at it */
.jr-plate {
  --jr-overlap: calc(var(--jr-node) / 2 - var(--jr-road) / 2 - 10px);
  position: relative; z-index: 1; width: 100%; min-width: 0;
  margin-top: calc(var(--jr-overlap) * -1); padding: calc(var(--jr-overlap) + 10px) 10px 12px;
  background: #fff; border: 3px solid hsl(var(--h), 62%, 80%); border-radius: 24px;
  box-shadow: 0 10px 22px rgba(30, 40, 90, .14);
}
.jr-text { display: grid; gap: 0; justify-items: center; }
.jr-place { font-size: var(--jr-place); font-weight: 700; line-height: 1.4; }
.jr-title { font-size: var(--jr-title); font-weight: 500; line-height: 1.5; color: hsl(var(--h), 68%, 27%); }
.jr-nb { white-space: nowrap; }
.jr-hint { margin: 6px 0 0; font-size: calc(var(--jr-title) * .9); line-height: 1.7; color: var(--jr-ink-2); }
.jr-you {
  display: inline-flex; align-items: center; gap: 8px; margin: 8px 0 0; padding: 0 16px 0 14px; border-radius: 999px; white-space: nowrap;
  background: var(--jr-accent); color: #fff; font-size: calc(var(--jr-name) * .95); font-weight: 700; line-height: 1.7;
}
.jr-arrow { font-size: .8em; }

/* the people: small round faces with the name beside them, always in the order of their numbers */
.jr-people { display: flex; flex-wrap: wrap; justify-content: center; gap: 7px; list-style: none; margin: 8px 0 0; padding: 0; min-width: 0; }
.jr-people:empty { display: none; }
.jr-item { display: flex; max-width: 100%; min-width: 0; margin: 0; }
.jr .jr-chip {
  position: relative; display: inline-flex; align-items: center; gap: 8px; max-width: 100%; min-width: 0; min-height: 0;
  margin: 0; padding: 3px 5px 3px 13px; border-radius: 999px;
  background: hsl(var(--h), 92%, 95%); border: 2px solid hsl(var(--h), 58%, 76%); color: var(--jr-ink);
  font: 600 var(--jr-name) / 1.4 var(--font, system-ui, sans-serif); text-align: start;
}
.jr .jr-chip .jr-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jr .jr-chip .av { --av: var(--jr-av); }
.jr-face { position: relative; display: inline-flex; flex: none; }
.jr-dot { position: absolute; inset-inline-end: -3px; bottom: -3px; width: 14px; height: 14px; border-radius: 50%; background: #18a957; border: 2px solid #fff; }
button.jr-chip { cursor: pointer; appearance: none; }
button.jr-chip:hover { background: hsl(var(--h), 92%, 90%); }
.jr .jr-chip:focus-visible, .jr .jr-more:focus-visible { outline: 3px solid var(--jr-accent); outline-offset: 3px; }

/* on a narrower road the plates are narrow too: the face above the name, so even a long name has the whole width of the plate */
.jr-snake.jr-md .jr-chip { flex-direction: column; justify-content: flex-start; gap: 2px; padding: 5px 8px 3px; border-radius: 18px; text-align: center; }
.jr-snake.jr-md .jr-people { gap: 6px; }
.jr-snake.jr-md .jr-more { min-height: 44px; align-self: center; }
.jr-snake.jr-md .jr-plate { padding-inline: 6px; }

/* the person the page points at: a ring and a glow around the face and a label at the stop, so it is more than colour */
.jr .jr-chip.jr-me {
  background: #fff; border-color: var(--jr-accent);
  box-shadow: 0 0 0 3px #fff, 0 0 0 6px var(--jr-accent), 0 0 22px 8px rgba(39, 64, 201, .38);
  animation: jr-glow 2.4s ease-in-out infinite;
}
@keyframes jr-glow { 0%, 100% { box-shadow: 0 0 0 3px #fff, 0 0 0 6px var(--jr-accent), 0 0 18px 6px rgba(39, 64, 201, .3); } 50% { box-shadow: 0 0 0 3px #fff, 0 0 0 6px var(--jr-accent), 0 0 30px 12px rgba(39, 64, 201, .5); } }
.jr-mine .jr-plate { border-color: var(--jr-accent); border-width: 4px; box-shadow: 0 0 0 5px rgba(39, 64, 201, .16), 0 12px 26px rgba(30, 40, 90, .2); }
.jr-mine .jr-node::after {
  content: "▼"; position: absolute; left: 50%; top: calc(var(--jr-node) * -.46); transform: translateX(-50%);
  font-size: calc(var(--jr-node) * .42); line-height: 1; color: var(--jr-accent); text-shadow: 0 2px 0 #fff, 0 0 8px #fff;
  animation: jr-bob 1.1s ease-in-out infinite;
}
@keyframes jr-bob { 0%, 100% { transform: translate(-50%, 0); } 50% { transform: translate(-50%, 8px); } }

/* "+4": the rest of the people of a crowded stop; a tap opens the whole list */
.jr .jr-more {
  display: inline-flex; align-items: center; justify-content: center; min-height: calc(var(--jr-av) + 12px); min-width: calc(var(--jr-av) + 12px); margin: 0; padding: 0 14px;
  border-radius: 999px; background: #fff; border: 2px dashed hsl(var(--h), 55%, 52%); color: hsl(var(--h), 68%, 27%);
  font: 700 var(--jr-name) / 1.4 var(--font, system-ui, sans-serif); cursor: pointer;
}
.jr .jr-more:hover { background: hsl(var(--h), 92%, 94%); }
.jr-more-n { unicode-bidi: isolate; }

/* a stop nobody has reached: quieter, but still easy to read */
.jr-empty .jr-node { border-color: #bcc5e0; background: #f4f6fc; box-shadow: 0 4px 10px rgba(24, 32, 80, .12); }
.jr-empty .jr-emoji { filter: grayscale(.75); opacity: .6; }
.jr-empty .jr-lv { background: #5f6a90; }
.jr-empty .jr-plate { background: rgba(255, 255, 255, .62); border-color: #cdd5ec; border-style: dashed; box-shadow: none; }
.jr-empty .jr-place { color: #3d4868; }
.jr-empty .jr-title { color: #56618a; }

/* the stop where the farthest person is */
.jr-top .jr-plate { border-color: hsl(var(--h), 70%, 62%); }

/* ---------- accessible text that is not drawn ---------- */
.jr-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* ---------- the snake: projectors and tablets ---------- */
.jr-snake .jr-row:nth-child(even) { flex-direction: row-reverse; }            /* the second row runs back, from the left */
.jr-snake .jr-stop { flex: 1 1 var(--jr-basis); }
.jr-snake .jr-stop.jr-alt { margin-top: var(--jr-wobble); }

/* a short screen: no title under the name of a stop, tighter spacing and a smaller milestone */
.jr-snake.jr-compact { --jr-gapy: calc(var(--jr-node) * .12); --jr-wobble: calc(var(--jr-node) * .1); }
.jr-snake.jr-compact .jr-title { display: none; }
.jr-snake.jr-compact .jr-plate { padding-bottom: 8px; }
.jr-snake.jr-compact.jr-xl { --jr-node: max(52px, calc(84px * var(--jr-s))); --jr-place: max(20px, calc(30px * var(--jr-s))); --jr-pady: calc(var(--jr-node) * .15); }
.jr-snake.jr-compact.jr-md { --jr-node: 48px; --jr-emoji: 26px; --jr-lv: 18px; --jr-road: 22px; --jr-turn: 28px; --jr-av: 28px; --jr-place: 18px; --jr-padx: 48px; --jr-pady: 12px; --jr-gapy: 10px; --jr-wobble: 8px; }

/* ---------- the vertical road: phones ---------- */
.jr-vertical .jr-row { flex-direction: column; align-items: stretch; gap: var(--jr-gapy); }
.jr-vertical .jr-stop { display: grid; grid-template-columns: var(--jr-gutter) minmax(0, 1fr); column-gap: 6px; align-items: start; }
.jr-vertical .jr-node { grid-column: 1; grid-row: 1; justify-self: start; margin-top: 8px; }
.jr-vertical .jr-stop.jr-alt .jr-node { justify-self: end; }
.jr-vertical .jr-plate { grid-column: 2; grid-row: 1; margin: 0; padding: 10px 12px 12px; text-align: start; border-radius: 20px; }
.jr-vertical .jr-text { justify-items: start; }
.jr-vertical .jr-people { justify-content: flex-start; margin-top: 8px; }
.jr-vertical .jr-mine .jr-node::after { top: calc(var(--jr-node) * -.5); }
.jr-vertical .jr-chip { min-height: 44px; }
.jr-vertical .jr-more { min-height: 44px; }
.jr-vertical .jr-you { margin-top: 8px; }

/* ---------- the strip: one thin row (the projector while a program is on the screen) ---------- */
.jr-strip { border-radius: 22px; }
.jr-strip.jr-xl { --jr-node: max(40px, calc(64px * var(--jr-s))); --jr-emoji: calc(var(--jr-node) * .53); --jr-lv: calc(var(--jr-node) * .34); --jr-road: calc(var(--jr-node) * .44); --jr-av: max(26px, calc(38px * var(--jr-s))); --jr-stub: calc(var(--jr-node) * .56); --jr-padx: calc(var(--jr-node) * .62); --jr-pady: calc(var(--jr-node) * .28); }
.jr-strip.jr-md, .jr-strip.jr-sm { --jr-node: 44px; --jr-emoji: 24px; --jr-lv: 18px; --jr-road: 18px; --jr-av: 28px; --jr-stub: 22px; --jr-padx: 20px; --jr-pady: 12px; }
.jr-strip .jr-stop { flex: 1 1 0; }
.jr-strip .jr-row { gap: 6px; }
.jr-strip .jr-plate { margin: 4px 0 0; padding: 0; background: none; border: 0; box-shadow: none; }
.jr-strip .jr-text, .jr-strip .jr-hint, .jr-strip .jr-you { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); }
.jr-strip .jr-empty .jr-plate { background: none; }
.jr-strip .jr-people { gap: 5px; margin-top: 6px; }
.jr-strip .jr-many .jr-chip .av { --av: calc(var(--jr-av) * .75); }          /* a crowded stop: smaller faces, so that everybody still fits in a few rows */
.jr-strip .jr-chip { padding: 0; background: none; border: 0; box-shadow: none; }
.jr-strip .jr-chip.jr-me { box-shadow: 0 0 0 3px var(--jr-accent), 0 0 16px 6px rgba(39, 64, 201, .4); border-radius: 50%; }
.jr-strip .jr-name { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); }
.jr-strip .jr-more { min-height: 30px; min-width: 30px; padding: 0 8px; font-size: 18px; }
.jr-strip .jr-mine .jr-plate { box-shadow: none; }

/* ---------- somebody travelling to a higher stop ---------- */
.jr-fly { position: absolute; inset: 0; z-index: 4; pointer-events: none; overflow: visible; }
.jr-traveller { position: absolute; display: grid; place-items: center; transition: transform 1.7s cubic-bezier(.45, 0, .2, 1); }
.jr-traveller .av { --av: var(--jr-av); box-shadow: 0 0 0 3px #fff, 0 0 0 6px var(--jr-gold), 0 8px 20px rgba(0, 0, 0, .35); }
.jr-traveller.jr-going .av { animation: jr-hop 1.7s ease-in-out both; }
@keyframes jr-hop { 0%, 100% { transform: translateY(0) scale(1); } 50% { transform: translateY(-34px) scale(1.55); } }
.jr-chip.jr-await { visibility: hidden; }
.jr-chip.jr-pop { animation: jr-pop .7s cubic-bezier(.2, 1.5, .4, 1) both; }
@keyframes jr-pop { 0% { transform: scale(.4); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .jr-road-dash, .jr-flag, .jr .jr-chip.jr-me, .jr-mine .jr-node::after, .jr-chip.jr-pop { animation: none; }
  .jr-mine .jr-node::after { transform: translateX(-50%); }
  .jr-traveller { transition: none; }
}

/* ====================================================================== celebrations */

.cel { z-index: 90; display: grid; place-items: center; pointer-events: none; overflow: hidden; animation: cel-in .25s ease-out both; }
.cel-page { position: fixed; inset: 0; }
.cel-box { position: absolute; inset: 0; }
.cel-host { position: relative; }
.cel:not(.cel-small) { background: radial-gradient(circle at 50% 46%, rgba(255, 255, 255, .5) 0, rgba(18, 26, 78, .48) 100%); }
.cel-leaving { animation: cel-out .45s ease-in both; }
@keyframes cel-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes cel-out { from { opacity: 1; } to { opacity: 0; } }

.cel-card {
  position: relative; z-index: 1; display: grid; justify-items: center; gap: 14px; text-align: center; direction: rtl;
  width: min(900px, 92%); padding: 32px 40px 30px; border-radius: 40px; background: #fff; color: var(--ink, #17203a);
  box-shadow: 0 0 0 8px hsl(var(--cel-h, 210), 70%, 72%), 0 36px 90px rgba(12, 18, 60, .5);
  font-family: var(--font); animation: cel-pop .7s cubic-bezier(.2, 1.35, .4, 1) both;
}
@keyframes cel-pop { from { transform: translateY(40px) scale(.7); opacity: 0; } to { transform: none; opacity: 1; } }
.cel-stage { display: flex; align-items: center; justify-content: center; gap: 28px; }
.cel-avatar .av { box-shadow: 0 0 0 6px #fff, 0 0 0 12px hsl(var(--cel-h, 210), 65%, 60%), 0 14px 34px rgba(12, 18, 60, .35); }
.cel-emoji .ic-page, .cel-emoji .ic-hand, .cel-emoji .ic-printer, .cel-emoji .ic-box, .cel-emoji .ic-mic, .cel-emoji .ic-signal, .cel-emoji .ic-loop, .cel-emoji .ic-wrench, .cel-emoji .ic-bug, .cel-emoji .ic-brain { width: 1em; height: 1em; color: #fff; }
.cel-emoji { font-size: clamp(64px, 11vw, 132px); line-height: 1; filter: drop-shadow(0 10px 16px rgba(12, 18, 60, .3)); animation: cel-emoji 1.1s .15s cubic-bezier(.2, 1.6, .4, 1) both; }
@keyframes cel-emoji { from { transform: scale(.2) rotate(-28deg); opacity: 0; } 55% { transform: scale(1.25) rotate(8deg); opacity: 1; } to { transform: scale(1) rotate(0); opacity: 1; } }
.cel-text { margin: 0; font-size: clamp(24px, 3.1vw, 54px); font-weight: 700; line-height: 1.6; overflow-wrap: anywhere; }
.cel-more { margin: -4px 0 0; color: var(--ink-2, #4b5675); font-size: clamp(18px, 1.9vw, 32px); font-weight: 400; line-height: 1.7; }

/* an arrival or a newcomer: a quiet banner at the top, no confetti */
.cel-small { place-items: start center; padding-top: 4vh; }
.cel-small .cel-card { display: flex; align-items: center; justify-content: center; gap: 20px; width: auto; max-width: min(92%, 920px); padding: 12px 32px 12px 24px; border-radius: 999px; box-shadow: 0 0 0 5px hsl(var(--cel-h, 150), 60%, 72%), 0 18px 44px rgba(12, 18, 60, .32); animation: cel-drop .6s cubic-bezier(.2, 1.3, .4, 1) both; }
.cel-small .cel-stage { gap: 12px; }
.cel-small .cel-text { font-size: clamp(20px, 2.2vw, 38px); }
@keyframes cel-drop { from { transform: translateY(-70px); opacity: 0; } to { transform: none; opacity: 1; } }

/* confetti: each piece gets its own random numbers from celebrate.js (custom properties set through the DOM) */
.cel-confetti { position: absolute; inset: 0; overflow: hidden; }
.cf { position: absolute; top: -40px; left: var(--x); width: var(--w); height: var(--h); background: hsl(var(--hue), 80%, 58%); animation: cf-fall var(--dur) var(--delay) cubic-bezier(.25, .55, .5, 1) both; }
.cf-1 { border-radius: 50%; height: var(--w); }
.cf-2 { clip-path: polygon(50% 0, 100% 100%, 0 100%); }
@keyframes cf-fall {
  0% { transform: translate3d(0, 0, 0) rotate(0); opacity: 0; }
  8% { opacity: 1; }
  100% { transform: translate3d(var(--dx), var(--fall), 0) rotate(var(--rot)); opacity: .95; }
}

@media (prefers-reduced-motion: reduce) {
  .cel, .cel-card, .cel-emoji, .cel-small .cel-card { animation: none; }
  .cel-leaving { opacity: 0; transition: opacity .3s; animation: none; }
}
