/* Agavist, the site. One world with the app (research/design/WORLDS.md):
   white ground, agave green for the action and the structure around it, ink for
   everything already recorded, Instrument Sans for every word (its regular for
   reading, its medium and up for the voice), and a serif italic only where a
   botanist would set one: the plants' Latin names and the old journals' titles.
   Scale and spacing follow .claude/skills/award-design/design-tokens.md; this
   world's colours are its own. */

@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/instrument-sans-regular.woff") format("woff");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/instrument-sans-medium.woff") format("woff");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/instrument-sans-semibold.woff") format("woff");
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/instrument-sans-bold.woff") format("woff");
}

:root {
  color-scheme: light only;              /* the app is light only; so is its site */
  --paper: #fff;
  --label: #fbf7e9;                      /* paper labels: the 1912 plate's own margin, a third of the way from white; never the page's ground */
  --ink: #171410;                        /* 18.4:1 on white; warm, like the prints' own black */
  --soft: #5c5244;                       /* 7.4:1  secondary text, a grey with the plates' soil in it */
  --cap: #695e50;                        /* 6.4:1  captions, credits */
  --mute: #7e8683;                       /* 3.7:1  large display text only */
  --sage: #5f6f51;                       /* 5.4:1  large display text only: the 1868 tobalá's leaf (#8c9a7f), darkened to read */
  --green: #2f7a6b;                      /* 5.1:1  the accent: actions, links, status */
  --deep: #1e5b50;                       /* 7.9:1  the mark, pressed */
  --tint: #edf4f1;
  --rule: rgba(17, 19, 22, .1);
  --bezel: #17191b;
  /* one light for every object: the warm, soft shadow the 1868 plate casts */
  --lift: 0 1px 2px rgba(58, 46, 26, .1), 0 10px 22px -10px rgba(58, 46, 26, .3);
  --lift-phone: 0 2px 4px rgba(58, 46, 26, .1), 0 26px 46px -20px rgba(58, 46, 26, .4);
  --lie: 0 1px 1px rgba(58, 46, 26, .1), 0 3px 8px -4px rgba(58, 46, 26, .2);          /* paper lying on the page, not lifted off it */
  /* real paper: the fibre of a 1912 plate's margin, its colour taken to near white */
  --paper-grain: var(--label) url("img/paper.webp") 0 0 / 600px 333px;
  --display: "Instrument Sans", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --sans: "Instrument Sans", ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --serif: ui-serif, "New York", Georgia, "Times New Roman", serif;
  --gutter: clamp(1rem, 4.2vw, 3.4rem);
  --shell: 72rem;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font: 400 1rem/1.55 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; height: auto; }
a { color: var(--green); text-decoration-thickness: 1px; text-underline-offset: .2em; }
a:hover { color: var(--deep); }
:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; border-radius: 4px; }
p { margin: 0; }
figure { margin: 0; }
/* a plant's Latin name and an old journal's title, set the way the plates set them */
cite, figcaption i, .foot-notes i { font-family: var(--serif); font-size: 1.04em; }

.wrap { width: min(100% - 2 * var(--gutter), var(--shell)); margin-inline: auto; }

/* ---------- skip link ---------- */
.skip { position: absolute; left: .8rem; top: -4rem; z-index: 10; padding: .7rem 1rem; background: var(--ink); color: #fff; border-radius: 6px; font: 600 .9rem/1 var(--display); text-decoration: none; }
.skip:focus { top: .8rem; }

/* ---------- brand row ---------- */
.top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding-block: .6rem; }
.brand { display: inline-flex; align-items: center; gap: .5rem; color: var(--ink); text-decoration: none; }
.brand:hover { color: var(--ink); }
.mark { flex: none; width: 2rem; height: 2rem; color: var(--deep); }
/* the wordmark is the app's own lockup: Instrument Sans Bold, lowercase */
.word { font: 700 1.5rem/1 var(--display); letter-spacing: -.02em; transform: translateY(-.04em); }
.nav { display: flex; gap: 1.2rem; }
.nav a { font: 600 .9rem/1 var(--display); color: var(--ink); text-decoration: none; padding: .95rem .2rem; }   /* 44 px to tap */
.nav a:hover, .nav a[aria-current="page"] { color: var(--green); }

