/*
  MEOWGENTS.

  One stylesheet for every page. The palette is a sunny living room with a cat
  in it: peach walls, warm wood, a ginger coat and a lavender cat tree. It is
  soft on purpose - this is somewhere you leave a cat, not a trading terminal -
  but the numbers are still set in a mono face and given room, because they are
  the part people are actually here to read.

  The variable names are the farm's (--straw, --barn, --soil...) because every
  page and component reads them; only their values changed. The MEOWGENTS layer at
  the foot of this file restyles the chrome on top.
*/

:root {
  --soil: #3c2a44;
  --soil-dark: #2b2031;
  --soil-light: #5b4865;
  --field: #8fc7a0;
  --field-dark: #5fa37a;
  --straw: #ff8a5b;
  --straw-pale: #ffe3d3;
  --barn: #e8604c;
  --barn-dark: #b8432f;
  --sky: #fbe9dd;
  --cream: #fff7f0;
  --ink: #2b2031;
  --ink-soft: #6a5a70;
  --line: #f1dfd3;
  --panel: #fffdfb;
  --good: #2f9e6f;
  --warn: #d98a1c;
  --bad: #d64545;

  --lavender: #b7a2c9;
  --lavender-pale: #efe7f6;
  --mint-pale: #e3f4ea;

  /* A third ink, for the things that are present but not being read yet. */
  --ink-faint: #a092a6;

  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
  --sans: ui-rounded, "SF Pro Rounded", "Nunito", "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
  /*
    A display face for the few places a heading should have some weight to it.
    Local names only, resolving down to the body serif — there is no font on a
    CDN here and there is not going to be: a script tag pointing at somebody
    else's host is a dependency that can change between page loads.
  */
  --display: ui-rounded, "SF Pro Rounded", "Nunito", "Arial Rounded MT Bold", "Segoe UI Variable Display", "Segoe UI", system-ui, sans-serif;

  --radius: 16px;

  /*
    Three depths rather than one.

    Everything used to share a single heavy shadow, which flattens a page in the
    opposite way to having none: if a stat strip, a panel and a floating tooltip
    all sit the same distance off the paper, none of them reads as nearer.
  */
  --shadow-sm: 0 1px 2px rgba(43, 32, 49, 0.06), 0 1px 0 rgba(255, 255, 255, 0.6) inset;
  --shadow: 0 1px 0 rgba(43, 32, 49, 0.05), 0 2px 6px -2px rgba(43, 32, 49, 0.12),
    0 12px 28px -18px rgba(43, 32, 49, 0.4);
  --shadow-lg: 0 2px 4px rgba(43, 32, 49, 0.06), 0 10px 20px -8px rgba(43, 32, 49, 0.18),
    0 30px 60px -40px rgba(43, 32, 49, 0.5);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
}

/*
  Paper, not a colour swatch.

  Three layers, all of them CSS: a fine diagonal weave at very low contrast so
  the surface has a grain, a warm bloom from the top where the light is, and the
  cream underneath. It is deliberately barely visible — the point is that a
  large empty area stops reading as a blank rectangle, not that anybody notices
  a texture. `background-attachment: fixed` keeps the light where the window is
  rather than sliding the bloom up the page as it scrolls.
*/
body {
  background-color: var(--cream);
  background-image:
    repeating-linear-gradient(
      45deg,
      rgba(67, 48, 31, 0.014) 0 1px,
      transparent 1px 4px
    ),
    repeating-linear-gradient(
      -45deg,
      rgba(67, 48, 31, 0.014) 0 1px,
      transparent 1px 4px
    ),
    radial-gradient(120% 70% at 50% -10%, rgba(255, 252, 240, 0.9), transparent 60%);
  background-attachment: fixed, fixed, fixed;
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* Warm, and not the browser's blue. */
::selection {
  background: var(--straw-pale);
  color: var(--soil-dark);
}

/*
  A visible focus ring, on the keyboard only.

  Several controls here spend money — a withdrawal, a mint, a launchpad switch —
  and somebody tabbing to one should be able to see where they are. `:focus-
  visible` keeps it off a mouse click, which is where an always-on ring gets
  removed by the next person for looking wrong.
*/
:focus-visible {
  outline: 2px solid var(--soil);
  outline-offset: 2px;
  border-radius: 4px;
}

/*
  Underlines that sit under the text rather than through its descenders, and
  start faint. A page this dense with links reads as scribbled-on when every one
  of them is at full strength.
*/
a {
  color: var(--barn-dark);
  text-decoration-color: rgba(124, 36, 28, 0.3);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color 0.12s ease, color 0.12s ease;
}

a:hover {
  color: var(--barn);
  text-decoration-color: currentColor;
}

/* --- chrome --------------------------------------------------------------- */

.top {
  display: flex;
  align-items: baseline;
  gap: 1.4rem;
  flex-wrap: wrap;
  padding: 0.95rem 1.5rem;
  border-top: 3px solid var(--straw);
  border-bottom: 1px solid var(--line);
  background: var(--panel);
  position: sticky;
  top: 0;
  z-index: 20;
}

.brand {
  font-weight: 700;
  font-size: 1.15rem;
  letter-spacing: 0.02em;
  color: var(--ink);
  text-decoration: none;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}

.brand .ticker {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--barn);
  border: 1px solid rgba(168, 53, 42, 0.3);
  border-radius: 999px;
  padding: 0.05rem 0.5rem;
  background: rgba(168, 53, 42, 0.06);
}

.top nav {
  display: flex;
  gap: 1.1rem;
  font-size: 0.92rem;
}

.top nav a {
  color: var(--ink-soft);
  text-decoration: none;
}

.top nav a:hover,
.top nav a[aria-current="page"] {
  color: var(--ink);
  border-bottom: 2px solid var(--straw);
}

.top .right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-soft);
  /*
    May shrink. Without this the cluster - a stamp, Connect, and the farmbar
    the script appends - is a rigid block, and at 1280 on the front page it did
    not fit beside the nav and dropped to a second row. Every other page kept
    one row, so the front door was the odd one out.
  */
  min-width: 0;
  flex-shrink: 1;
}
/* The stamp is a status, not a control; it should not compete with buttons. */
.top .right > #freshness:empty {
  display: none;
}

main {
  max-width: var(--column);
  margin: 0 auto;
  padding: 1.75rem 1.5rem 5rem;
}

/*
  The reading column on a page whose `main` is full width.

  `index.html` runs the field edge to edge, so its prose sits in a wrapper of
  its own. That wrapper used to carry `max-width: 1180px` as an inline style,
  which meant the front page ignored every change made to `main` and was the
  reason narrowing the column here had no effect on the page people actually
  land on.
*/
.column {
  max-width: var(--column);
  margin: 0 auto;
  padding: 1.75rem 1.5rem 0;
}

main.wide {
  max-width: none;
  padding: 0 0 4rem;
}

/*
  A real type scale, sized against the viewport.

  The old one ran 2.15rem / 1.2rem / body, so a page heading and a section
  heading were nearly the same size and neither had much to say. `clamp` lets
  the top of the scale be genuinely large on a wide screen without overflowing a
  phone.
*/
h1 {
  font-family: var(--display);
  font-size: clamp(2.3rem, 1.6rem + 2.4vw, 3.2rem);
  font-weight: 600;
  margin: 0 0 0.7rem;
  letter-spacing: -0.022em;
  line-height: 1.06;
  text-wrap: balance;
}

/*
  A section heading with a mark against it.

  A straw rule in the margin, drawn with a pseudo-element so it costs no markup
  and appears on every page at once. It gives a long document something to scan
  down, which "slightly bolder text" never does.
*/
h2 {
  position: relative;
  font-family: var(--display);
  font-size: 1.42rem;
  font-weight: 600;
  letter-spacing: -0.012em;
  line-height: 1.2;
  margin: 2.8rem 0 0.9rem;
  text-wrap: balance;
}

main h2::before {
  content: "";
  position: absolute;
  left: -1.1rem;
  top: 0.28em;
  width: 3px;
  height: 1.05em;
  border-radius: 2px;
  background: var(--straw);
}

/*
  The third step of the scale, and it has to be above the body text.

  This was 1.05rem, set when the body was 16px. The body went to 17 and nothing
  moved this, so every h3 on the site computed to 16.8px against a 17px
  paragraph -- a heading smaller than the prose it introduces, which reads as a
  caption. Nothing errored and no page looked obviously wrong; it just quietly
  stopped being a heading.
*/
h3 {
  font-family: var(--display);
  font-size: 1.18rem;
  font-weight: 600;
  letter-spacing: -0.008em;
  line-height: 1.25;
  margin: 2rem 0 0.55rem;
}

/* The opening paragraph, given the room an opening paragraph is worth. The
   width is not set here — every element in the reading column takes it from
   `--measure`, near the foot of this file. */
.lede {
  color: var(--ink-soft);
  /* 1.2rem, not 1.08: at 17px body the old value was 17.28px, which is not a
     step, it is a rounding error wearing one. */
  font-size: 1.06rem;
  line-height: 1.55;
  margin: 0 0 1.6rem;
}

main p + p {
  margin-top: 1.05rem;
}

/* --- the scene ------------------------------------------------------------ */

.scene {
  position: relative;
  width: 100%;
  height: min(68vh, 660px);
  min-height: 420px;
  background: var(--sky);
  border-bottom: 1px solid var(--line);
  box-shadow: inset 0 -18px 24px -20px rgba(43, 32, 49, 0.35);
  overflow: hidden;
  cursor: grab;
}

