/*
 * Pickle Earn: the site's own rules, on top of shared-ui/components.css.
 *
 * Everything structural comes from the shared vocabulary - .ex-cell grids,
 * .ex-panel, .ex-kv, .ex-table, the pills and badges. What is here is the quest
 * card's inner rhythm, the progress bars, the identity rows and the footer the
 * home page keeps in its own stylesheet. Colour goes through the register
 * properties, never through a literal, for the same reason it does everywhere
 * else: a section that re-grounds itself has to be able to invert it.
 *
 * No rule here hides content. The Privy SDK forces `style-src 'unsafe-inline'`
 * on this origin; this file does not take that as licence, and the page's own
 * markup carries no style attribute - the progress bars are <progress> elements
 * for exactly that reason.
 */

/* ------------------------------------------------------------------- hero */
.earn-hero {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: var(--pickle-space-7);
  align-items: center;
}

.earn-hero .ex-panel { min-width: 0; }
.earn-hero .ex-actions .ex-btn { min-height: 52px; padding-inline: 26px; }

@media (max-width: 1023px) {
  .earn-hero { grid-template-columns: minmax(0, 1fr); gap: var(--pickle-space-6); }
}

/* ------------------------------------------------------------ the notice */
.earn-notice { padding-top: var(--pickle-space-4); }
.earn-notice .ex-banner { justify-content: space-between; }
.earn-notice .ex-banner span { flex: 1 1 auto; min-width: 0; }

/* The sign-in control and its menu share one positioned box, like wallet.js's. */
.earn-auth { position: relative; display: flex; align-items: center; height: var(--pickle-nav-h); }
.earn-auth .ex-wmenu { top: calc(50% + 24px); }

/* ---------------------------------------------------------- quest cards */
/* The board lays its own tiles rather than borrowing `.ex-cells`, which is one
   panel divided by its own background showing through 1px gaps. That is right
   when the grid is full and wrong when it is not: four quests in three columns
   left two empty tracks reading as a grey slab the width of two cards, and no
   number of quests divides evenly by three. Separate tiles have no empty tracks
   to show, and three, four or seven of them look deliberate either way.

   They also wrap by width rather than by a fixed count, so a narrow laptop gets
   two across instead of three squeezed ones. */
.earn-tiles {
  display: grid;
  gap: var(--pickle-space-3);
  /* min(), not the bare length: auto-fill holds a 19rem track even when the
     container is narrower than 19rem, and the row then hangs off the phone. */
  grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
  align-items: stretch;
}

.earn-tiles.two { grid-template-columns: repeat(auto-fill, minmax(min(26rem, 100%), 1fr)); }

.earn-tiles > .ex-cell {
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
}

.earn-quest { display: flex; flex-direction: column; gap: var(--pickle-space-3); min-width: 0; }

.earn-quest-head {
  display: flex;
  gap: var(--pickle-space-3);
  align-items: center;
  justify-content: space-between;
}

.earn-quest-kicker {
  color: var(--pickle-subtle);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
  letter-spacing: var(--pickle-tracking-caps);
  text-transform: uppercase;
}

.earn-quest h3 { margin: 0; font-size: var(--pickle-text-lg); }
.earn-quest > p { margin: 0; color: var(--pickle-muted); font-size: var(--pickle-text-sm); line-height: 1.6; }

/* Everything above is content; from here down is the foot of the card. The
   auto margin needs this specificity to survive `.earn-quest > p { margin: 0 }`,
   which is a child selector and was quietly winning - which is why a short card
   left its points floating in the middle with a hand's width of nothing under
   them. */
.earn-quest > .earn-quest-pay { margin-top: auto; }

.earn-quest-extra { color: var(--pickle-muted); font-size: var(--pickle-text-sm); }

/* Why a card cannot be claimed is a note about the service, not part of the
   quest's description, and it should not read like one. */
/* The line that says why a card cannot be claimed is about the service, not
   about the quest, so it is quieter than the body it sits under. By class:
   :last-of-type counts element names, and the pay row is a <p> too, so a
   positional selector never reaches this one. */
.earn-quest-why { color: var(--pickle-subtle); }
.earn-quest-extra b { color: var(--pickle-text); font-weight: 500; }

.earn-quest-pay {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pickle-space-3);
  align-items: center;
  padding-top: var(--pickle-space-3);
  border-top: 1px solid var(--pickle-line);
  color: var(--pickle-subtle);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
  letter-spacing: .08em;
  text-transform: uppercase;
}

.earn-quest-pay b {
  color: var(--pickle-accent-text);
  font-family: var(--pickle-font-display);
  font-size: var(--pickle-text-lg);
  font-weight: 600;
  letter-spacing: -.02em;
  text-transform: none;
}

/* A done card is marked by a rule down its left, never by fading it. */
.earn-quest.is-done { box-shadow: inset 2px 0 0 var(--pickle-mint); }
.earn-quest.is-pending { box-shadow: inset 2px 0 0 var(--pickle-amber); }
.earn-quest.is-link { box-shadow: inset 2px 0 0 var(--pickle-amber); }

/* The review desk. Two columns of submissions, each a cell with its own small
   form; the decision controls sit at the bottom so the eye reads the evidence
   first and the buttons last. */
.earn-review { display: flex; flex-direction: column; }

.earn-review .ex-kv { margin-block: var(--pickle-space-3); }
.earn-review .ex-kv dd { overflow-wrap: anywhere; }