/* ---------- the shared objects: a phone, a paper label ---------- */
.phone {
  --w: 15rem;
  position: relative; width: var(--w);
  padding: calc(var(--w) * .03);
  border-radius: calc(var(--w) * .185);
  background: var(--bezel);
  box-shadow: inset 0 0 0 1px #3d4145, inset 0 0 0 calc(var(--w) * .012) #25282b, var(--lift-phone);
}
.phone > img { width: 100%; border-radius: calc(var(--w) * .155); background: #fff; }
.phone::before, .phone::after { content: ""; position: absolute; width: 3px; background: #2b2e31; }
.phone::before { left: -3px; top: 21%; height: 7%; border-radius: 2px 0 0 2px; }
.phone::after { right: -3px; top: 27%; height: 12%; border-radius: 0 2px 2px 0; }

.specimen {
  margin: 0; display: grid; gap: .15rem; width: max-content; max-width: 15rem;
  padding: .65rem .85rem .6rem;
  background: var(--paper-grain); color: var(--soft);   /* 5.1:1 even on the paper's darkest specks */
  border: 1px solid rgba(17, 19, 22, .55); outline: 1px solid rgba(17, 19, 22, .2); outline-offset: -5px;
  border-radius: 3px;
  box-shadow: var(--lift);
  font: 400 .875rem/1.15 var(--sans);
  transform: rotate(var(--tilt, -.8deg));
}
.specimen b { font: 600 1.05rem/1.15 var(--display); color: var(--ink); letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.specimen i { font: italic 400 .95rem/1.15 var(--serif); color: var(--ink); }

/* ---------- hero ---------- */
.hero { overflow-x: clip; }
.hero-grid { display: grid; gap: 1.6rem; align-items: center; padding-block: clamp(1rem, 4vw, 2.4rem) clamp(3.4rem, 8vw, 4.5rem); }
h1 {
  margin: 0;
  /* t-hero at its ceiling; sized so "Know the agave." (7.4em wide) always holds one line */
  font: 500 clamp(2.2rem, 11.8vw, 4.4rem)/1 var(--display);
  letter-spacing: -.032em;
  word-spacing: .04em;                   /* display type at this tracking closes its word gaps */
}
h1 span { display: block; }
h1 .tone { color: var(--sage); }
h1 span, h2 { text-wrap: balance; }
.lede { margin: 1.2rem 0 1.4rem; max-width: 22rem; text-wrap: balance; font-size: clamp(1.15rem, 1rem + .4vw, 1.25rem); line-height: 1.5; color: var(--soft); }
/* the honest status today: plain ink, no icon, no store badge. It is news, and there is nothing to download yet. The one
   action is to write to us, labelled as that, with the address in it */
.status { display: grid; justify-items: start; gap: .2rem; max-width: 24rem; color: var(--ink); }
.status b { font: 600 1.15rem/1.2 var(--display); letter-spacing: -.01em; }
.status span { font-size: 1rem; line-height: 1.45; color: var(--soft); text-wrap: balance; }
.btn {
  display: inline-flex; align-items: center; flex: none; min-height: 3.2rem; padding: .75rem 1.5rem;
  background: var(--green); color: #fff; border-radius: 8px; text-decoration: none;
  font: 600 1.06rem/1.1 var(--display); letter-spacing: -.005em;
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, .2), 0 1px 2px rgba(58, 46, 26, .18);   /* a pressed edge, no glow */
  transition: background-color .15s ease, translate .15s ease;
}
.btn:hover { background: var(--deep); color: #fff; translate: 0 -1px; }
.btn:active { translate: 0 0; }
.btn:focus-visible { outline-offset: 4px; }
/* the hero's ask: the button, then what it is for, with the address printed so it can be copied */
.ask-cta { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem 1.2rem; margin-top: 1.2rem; max-width: 27rem; }
.ask-cta span { flex: 1 1 12rem; font-size: .92rem; line-height: 1.35; color: #3f372c; text-wrap: balance; }
.ask-cta > .mail { font: 600 1rem/1.2 var(--display); letter-spacing: -.005em; padding-block: .8rem; }   /* 44 px to tap */
.ask-cta span a { display: inline-block; padding-block: .45rem; font: 600 1rem/1.3 var(--display); letter-spacing: -.005em; }   /* 44 px to tap */

/* the art: the 1868 plate, the phone that names it, the plate's label */
.hero-art { position: relative; container-type: inline-size; aspect-ratio: 100 / 176; margin-inline: calc(-1 * var(--gutter)); }
@media (min-width: 34rem) and (max-width: 59.99rem) { .hero-art { width: 30rem; margin-inline: auto; } }
.plate { position: absolute; z-index: 1; top: 0; left: 0; width: 100%; }
.plate img { position: relative; z-index: 1; width: 100%; }
.plate::after { /* the plant's own shadow on the ground */
  content: ""; position: absolute; z-index: 0; left: 18%; right: 14%; bottom: 0; height: 12%;
  background: radial-gradient(closest-side, rgba(74, 60, 36, .18), rgba(74, 60, 36, 0));
}
.hero-art .phone { --w: 58cqw; position: absolute; z-index: 3; left: 3%; top: 58cqw; }
.hero-art .specimen { position: absolute; z-index: 4; right: max(3.4%, 12px); top: 81cqw; --tilt: 1.2deg; }

/* when the page opens the phone's result develops under a scan line, top to bottom, once (a clock, not a scroll; none with
   reduced motion): a white sheet over the screen is wiped away, the green line riding its edge */
.hero-develop { display: none; position: absolute; z-index: 1; left: calc(var(--w) * .03); top: calc(var(--w) * .03); width: calc(100% - var(--w) * .06); aspect-ratio: 402 / 874; border-radius: calc(var(--w) * .155); overflow: hidden; background: #fff; pointer-events: none; }

/* a loupe: one line of the screen, lifted onto paper at a size you can read */
.loupe {
  position: absolute; z-index: 2;
  padding: .6rem;
  background: var(--paper-grain);
  border: 1px solid rgba(17, 19, 22, .55); outline: 1px solid rgba(17, 19, 22, .2); outline-offset: -5px;
  border-radius: 3px;
  box-shadow: var(--lift);
  transform: rotate(-.7deg);
}
.loupe img { width: 100%; border-radius: 6px; box-shadow: 0 0 0 1px rgba(17, 19, 22, .08); }
/* the taste and the maker start at 47% of the phone's height, under the bottle's name; the label covers them, wider
   than the phone */
/* on a phone it stays inside the page with a gutter to spare: 95.8cqw is what is left of the art's width after the phone's
   own left edge and this label's, minus 14 px */
.hero-art .loupe--rows { top: 47%; left: 2%; width: min(166%, calc(95.8cqw - 14px)); }

@media (min-width: 60rem) {
  h1 { font-size: clamp(3.5rem, 5.7vw, 4.4rem); }
  /* the first screen is the hero alone: the next heading starts below the fold, never sliced by it */
  .hero { display: grid; align-items: center; min-height: min(calc(100svh - 4rem), 56rem); }
  .hero-grid { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
  .hero-art { aspect-ratio: auto; height: 42rem; margin-inline: 0; }
  /* the plate is the star, as on the phone: twice the column's plant, cropped by the
     page's right edge on purpose, its leftmost leaves stopping short of the headline */
  .plate { left: -6%; width: 158%; top: .1rem; }
  .hero-art { height: 40rem; }
  .hero-grid { padding-bottom: 2.4rem; }
  /* the phone steps over the column line toward the words it proves */
  .hero-art .phone { --w: clamp(14.5rem, 18vw, 17rem); left: -6%; top: auto; bottom: 0; }
  .hero-art .specimen { left: auto; right: -2%; top: 70%; }
  /* on a wide page the label reaches back under the headline, tying the words to the screen */
  .hero-art .loupe--rows { left: -48%; width: 148%; }
}
@media (min-width: 72rem) {
  /* room for a bigger phone: its rows read at 11 px and more */
  .hero-art .phone { --w: clamp(17rem, 21vw, 19rem); left: -4%; }
  .hero-art .loupe--rows { left: -38%; width: 138%; }
}
@media (min-width: 60rem) and (max-width: 72rem) {
  /* on a narrow desktop the headline column is narrow too: the headline and the phone keep the wide page's proportions, the
     phone a little further from the words, and the label reaching back less, clear of the status line */
  h1 { font-size: clamp(3.4rem, 6.2vw, 4.2rem); }
  .hero-art .phone { --w: clamp(15.5rem, 21vw, 17rem); left: -5%; }
  .hero-art .loupe--rows { left: -20%; width: 120%; }
}
@media (min-width: 34rem) and (max-width: 59.99rem) {
  /* a tablet held upright: the headline across the page, the lede and the status side by side under it, and the ask at the
     page's left edge, where the headline starts */
  .hero-copy { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 2.4rem; align-items: start; }
  .hero-copy h1 { grid-column: 1 / -1; }
  .hero-copy .lede { grid-column: 1; grid-row: 2; margin: 1.2rem 0 0; }
  .hero-copy .status { grid-column: 2; grid-row: 2; margin-top: 1.45rem; }
  .hero-copy .ask-cta { grid-column: 1 / -1; grid-row: 3; margin-top: 1.8rem; }
}
@media (max-width: 33.99rem) {
  /* on a phone the plant keeps the page's own gutters, so its leaf tips stop where the text stops; the phone climbs over its
     lower leaves, so the product is on the first screen and not below it */
  .plate { left: 4.3%; width: 91.4%; }
  .hero-art { aspect-ratio: 100 / 186; }   /* the phone (66cqw wide, 2.1 times that tall) ends at 179cqw */
  .hero-art .phone { --w: 66cqw; top: 40cqw; }
  .hero-art .specimen { top: 60cqw; }
  .hero-art .specimen i { display: none; }   /* the journal's name is in the footer; on a phone the tag fits beside the phone, not over it */
}

@media (prefers-reduced-motion: no-preference) {
  .hero-develop { display: block; animation: develop 1.2s cubic-bezier(.5, .05, .3, 1) .55s both; }
  .hero-develop .scan-line { opacity: 0; animation: develop-line 1.2s cubic-bezier(.5, .05, .3, 1) .55s both; }
  @keyframes develop { from { clip-path: inset(0 0 0 0); } to { clip-path: inset(100% 0 0 0); } }
  @keyframes develop-line { 0% { translate: 0 0; opacity: 0; } 8% { opacity: 1; } 92% { opacity: 1; } 100% { translate: 0 100%; opacity: 0; } }
  /* the copy settles into its lines, the headline first; position only, never opacity, so the words are at full contrast
     (and readable by anything that looks) from the first frame. The art follows on its own clock below */
  .hero-copy h1 span, .hero-copy .lede, .hero-copy .status, .hero-copy .ask-cta { animation: line-up .9s cubic-bezier(.16, 1, .3, 1) both; }
  .hero-copy h1 span + span { animation-delay: .09s; }
  .hero-copy .lede { animation-delay: .2s; }
  .hero-copy .status { animation-delay: .28s; }
  .hero-copy .ask-cta { animation-delay: .36s; }
  @keyframes line-up { from { translate: 0 .36em; } to { translate: 0 0; } }
  .plate img { animation: rise .6s ease-out both; }
  .hero-art .phone { animation: rise .5s ease-out .15s both; }
  .hero-art .specimen { animation: rise .4s ease-out .45s both; }
  @keyframes rise { from { opacity: 0; translate: 0 4px; } to { opacity: 1; translate: 0 0; } }
  /* a lifted label starts as the screen's own line, at the screen's size, then rises onto its paper as it scrolls into
     view. --from is the scale that matches the screen; --ox is the one point that lands the label's centre on the line's
     centre at that scale: (line's centre in label widths - from / 2) / (1 - from). The top edge stays put. */
  .loupe { --from: .52; transform-origin: var(--ox, 50%) 0; }

  @keyframes lift {
    from { transform: rotate(0deg) scale(var(--from)); box-shadow: none; }
    to { transform: rotate(var(--to, -.7deg)) scale(1); box-shadow: var(--shade-to, var(--lift)); }
  }
  @supports (animation-timeline: view()) {
    .hero-art .loupe--rows { --ox: 4%; --from: .53; animation: lift linear both; animation-timeline: view(); animation-range: entry 0% cover 34%; }
    /* the app's card is pinned onto the plant as the section comes in */
    .loupe--kin { animation: pin-on linear both; animation-timeline: view(); animation-range: entry 10% entry 100%; }
    @keyframes pin-on { from { opacity: 0; translate: 0 .9rem; } to { opacity: 1; translate: 0 0; } }
  }
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* "your map fills in, state by state": the one-bottle states first, Oaxaca last, then the pins, then its tag */
    .map-fill { animation: map-in linear both; animation-timeline: --map; animation-range: entry calc(6% + var(--i) * 10%) entry calc(20% + var(--i) * 10%); }
    .map-places { animation: map-drop linear both; animation-timeline: --map; animation-range: entry 64% entry 86%; }
    .map-tag { animation: map-in linear both; animation-timeline: --map; animation-range: entry 78% entry 98%; }
    @keyframes map-in { from { opacity: 0; } to { opacity: 1; } }
    @keyframes map-drop { from { opacity: 0; translate: 0 -2.2%; } to { opacity: 1; translate: 0 0; } }
  }
}
@media (prefers-reduced-motion: no-preference) and (min-width: 60rem) {
  /* on a wide page the hero is in view at load, so its label lifts on a clock, once */
  /* the lifted row waits for the scan line: invisible until the screen has developed past it, then it rises onto its paper */
  .hero-art .loupe--rows { --ox: 90%; --from: .54; animation: lift .6s cubic-bezier(.2, .8, .2, 1) 1.25s both, appear .01s linear 1.25s both; animation-timeline: auto, auto; animation-range: normal; }
  @keyframes appear { from { opacity: 0; } to { opacity: 1; } }
}

/* ---------- sections ---------- */
h2 {
  margin: 0 0 .8rem;
  font: 500 clamp(1.9rem, 1.1rem + 2.1vw, 3.2rem)/1.06 var(--display);
  letter-spacing: -.028em;
  word-spacing: .04em;
  text-wrap: balance;
}
.section-copy p { font-size: clamp(1.05rem, 1rem + .3vw, 1.3rem); color: var(--soft); max-width: 27rem; text-wrap: balance; }
.section-copy p span { display: block; }

/* the scan: the app reading a made-up label, and a drawing of what it picks out. The phone, whole, shows the app's own scanner
   mid-read and then, as the drawing finishes, the app's own answer for the same label. The drawing is made here and carries a
   tag that says it is made up: a label sits in the scanner's four corners, a line reads down it and boxes two words, each
   leads to its answer. Scrolled into view it plays once, in order; with no scroll-driven animation or with reduced motion it
   simply shows the finished picture and the answer. On a phone the drawing tells it alone, in one screen. It is the page's
   one centred section, a pause between the zig-zag rows. */
.scan { padding-block: clamp(2rem, 5.5vw, 3rem) clamp(2rem, 5vw, 3rem); overflow-x: clip; }
.scan-stage { display: grid; justify-items: center; gap: 1.8rem; margin-top: 2rem; timeline-scope: --reader; }
/* a phone shows the drawing alone: the same label twice, a screen apart, was one too many on a small screen */
.scan-stage .phone { display: none; }
/* the scanner lies over the answer, same screen, same size; the scan line wipes it away, top to bottom, and the answer shows
   where it has passed. Without the animation it is not there at all */
.phone--scan .scan-screen { display: none; position: absolute; z-index: 1; left: calc(var(--w) * .03); top: calc(var(--w) * .03); width: calc(100% - var(--w) * .06); aspect-ratio: 402 / 874; border-radius: calc(var(--w) * .155); overflow: hidden; pointer-events: none; }
.phone--scan .scan-feed { width: 100%; height: 100%; border-radius: 0; object-fit: cover; }
/* the line sits on the wipe's edge: three pixels of the app's green, and the soft glow the scanner itself draws around it */
.scan-line { position: absolute; inset: 0; opacity: 0; background: linear-gradient(var(--green), var(--green)) 0 0 / 100% 3px no-repeat, linear-gradient(to bottom, rgba(47, 122, 107, 0), rgba(47, 122, 107, .34) 50%, rgba(47, 122, 107, 0)) 0 -2.2rem / 100% 4.4rem no-repeat; }
.reader { position: relative; container-type: inline-size; width: min(100%, 46rem); margin: 0; view-timeline: --reader block; }
.reader-art { display: block; width: 100%; height: auto; overflow: visible; }
.p-kind { font: 400 24px var(--sans); letter-spacing: 2.2px; fill: var(--soft); }
.p-name { font: 600 40px var(--serif); fill: var(--ink); letter-spacing: -.2px; }
.p-plant { font: 600 38px var(--serif); fill: #a33e2c; }
.p-village { font: 400 24px var(--sans); fill: var(--soft); }
.p-lot { font: 400 18px var(--sans); fill: var(--cap); }
.r-box { fill: rgba(47, 122, 107, .1); stroke: var(--green); stroke-width: 2.4; }
.r-leader { fill: none; stroke: var(--green); stroke-width: 4; stroke-linecap: round; stroke-linejoin: round; }
.r-dot { stroke: #fff; stroke-width: 4.5; }
.r-corners { fill: none; stroke: var(--green); stroke-width: 5; stroke-linecap: round; }
.r-sweep { opacity: 0; }
/* the tag on the drawing's own label: it is made up, said where the eye already is */
.r-tag text { font: 600 17px var(--display); letter-spacing: -.1px; fill: var(--ink); }
/* the answers are real text over the drawing, sized by its width: 15 px and 14 px on a phone, 32 px and 20 px wide. Their left
   edge sits at the leaders' dots; the name's middle sits on each dot's line (52.1% and 71.4% of the drawing's height) */
.r-answers { position: absolute; inset: 0; pointer-events: none; }
.r-answer { position: absolute; left: 59.5%; margin: 0; display: grid; gap: .16em; font-size: 4.4cqw; line-height: 1; }
.r-answer b { font: 600 1em/1 var(--display); letter-spacing: -.012em; color: var(--ink); white-space: nowrap; }
.r-answer span { font: 400 max(14px, .62em)/1.15 var(--sans); color: var(--soft); white-space: nowrap; }
.r-answer--plant { top: calc(52.1% - .5em); }
.r-answer--village { top: calc(71.4% - .5em); }
/* a phone: the label large, its two words boxed, and what the app found beneath it as two rows. The drawing is cropped to its
   left 54% (the label and its corners), so the leaders and the answers on its right do not show; each boxed word carries a key
   (the plant's mark, a pin) that its row repeats. Wider than a phone, the keys and rows do not exist */
.r-legend, .r-badge { display: none; }
@media (max-width: 40rem) {
  .scan-stage { gap: 2.6rem; }
  .reader { overflow: hidden; aspect-ratio: 610 / 860; }
  .reader-art { position: absolute; left: 0; top: 0; width: 185.2%; max-width: none; height: auto; }
  .r-leader, .r-dot, .r-answers { display: none; }
  .r-badge { display: block; }
  .r-legend { display: grid; gap: 1rem; width: min(100%, 21rem); margin: -.6rem 0 0; padding: 0; list-style: none; justify-self: center; }
  .r-legend li { display: grid; grid-template-columns: 2.3rem minmax(0, 1fr); grid-template-areas: "key name" "key sub"; column-gap: .9rem; align-items: center; }
  .key { grid-area: key; display: grid; place-items: center; width: 2.3rem; height: 2.3rem; border-radius: 50%; }
  .key--plant { background: #2f7a6b; }
  .key--village { background: #1e5b50; }
  .key svg { width: 1.45rem; height: 1.45rem; }
  .r-legend b { grid-area: name; align-self: end; font: 600 1.2rem/1.15 var(--display); letter-spacing: -.012em; color: var(--ink); }
  .r-legend span { grid-area: sub; align-self: start; font-size: 1rem; line-height: 1.3; color: var(--soft); }
}
@media (min-width: 52rem) {
  /* the group is one object, the whole phone and the drawing, centred under its heading */
  .scan-copy { text-align: center; }
  .scan-copy h2 { font-size: clamp(3rem, 4.8vw, 4.2rem); letter-spacing: -.032em; margin-bottom: 1rem; }   /* a step under the hero's headline at every width */
  .scan-copy h2, .scan-copy p { margin-inline: auto; }
  .scan-stage { grid-template-columns: auto minmax(0, 44rem); justify-content: center; align-items: center; gap: 2rem 3rem; margin-top: 3rem; }
  .scan-stage .phone { display: block; --w: 15.5rem; }
  .reader { width: 100%; }
}
@media (min-width: 72rem) {
  /* room for the phone at a size its rows read at: 11 px and more */
  .scan-stage .phone { --w: 17.5rem; }
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* one reading: the corners close, then the line goes down the label AND down the phone's screen together (the scanner gives way
       to the answer behind the line), and only then does the drawing say what it picked out */
    .r-corners { transform-box: fill-box; transform-origin: center; animation: r-close linear both; animation-timeline: --reader; animation-range: entry 0% entry 54%; }
    .r-sweep { animation: r-sweep linear both; animation-timeline: --reader; animation-range: entry 56% contain 4%; }
    .r-box, .r-dot { animation: r-fade linear both; animation-timeline: --reader; }
    .r-box--plant { animation-range: contain 2% contain 7%; }
    .r-box--village { animation-range: contain 6% contain 11%; }
    .r-leader { stroke-dasharray: 1; animation: r-draw linear both; animation-timeline: --reader; }
    .r-leader--plant { animation-range: contain 8% contain 15%; }
    .r-dot--plant { animation-range: contain 14% contain 17%; }
    .r-leader--village { animation-range: contain 22% contain 29%; }
    .r-dot--village { animation-range: contain 28% contain 31%; }
    .r-answer { animation: r-rise linear both; animation-timeline: --reader; }
    .r-answer--plant { animation-range: contain 15% contain 22%; }
    .r-answer--village { animation-range: contain 29% contain 36%; }
    @keyframes r-close { from { opacity: 0; scale: 1.14; } 55% { opacity: 1; } to { opacity: 1; scale: 1; } }
    @keyframes r-sweep { from { opacity: 0; translate: 0 62px; } 8% { opacity: 1; } 92% { opacity: 1; } to { opacity: 0; translate: 0 518px; } }
    @keyframes r-fade { from { opacity: 0; } to { opacity: 1; } }
    @keyframes r-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
    @keyframes r-rise { from { opacity: 0; translate: -.7em 0; } to { opacity: 1; translate: 0 0; } }
  }
}
/* then the scan line runs down the phone's screen and the scanner gives way to what the app made of the label. Only where the
   drawing's own timeline can reach the phone (timeline-scope) and motion is welcome; everywhere else the phone simply shows
   the answer */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) and (timeline-scope: --reader) {
    .phone--scan .scan-screen { display: block; }
    .phone--scan .scan-feed { animation: scan-wipe linear both; animation-timeline: --reader; animation-range: entry 56% contain 4%; }
    .scan-line { animation: scan-line linear both; animation-timeline: --reader; animation-range: entry 56% contain 4%; }
    @keyframes scan-wipe { from { clip-path: inset(0 0 0 0); } to { clip-path: inset(100% 0 0 0); } }
    @keyframes scan-line { 0% { translate: 0 0; opacity: 0; } 6% { opacity: 1; } 94% { opacity: 1; } 100% { translate: 0 100%; opacity: 0; } }
  }
}
@media (max-width: 40rem) and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .r-corners { animation-range: entry 0% entry 26%; }
    .r-sweep { animation-range: entry 28% entry 74%; }
    .r-box--plant { animation-range: entry 76% entry 84%; }
    .r-box--village { animation-range: entry 82% entry 90%; }
    .r-badge { animation: r-fade linear both; animation-timeline: --reader; }
    .r-badge--plant { animation-range: entry 80% entry 88%; }
    .r-badge--village { animation-range: entry 86% entry 94%; }
    /* each row rises as it comes into view, on its own timeline: the drawing's ran out while the rows were still below the
       fold, and its per-row ranges lost to the shorthand, so the rows sat half faded wherever a reader stopped */
    .r-legend li { animation: r-rise linear both; animation-timeline: view(); animation-range: entry 25% entry 100%; }
  }
}

/* kinship: the one plant both bottles come from, labelled twice, and what the app says about it: its own card, lifted onto
   paper and pinned across the plant. No phone here: the hero and the scan already hold one */
.kin { padding-block: clamp(2.4rem, 6.5vw, 4rem) clamp(2.2rem, 5vw, 3rem); overflow-x: clip; }
.kin-grid { display: grid; gap: 2.4rem; align-items: center; }
.kin-stage { position: relative; display: grid; grid-template-columns: 1fr; }
/* the one plant behind the cuishe and the barril, engraved in 1877 and lifted off its newspaper page, pot and all; it
   stands on the table like the hero's tobalá, with its own soft shadow */
.kin-plate { position: relative; z-index: 1; width: min(58%, 26rem); margin: 0 0 3.6rem .2rem; }   /* the margin is the card's overhang */
.kin-plate img { position: relative; z-index: 1; width: 100%; }
.kin-plate::after {
  content: ""; position: absolute; z-index: 0; left: 22%; right: 20%; bottom: -1%; height: 9%;
  background: radial-gradient(closest-side, rgba(74, 60, 36, .2), rgba(74, 60, 36, 0));
}
.kin-plate .specimen { position: absolute; z-index: 3; padding: .5rem .7rem .45rem; }
.kin-plate .specimen b { font-size: 1rem; }
.kin-plate .tag-a { left: 40%; top: 4%; --tilt: -1.3deg; }
.kin-plate .tag-b { left: 66%; top: 34%; --tilt: 1.2deg; }
.kin-plate figcaption { position: absolute; left: 0; right: 0; top: 100%; margin-top: .5rem; font-size: .875rem; line-height: 1.3; color: var(--cap); }
@media (max-width: 40rem) {
  .kin-plate .specimen span { display: none; }   /* the names stay on the plant */
  .kin-plate figcaption { left: 106%; right: auto; top: 3%; width: 8.4rem; margin: 0; }   /* the card covers the line under the pot; the corner beside the plant's top is free */
}
/* the app's own card, "Same plant as your Barril", pinned across the plant's foot and reaching out to its right */
.kin-plate .loupe--kin { z-index: 4; left: 20%; top: 79%; width: min(150%, 22rem); }
@media (min-width: 40rem) {
  .kin-plate { margin: 0 auto 2.6rem; }
  .kin-plate .loupe--kin { left: 46%; top: 70%; }
}
@media (min-width: 80rem) {
  /* the plant leads, labelled twice, and the app's card is pinned across its lower leaves; the words stand to their right,
     centred on them. Below 80rem the section stays stacked */
  .kin-grid { grid-template-columns: minmax(0, 1fr) 27.4rem; grid-template-areas: "stage copy"; column-gap: 3.4rem; align-items: center; }
  .kin-grid > .section-copy { grid-area: copy; }
  .kin-stage { grid-area: stage; display: block; padding-bottom: 2.6rem; }
  .kin-plate { width: 28rem; margin: 0 0 0 auto; }
  /* on a wide page the card reaches back out to the left, into the stage's open side, across the lower leaves */
  .kin-plate .loupe--kin { left: -47%; top: 60%; width: 22rem; }
  .kin-plate .tag-a { left: 22%; top: 3%; --tilt: -1.3deg; }
  .kin-plate .tag-b { left: auto; right: -3%; top: 50%; --tilt: 1.2deg; }
  .kin-plate figcaption { text-align: center; }
}

/* plain words: the word as the bottle's page shows it, the sheet that opens when it is tapped, and the plain names the app gives
   other label words. The two strips stand one over the other, the same width, like the one screen they were cut from; a touch
   ring marks the tap. Beside them, the heading and the slip of words */
.words { padding-block: clamp(2.8rem, 7vw, 4.4rem); overflow-x: clip; }
.words-grid { display: grid; gap: 1.8rem; }
.words h2 span { display: block; }
.words-stage { display: grid; gap: 1.1rem; }
.words-stage .loupe { position: relative; transform: none; --shade-to: var(--lie); box-shadow: var(--lie); }
.loupe--page { z-index: 1; }
/* the sheet's top corners are clear in the picture itself, so the paper shows there; it brings its own edge */
.loupe--sheet { z-index: 2; }
.loupe--sheet img { border-radius: 0; box-shadow: none; filter: brightness(1.075); }   /* the sheet as the phone draws it, a step brighter, so it reads as the white sheet it is */
/* the plain names the app gives other label words: an open list, ruled, in the page's own type (the paper is for the screens) */
.word-slip { margin: 0; padding: 0; max-width: 100%; }
.word-slip div { display: grid; grid-template-columns: 7.2rem auto; align-items: baseline; gap: 1rem; padding: .95rem 0; border-top: 1px solid rgba(17, 19, 22, .16); }
.word-slip div:last-child { border-bottom: 1px solid rgba(17, 19, 22, .16); }
.word-slip dt { font: 600 1.6rem/1.1 var(--display); letter-spacing: -.02em; color: var(--ink); }
.word-slip dd { margin: 0; font-size: 1.1rem; line-height: 1.3; color: var(--soft); }
@media (min-width: 52rem) {
  .words-grid { grid-template-columns: minmax(0, 1.12fr) minmax(0, .88fr); grid-template-areas: "stage copy" "stage slip"; column-gap: clamp(2.4rem, 6vw, 5.4rem); row-gap: 0; }
  .words-stage { grid-area: stage; align-self: center; }
  .words-copy { grid-area: copy; align-self: end; }
  .word-slip { grid-area: slip; align-self: start; justify-self: start; width: min(100%, 27rem); margin-top: 1.9rem; }
}
@media (min-width: 63rem) {
  .words-grid { grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); column-gap: 3.4rem; }
  .words-stage { justify-self: start; width: min(100%, 35rem); }
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .loupe--sheet { animation: sheet-up linear both; animation-timeline: view(); animation-range: entry 34% cover 44%; }
    @keyframes sheet-up { from { opacity: 0; translate: 0 1.4rem; } to { opacity: 1; translate: 0 0; } }
  }
}

/* the map: the app's map at page size on a sheet of the labels' paper that runs the page's full width, its title
   printed on the sheet like a map's own title, where the other sections put words on white */
.map-spread { padding-block: clamp(1.2rem, 3.4vw, 2rem); }
/* a band, not a card: no shadow on one edge, a hairline on both */
.map-sheet {
  background: var(--paper-grain);
  border-block: 1px solid rgba(23, 20, 16, .08);
  box-shadow: 0 14px 18px -16px rgba(58, 46, 26, .42);   /* the sheet lies on the page: the labels' light, falling below it */
  padding-block: clamp(2rem, 6vw, 3.4rem) clamp(4.6rem, 10vw, 4.6rem);   /* the map's tag hangs below the map: room for it, and a margin under it */
}
/* the paper's specks never touch the words: a halo of the paper's own colour around each letter */
.map-title h2, .map-title p { text-shadow: 0 0 .3rem var(--label), 0 0 .15rem var(--label), 0 0 .08rem var(--label); }
.map-grid { display: grid; gap: 1.2rem; }
/* the one thing the map must say: this is a sample. Reading size, in ink, right under the line it qualifies */
.map-key { display: flex; align-items: center; gap: .3rem; margin-top: .9rem; font-size: .95rem; line-height: 1; color: var(--soft); }
.map-key i { display: block; width: 1.7rem; height: .8rem; background: var(--c); border-radius: 2px; box-shadow: inset 0 0 0 1px rgba(23, 20, 16, .12); }
.map-key span { margin-inline: .35rem .45rem; }
.map-key span:last-child { margin-right: 0; }
.map-title .map-sample { margin-top: 1rem; font-size: 1rem; line-height: 1.4; color: var(--ink); }
.map-stage { position: relative; container-type: inline-size; view-timeline: --map block; }
/* the land, then each tinted state, then the pins, stacked; multiplied onto the paper as one picture, so the tints replace
   the land beneath them instead of darkening it */
.map-art { position: relative; mix-blend-mode: multiply; }
.map-art img { display: block; width: 100%; height: auto; }
.map-art .map-fill { position: absolute; inset: 0; height: 100%; }
/* the villages: a ringed dot at each place the map could place, its name on a leader line in the blank sea below (written by
   tools/map.py). They are real elements, not part of the picture, so they keep one readable size at every width */
.map-places { position: absolute; inset: 0; pointer-events: none; }
.map-leaders { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.map-leaders path { fill: none; stroke: var(--deep); stroke-width: 1.4px; vector-effect: non-scaling-stroke; }
.map-leaders path.halo { stroke: #fff; stroke-width: 3.8px; }   /* a white underlay: the line shows over the dark state too */
.pin { position: absolute; left: calc(var(--x) * 1%); top: calc(var(--y) * 1%); z-index: 2; width: clamp(10px, 1.7cqw, 13px); aspect-ratio: 1; translate: -50% -50%; border-radius: 50%; background: #fff; border: clamp(2.2px, .38cqw, 3px) solid var(--deep); box-shadow: 0 0 0 1.5px rgba(255, 255, 255, .95); }
.plabel { position: absolute; z-index: 2; top: calc(var(--y) * 1%); translate: 0 -50%; font: 600 clamp(.875rem, 1.8cqw, .95rem)/1 var(--display); letter-spacing: -.005em; color: var(--ink); white-space: nowrap; text-shadow: 0 0 .3rem var(--label), 0 0 .15rem var(--label), 0 0 .08rem var(--label); }
.plabel { line-height: 1.12; }
.plabel--l { right: calc((100 - var(--x)) * 1%); margin-right: .5rem; text-align: right; }
.pin--n { display: grid; place-items: center; width: clamp(15px, 2.4cqw, 19px); }
.pin--n::after { content: attr(data-n); font: 700 clamp(.5625rem, 1.25cqw, .6875rem)/1 var(--display); color: var(--deep); }
.plabel--r { left: calc(var(--x) * 1%); margin-left: .5rem; }
/* one tag gives the map its reading: where the sample shelf's bottles cluster */
.map-tag { position: absolute; z-index: 3; left: 67%; top: 100%; --tilt: 0deg; padding: .45rem .7rem .4rem; background: transparent; box-shadow: none; }   /* printed, not stuck on */
.map-tag b { font-size: .95rem; }
@media (max-width: 51.99rem) {
  .map-stage { margin-bottom: 3.4rem; }
  .map-sheet { padding-bottom: 2.2rem; }
}
@media (min-width: 52rem) {
  .map-grid { grid-template-columns: minmax(0, .6fr) minmax(0, 1.4fr); gap: 2.4rem; align-items: center; }
  .map-tag { left: 69%; top: 101%; }   /* in the Pacific below Chiapas, off every tinted state, clear of the names */
}

/* the close: the whole plate the hero's tobalá was cut out of, edge to edge, then the one line and where to say hello */
.close { padding-block: 0 clamp(3.4rem, 8vw, 4.5rem); }
.close-plate { margin: 0; }
/* the print's own top edge, kept hard: the leaf tips touch it in the 1868 print itself. Only its paper's foot softens into the page */
.close-plate img { width: 100%; height: auto; -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 7px), transparent 100%); mask-image: linear-gradient(to bottom, #000 calc(100% - 7px), transparent 100%); }
.close-plate figcaption { margin-top: .8rem; font-size: .875rem; line-height: 1.4; color: var(--cap); }
/* the line gets a section's worth of room and the page's largest type: it is the last beat, not the plate's caption */
.close-row { display: grid; gap: 1.8rem; margin-top: clamp(3.4rem, 8vw, 6rem); }
.close h2 { margin: 0; font: 500 clamp(3rem, 8.4vw, 7.4rem)/.97 var(--display); letter-spacing: -.042em; word-spacing: .04em; }
.close h2 span { display: block; text-wrap: balance; }
.get { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: .9rem 1rem; }
.get > .ask-cta { grid-column: 1 / -1; margin-top: .4rem; max-width: 26rem; }
.app-icon { flex: none; width: 3.4rem; height: 3.4rem; border-radius: 22.4%; box-shadow: var(--lift); }
.get > p:not(.ask-cta) { display: grid; gap: .2rem; max-width: 19rem; }
.get b { font: 600 clamp(1.15rem, 1rem + .6vw, 1.5rem)/1.15 var(--display); letter-spacing: -.01em; }
.get > p:not(.ask-cta) span { color: var(--soft); font-size: .9rem; }
@media (min-width: 52rem) {
  /* under the line, one row: the icon and the status, then the way to say hello */
  .close-row { gap: 2.6rem; }
  .get { grid-template-columns: auto auto auto; justify-content: start; column-gap: 1rem; }
  .get > .ask-cta { grid-column: auto; margin: 0 0 0 2.2rem; }
}


/* ---------- footer ---------- */
.foot { padding-block: 2.4rem 3.4rem; border-top: 1px solid var(--rule); color: var(--cap); font-size: .875rem; }
.foot-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1rem 2rem; }
.foot .word { font-size: 1.25rem; }
.foot .mark { width: 1.6rem; height: 1.6rem; }
.foot-links { display: flex; gap: 1.2rem; }
.foot-links a { font: 600 .9rem/1 var(--display); color: var(--ink); text-decoration: none; padding-block: .95rem; }
.foot-links a:hover, .foot-links a[aria-current="page"] { color: var(--green); }
.foot-notes { display: grid; gap: .6rem; margin-top: 1.6rem; max-width: 44rem; line-height: 1.6; }
.foot-notes a { color: inherit; }

/* ---------- reading pages (privacy, terms, support) ---------- */
.doc { padding-block: clamp(2.4rem, 6vw, 3.6rem) clamp(3.4rem, 9vw, 5.4rem); }

.doc h1 { font-size: clamp(2.5rem, 1.6rem + 3vw, 3.4rem); letter-spacing: -.03em; }
.doc-meta { margin: 1rem 0 2rem; color: var(--cap); font-size: .9rem; }
.doc-lede { font: 600 clamp(1.15rem, 1rem + .6vw, 1.5rem)/1.15 var(--display); letter-spacing: -.01em; color: var(--ink); margin-bottom: 1.6rem; }
.doc ul, .doc ol { margin: 0; padding-left: 1.2rem; display: grid; gap: .9rem; }
.doc li { padding-left: .3rem; }
.doc li::marker { color: var(--green); }
.doc ol > li::marker { font: 600 1rem var(--display); }
.doc li ul { margin-top: .6rem; gap: .4rem; }
.doc strong { font-weight: 600; }
.doc .contact { margin-top: 2rem; }
/* a long policy reads in sections: a heading a size above the text, never a home-page headline */
.doc h2 { margin: 2.4rem 0 .8rem; font: 600 clamp(1.2rem, 1.1rem + .4vw, 1.35rem)/1.2 var(--display); letter-spacing: -.01em; }
.doc h2 + p { margin-bottom: .8rem; }
.doc p + p { margin-top: .8rem; }
/* support: the app's own Settings rows, lifted onto paper; after the questions on a phone, across the band's lower edge on a
   wide page, so the first screen holds the address and where it lives in the app */
.doc-aside--card { display: grid; justify-items: start; margin-top: 2rem; }
.doc-aside--card .loupe--settings { position: relative; width: min(100%, 22rem); transform: rotate(-.7deg); }
.doc-aside--card .specimen { position: relative; z-index: 3; margin: -.5rem 0 0 auto; --tilt: 1.2deg; }
@media (min-width: 60rem) {
  .has-card { position: relative; }
  .ask-band { min-height: 19.5rem; }
  .ask-band > .wrap { display: flex; flex-direction: column; align-items: flex-start; min-height: calc(19.5rem - 6.4rem); }
  .doc-aside--card { position: absolute; z-index: 4; top: 2.6rem; right: max(var(--gutter), calc((100% - var(--shell)) / 2)); width: 29rem; margin: 0; justify-items: end; }
  .doc-aside--card .loupe--settings { width: 100%; }
  .doc-aside--card .specimen { margin: -.5rem 1.2rem 0 0; }
  .doc { display: block; padding-top: 4.4rem; }
}
/* the founder's blanks in a draft: impossible to miss, gone before anything is published */
.fill { background: #fff1b8; box-shadow: 0 0 0 .15em #fff1b8; border-radius: 2px; color: var(--ink); -webkit-box-decoration-break: clone; box-decoration-break: clone; }

.ask { display: grid; gap: .5rem; margin-block: 1.2rem 0; }
/* support: the ask on a band of the labels' paper, like the map's; the specks never touch the words */
.ask-band { background: var(--paper-grain); border-block: 1px solid rgba(23, 20, 16, .08); box-shadow: 0 14px 18px -16px rgba(58, 46, 26, .42); padding-block: clamp(2rem, 6vw, 3.2rem); }
.ask-band h1, .ask-band .doc-meta, .ask-band a { text-shadow: 0 0 .3rem var(--label), 0 0 .15rem var(--label), 0 0 .08rem var(--label); }
.ask-band h1 { font-size: clamp(2.5rem, 1.6rem + 3vw, 3.4rem); letter-spacing: -.03em; }
.ask .doc-meta { margin: 0; font-size: clamp(1.05rem, 1rem + .3vw, 1.15rem); color: var(--soft); }
.ask a { font: 700 clamp(1.5rem, 1.1rem + 2vw, 2.6rem)/1.05 var(--display); letter-spacing: -.03em; overflow-wrap: anywhere; }
.faq { margin: 0; display: grid; gap: 1.6rem; }
.faq dt { font: 600 1.15rem/1.15 var(--display); letter-spacing: -.01em; }
.faq dd { margin: .4rem 0 0; max-width: 34rem; color: var(--soft); text-wrap: pretty; }   /* about 70 characters a line */
.faq dd b { font-weight: 600; color: var(--ink); }   /* the app's own button and tab names */
.faq .plain { margin: 0 0 .5rem; padding-left: 1.1rem; display: grid; gap: .15rem; }
.faq .plain li::marker { color: var(--green); }
@media (min-width: 60rem) {
  .faq { display: block; column-count: 2; column-gap: 5rem; }
  .faq > div { break-inside: avoid; margin-bottom: 2.2rem; }
}

/* ---------- wide page: one right-hand column, last so it wins over each section's own ---------- */
@media (min-width: 72rem) {
  .words-grid { grid-template-columns: minmax(0, 1fr) 27.4rem; }
}