.scene:active {
  cursor: grabbing;
}

.scene canvas {
  display: block;
  width: 100%;
  height: 100%;
  /* Dragging the field is a pan, not a text selection. Without this, a drag
     across the scene highlights whatever prose happens to sit under the
     pointer, and the page ends up half selected in blue. `touch-action` is the
     same thing for a finger: without it a drag scrolls the page instead of
     moving the camera, and the field cannot be panned on a phone at all. */
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  cursor: grab;
}

.scene canvas:active {
  cursor: grabbing;
}

.scene .hint {
  position: absolute;
  right: 0.9rem;
  bottom: 0.7rem;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: rgba(43, 32, 49, 0.5);
  background: rgba(255, 253, 247, 0.75);
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  pointer-events: none;
}

/*
  The empty-field notice.

  A card, not a wash. The first version covered the whole scene in 82% cream to
  say "nothing here", which dimmed the sky, the barn and the moving clouds
  behind it and read as a rendering fault rather than as a message. The scene is
  worth looking at even with nobody farming on it, so the notice now sits in the
  middle of it and lets the rest through.
*/
.scene .empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  pointer-events: none;
}
/*
  `hidden` must win.

  An author `display` beats the attribute's user-agent `display: none`, so the
  rule above kept this overlay on top of the canvas on every visit - invisible,
  because it had no background, until a global `.empty` gave it one and the
  whole field disappeared behind a panel-white sheet for every visitor. The
  canvas was painting the entire time. Any element this stylesheet gives a
  `display` to and the page toggles with `hidden` needs this line.
*/
.scene .empty[hidden] {
  display: none;
}

.scene .empty .card {
  background: rgba(255, 253, 247, 0.94);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.85rem 1.3rem;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.88rem;
  color: var(--soil-dark);
  line-height: 1.6;
  pointer-events: auto;
}

.scene .empty .card .muted {
  font-size: 0.8rem;
}

/* The card that follows the cursor over a plot. */
.tip {
  position: absolute;
  pointer-events: none;
  z-index: 5;
  min-width: 190px;
  max-width: 280px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 0.6rem 0.7rem;
  font-size: 0.85rem;
  opacity: 0;
  transition: opacity 90ms;
}

.tip[data-show="1"] {
  opacity: 1;
}

.tip .who {
  font-weight: 700;
}

.tip .row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-soft);
}

/* What the category the farmer is growing actually covers. Without it the card
   says "meme" and leaves the reader to guess whether that is a token, a plant
   or a mood. */
.tip .means {
  margin: 0.3rem 0 0.15rem;
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--ink);
}

.tip .persona {
  margin-top: 0.4rem;
  font-style: italic;
  color: var(--ink-soft);
  font-size: 0.8rem;
  line-height: 1.4;
}

/* --- stat strip ----------------------------------------------------------- */

/*
  Borders on the tiles, not a coloured gap behind them. The gap trick paints
  the container in the rule colour and lets it show through between tiles —
  which also lets it show through wherever a row is not full, as a large
  beige block after the last tile. Tiles that carry their own hairlines leave
  an unfilled row looking like what it is: nothing there.
*/
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0;
  background: var(--panel);
  border-block: 1px solid var(--line);
}

.stats div {
  background: var(--panel);
  padding: 0.95rem 1.1rem 1rem;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: -1px;
}

.stats dt {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  margin: 0;
}

.stats dd {
  margin: 0.2rem 0 0;
  font-family: var(--mono);
  font-size: 1.5rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.stats dd.muted {
  color: var(--ink-soft);
  font-size: 0.95rem;
  font-weight: 400;
}

/* --- panels and tables ---------------------------------------------------- */

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow);
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

th {
  text-align: left;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  font-weight: 600;
  padding: 0.5rem 0.6rem;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}

td {
  padding: 0.6rem;
  border-bottom: 1px solid rgba(216, 203, 176, 0.5);
  vertical-align: top;
}

tbody tr:nth-child(even) {
  background: rgba(227, 180, 72, 0.045);
}

tbody tr:hover {
  background: rgba(227, 180, 72, 0.12);
}

.mono {
  font-family: var(--mono);
  font-size: 0.85em;
}

.muted {
  color: var(--ink-soft);
}

.pill {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--cream);
  white-space: nowrap;
}

.pill[data-stage="ripe"] {
  border-color: rgba(63, 125, 67, 0.4);
  background: rgba(63, 125, 67, 0.12);
  color: var(--good);
}

.pill[data-stage="rotten"] {
  border-color: rgba(163, 51, 39, 0.4);
  background: rgba(163, 51, 39, 0.1);
  color: var(--bad);
}

.pill[data-stage="fallow"] {
  color: var(--ink-soft);
}

/* --- the forge ------------------------------------------------------------ */

.form-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 900px) {
  .form-grid {
    grid-template-columns: minmax(0, 1fr) 320px;
    align-items: start;
  }
}

label {
  display: block;
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: 0.3rem;
}

label .note {
  font-weight: 400;
  color: var(--ink-soft);
  font-size: 0.82rem;
}

input[type="text"],
textarea {
  width: 100%;
  font-family: inherit;
  font-size: 1rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: inherit;
}

textarea {
  min-height: 6.5rem;
  resize: vertical;
  line-height: 1.5;
}

input:focus-visible,
textarea:focus-visible,
button:focus-visible {
  outline: 2px solid var(--straw);
  outline-offset: 1px;
}

.field-row {
  margin-bottom: 1.3rem;
}

.counter {
  float: right;
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-soft);
}

.counter[data-over="1"] {
  color: var(--bad);
}

/*
  The five categories.

  Laid out so the *category* is the headline and the plant is a caption under
  it. The first version gave them equal weight and people read the grid as a
  menu of things to create rather than as subjects an agent may launch about —
  which is the single thing about this project that is easy to misread, so the
  type sizes are doing real work here.
*/
.crops {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 0.6rem;
}

.crop {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.6rem 0.7rem;
  background: var(--panel);
  transition: border-color 120ms, background 120ms;
}

.crop[data-pick="like"] {
  border-color: var(--field-dark);
  background: rgba(121, 145, 63, 0.1);
}

.crop[data-pick="dislike"] {
  border-color: rgba(163, 51, 39, 0.5);
  background: rgba(163, 51, 39, 0.07);
}

.crop-head {
  display: grid;
  grid-template-columns: 38px 1fr auto;
  align-items: center;
  gap: 0.6rem;
}

.crop canvas {
  width: 38px;
  height: 38px;
}

.crop .name {
  font-weight: 700;
  font-size: 1.02rem;
  line-height: 1.15;
  letter-spacing: -0.01em;
}

/* The plant, demoted to a caption. It is a picture of the category, not a
   second thing you are choosing between. */
.crop .plant {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-soft);
  opacity: 0.75;
}

.crop .means {
  margin: 0.5rem 0 0;
  font-size: 0.84rem;
  line-height: 1.4;
  color: var(--ink);
}

.crop .eg {
  margin: 0.3rem 0 0;
  font-size: 0.76rem;
  line-height: 1.35;
  color: var(--ink-soft);
}

.crop .eg b {
  font-weight: 600;
  font-style: normal;
}

.crop .picks {
  display: flex;
  gap: 0.25rem;
}

.crop button {
  font-family: var(--mono);
  font-size: 0.78rem;
  width: 1.9rem;
  height: 1.9rem;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--cream);
  cursor: pointer;
  color: var(--ink-soft);
  line-height: 1;
}

.crop button:hover {
  border-color: var(--ink-soft);
}

.crop button[aria-pressed="true"] {
  color: var(--panel);
}

.crop button.like[aria-pressed="true"] {
  background: var(--field-dark);
  border-color: var(--field-dark);
}

.crop button.dislike[aria-pressed="true"] {
  background: var(--bad);
  border-color: var(--bad);
}

.btn {
  font-family: inherit;
  font-size: 1rem;
  font-weight: 600;
  padding: 0.6rem 1.2rem;
  border-radius: 8px;
  border: 1px solid var(--barn-dark);
  background: var(--barn);
  color: #fff;
  cursor: pointer;
}

.btn:hover {
  background: var(--barn-dark);
}

.btn[disabled] {
  /*
    Neutral, not faded red. The barn colour at 45% opacity is pink, and at the
    foot of the mint form a pink button reads as something having gone wrong.
    Disabled means "not yet", and a quiet panel-coloured button says that.
  */
  background: var(--cream);
  border-color: var(--line);
  color: var(--ink-faint);
  cursor: not-allowed;
  box-shadow: none;
}
.btn[disabled]:hover {
  background: var(--cream);
}

.btn.ghost {
  background: var(--panel);
  color: var(--ink);
  border-color: var(--line);
}

.slider {
  width: 100%;
  accent-color: var(--barn);
}

.notice {
  border-left: 3px solid var(--straw);
  background: rgba(227, 180, 72, 0.1);
  padding: 0.7rem 0.9rem;
  border-radius: 0 8px 8px 0;
  font-size: 0.88rem;
  margin: 1rem 0;
}

.notice.bad {
  border-left-color: var(--bad);
  background: rgba(163, 51, 39, 0.08);
}

.notice.good {
  border-left-color: var(--good);
  background: rgba(63, 125, 67, 0.1);
}