/* The page-wide identity row gives its key a 9rem column and a gap after it.
   Inside a half-width card that is half the card spent on the word ACCOUNT,
   and the gap cuts the rule under the row into two floating pieces. Tighter
   key, no gap, so the rule is one line across the card.

   Only where there are two columns to tighten. Under 768px the shared sheet
   stacks the pair and takes the key's own hairline away, so forcing the grid
   back would leave a rule that starts a third of the way across the card. */
@media (min-width: 768px) {
  .earn-review .ex-kv { grid-template-columns: minmax(4rem, 6.5rem) minmax(0, 1fr); column-gap: 0; }
  .earn-review .ex-kv dt { padding-inline-end: var(--pickle-space-3); }
}

/* The label sits on the field it names, and the decision block sinks to the
   foot so Approve lines up across a row of cards of different heights. */
.earn-review-act {
  display: grid;
  gap: var(--pickle-space-2);
  margin-block-start: var(--pickle-space-4);
  padding-block-start: var(--pickle-space-4);
  /* The auto margin below sinks this block, and in the shortest card of a row
     that leaves a tall bare band above it. A rule turns the band into the top
     of a section rather than into a gap where something failed to render. */
  border-block-start: 1px solid var(--pickle-line);
}
.earn-review-act label { margin: 0; }
/* a label belongs to the field under it, so it wants more air above than below */
.earn-review-act input + label { margin-block-start: var(--pickle-space-2); }
.earn-review-act .ex-actions { margin: var(--pickle-space-2) 0 0; }
.earn-review > .earn-review-act { margin-top: auto; }

/* Unbinding and excluding are about the person, not this submission, so they
   come after the decision and under a rule, quiet rather than in the way. */
.earn-review-who {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--pickle-space-2, 8px);
  margin-block-start: var(--pickle-space-4);
  padding-block-start: var(--pickle-space-3);
  border-block-start: 1px solid var(--pickle-line);
}
.earn-review-who .ex-note { margin-inline-end: auto; }

/* The bots panel. A job is a row of three: what it is, how it is, what can be
   done to it; the credential forms sit under them because reading the state
   comes before changing it. */
/* A job is a headline and a sentence, not a three-column identity row: reusing
   that grid squeezed the name and its description into a 5rem column, which
   wrapped "posts the day's rally into the community" into a tower of single
   words. Name, state and the three verbs on one line; what it does underneath,
   where a sentence has the width to be one. */
.earn-jobs { margin-block: var(--pickle-space-4); border: 1px solid var(--pickle-line); border-radius: var(--pickle-radius); }
.earn-job { padding: var(--pickle-space-3) var(--pickle-space-4); background: var(--pickle-surface-1); }
.earn-job + .earn-job { border-top: 1px solid var(--pickle-line); }
.earn-job-top { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pickle-space-2); }
.earn-job-name { font-size: var(--pickle-text-sm); color: var(--pickle-text); }
.earn-job-do { display: flex; flex-wrap: wrap; gap: var(--pickle-space-2); margin-inline-start: auto; }
.earn-job-about, .earn-job-err {
  margin: var(--pickle-space-2) 0 0;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-xs);
  line-height: 1.5;
  overflow-wrap: anywhere;
}
.earn-job-err { color: var(--pickle-amber); font-family: var(--pickle-font-mono); }

/* The credential forms. One rule about secrets, said once above all three,
   instead of the same paragraph three times. */
.earn-creds-rule { margin-block: var(--pickle-space-4) 0; }
.earn-creds { margin-block-start: var(--pickle-space-5); }
.earn-creds-head {
  margin-block-end: var(--pickle-space-3);
  padding-block-start: var(--pickle-space-4);
  border-block-start: 1px solid var(--pickle-line);
}
.earn-creds-grid {
  display: grid;
  gap: var(--pickle-space-4);
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

/* "Bot token, from the developer portal" wraps to two lines where "Server id"
   takes one, and top-aligned fields then put four inputs on three different
   baselines. The field is a column with the input pushed to its foot, and the
   grid stretches every field in a row to one height, so the inputs line up
   however long the labels are. */
.earn-cred { display: flex; flex-direction: column; }
.earn-creds label { display: block; margin: 0 0 var(--pickle-space-2); }
.earn-cred input { margin-block-start: auto; }

/* The state of the field is a note about it, not a second label: the tracked
   uppercase of a label made the two compete for the same job. */
.earn-creds label small {
  display: block;
  margin-block-start: 2px;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-2xs);
  font-weight: 400;
  letter-spacing: .02em;
  text-transform: none;
}
.earn-creds label small.on { color: var(--pickle-subtle); }
.earn-creds .ex-actions { margin-block: var(--pickle-space-4) 0; }
.earn-log { list-style: none; margin: var(--pickle-space-3) 0 0; padding: 0; max-height: 26rem; overflow-y: auto; }
.earn-log li { padding-block: var(--pickle-space-1, 4px); border-block-start: 1px solid var(--pickle-line); font-size: var(--pickle-text-xs); overflow-wrap: anywhere; }
.earn-log li.warn { color: var(--pickle-amber); }
.earn-log li.err { color: var(--pickle-red, var(--pickle-amber)); }
.earn-log .mono { color: var(--pickle-muted); margin-inline-end: var(--pickle-space-2, 8px); }
.earn-quest-link { display: flex; flex-wrap: wrap; align-items: center; gap: var(--pickle-space-2, 8px); }
.earn-quest-link .ex-hint { flex: 1 1 12rem; margin: 0; }

.earn-quest-act { margin: 0; }
.earn-quest-form { display: grid; gap: var(--pickle-space-2); }
.earn-quest-form label { margin: 0; }
.earn-quest-form input, .earn-quest-form textarea { min-height: 2.5rem; }
.earn-quest-form textarea { min-height: 5.5rem; }
.earn-quest-form .ex-btn { justify-self: start; }
.earn-quest-form .ex-hint { margin: 0; }

.earn-quiz ol { display: grid; gap: var(--pickle-space-3); margin: 0; padding-left: 1.2rem; }
.earn-quiz li { display: grid; gap: var(--pickle-space-1); color: var(--pickle-muted); font-size: var(--pickle-text-sm); }
.earn-quiz li label { color: var(--pickle-text); font-family: var(--pickle-font); font-size: var(--pickle-text-sm); letter-spacing: 0; text-transform: none; }

.earn-quest .ex-out { margin: 0; }

/* ---------------------------------------------------------------- board */
.earn-board .ex-tabs { margin-bottom: var(--pickle-space-5); }
.earn-week { margin-bottom: var(--pickle-space-6); }

.earn-week-head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pickle-space-3);
  align-items: baseline;
  margin: 0 0 var(--pickle-space-4);
}

.earn-week-head h3 { margin: 0; font-size: var(--pickle-text-xl); }
.earn-week-n { color: var(--pickle-accent-text); margin-right: .5rem; }

/* ------------------------------------------------------------ progress
 * A <progress> so no width lands in the markup. Styled the same in every
 * engine: a hairline track, a flat accent fill, 2px radius.
 */
progress.earn-bar {
  display: block;
  width: 100%;
  height: 6px;
  appearance: none;
  -webkit-appearance: none;
  border: 0;
  border-radius: var(--pickle-radius);
  background: var(--pickle-surface-3);
  /* Through the register, like every other accent-as-text in the system. */
  color: var(--pickle-accent-text);
  overflow: clip;
}

progress.earn-bar::-webkit-progress-bar { background: var(--pickle-surface-3); border-radius: var(--pickle-radius); }
progress.earn-bar::-webkit-progress-value { background: var(--pickle-mint); border-radius: var(--pickle-radius); }
progress.earn-bar::-moz-progress-bar { background: var(--pickle-mint); border-radius: var(--pickle-radius); }

.earn-level { display: grid; gap: var(--pickle-space-2); }

.earn-level-row {
  display: flex;
  gap: var(--pickle-space-3);
  align-items: baseline;
  justify-content: space-between;
}

.earn-level-row b { font-family: var(--pickle-font-display); font-size: var(--pickle-text-lg); font-weight: 600; }

.earn-cats { display: grid; gap: var(--pickle-space-3); }

.earn-cat-row {
  display: grid;
  grid-template-columns: minmax(0, 9rem) minmax(0, 1fr) auto;
  gap: var(--pickle-space-3);
  align-items: center;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-sm);
}

.earn-cat-row .mono { color: var(--pickle-text); font-size: var(--pickle-text-xs); }

/* ---------------------------------------------------------- identities */
.earn-ids {
  display: grid;
  gap: 1px;
  margin: var(--pickle-space-4) 0;
  background: var(--pickle-line);
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
  overflow: clip;
}

.earn-id {
  display: flex;
  gap: var(--pickle-space-3);
  align-items: center;
  min-height: 3rem;
  padding: var(--pickle-space-2) var(--pickle-space-4);
  background: var(--pickle-surface-1);
}

.earn-id-k {
  flex: 0 0 5rem;
  color: var(--pickle-subtle);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
  letter-spacing: var(--pickle-tracking-caps);
  text-transform: uppercase;
}

.earn-id-v { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; font-size: var(--pickle-text-sm); }
.earn-id-v em { color: var(--pickle-subtle); font-style: normal; }
.earn-id-act { display: inline-flex; flex-wrap: wrap; gap: var(--pickle-space-2); align-items: center; justify-content: flex-end; }
.earn-tg-link { display: inline-flex; flex-wrap: wrap; gap: var(--pickle-space-2); align-items: center; }
.earn-tg-link .mono { color: var(--pickle-accent-text); font-size: var(--pickle-text-xs); }

@media (max-width: 639px) {
  .earn-id { flex-wrap: wrap; }
  .earn-id-act { width: 100%; justify-content: flex-start; }
}

/* --------------------------------------------------------------- budgets */
.ex-wf .fill.earn-w45 { width: 45%; }
.ex-wf .fill.earn-w18 { width: 18%; }
.ex-wf .fill.earn-w17 { width: 17%; }
.ex-wf .fill.earn-w12 { width: 12%; }
.ex-wf .fill.earn-w8 { width: 8%; }

.earn-cat {
  display: inline-block;
  min-width: 1.4rem;
  margin-right: var(--pickle-space-2);
  color: var(--pickle-accent-text);
  font-family: var(--pickle-font-mono);
  font-weight: 500;
}

/* ------------------------------------------------------------- account */
.earn-grid-2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--pickle-space-4);
  align-items: start;
}