footer {
  border-top: 1px solid var(--line);
  padding: 1.5rem;
  text-align: center;
  font-size: 0.82rem;
  color: var(--ink-soft);
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* A dollar value under an ETH one. Deliberately quieter and on its own line:
   the ETH came off the chain and is exact, the dollars are a conversion at one
   venue's price at one moment, and the two should not read as equally solid.

   It is the ETH that sits here now, under the dollars, since money.js swapped
   which line leads. The class is named for the job rather than the currency for
   exactly that reason: it is whichever figure is the quieter one. */
.second {
  display: block;
  font-size: 0.78em;
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}

/* --- ranked tables and their sort bars ---------------------------------------
   These lived inside launches.html, which meant the moment a second page wanted
   a right-aligned number or an "unknown" dash it silently got neither. Shared,
   because three pages now render the same kinds of figure and they must read
   identically wherever they appear. */

.sortbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin: 1.2rem 0 0.8rem;
}

.sortbtn {
  font-family: var(--mono);
  font-size: 0.76rem;
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink-soft);
  cursor: pointer;
}

.sortbtn:hover {
  border-color: var(--ink-soft);
}

.sortbtn[aria-pressed="true"] {
  background: var(--soil);
  border-color: var(--soil);
  color: var(--cream);
}

td.num,
th.num {
  text-align: right;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ticker {
  font-family: var(--mono);
  font-weight: 600;
}

/* A figure nobody could find out. Never a zero: a zero would be a claim about
   the market rather than about the reader. */
.unknown {
  color: var(--ink-faint, var(--ink-soft));
  opacity: 0.7;
  font-style: italic;
}

.up {
  color: var(--good);
}

.down {
  color: var(--bad);
}

/* --- the boost picker ---------------------------------------------------------
   A slot is a thing you point at one farmer, so the control has to show which
   farmers are chosen *and in what order* — the order is priority, and an owner
   who sells down to fewer slots keeps whichever they named first. A plain list
   of ticks would hide the half that matters. */

.picker {
  list-style: none;
  margin: 1rem 0 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.picker li {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 0.8rem;
  border-bottom: 1px solid var(--line);
  background: var(--panel);
}

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

/* Out of slots. Dimmed rather than hidden: the farmer is still yours, and the
   reason it cannot be ticked is that something else is holding the slot. */
.picker li.off {
  opacity: 0.55;
}

.picker label {
  display: flex;
  gap: 0.6rem;
  align-items: center;
  cursor: pointer;
  margin: 0;
}

.picker li.off label {
  cursor: default;
}

.picker .tags {
  display: flex;
  gap: 0.4rem;
  align-items: center;
}

.picker .slot,
.picker .on {
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.15rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap;
}

.picker .slot {
  border: 1px solid var(--line);
  color: var(--ink-soft);
}

/* What the chain says right now, as distinct from what the reader has ticked
   and not yet saved. Two different facts and they must not look the same. */
.picker .on {
  background: var(--good);
  color: var(--cream);
}

/* --- the call to action -------------------------------------------------------
   One band, twice on the front page: under the headline for somebody who has
   already decided, and under the last section for somebody who read it all. It
   is the only element on the site that is trying to get you to do something, so
   it is allowed to be the loudest thing on the page and nothing else is. */

.cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  margin: 1.5rem 0 2rem;
  padding: 1.25rem 1.4rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-left: 4px solid var(--barn);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.cta .say {
  flex: 1 1 22ch;
  min-width: 0;
}

.cta .say strong {
  display: block;
  font-size: 1.05rem;
}

.cta .say span {
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* An anchor, not a button, because it navigates — so it opens in a new tab on
   a middle click and can be copied like any other link. It is only dressed as
   a button. */
.cta .go {
  font-family: inherit;
  font-size: 1.05rem;
  font-weight: 700;
  padding: 0.7rem 1.6rem;
  border-radius: 8px;
  border: 1px solid var(--barn-dark);
  background: var(--barn);
  color: #fff;
  text-decoration: none;
  white-space: nowrap;
}

.cta .go:hover {
  background: var(--barn-dark);
  color: #fff;
}

/* The price, when the chain would say. Absent rather than guessed: this is a
   number somebody is about to pay. */
.cta .price {
  font-family: var(--mono);
  font-size: 0.85rem;
  color: var(--ink-soft);
  flex-basis: 100%;
  margin: 0;
}

@media (max-width: 560px) {
  .cta .go {
    flex: 1 1 100%;
    text-align: center;
  }
}

/* The farmer being minted, drawn while the form is filled in. Sized in the page
   rather than on the element, because the canvas measures itself every frame and
   a fixed width/height attribute would fight the sticky column it lives in. */
.preview {
  display: block;
  width: 100%;
  height: 190px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: #8aa24d;
}

/* --- what a farmer said about its own launch ---------------------------------
   Collapsed under its row and opened on request. Nine columns of figures with a
   paragraph wedged into each is a table nobody can scan, and scanning is what
   the launches page is for. */

.whybtn {
  font-family: var(--mono);
  font-size: 0.72rem;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--ink-soft);
  cursor: pointer;
}

.whybtn:hover {
  border-color: var(--ink-soft);
}

.whybtn[aria-expanded="true"] {
  background: var(--soil);
  border-color: var(--soil);
  color: var(--cream);
}

.whyrow > td {
  padding: 0;
  background: var(--cream);
}

.why {
  padding: 0.9rem 1.1rem;
  border-left: 3px solid var(--straw);
}

/* The farmer's own sentence. Set in the reading face rather than the mono the
   figures use: it is prose, and it should not look like another measurement. */
.why .said {
  margin: 0 0 0.5rem;
  /* Its own measure, narrower than the page's: this is small print inside a
     table row, not a paragraph in the reading column. */
  max-width: 37rem;
  font-size: 0.95rem;
  line-height: 1.5;
}

.why .lead {
  display: block;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: 0.15rem;
}

/* Present for a screen reader, absent for everybody else — the column of
   toggles has no useful visible heading. */
.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* --- a launch somebody was linked to -----------------------------------------
   Every token this farm launches carries its own row's address as its website,
   so a visitor can arrive here from a launchpad pointed at one line of a long
   table. Marked rather than filtered: the row is worth seeing in the company of
   the others, which is the whole reason the link goes to the table at all. */

#ledger tr.linked > td {
  background: #fdf3d6;
  box-shadow: inset 0 1px 0 var(--straw), inset 0 -1px 0 var(--straw);
}

#ledger tr.linked > td:first-child {
  box-shadow:
    inset 3px 0 0 var(--straw),
    inset 0 1px 0 var(--straw),
    inset 0 -1px 0 var(--straw);
}

/* --- what a farmer takes after -----------------------------------------------
   Five token addresses an owner points their agent at. Not a gate — the taste
   gate is on chain and unchanged — so this is deliberately light: a list you can
   edit in a moment, because that is the whole promise. */

/* --- something the reader can fix ---------------------------------------------
   A farmer whose wallet cannot cover a launch fee. Not an error - the crop is
   growing correctly and ripens on time - so it is the warning colour rather
   than the bad one, and it sits beside the countdown rather than replacing it.
   A class rather than an inline style, so the two pages showing it cannot drift
   and neither can beat the stylesheet (trap 46). */
.warnnote {
  color: var(--warn);
}

/* --- which launchpad a token lives on ------------------------------------------
   Shown beside a ticker that has no outbound link, so a reader knows why: the
   token is on a launchpad whose page this site has not verified a link for. */
.pad-tag {
  display: inline-block;
  margin-left: 0.45rem;
  padding: 0.05rem 0.45rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  vertical-align: middle;
}

/* --- funding a farmer -----------------------------------------------------------
   The shortfall and the one button that fixes it. On the tile it is a single
   quiet row under the balance; in the wallet panel it is a field and a button
   in the same shape as a withdrawal, so topping up and taking out read as the
   two halves of one control. */
.tilefund {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  margin: 0.15rem 0 0.35rem;
  font-size: 0.82rem;
}
.fundbtn {
  padding: 0.25rem 0.7rem;
  font-size: 0.82rem;
  border-radius: 6px;
}
.fundrow {
  display: grid;
  gap: 0.35rem;
  padding: 0.7rem 0 0.9rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 0.6rem;
}
.fundctl {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.fundamt {
  width: 9rem;
}
.fundnote {
  font-size: 0.85rem;
}

/* --- an empty state ------------------------------------------------------------
   A page with nothing to show yet used to be one sentence and then the bottom
   of the screen. This is the shape for that: what the page is for, why it is
   empty, and the single action that fills it.

   Named `.empty-state`, not `.empty`. The field already has a `.scene .empty`
   overlay, and the first version of this was called `.empty` too: the
   overlay matched it, took its panel background, and covered the whole front
   page field for every visitor. A generic word is a collision waiting for a
   second author. */
.empty-state {
  margin: 1.5rem 0 0;
  padding: 1.6rem 1.7rem 1.7rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  text-align: center;
}
.empty-state h2 {
  margin: 0 0 0.35rem;
  font-size: 1.3rem;
}
main .empty-state h2::before {
  display: none;
}
.empty-state p {
  margin: 0 auto;
  max-width: 34rem;
  color: var(--ink-soft);
}
.empty-state .actions {
  display: flex;
  justify-content: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 1.2rem;
}

/* --- the gallery of agents --------------------------------------------------

   My farmers used to stack a full panel per agent: market table, wallet,
   launchpad, pairs, references, fee claim. For one agent that is the right
   page. For four it is a scroll, and the thing an owner wants most often -
   which of these is mine, what is in its wallet, what is its address - was
   spread across screens of controls they were not looking for.

   So the default is tiles and the detail is one click in. `auto-fill` rather
   than `auto-fit`: with two agents, `auto-fit` stretches them across the whole
   width into two enormous cards, which reads as a bug rather than as a
   gallery. */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13.5rem, 1fr));
  gap: 0.9rem;
  margin: 1.25rem 0 0;
}