.earn-grid-2 > .ex-panel { min-width: 0; }
.earn-grid-2 .ex-kv dd small { color: var(--pickle-subtle); }

@media (max-width: 1023px) {
  .earn-grid-2 { grid-template-columns: minmax(0, 1fr); }
}

.earn-plain {
  display: grid;
  gap: var(--pickle-space-3);
  margin: 0;
  padding-left: 1.1rem;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-base);
  line-height: 1.6;
}

/* ---------------------------------------------------------- leaderboard */
.earn-lb tr.me td { background: var(--pickle-mint-soft); }
.earn-rank { color: var(--pickle-subtle); font-family: var(--pickle-font-mono); }

/* --------------------------------------------------------------- rules */
.earn-phase { margin-top: var(--pickle-space-5); padding: var(--pickle-space-4) var(--pickle-space-5); color: var(--pickle-muted); line-height: 1.6; }
.earn-phase strong { color: var(--pickle-text); }
/* The rules open in two columns on anything wider than a tablet: the headline
   and its lede on the left, the phase note and the six rules on the right. One
   column stacked them all down the left at four different measures - the
   headline at 22ch, the lede at 56ch, the note at 840px, the list at 70ch -
   with the right half of the screen empty behind them. */
.earn-rules-intro { display: grid; gap: var(--pickle-space-5); }

/* The lead is a grid item now, not the last thing before the list, so its own
   section-head margin lands between the lede and the phase note where the grid
   gap already is. Grid items do not collapse margins, so the two would add. */
.earn-rules-lead { margin-bottom: 0; }
.earn-rules-lead .ex-lede { max-width: none; }

@media (min-width: 68rem) {
  .earn-rules-intro {
    grid-template-columns: minmax(0, 23rem) minmax(0, 1fr);
    gap: var(--pickle-space-7);
    align-items: start;
  }

  .earn-rules-lead {
    position: sticky;
    top: calc(var(--pickle-bar-h) + var(--pickle-space-5));
  }

  /* In a column of its own the headline sets its own measure, and a display
     size meant to span a hero would shatter into single words here. Only in
     that column: at one column it is the page's first headline and has to be
     the largest, not smaller than the six sections under it. */
  .earn-rules-lead h2 { max-width: none; font-size: clamp(1.6rem, 2.6vw, 2.4rem); }
}
.earn-rules-body .ex-caveat { margin-block-end: var(--pickle-space-5); }

.flow-steps { margin: 0; padding: 0; list-style: none; max-width: 70ch; }
.earn-rules-body .flow-steps { max-width: none; }
.earn-rules-body .flow-steps li:last-child { border-bottom: 0; padding-bottom: 0; }
.earn-rules-body .flow-steps li:first-child { padding-top: 0; }
.earn-rules-body .flow-steps li:first-child .n { top: 0; }

.flow-steps li {
  position: relative;
  padding: var(--pickle-space-4) 0 var(--pickle-space-4) 3rem;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-base);
  line-height: 1.6;
  border-bottom: 1px solid var(--pickle-line);
}

.flow-steps li .n {
  position: absolute;
  top: var(--pickle-space-4);
  left: 0;
  color: var(--pickle-accent-text);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
}

.flow-steps li strong { color: var(--pickle-text); font-weight: 600; }

.earn-say h3 { margin-bottom: var(--pickle-space-3); font-size: var(--pickle-text-base); }
.earn-say ul { display: grid; gap: var(--pickle-space-2); margin: 0; padding-left: 1.1rem; }

/* --------------------------------------------------------------- footer
 * The same footer the home page has, from web/public/css/home.css.
 */
.foot {
  padding: var(--pickle-section) var(--pickle-gutter) var(--pickle-space-6);
  border-top: 1px solid var(--pickle-line);
}

.foot-body,
.foot-disc,
.foot-run {
  width: min(100%, var(--pickle-content));
  margin-inline: auto;
}

.foot-run { text-align: center; }

.foot-body {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: var(--pickle-space-6);
}

.foot-blurb {
  max-width: 34ch;
  margin-top: var(--pickle-space-4);
  color: var(--pickle-muted);
  line-height: 1.6;
}

.foot-h {
  margin: 0 0 var(--pickle-space-4);
  color: var(--pickle-subtle);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
  font-weight: 400;
  letter-spacing: var(--pickle-tracking-caps);
  text-transform: uppercase;
}

.foot-apps ul {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--pickle-space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.foot-apps a { color: var(--pickle-muted); }
.foot-apps a:hover { color: var(--pickle-text); }

.foot-disc {
  margin-top: var(--pickle-space-7);
  padding-top: var(--pickle-space-5);
  color: var(--pickle-subtle);
  font-size: var(--pickle-text-xs);
  line-height: 1.7;
  border-top: 1px solid var(--pickle-line);
}

.foot-run {
  margin-top: var(--pickle-space-5);
  color: var(--pickle-subtle);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
}

@media (max-width: 719px) {
  .foot-body { grid-template-columns: minmax(0, 1fr); }
  .earn-cat-row { grid-template-columns: minmax(0, 1fr) auto; }
  .earn-cat-row progress { grid-column: 1 / -1; }
}

/* ===================================================================== motion
 * On the same contract as shared-ui/motion.css, which loads before this file:
 *
 *   1. Every rule that hides something sits inside
 *      `@media (prefers-reduced-motion: no-preference)`, so a reader who asked
 *      for less motion never has content hidden and then revealed.
 *   2. Scroll-driven rules also sit inside `@supports (animation-timeline:
 *      view())`. A browser without them matches nothing here.
 *   3. Nothing waits for a script. The keyframes below run from the stylesheet;
 *      React only adds `.ex-fresh` and `.earn-pop` when something happened.
 *
 * `ex-in-sm` is motion.css's own keyframe, reused rather than redeclared so a
 * row here rises exactly the way a cell there does.
 */

/* A figure that was just credited. */
@keyframes earn-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.16); }
  100% { transform: scale(1); }
}

/* A bar that grows into its share as it arrives. */
@keyframes earn-grow {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

@media (prefers-reduced-motion: no-preference) {
  .earn-pop { display: inline-block; animation: earn-pop .5s var(--pickle-ease); }

  @supports (animation-timeline: view()) {
    /* Rows arrive one after another: leaderboard, history, rules tables, the
     * six rules, the roadmap, the budget bars. Longhands, never the shorthand,
     * which would reset the timeline to time. */
    .earn-rows tbody tr,
    .flow-steps li,
    .earn-roadmap > div,
    .ex-wf > div,
    .earn-ids .earn-id,
    .earn-week-head {
      animation-name: ex-in-sm;
      animation-duration: auto;
      animation-fill-mode: both;
      animation-timeline: view(block);
      animation-range: entry 0% entry 55%;
    }

    .earn-rows tbody tr:nth-child(3n + 2),
    .flow-steps li:nth-child(3n + 2),
    .ex-wf > div:nth-child(3n + 2) { animation-range: entry 0% entry 68%; }

    .earn-rows tbody tr:nth-child(3n),
    .flow-steps li:nth-child(3n),
    .ex-wf > div:nth-child(3n) { animation-range: entry 0% entry 80%; }

    /* The budget bars grow from the left into their share. */
    .ex-wf .fill {
      transform-origin: left center;
      animation-name: earn-grow;
      animation-duration: auto;
      animation-fill-mode: both;
      animation-timeline: view(block);
      animation-range: entry 10% entry 75%;
    }

  }
}

/* Hover and press hide nothing, so they sit outside the gate; base.css already
 * collapses every transition under reduced motion. */
.earn-quest {
  transition:
    background var(--pickle-fast) var(--pickle-ease),
    transform var(--pickle-base) var(--pickle-ease),
    box-shadow var(--pickle-base) var(--pickle-ease);
}

.earn-quest:hover { background: var(--pickle-surface-3); transform: translateY(-2px); }
.earn-quest:hover .earn-quest-pay b { color: var(--pickle-mint-hi); }
.earn-quest-pay b { transition: color var(--pickle-fast) var(--pickle-ease); }

.earn-lb tbody tr, .earn-rows tbody tr { transition: background var(--pickle-fast) var(--pickle-ease); }

.ex-badge, .ex-pill { transition: color var(--pickle-fast) var(--pickle-ease), border-color var(--pickle-fast) var(--pickle-ease); }

progress.earn-bar::-webkit-progress-value { transition: width var(--pickle-slow) var(--pickle-ease); }

}

/* ============================================================ the ledger tape
 * The post of the day beside the ledger writing what interactions become.
 * Two columns on a desktop, stacked below it.
 */
.earn-ledger-band { padding-top: 0; }

.earn-ledger {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: var(--pickle-space-5);
  align-items: start;
}

.earn-post {
  padding: var(--pickle-space-5);
  background: var(--pickle-surface-1);
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
}

.earn-post-head {
  display: flex;
  gap: var(--pickle-space-3);
  align-items: center;
}

.earn-post-head img { flex: 0 0 auto; width: 28px; height: 33px; }
.earn-post-head div { display: grid; min-width: 0; flex: 1 1 auto; }
.earn-post-head b { font-family: var(--pickle-font-display); font-weight: 600; }
.earn-post-head span.mono { color: var(--pickle-subtle); font-size: var(--pickle-text-2xs); }

.earn-post-text {
  margin: var(--pickle-space-4) 0 0;
  color: var(--pickle-text);
  font-size: var(--pickle-text-lg);
  line-height: 1.5;
  letter-spacing: -.01em;
}

.earn-post-foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pickle-space-4) var(--pickle-space-5);
  margin-top: var(--pickle-space-5);
  padding-top: var(--pickle-space-4);
  color: var(--pickle-subtle);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
  letter-spacing: var(--pickle-tracking-caps);
  text-transform: uppercase;
  border-top: 1px solid var(--pickle-line);
}

.earn-post-foot b {
  margin-right: 6px;
  color: var(--pickle-accent-text);
  font-family: var(--pickle-font-display);
  font-size: var(--pickle-text-lg);
  font-weight: 600;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}

.earn-tape {
  padding: var(--pickle-space-5);
  background: var(--pickle-surface-input);
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
}

.earn-tape .ex-list-head { margin-bottom: var(--pickle-space-3); }

.earn-tape-lines { display: grid; margin: 0; padding: 0; list-style: none; }

.earn-tape-line {
  display: grid;
  grid-template-columns: 3.2rem 6.5rem minmax(0, 1fr) auto;
  gap: var(--pickle-space-3);
  align-items: baseline;
  padding: 9px 0;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-sm);
  border-bottom: 1px solid var(--pickle-line);
}