.tile {
  display: grid;
  cursor: pointer;
  justify-items: center;
  gap: 0.3rem;
  padding: 1rem 0.9rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  font: inherit;
  color: inherit;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.12s ease, transform 0.12s ease;
}

.tile:hover,
.tile:focus-visible {
  border-color: var(--field);
  transform: translateY(-2px);
}

/* The figure is the identity: a farmer's colours come from its vault address,
   so this is what an owner actually recognises. The soil-coloured ground under
   it stops a pale farmer floating in an empty box. */
.tileart {
  width: 7.5rem;
  height: 7.5rem;
  display: block;
  border-radius: calc(var(--radius) - 2px);
  background: linear-gradient(180deg, var(--cream) 0%, var(--cream) 68%, #e6dcc4 100%);
}

/* The name doubles as the keyboard route into the agent, so it is a real
   button rather than a span the mouse happens to hit. */
.tilename {
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
  font-weight: 600;
  font-size: 1.02rem;
  margin-top: 0.35rem;
  overflow-wrap: anywhere;
}

.tilestage {
  line-height: 1;
}

/* The one figure on a tile, and it earns its place: an agent with an empty
   wallet cannot pay a launch fee. */
.tilebal {
  font-weight: 600;
}

.tilebal .second {
  font-size: 0.76em;
}

/* The wallet address, copyable without opening the agent.

   Its own control rather than part of the tile's click, because the two things
   an owner does here are different: open this farmer, or take its address to
   send it ETH. `mountCopy` says whether it actually copied — an address
   somebody believes is on their clipboard and is not is how money goes to the
   wrong place. */
.tileaddr {
  font: inherit;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-faint);
  background: none;
  border: 1px solid transparent;
  border-radius: 5px;
  padding: 0.15rem 0.4rem;
  cursor: copy;
}

.tileaddr:hover,
.tileaddr:focus-visible {
  color: var(--ink);
  border-color: var(--line);
  background: var(--cream);
}

/* Back to the gallery. Above the detail, where a reader looks first. */
.backall {
  margin: 1.25rem 0 0.25rem;
}

/* The address an owner sends ETH to, and why.

   Given its own block rather than a line in the corner: funding is the one
   thing an owner must do for a farmer to launch at all, and it was previously
   a shortened explorer link nobody could copy from. */
.fundbox {
  margin: 0.75rem 0 0.9rem;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--straw);
  border-radius: var(--radius);
  background: var(--cream);
}

.fundwhy strong {
  display: block;
  margin-bottom: 0.2rem;
}

.fundwhy .muted {
  display: block;
  font-size: 0.86rem;
  line-height: 1.45;
}

.fundaddr {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  margin-top: 0.7rem;
}

/* The whole address, never shortened. It is what has to be pasted, and a
   shortened one is worse than none: it looks copyable and is not. */
.fundhex {
  flex: 1 1 24rem;
  min-width: 0;
  overflow-wrap: anywhere;
  font-size: 0.82rem;
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--paper);
}

/* The shortened address in the card header, which copies on click. Looks like
   the text it replaced rather than like a button, because it sits in a line of
   prose. */
.addrcopy {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}

.addrcopy:hover {
  color: var(--barn);
}

/* Money waiting to be claimed. Same panel as its siblings, in the barn colour
   rather than the field's, because this one is about the farmer's earnings
   rather than about what it grows — and because it only appears when there is
   something in it, so it should read as a thing to act on. */
.collect {
  margin: 0 0 1.2rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--barn);
  border-radius: var(--radius);
  background: var(--cream);
}

.collect .refnote:empty {
  display: none;
}

.refs {
  margin: 0 0 1.2rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--field);
  border-radius: var(--radius);
  background: var(--cream);
}

.refhead {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.8rem;
  align-items: baseline;
  margin-bottom: 0.6rem;
}

.refhead .muted {
  font-size: 0.8rem;
}

.refrow {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--line);
}

.refrow:last-child {
  border-bottom: 0;
}

/* The position, because order is the owner's emphasis and the contract keeps
   it — a model reading five examples reads the first one first. */
.refn {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--ink-soft);
  width: 1.2em;
}

.refwho {
  flex: 1 1 16ch;
  min-width: 0;
  display: flex;
  gap: 0.45rem;
  align-items: baseline;
  flex-wrap: wrap;
  font-size: 0.9rem;
}

.refaddr {
  font-size: 0.72rem;
  color: var(--ink-soft);
}

.refadd {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.7rem;
}

.refinput {
  flex: 1 1 22ch;
  min-width: 0;
  font-family: var(--mono);
  font-size: 0.8rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--panel);
  color: var(--ink);
}

.refbtn {
  font-size: 0.82rem;
  padding: 0.45rem 0.9rem;
}

.refnote {
  font-size: 0.78rem;
  margin: 0.55rem 0 0;
}

/* --- the $FARM address, in every header --------------------------------------
   A token's contract address is the first thing somebody needs and the thing
   they most often come back to copy, so it sits at the top of every page rather
   than inside a document. Before the token exists it says so: a placeholder
   address is the one kind of wrong value that costs a stranger money. */

.farmbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  /* Four things in a row is more than a phone has room for, and the failure
     without this was not a wrap -- the row simply grew past the viewport and
     the last button was cut off at the edge. */
  flex-wrap: wrap;
  row-gap: 0.4rem;
}

.ca {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.18rem 0.2rem 0.18rem 0.55rem;
  background: var(--cream);
}

/* Absent, and dressed as absent. Same treatment every unknown figure gets. */
.ca.none {
  padding: 0.25rem 0.7rem;
  font-style: italic;
  opacity: 0.75;
}

.cacopy {
  font-family: var(--mono);
  font-size: 0.75rem;
  border: 0;
  background: none;
  color: var(--ink-soft);
  cursor: pointer;
  padding: 0;
}

.cacopy:hover {
  color: var(--ink);
}

.caout {
  font-size: 0.75rem;
  line-height: 1;
  padding: 0.15rem 0.35rem;
  border-radius: 999px;
  color: var(--ink-soft);
  text-decoration: none;
}

.caout:hover {
  background: var(--panel);
  color: var(--ink);
}

.farmlink,
.followlink {
  font-size: 0.78rem;
  padding: 0.35rem 0.8rem;
  text-decoration: none;
  /* "Follow us" is two words and broke across two lines inside the button at
     phone width, which is the shape of a mistake rather than of a label. */
  white-space: nowrap;
}

.farmlink {
  font-family: var(--mono);
}

/* Set in the reading face, not the mono: `$FARM` is a ticker and this is a
   sentence. Same size and padding as its neighbour, so the two read as a pair
   of small links rather than one button standing beside a chip. */
.followlink {
  font-family: var(--sans);
}

/* The header wraps on a phone, and the address is the half worth keeping whole:
   it is either fully readable or it is not an address. */
@media (max-width: 640px) {
  .farmbar {
    order: 2;
  }
}

/* --- which launchpad a farmer goes to ----------------------------------------
   Only one exists today. The rest are shown because an owner deciding whether
   to mint should know what is coming — but they are real disabled buttons, not
   divs dressed as buttons, so a screen reader hears that they cannot be chosen
   and a keyboard skips them. */

.pads {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 0.6rem;
}

.pad {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  text-align: left;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--panel);
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.pad:hover:not([disabled]) {
  border-color: var(--ink-soft);
}

.pad[aria-checked="true"] {
  border-color: var(--soil);
  box-shadow: inset 0 0 0 1px var(--soil);
}

.pad[disabled] {
  cursor: not-allowed;
  background: var(--cream);
}

/* Dimmed, but the badge on top of it is not — the point of showing an
   unavailable launchpad is that somebody reads why it is unavailable. */
.pad[disabled] .pad-name,
.pad[disabled] .pad-note {
  opacity: 0.45;
}

.pad-name {
  font-weight: 600;
}

.pad-note {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.pad-soon {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.15rem 0.45rem;
  border-radius: 999px;
  background: var(--straw);
  color: var(--soil);
  white-space: nowrap;
}

/* The switcher on My farmers. Same cards as the forge — a launchpad should look
   the same wherever it is offered — in a panel that matches the reference list
   beside it. */
.pads-panel {
  margin: 0 0 1.2rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--soil);
  border-radius: var(--radius);
  background: var(--cream);
}

.pads-panel .pads {
  margin-top: 0.6rem;
}

/* The one it is already on. Not a "coming soon" badge and not the same colour:
   one says nothing exists yet, the other says this is where you are. */
.pad-on {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 0.15rem 0.45rem;
  border-radius: 999px;
  background: var(--good);
  color: var(--cream);
  white-space: nowrap;
}

/* The current launchpad is disabled so it cannot be paid for twice, but it must
   not read as unavailable the way the unbuilt ones do. */
.pad[disabled]:has(.pad-on) {
  background: var(--panel);
  border-color: var(--soil);
}

.pad[disabled]:has(.pad-on) .pad-name,
.pad[disabled]:has(.pad-on) .pad-note {
  opacity: 1;
}