.earn-tape-lines > .earn-tape-line:last-child { border-bottom: 0; }
.earn-tape-t { color: var(--pickle-subtle); font-size: var(--pickle-text-2xs); }
.earn-tape-what { color: var(--pickle-accent-text); font-size: var(--pickle-text-xs); letter-spacing: .08em; text-transform: uppercase; }
.earn-tape-line.is-multiplier .earn-tape-what,
.earn-tape-line.is-streak .earn-tape-what { color: var(--pickle-amber); }
.earn-tape-fact { min-width: 0; overflow-wrap: anywhere; }
.earn-tape-pp { color: var(--pickle-text); font-size: var(--pickle-text-sm); font-weight: 500; font-variant-numeric: tabular-nums; }

/* The tape writes itself: each line fades in at its own delay, holds, and the
 * whole page of eight fades out together to start again. 14 seconds a cycle,
 * 1.1 seconds between lines, so the last one lands with a second to read before
 * the wipe. Under reduced motion the lines are simply there. */
@keyframes earn-tape-write {
  0% { opacity: 0; transform: translateX(-6px); }
  4% { opacity: 1; transform: none; }
  88% { opacity: 1; }
  96% { opacity: 0; }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: no-preference) {
  .earn-tape-line { animation: earn-tape-write 14s var(--pickle-ease) infinite both; }
  .earn-tape-line:nth-child(2) { animation-delay: 1.1s; }
  .earn-tape-line:nth-child(3) { animation-delay: 2.2s; }
  .earn-tape-line:nth-child(4) { animation-delay: 3.3s; }
  .earn-tape-line:nth-child(5) { animation-delay: 4.4s; }
  .earn-tape-line:nth-child(6) { animation-delay: 5.5s; }
  .earn-tape-line:nth-child(7) { animation-delay: 6.6s; }
  .earn-tape-line:nth-child(8) { animation-delay: 7.7s; }
}

@media (max-width: 1023px) {
  .earn-ledger { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 639px) {
  .earn-tape-line { grid-template-columns: 3.2rem minmax(0, 1fr) auto; }
  .earn-tape-what { grid-column: 2; }
  .earn-tape-fact { grid-column: 2 / span 2; }
}

/* ------------------------------------------------------------- referral */
.earn-referral { display: grid; gap: var(--pickle-space-2); }

.earn-referral-link {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pickle-space-2);
  align-items: center;
  padding: var(--pickle-space-2) var(--pickle-space-3);
  background: var(--pickle-surface-input);
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
}

.earn-referral-link .mono { flex: 1 1 12rem; min-width: 0; color: var(--pickle-accent-text); font-size: var(--pickle-text-xs); overflow-wrap: anywhere; }
.earn-referral .ex-hint { margin: 0; }

/* ------------------------------------------------------- launch boost
 * One loud element: the factor, set in the display face as large as the panel
 * holds, in its own column behind a hairline. Everything else is quiet - a
 * sentence, three terms, the clock, and a rail across the foot of the panel
 * that shows how much of the window has gone. Before the window the factor is
 * an outline (a boost that is not running must not look like one); after it,
 * one line of record. A <progress> for the rail, so no width lands in markup.
 */
.earn-boost {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "x body clock" "rail rail rail";
  column-gap: var(--pickle-space-6);
  row-gap: var(--pickle-space-5);
  align-items: center;
  margin: 0 0 var(--pickle-space-6);
  padding: var(--pickle-space-5) var(--pickle-space-6) var(--pickle-space-4);
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
  background: var(--pickle-surface-2);
}

.earn-boost.is-active { border-color: var(--pickle-mint-line); }

.earn-boost-x {
  grid-area: x;
  align-self: stretch;
  display: flex;
  align-items: center;
  padding-right: var(--pickle-space-6);
  border-right: 1px solid var(--pickle-line);
  color: var(--pickle-accent-text);
  font-family: var(--pickle-font-display);
  font-size: clamp(4.5rem, 8vw, 7.5rem);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.06em;
  line-height: .8;
}

.earn-boost.is-before .earn-boost-x {
  color: transparent;
  -webkit-text-stroke: 1.5px var(--pickle-subtle);
}

.earn-boost-body { grid-area: body; min-width: 0; }

.earn-boost-name {
  margin: 0 0 var(--pickle-space-2);
  color: var(--pickle-muted);
  font-size: var(--pickle-text-sm);
  font-weight: 500;
}

.earn-boost-body h2 {
  margin: 0;
  font-size: var(--pickle-text-2xl);
  font-weight: 600;
  letter-spacing: -.03em;
  line-height: 1.05;
}

.earn-boost-terms {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pickle-space-2) var(--pickle-space-5);
  margin: var(--pickle-space-3) 0 0;
  padding: 0;
  list-style: none;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-sm);
}

/* A short mint tick before each term: a list marker, not decoration. */
.earn-boost-terms li { display: inline-flex; gap: var(--pickle-space-2); align-items: center; }
.earn-boost-terms li::before { content: ""; width: 10px; height: 1px; background: var(--pickle-mint); }
.earn-boost.is-before .earn-boost-terms li::before { background: var(--pickle-subtle); }

.earn-boost-clock { grid-area: clock; }

.earn-boost-when {
  margin: 0 0 var(--pickle-space-2);
  color: var(--pickle-muted);
  font-size: var(--pickle-text-sm);
}

.earn-count { display: flex; gap: var(--pickle-space-2); }

.earn-count-cell {
  display: grid;
  justify-items: center;
  gap: 4px;
  min-width: 3.4rem;
  padding: var(--pickle-space-2) var(--pickle-space-2) 6px;
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
  background: var(--pickle-bg);
}

.earn-count-cell b {
  color: var(--pickle-text);
  font-size: var(--pickle-text-xl);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.earn-count-cell small { color: var(--pickle-subtle); font-size: var(--pickle-text-2xs); }

.earn-boost-rail {
  grid-area: rail;
  display: grid;
  grid-template-columns: auto 1fr auto;
  column-gap: var(--pickle-space-3);
  row-gap: var(--pickle-space-2);
  color: var(--pickle-subtle);
  font-size: var(--pickle-text-2xs);
}

.earn-boost-rail > span:nth-of-type(2) { justify-self: center; color: var(--pickle-muted); }

.earn-boost-rail progress { grid-column: 1 / -1; height: 3px; }

.earn-boost.is-after {
  display: flex;
  gap: var(--pickle-space-3);
  align-items: baseline;
  padding: var(--pickle-space-3) var(--pickle-space-4);
  color: var(--pickle-muted);
  font-size: var(--pickle-text-sm);
  background: transparent;
}

.earn-boost.is-after .earn-boost-x {
  padding: 0;
  border: 0;
  color: var(--pickle-subtle);
  font-size: var(--pickle-text-lg);
  letter-spacing: -.02em;
}

@media (max-width: 1023px) {
  .earn-boost { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "x body" "clock clock" "rail rail"; }
}

@media (max-width: 639px) {
  .earn-boost {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "x" "body" "clock" "rail";
    row-gap: var(--pickle-space-4);
    padding: var(--pickle-space-5) var(--pickle-space-4) var(--pickle-space-4);
  }
  .earn-boost-x { padding: 0; border: 0; font-size: 4.5rem; }
  .earn-count { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .earn-count-cell { min-width: 0; }
}

/* ------------------------------------------------- the launch gate
 * Before the testnet goes public, the testnet tab holds this instead of cards:
 * the same clock as the boost, so the two read as one family.
 */
.earn-gate {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "body clock";
  gap: var(--pickle-space-5) var(--pickle-space-6);
  align-items: center;
  padding: var(--pickle-space-6);
  border: 1px dashed var(--pickle-line-strong, var(--pickle-line));
  border-radius: var(--pickle-radius);
}

.earn-gate.is-compact { padding: var(--pickle-space-4) var(--pickle-space-5); }
.earn-gate-body { grid-area: body; min-width: 0; }
.earn-gate h3 { margin: 0; font-size: var(--pickle-text-xl); letter-spacing: -.02em; }
.earn-gate p:not(.earn-boost-name) { max-width: 60ch; margin: var(--pickle-space-3) 0 0; color: var(--pickle-muted); font-size: var(--pickle-text-sm); line-height: 1.6; }

@media (max-width: 767px) {
  .earn-gate { grid-template-columns: minmax(0, 1fr); grid-template-areas: "body" "clock"; padding: var(--pickle-space-5) var(--pickle-space-4); }
  .earn-gate .earn-count { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .earn-gate .earn-count-cell { min-width: 0; }
}

/* ------------------------------------------------------ testnet quests */
.earn-testnet-sum {
  display: flex;
  flex-wrap: wrap;
  gap: var(--pickle-space-3);
  align-items: baseline;
  margin: var(--pickle-space-2) 0 var(--pickle-space-5);
  padding-top: var(--pickle-space-5);
  border-top: 1px solid var(--pickle-line);
}

.earn-testnet-sum h3 { margin: 0; font-size: var(--pickle-text-xl); }
.earn-testnet .earn-week-head h3 { font-size: var(--pickle-text-lg); }

/* A Verify button and the link to where the quest is done, side by side and
   wrapping to two rows on a narrow card rather than squeezing either. */
.earn-quest-row { display: flex; flex-wrap: wrap; gap: var(--pickle-space-2); align-items: center; }
.earn-quest-row .ex-hint { flex: 1 1 100%; margin: 0; }

.earn-progress { display: grid; gap: var(--pickle-space-2); }

.earn-progress-row {
  display: flex;
  gap: var(--pickle-space-3);
  align-items: baseline;
  justify-content: space-between;
  font-size: var(--pickle-text-sm);
}

.earn-progress-row .mono { color: var(--pickle-text); }
.earn-quest-ready, .earn-quest > p.earn-quest-ready { color: var(--pickle-accent-text); }

/* The per-card mark of the boost, in the banner's own voice: the factor in
   the display face, then the word, on the accent's hairline. */
.ex-badge.earn-x2 {
  gap: 5px;
  color: var(--pickle-muted);
  font-family: var(--pickle-font);
  font-size: var(--pickle-text-2xs);
  letter-spacing: 0;
  text-transform: none;
  border-color: var(--pickle-mint-line);
}

.ex-badge.earn-x2 b {
  color: var(--pickle-accent-text);
  font-family: var(--pickle-font-display);
  font-size: var(--pickle-text-sm);
  font-weight: 700;
  letter-spacing: -.03em;
}

/* The review desk's wallet check: the address and its button on one line,
   the button never squeezed below its label. */
.earn-check { margin-block: var(--pickle-space-3); }
.earn-check-row { display: flex; gap: var(--pickle-space-2); }
.earn-check-row input { flex: 1 1 auto; min-width: 0; }
.earn-check-row .ex-btn { flex: none; }
.earn-check-table td:last-child { color: var(--pickle-muted); overflow-wrap: anywhere; }
.earn-check-table small { color: var(--pickle-subtle); margin-inline-start: var(--pickle-space-1, 4px); }

/* The verification dialog (components/CaptchaGate). Always in the document, as
   Cloudflare's invisible widget needs a home, but clipped to nothing - never
   display:none, which would stop the widget running - until a check or a
   claim is under way. Then the site dims behind a small panel in the middle:
   a spinner while it works, Cloudflare's checkbox when it needs the person. */
.captcha-gate {
  position: fixed;
  inset: 0;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  pointer-events: none;
}
.captcha-gate.on {
  z-index: 1000;
  display: grid;
  place-items: center;
  width: auto;
  height: auto;
  padding: var(--pickle-space-4, 16px);
  overflow: auto;
  clip-path: none;
  pointer-events: auto;
  background: rgb(5 6 6 / 72%);
  backdrop-filter: blur(3px);
}
.captcha-gate-panel {
  width: min(100%, 24rem);
  padding: var(--pickle-space-5, 24px);
  background: var(--pickle-surface-1);
  border: 1px solid var(--pickle-line);
  border-radius: var(--pickle-radius);
  box-shadow: 0 24px 64px rgb(0 0 0 / 55%);
  text-align: center;
}
.captcha-gate-say {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--pickle-space-3, 12px);
  margin: 0;
  color: var(--pickle-text);
  font-size: var(--pickle-text-sm);
}
.captcha-gate.asking .captcha-gate-say { margin-block-end: var(--pickle-space-3, 12px); }
.captcha-gate-spin {
  flex: none;
  width: 18px;
  height: 18px;
  border: 2px solid var(--pickle-line);
  border-top-color: var(--pickle-mint);
  border-radius: 50%;
}
/* Empty while Cloudflare answers invisibly; the checkbox's height only when
   it is asked for, so the loading panel is not a box with a hole in it. */
.captcha-gate-box { display: flex; justify-content: center; }
.captcha-gate.asking .captcha-gate-box { min-height: 65px; }
.captcha-gate-close { margin-block-start: var(--pickle-space-3, 12px); }
@media (prefers-reduced-motion: no-preference) {
  .captcha-gate-spin { animation: captcha-gate-turn .8s linear infinite; }
  .captcha-gate.on .captcha-gate-panel { animation: ex-in-sm 220ms var(--pickle-ease, ease-out) both; }
}
@keyframes captcha-gate-turn { to { transform: rotate(360deg); } }

/* The repost call (components/RepostCall), under the bar on every page until
   today's repost is done. The loudest thing on the site on purpose: a mint
   band, the payout in display type, the X button first. It is a band in the
   flow rather than a sticky bar, so on a phone it scrolls away with the
   header instead of sitting on the cards. */
.earn-rt {
  background:
    linear-gradient(90deg, var(--pickle-mint-soft), transparent 70%),
    var(--pickle-surface-1);
  border-block: 1px solid var(--pickle-mint-line);
}
.earn-rt-in {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--pickle-space-3) var(--pickle-space-5);
  padding-block: var(--pickle-space-4);
}
.earn-rt-say { flex: 1 1 22rem; min-width: 0; }
.earn-rt-kicker {
  display: flex;
  align-items: center;
  gap: var(--pickle-space-2);
  margin: 0;
  color: var(--pickle-accent-text);
  font-family: var(--pickle-font-mono);
  font-size: var(--pickle-text-2xs);
  letter-spacing: .08em;
  text-transform: uppercase;
}
.earn-rt-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--pickle-mint);
  box-shadow: 0 0 0 0 var(--pickle-mint-line);
}
.earn-rt h2 {
  margin: var(--pickle-space-1, 4px) 0 var(--pickle-space-1, 4px);
  font-size: clamp(1.15rem, 1rem + 1vw, 1.6rem);
  line-height: 1.2;
}
.earn-rt h2 b { color: var(--pickle-accent-text); font-family: var(--pickle-font-display); white-space: nowrap; }
.earn-rt-boost { color: var(--pickle-muted); font-size: var(--pickle-text-xs); font-weight: 400; }
.earn-rt-post {
  display: block;
  color: var(--pickle-muted);
  font-size: var(--pickle-text-xs);
  overflow-wrap: anywhere;
}
.earn-rt-do { display: flex; flex-wrap: wrap; gap: var(--pickle-space-2); }
.earn-rt-out { flex-basis: 100%; margin: 0; color: var(--pickle-amber); font-size: var(--pickle-text-xs); }
@media (max-width: 560px) {
  .earn-rt-do { width: 100%; }
  .earn-rt-do .ex-btn { flex: 1 1 auto; justify-content: center; }
}
@media (prefers-reduced-motion: no-preference) {
  .earn-rt-dot { animation: earn-rt-ping 1.8s var(--pickle-ease, ease-out) infinite; }
}
@keyframes earn-rt-ping {
  0% { box-shadow: 0 0 0 0 var(--pickle-mint-line); }
  80%, 100% { box-shadow: 0 0 0 8px transparent; }
}