/* --- what a farmer is holding ------------------------------------------------
   First panel in the card, because it is the money. Each row is a balance and,
   if there is anything there, the field and button that take it out. */

.wallet {
  margin: 0 0 1.2rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--good);
  border-radius: var(--radius);
  background: var(--cream);
}

.holdings {
  margin-top: 0.6rem;
}

.holding {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  align-items: center;
  justify-content: space-between;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--line);
}

.holding:last-child {
  border-bottom: 0;
}

/* The balance itself, in the mono the rest of the figures use. */
.hamt {
  font-family: var(--mono);
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
}

.hsym {
  font-size: 0.8rem;
  color: var(--ink-soft);
}

.hout {
  display: flex;
  gap: 0.4rem;
  align-items: center;
}

/* Wide enough for a full eighteen-decimal balance, which is what goes in it:
   the shown amount is rounded for reading and the field never is. */
.hout .amt {
  flex: 0 1 16rem;
  font-size: 0.78rem;
}

.hnote {
  font-size: 0.8rem;
}

/* --- the pairs a launchpad supports -------------------------------------------
   Under the launchpad they belong to. ETH is the one in use and reads as such;
   the rest are shown so an owner can see what the venue already does without
   taking a sentence on trust, and every one is plainly not available yet. */

.pairs {
  margin-top: 0.9rem;
  padding-top: 0.8rem;
  border-top: 1px dashed var(--line);
}

.pairhead {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.8rem;
  align-items: baseline;
}

.pairhead .muted {
  font-size: 0.78rem;
}

.pairchips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-top: 0.55rem;
}

.pairchip {
  font-family: var(--mono);
  font-size: 0.7rem;
  padding: 0.18rem 0.5rem;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink-soft);
  background: var(--panel);
  opacity: 0.7;
}

/* The one that actually works. Full opacity and the good colour, so "planned"
   and "in use" are never the same picture. */
.pairchip.on {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  opacity: 1;
  border-color: var(--good);
  color: var(--good);
  font-weight: 600;
}

.pairchip .pairtag {
  font-size: 0.6rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  opacity: 0.85;
}

.pairchip.more {
  border-style: dashed;
}

.pairnote {
  font-size: 0.78rem;
  margin: 0.6rem 0 0;
  /* 28rem, not 72ch: at 0.78rem those were the same 449px, and the rem stays
     that width if the note is ever set at another size. */
  max-width: 28rem;
}

/* --- the chrome, refined ------------------------------------------------------
   Everything on the page except the field itself. The scene is drawn by
   `sprites.js` and is not touched by any of this. */

/* The bar reads as glass over the farm rather than a strip laid on top of it,
   and gains a hairline of light along its bottom edge so it separates from the
   sky without a hard rule. */
.top {
  background: color-mix(in srgb, var(--panel) 82%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  -webkit-backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset, 0 8px 20px -20px rgba(43, 32, 49, 0.6);
}

@supports not (backdrop-filter: blur(2px)) {
  .top {
    background: var(--panel);
  }
}

.brand {
  font-family: var(--display);
  letter-spacing: -0.01em;
}

/* The current page, marked with the straw rather than a browser underline. */
.top nav a {
  position: relative;
  padding-bottom: 2px;
  text-decoration: none;
  color: var(--ink-soft);
}

.top nav a:hover {
  color: var(--ink);
}

.top nav a[aria-current="page"] {
  color: var(--ink);
  font-weight: 600;
}

.top nav a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 2px;
  border-radius: 2px;
  background: var(--straw);
}

/* --- panels ------------------------------------------------------------------
   A card should look like a sheet resting on the paper: a light top edge where
   it catches the window, a soft contact shadow underneath. One flat drop shadow
   on everything is what made the page look printed rather than laid out. */

.panel {
  position: relative;
  background: linear-gradient(180deg, #fffefb 0%, var(--panel) 100%);
  box-shadow: var(--shadow);
}

.panel::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset;
  pointer-events: none;
}

/* --- the numbers -------------------------------------------------------------
   The stats strips are the first thing read on three pages. The figure carries
   the weight; the label steps back into small caps and gets out of the way. */

.stats dt {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.stats dd {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* --- lists -------------------------------------------------------------------
   `how.html` is one long numbered explanation and the browser's own markers set
   it in the body face at body size, so the structure disappeared into the prose.
   These are set in the mono, in straw, hung in the margin. */

main ol {
  counter-reset: step;
  list-style: none;
  padding-left: 0;
}

main ol > li {
  counter-increment: step;
  position: relative;
  padding-left: 2.4rem;
  margin-bottom: 0.9rem;
}

main ol > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0.05em;
  width: 1.6rem;
  height: 1.6rem;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--straw-pale);
  border: 1px solid color-mix(in srgb, var(--straw) 60%, transparent);
  color: var(--soil);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
}

main ul {
  padding-left: 1.1rem;
}

main ul > li {
  margin-bottom: 0.4rem;
}

main ul > li::marker {
  color: var(--straw);
}

/* Lists inside a panel are furniture, not prose — leave them alone. */
.panel ol,
.panel ul,
.picker,
.holdings {
  counter-reset: none;
}

.panel ol > li::before {
  display: none;
}

.panel ol {
  list-style: decimal;
  padding-left: 1.2rem;
}

.panel ol > li {
  padding-left: 0;
}

/* --- inline code -------------------------------------------------------------
   Contract and function names run through the prose on every page. They were
   bare mono, which at body size reads as a font that failed to load. */

main p .mono,
main li .mono,
main p code,
main li code {
  font-size: 0.86em;
  padding: 0.08em 0.34em;
  border-radius: 4px;
  background: color-mix(in srgb, var(--straw-pale) 45%, transparent);
  border: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}

/* --- rules and footer -------------------------------------------------------- */

footer {
  margin-top: 3rem;
  border-top: 1px solid var(--line);
  background: linear-gradient(180deg, transparent, rgba(226, 214, 189, 0.25));
  color: var(--ink-faint);
  font-size: 0.85rem;
}

/* --- buttons ------------------------------------------------------------------
   A press should feel like one. */

.btn {
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset, 0 1px 2px rgba(43, 32, 49, 0.18);
  transition: background 0.12s ease, transform 0.06s ease, box-shadow 0.12s ease;
}

.btn:active:not([disabled]) {
  transform: translateY(1px);
  box-shadow: 0 1px 1px rgba(43, 32, 49, 0.2);
}

.btn.ghost:hover {
  border-color: var(--ink-faint);
  background: var(--cream);
}

/* --- tables ------------------------------------------------------------------
   Rows that respond to the cursor, and headers that read as headers. */

thead th {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-weight: 600;
}

tbody tr:hover > td {
  background: color-mix(in srgb, var(--straw-pale) 26%, transparent);
}

/* Not the opened reasoning row: it is already tinted and a second tint on hover
   makes it look selected. */
tbody tr.whyrow:hover > td {
  background: var(--cream);
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* --- the nav on a small screen ------------------------------------------------
   Wrapping put "How it works" off the right edge, where it was unreachable and
   looked like a rendering fault. One row that scrolls sideways keeps every page
   in reach and reads as a deliberate strip rather than a broken grid. */

@media (max-width: 760px) {
  .top {
    gap: 0.6rem 1rem;
    padding: 0.7rem 1rem;
  }

  .top nav {
    order: 3;
    width: 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 1.15rem;
    padding-bottom: 0.35rem;
    /* No scrollbar under a six-item strip; the overflow is obvious from the
       items running to the edge. */
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .top nav::-webkit-scrollbar {
    display: none;
  }

  .top nav a {
    white-space: nowrap;
  }
  /*
    Say that it scrolls. The nav ran off the right edge with the last two
    links simply absent, and a cut-off word reads as a bug rather than as a
    row that continues. A fade on the right edge is the conventional signal;
    it is painted by the nav's own mask so it costs no markup.
  */
  .top nav {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent);
    padding-right: 2.5rem;
  }

  /*
    On a phone the cluster comes apart.

    `.right` holds the stamp, Connect and - appended by farmbar.js - the CA
    chip, $FARM and Follow. As one flex item it had to wrap as one unit, which
    put Connect alone on a row, then the farmbar on the next, then the nav:
    four rows of chrome before the page. `display: contents` dissolves the
    wrapper so each child is a flex item of `.top` and takes its own row:

      1  brand ................................ Connect
      2  nav, full width, scrolls sideways, fades at the edge
      3  CA chip · $FARM · Follow

    The stamp is last and small. On a phone "block 58862427" is not a status
    anybody acts on; the front page's stale alarm still shows because it sets
    its own colour and text.
  */
  .top .right {
    display: contents;
  }
  .top .right > #connect {
    order: 1;
    margin-left: auto;
    padding: 0.45rem 0.9rem;
    font-size: 0.92rem;
  }
  .top .right > .farmbar {
    order: 4;
    width: 100%;
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .top .right > .farmbar::-webkit-scrollbar {
    display: none;
  }
  .top .right > #freshness {
    order: 5;
    width: 100%;
    font-size: 0.7rem;
    color: var(--ink-faint);
  }
}

/* A chip is a word in a sentence, so the punctuation after it should sit where
   punctuation sits. Without the pull, the padding leaves a visible gap before
   every comma and full stop. */
main p .mono,
main li .mono,
main p code,
main li code {
  padding: 0.06em 0.3em;
  margin-right: -0.06em;
}

/* --- the stats strip, rebuilt -------------------------------------------------
   Six equal cells divided by hard rules read as a spreadsheet: every figure the
   same size, the same weight, and nothing to look at first. What these strips
   are actually for is one glance, so the figure gets the room and the label
   steps right back. */

.stats {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(180deg, #fffefb, var(--panel));
  box-shadow: var(--shadow);
  margin-block: 1.4rem;
}

.stats div {
  position: relative;
  background: transparent;
  border: 0;
  margin: 0;
  padding: 1.05rem 1.2rem 1.15rem;
}

/*
  Separators that fade out at both ends.

  A full-height 1px rule between cells boxes each figure in; a gradient that
  falls away top and bottom reads as a gap between columns instead of a grid.
  Drawn as a pseudo-element so the first cell in each row can simply not have
  one — `:not(:first-child)` cannot know where a wrapped row begins, but a
  1px-wide element sitting at x=0 is invisible against the panel edge anyway.
*/
.stats div + div::before {
  content: "";
  position: absolute;
  left: 0;
  top: 12%;
  bottom: 12%;
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--line) 22%, var(--line) 78%, transparent);
}

.stats dt {
  font-family: var(--mono);
  font-size: 0.63rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 0.4rem;
}

.stats dd {
  margin: 0;
  font-family: var(--mono);
  font-size: 1.55rem;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* The exact ETH under a figure: a second line, quieter, and never mistaken for
   the figure itself. */
.stats dd .second {
  display: block;
  margin-top: 0.28rem;
  font-size: 0.8rem;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--ink-faint);
}

/* A figure nobody could produce is set in the prose face, so it never looks
   like a measurement. */
.stats dd.muted {
  font-family: var(--sans);
  font-size: 1.02rem;
  font-weight: 400;
  color: var(--ink-faint);
  padding-top: 0.35rem;
}

/* --- tables, rebuilt ---------------------------------------------------------
   These are the pages people come to read. The old rows were tight, greyish and
   uniformly weighted, so a ticker and a block number carried the same emphasis. */

table {
  font-size: 0.92rem;
  border-collapse: separate;
  border-spacing: 0;
}

thead th {
  padding: 0.7rem 0.7rem 0.6rem;
  background: linear-gradient(180deg, var(--panel), color-mix(in srgb, var(--panel) 88%, var(--cream)));
  border-bottom: 1px solid var(--line);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8) inset;
}

/* Room at the ends, so nothing sits against the panel edge. */
thead th:first-child,
tbody td:first-child {
  padding-left: 1rem;
}

thead th:last-child,
tbody td:last-child {
  padding-right: 1rem;
}

td {
  padding: 0.7rem;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
  vertical-align: middle;
}

/* Striping softened to almost nothing: the two-line money cells already give
   the eye a rhythm, and a strong stripe under them turns the table into bands. */
tbody tr:nth-child(even) > td {
  background: color-mix(in srgb, var(--straw) 3%, transparent);
}

/*
  A hover that marks the row rather than washing it.

  The tint is faint and a straw edge appears at the left, which is easier to
  follow across nine columns than a background change — the eye tracks the mark,
  not the shade.
*/
tbody tr:hover > td {
  background: color-mix(in srgb, var(--straw) 9%, transparent);
}

tbody tr:hover > td:first-child {
  box-shadow: inset 3px 0 0 var(--straw);
}

/* The reasoning row is its own block and must not take the row treatment. */
tbody tr.whyrow > td,
tbody tr.whyrow:hover > td {
  background: var(--cream);
  box-shadow: none;
}

/* The ticker is the row's name: it leads, and the token's full name sits under
   it in the prose face so the two are told apart at a glance. */
td .ticker {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* Figures line up on the decimal and read as one column, not nine numbers. */
td.num {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

td.num .second {
  color: var(--ink-faint);
}

/* Rank numbers on the leaderboard: the position is furniture, not a measurement. */
#board td:first-child,
#farmers td:first-child {
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 0.8rem;
}

/* --- corrections after seeing the strips with real figures --------------------

   `29.2337 ETH` wrapped onto two lines inside a 140px cell, which turns a
   glanceable number into a paragraph. The figure never wraps now; it shrinks
   with the cell instead, and the cells are given the width the unit actually
   needs. */

.stats {
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}

/* A strip inside a card sits closer to it than one standing on the page. This
   was written inline on the agent card, along with a border, a radius and an
   overflow the rule above already gave it -- and the inline `margin` shorthand
   that came with it is what silently cancels a horizontal margin. */
.panel .stats {
  margin-block: 1rem;
}

.stats dd {
  font-size: clamp(1.15rem, 0.95rem + 0.55vw, 1.5rem);
  white-space: nowrap;
}

.stats dd .second {
  white-space: nowrap;
}

/*
   The table header does not stick, and that was measured rather than decided.

   A sticky `thead` has to sit below the site header, which is itself sticky —
   so it needs that header's height as an offset. Measured on one page at three
   widths: 68px at 1400, 121px at 900, 159px on a phone, because the nav wraps
   differently at each. No constant is right at more than one of them, and the
   failure mode is not cosmetic: an offset that is too small parks the header
   *over* the first row and hides it.

   Reading the height in JavaScript and publishing it as a custom property would
   work, and it is a `ResizeObserver` on every page plus a shared module for a
   convenience on tables that top out around thirty rows. Not worth it. If these
   ever get long enough to need it, that is the way to do it — not a constant.
*/

/* --- what is allowed out of the column ---------------------------------------

   A ledger with ten columns of figures cannot be read at 43rem and should not
   be asked to try. So the tables, the stat strips and the sort bar break out,
   centred on the column and bounded by the viewport, while every word on the
   page stays in it.

   `50%` here resolves against the column, so the negative margin is exactly
   half the difference and the wide thing centres on the same axis as the text
   above it. Bounding by `100vw` rather than by nothing is what stops a table
   pushing the whole document sideways on a narrow window -- with the scroller
   below, the table then scrolls inside its own panel instead. */
.column > .stats,
.column > .sortbar,
.column > .form-grid,
.column > .gallery,
.column > .panel:has(> table):not(.fits),
main:not(.wide) > .stats,
main:not(.wide) > .sortbar,
main:not(.wide) > .form-grid,
main:not(.wide) > .gallery,
main:not(.wide) > .panel:has(> table):not(.fits) {
  --out: min(var(--wide), calc(100vw - 3rem));
  width: var(--out);
  margin-left: calc(50% - var(--out) / 2);
}

/*
   `.fits` opts a panel back into the column.

   Not every table is a ledger. The tier table on `how.html` is four short
   columns and reads better beside the prose it explains than stretched across
   the page -- and the column is one of the two edges this layout has, so
   leaving it there costs nothing.
*/

/* --- a table never widens the page -------------------------------------------

   `launches` puts ten columns in front of a phone and `best` puts ten more.
   They cannot fit and they should not try: the panel scrolls and the page does
   not. That was an inline `overflow-x: auto` on each panel that held a table,
   which is fine right up until somebody adds a table and does not know to write
   it — the roster on the front page and the category table on `how` were both
   missing it, and the front page scrolled 198px sideways on a phone with no
   error anywhere.

   `:has(> table)` rather than `.panel`, because `overflow-x` on a box also
   stops `overflow-y` being visible, and panels that hold no table hold things
   that need to escape their box. */
.panel:has(> table) {
  overflow-x: auto;
}

/* --- one reading column -------------------------------------------------------

   On a wide desktop the front page had a call-to-action band 1132px across
   sitting directly above prose 536px across, with six hundred pixels of nothing
   to the right of the text. Each element was individually reasonable — the band
   filled its 1180px container, the paragraphs stopped at a readable measure —
   and together they read as a page that had come apart.

   So the measure is a token, and everything in the text column uses it. Wide
   things stay wide on purpose: the field, the stats strip and the tables are
   not prose and are not bound by it. */

:root {
  /*
    A length, not `ch`.

    `ch` is the width of a "0" in the *element's own* font, so one token in `ch`
    is a different measure for every element that uses it: 70ch on the headline,
    set in a 3.2rem display face, computed to 1960px and constrained nothing at
    all, while the same token on a paragraph came out at 605. A column has one
    edge or it is not a column.
  */
  --measure: 40rem;

  /*
    The column, and the widest a thing that is not prose may get.

    `--column` is the measure plus the room a panel's own padding needs, so a
    paragraph inside a panel and a paragraph outside one land on the same right
    edge rather than a border's width apart.
  */
  --column: 43rem;
  --wide: 1180px;
}

.lede,
main p,
main ol > li,
main ul > li {
  max-width: var(--measure);
}

/*
   The headline sits in the column like everything else.

   It had a wider measure of its own for a while, on the ordinary editorial
   argument that display type needs more room per line than body text. That was
   true in isolation and wrong on the page: it put a third right edge on a
   layout that already had two, and a heading that overhangs the paragraph
   under it reads as a mistake rather than as scale.
*/
main h1 {
  max-width: none;
}

/* The call to action belongs to the text it interrupts, not to the page. */
.cta {
  max-width: var(--measure);
}

/*
  Below that width the band is a column, not a row: a button beside two lines of
  copy needs about 30rem before it stops looking cramped, and the measure on a
  narrow window is less than that.
*/
@media (max-width: 620px) {
  .cta {
    flex-direction: column;
    align-items: stretch;
  }

  .cta .go {
    text-align: center;
  }
}

/* Inside a panel the panel is the column, so the prose measure does not apply
   twice. Left in place it capped paragraphs at 38rem inside a 49rem card and
   left a gap down the right of every one of them, which reads as a mistake
   rather than as a measure. */
.panel p,
.panel li,
.panel .lede {
  max-width: none;
}

/*
  The approval panel on My farmers.

  Built from the same parts as `.collect` and `.refs` - a bordered block with a
  coloured left edge - so a farmer's card reads as one thing rather than three
  designs stacked. The edge is the field green here because this panel is about
  what is growing rather than about money.
*/
.approve {
  margin: 0 0 1.2rem;
  padding: 0.85rem 1rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--field);
  border-radius: var(--radius);
  background: var(--cream);
}

.approve .approvenote:empty {
  display: none;
}

.approveact {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: center;
  margin-top: 0.6rem;
}

/* A launch that is already signed for, in the good colour rather than a badge. */
.approved {
  margin: 0.6rem 0 0;
  color: var(--good);
  font-weight: 600;
}

/*
  The approval picker: three ideas as cards, then the owner's extras.

  Each card is a button so it can be picked from the keyboard; `aria-pressed`
  carries the pick and the style follows it. Cards stack on a phone and sit
  side by side when there is room. Nothing here may push the page sideways
  (trap 46), so every identifier wraps.
*/
.approve .roundhead {
  margin: 0 0 0.5rem;
}

.ideas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 0.65rem;
  margin: 0.7rem 0 0;
}

.idea {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  width: 100%;
  min-width: 0;
  padding: 0.7rem 0.75rem;
  text-align: left;
  font: inherit;
  color: var(--ink);
  background: var(--panel);
  border: 2px solid var(--line);
  border-radius: var(--radius);
  cursor: pointer;
  overflow-wrap: anywhere;
}

.idea:hover:not(:disabled) {
  border-color: var(--straw);
}

.idea[aria-pressed="true"] {
  border-color: var(--barn);
  box-shadow: 0 0 0 3px var(--straw-pale);
}

.idea.isapproved {
  border-color: var(--good);
}

.idea:disabled {
  cursor: default;
  opacity: 0.85;
}

.idealogo,
.minilogo {
  flex: 0 0 auto;
  border-radius: 12px;
  background: var(--sky);
  object-fit: cover;
}

.idealogo {
  width: 72px;
  height: 72px;
}

.minilogo {
  width: 22px;
  height: 22px;
  border-radius: 6px;
  vertical-align: middle;
}

.nologo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-faint);
  font-weight: 700;
}

.ideatext {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

.ideahead {
  display: block;
  line-height: 1.35;
}

.ideadesc {
  display: block;
  font-size: 0.88rem;
}

.ideawhy {
  display: block;
  font-size: 0.85rem;
  font-style: italic;
  color: var(--ink-soft);
}

.ideabadge,
.ideatag {
  display: inline-block;
  margin-left: 0.3rem;
  padding: 0 0.45rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.6;
  vertical-align: middle;
}

.ideabadge {
  color: var(--warn);
  border: 1px solid currentColor;
}

.ideatag {
  color: #fff;
  background: var(--good);
}

.ideabad {
  display: block;
  font-size: 0.8rem;
  color: var(--bad);
}

.pickform {
  margin: 0.9rem 0 0;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
}

.pickform .field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin: 0.6rem 0 0;
  font-size: 0.88rem;
}

.pickform .field .refinput {
  flex: 0 0 auto;
  width: 100%;
  box-sizing: border-box;
}

.logopick {
  margin: 0.8rem 0 0;
  padding: 0.5rem 0.7rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  font-size: 0.88rem;
}

.logopick label {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  margin-right: 1rem;
}

.uploadrow {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.8rem;
  align-items: center;
  margin-top: 0.5rem;
  font-size: 0.8rem;
}

.uploadrow input[type="file"] {
  max-width: 100%;
}

.uploadnote {
  margin: 0.5rem 0 0;
  font-size: 0.82rem;
}

.uploaded {
  display: flex;
  gap: 0.7rem;
  align-items: center;
  margin-top: 0.6rem;
  font-size: 0.8rem;
  overflow-wrap: anywhere;
}

.pickform [data-formnote]:empty {
  display: none;
}

.pickform .permanent {
  margin: 0.7rem 0 0;
  font-size: 0.82rem;
}

.confirmbox {
  margin: 0.8rem 0 0;
  padding: 0.75rem 0.85rem;
  border: 1px solid var(--warn);
  border-left: 3px solid var(--warn);
  border-radius: 10px;
  background: #fff8ec;
}

.confirmbox p {
  margin: 0 0 0.5rem;
}

.extras {
  margin: 0.4rem 0 0;
  padding-left: 1.1rem;
  font-size: 0.85rem;
  overflow-wrap: anywhere;
}

.standing {
  margin: 0 0 0.3rem;
}

/* The front page's roster: a cat whose round has ideas waiting. */
.ideaspill {
  display: inline-block;
  margin-top: 0.2rem;
  padding: 0 0.45rem;
  border-radius: 999px;
  font-size: 0.7rem;
  line-height: 1.6;
  color: var(--ink-soft);
  border: 1px solid var(--lavender);
  background: var(--lavender-pale);
  white-space: nowrap;
}

/*
  Which chain a farmer is on, beside its name (trap 66). Names are unique per
  chain, not across them, so once Base is live the tag is part of the name.
  Quiet on Robinhood, Base's own blue on Base.
*/
.chain-tag {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0 0.4em;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.5;
  vertical-align: middle;
  color: var(--ink-soft);
  border: 1px solid currentColor;
}
.chain-tag.base {
  color: #0052ff;
}

/* ==========================================================================
   The MEOWGENTS layer.

   Restyles the chrome every page shares, and adds the pieces the front page is
   built from (hero, steps, toy grid, treat jar). Everything above still
   applies; this only goes on top.
   ========================================================================== */

body {
  background-color: var(--cream);
  background-image:
    radial-gradient(circle at 12px 12px, rgba(232, 96, 76, 0.05) 2px, transparent 2.5px),
    radial-gradient(120% 70% at 50% -10%, rgba(255, 236, 222, 0.9), transparent 60%);
  background-size: 28px 28px, auto;
  background-attachment: fixed, fixed;
  font-size: 16.5px;
}

::selection {
  background: var(--straw-pale);
  color: var(--ink);
}

a {
  color: var(--barn-dark);
  text-decoration-color: rgba(184, 67, 47, 0.3);
}

h1,
h2,
h3 {
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* Section headings get a paw print in the margin instead of the farm's rule. */
main h2::before {
  left: -1.6rem;
  top: 0.1em;
  width: 1.05em;
  height: 1.05em;
  border-radius: 0;
  background: var(--straw);
  -webkit-mask: var(--paw) center / contain no-repeat;
  mask: var(--paw) center / contain no-repeat;
  opacity: 0.85;
}

:root {
  --paw: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 20 20%22%3E%3Cellipse cx=%2210%22 cy=%2214%22 rx=%224.6%22 ry=%223.8%22/%3E%3Ccircle cx=%224.2%22 cy=%229%22 r=%222%22/%3E%3Ccircle cx=%228%22 cy=%225.6%22 r=%222%22/%3E%3Ccircle cx=%2212%22 cy=%225.6%22 r=%222%22/%3E%3Ccircle cx=%2215.8%22 cy=%229%22 r=%222%22/%3E%3C/svg%3E");
}

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

.top {
  align-items: center;
  border-top: 0;
  border-bottom: 1px solid var(--line);
  background: rgba(255, 253, 251, 0.88);
  backdrop-filter: saturate(1.4) blur(10px);
  -webkit-backdrop-filter: saturate(1.4) blur(10px);
  padding: 0.7rem 1.5rem;
}

.brand {
  align-items: center;
  font-family: var(--display);
  font-weight: 900;
  font-size: 1.3rem;
  letter-spacing: 0.01em;
}

.brand .logo {
  width: 30px;
  height: 30px;
  flex: none;
}

.brand .ticker {
  font-family: var(--display);
  font-weight: 800;
  color: #fff;
  background: var(--barn);
  border: 0;
  padding: 0.12rem 0.55rem;
}

.top nav {
  gap: 0.25rem;
  font-weight: 700;
  font-size: 0.9rem;
}

.top nav a {
  padding: 0.35rem 0.7rem;
  border-radius: 999px;
  border: 0;
  transition: background 0.12s ease, color 0.12s ease;
}

.top nav a:hover,
.top nav a[aria-current="page"] {
  border: 0;
  color: var(--ink);
  background: var(--straw-pale);
}

.btn {
  border-radius: 999px;
  font-family: var(--display);
  font-weight: 800;
}

/* --- hero ----------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(60% 90% at 85% 40%, rgba(255, 200, 170, 0.55), transparent 70%),
    radial-gradient(50% 80% at 5% 90%, rgba(183, 162, 201, 0.35), transparent 70%),
    linear-gradient(180deg, #fff1e6, #fff7f0);
  border-bottom: 1px solid var(--line);
}

.hero-inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(2rem, 5vw, 4.5rem) 1.5rem clamp(1.5rem, 4vw, 3.5rem);
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: 2rem;
  align-items: center;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 800;
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--barn-dark);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.3rem 0.8rem;
  box-shadow: var(--shadow-sm);
}

.hero h1 {
  font-size: clamp(2.5rem, 1.6rem + 3.6vw, 4.4rem);
  font-weight: 900;
  line-height: 1;
  margin: 1rem 0 1rem;
  max-width: none;
}

.hero h1 .accent {
  color: var(--barn);
}

.hero .sub {
  font-size: 1.15rem;
  color: var(--ink-soft);
  max-width: 34rem;
  margin: 0 0 1.6rem;
  line-height: 1.55;
}

.hero .actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
}

.bigbtn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-weight: 900;
  font-size: 1.08rem;
  text-decoration: none;
  color: #fff;
  background: var(--barn);
  padding: 0.85rem 1.5rem;
  border-radius: 999px;
  box-shadow: 0 6px 0 var(--barn-dark), 0 14px 30px -12px rgba(232, 96, 76, 0.7);
  transition: transform 0.1s ease, box-shadow 0.1s ease;
}

.bigbtn:hover {
  color: #fff;
  transform: translateY(-2px);
  box-shadow: 0 8px 0 var(--barn-dark), 0 18px 34px -12px rgba(232, 96, 76, 0.7);
}

.bigbtn:active {
  transform: translateY(4px);
  box-shadow: 0 2px 0 var(--barn-dark);
}

.bigbtn.soft {
  color: var(--ink);
  background: #fff;
  box-shadow: 0 5px 0 var(--line), 0 12px 24px -14px rgba(43, 32, 49, 0.4);
}

.bigbtn.soft:hover {
  color: var(--ink);
  box-shadow: 0 7px 0 var(--line), 0 16px 28px -14px rgba(43, 32, 49, 0.4);
}

.hero .price {
  flex-basis: 100%;
  margin: 0.6rem 0 0;
  font-size: 0.85rem;
  color: var(--ink-soft);
}

.hero-art {
  position: relative;
  aspect-ratio: 1 / 1;
  max-width: 440px;
  width: 100%;
  justify-self: center;
}

.hero-art .blob {
  position: absolute;
  inset: 6%;
  border-radius: 46% 54% 50% 50% / 52% 44% 56% 48%;
  background: linear-gradient(160deg, #ffd8c2, #ffb99c);
  box-shadow: inset 0 -20px 40px rgba(232, 96, 76, 0.18);
}

.hero-art canvas {
  position: relative;
  width: 100%;
  height: 100%;
  display: block;
  cursor: pointer;
}

.hero-art .coat {
  position: absolute;
  left: 50%;
  bottom: 3%;
  transform: translateX(-50%);
  font-weight: 800;
  font-size: 0.82rem;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.25rem 0.8rem;
  box-shadow: var(--shadow-sm);
  white-space: nowrap;
}

@media (max-width: 820px) {
  .hero-inner {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero-art {
    max-width: 300px;
    order: -1;
  }
}

/* --- section frames ------------------------------------------------------- */

.section {
  max-width: 1180px;
  margin: 0 auto;
  padding: 3.5rem 1.5rem 0;
}

.section > .kicker {
  font-weight: 800;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--barn);
  margin: 0 0 0.3rem;
}

.section > h2 {
  font-size: clamp(1.7rem, 1.2rem + 1.6vw, 2.4rem);
  margin: 0 0 0.6rem;
  max-width: none;
}

.section > h2::before {
  display: none;
}

.section > .intro {
  color: var(--ink-soft);
  max-width: 44rem;
  margin: 0 0 1.6rem;
  font-size: 1.05rem;
}

/* --- the room ------------------------------------------------------------- */

.room {
  border-radius: 28px;
  overflow: hidden;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  background: var(--panel);
}

.room .scene {
  border-bottom: 0;
  box-shadow: none;
  background: var(--sky);
}

.room .stats {
  border-block: 0;
  border-top: 1px solid var(--line);
}

.room .stats div:last-child {
  border-right: 0;
}

.stats dt {
  font-weight: 800;
  letter-spacing: 0.06em;
}

.stats dd {
  font-family: var(--display);
  font-weight: 900;
}

.scene .hint {
  font-family: var(--sans);
  font-weight: 700;
  color: rgba(43, 32, 49, 0.55);
  background: rgba(255, 253, 251, 0.85);
}

.scene .empty .card {
  font-family: var(--sans);
  font-weight: 700;
  border-radius: 18px;
  color: var(--ink);
}

.tip {
  border-radius: 14px;
  box-shadow: var(--shadow-lg);
}

.tip .who {
  font-family: var(--display);
  font-weight: 900;
  font-size: 1rem;
}

/* --- steps ---------------------------------------------------------------- */

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1rem;
  counter-reset: step;
}

@media (min-width: 1060px) {
  .steps {
    /* Six steps: two even rows of three. */
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.step {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: 0.9rem 1.1rem 1.2rem;
  box-shadow: var(--shadow);
  counter-increment: step;
}

.step::before {
  content: counter(step);
  position: absolute;
  top: 1.3rem;
  left: 1.4rem;
  width: 1.7rem;
  height: 1.7rem;
  display: grid;
  place-content: center;
  border-radius: 50%;
  background: var(--barn);
  color: #fff;
  font-weight: 900;
  font-size: 0.85rem;
  z-index: 1;
}

.step canvas {
  display: block;
  width: 100%;
  height: 140px;
  border-radius: 16px;
  background: linear-gradient(180deg, #fff1e6 0 64%, #e8c7a4 64% 100%);
  margin-bottom: 0.8rem;
}

.step h3 {
  margin: 0 0 0.3rem;
  font-size: 1.12rem;
}

.step p {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.93rem;
  line-height: 1.5;
}

.step.warn canvas {
  background: linear-gradient(180deg, #efe9f2 0 64%, #d9cfd6 64% 100%);
}

.step.warn::before {
  content: "!";
  background: var(--ink-soft);
}

/* --- the five toys -------------------------------------------------------- */

.toys {
  display: grid;
  /* auto-fit, so five toys stretch across a wide row rather than leaving
     empty columns beside them. */
  grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
  gap: 0.75rem;
}

.toy {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 0.7rem 0.85rem 0.85rem;
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}

.toy:hover {
  transform: translateY(-3px) rotate(-0.6deg);
  box-shadow: var(--shadow);
}

.toy canvas {
  display: block;
  width: 100%;
  height: 72px;
  border-radius: 12px;
  background: var(--straw-pale);
}

.toy .name {
  font-family: var(--display);
  font-weight: 900;
  font-size: 1.02rem;
  margin: 0.55rem 0 0.1rem;
}

.toy .as {
  font-size: 0.72rem;
  font-weight: 800;
  color: var(--barn);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.toy .means {
  font-size: 0.82rem;
  color: var(--ink-soft);
  line-height: 1.4;
  margin: 0.25rem 0 0;
}

/* --- roster and treat jar ------------------------------------------------- */

.card-soft {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 22px;
  box-shadow: var(--shadow);
  padding: 0.6rem 0.7rem;
  overflow-x: auto;
}

.card-soft table {
  font-size: 0.88rem;
}

.pill {
  font-family: var(--sans);
  font-weight: 700;
  background: var(--straw-pale);
  border-color: transparent;
}

.pill[data-stage="fallow"] {
  background: var(--lavender-pale);
}

.pill[data-stage="ripe"] {
  background: var(--mint-pale);
  border-color: transparent;
}

.pill[data-stage="rotten"] {
  border-color: transparent;
}

tbody tr:nth-child(even) {
  background: rgba(255, 138, 91, 0.04);
}

tbody tr:hover {
  background: rgba(255, 138, 91, 0.1);
}

.jar {
  display: grid;
  grid-template-columns: 150px minmax(0, 1fr);
  gap: 1.5rem;
  align-items: center;
  background: linear-gradient(135deg, #fff4e8, #fdeee6 60%, var(--lavender-pale));
  border: 1px solid var(--line);
  border-radius: 26px;
  padding: 1.4rem 1.6rem;
  box-shadow: var(--shadow);
}

.jar canvas {
  width: 150px;
  height: 170px;
  display: block;
}

.jar h3 {
  margin: 0 0 0.3rem;
  font-size: 1.35rem;
}

.jar p {
  margin: 0.4rem 0 0;
  color: var(--ink-soft);
}

.jar #siloState {
  color: var(--ink);
  font-weight: 700;
}

@media (max-width: 640px) {
  .jar {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    text-align: center;
  }
}

/* --- closing call to action ----------------------------------------------- */

.adopt {
  max-width: 1180px;
  margin: 4rem auto 0;
  padding: 0 1.5rem;
}

.adopt .box {
  position: relative;
  overflow: hidden;
  border-radius: 32px;
  background: linear-gradient(135deg, var(--barn), #ff9a6b);
  color: #fff;
  padding: clamp(1.8rem, 4vw, 3rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 1.5rem;
  align-items: center;
  box-shadow: var(--shadow-lg);
}

.adopt h2 {
  color: #fff;
  margin: 0 0 0.4rem;
  font-size: clamp(1.6rem, 1.1rem + 1.8vw, 2.4rem);
}

.adopt h2::before {
  display: none;
}

.adopt p {
  margin: 0;
  color: rgba(255, 255, 255, 0.92);
}

.adopt .bigbtn {
  background: #fff;
  color: var(--barn-dark);
  box-shadow: 0 6px 0 rgba(120, 40, 25, 0.35);
}

.adopt .price {
  margin-top: 0.6rem;
  font-size: 0.85rem;
  color: rgba(255, 255, 255, 0.85);
}

@media (max-width: 720px) {
  .adopt .box {
    grid-template-columns: minmax(0, 1fr);
  }
}

footer {
  font-family: var(--sans);
  font-weight: 600;
  text-align: center;
  border-top: 1px solid var(--line);
  margin-top: 4rem;
}
