/* /partner — the merchant and retailer landing page.
 *
 * This is the one page on the site with a different job. Everywhere else is a catalogue
 * read by a shopper; this is a business page read by a workshop owner in Jaipur or a buyer
 * in Berlin, on a phone, in under two minutes, deciding whether to trust a stranger with
 * their goods. It uses site.css's palette and nothing else of its restraint.
 *
 * FOUR THINGS ARE DELIBERATELY UNLIKE THE REST OF THE SITE
 *
 *  1. MANROPE, NOT PLEX MONO, FOR DISPLAY. The site is monospace because a catalogue is
 *     scanned. A headline that has to land in one glance is not scanned, it is SEEN, and
 *     monospace at 90px reads as a terminal rather than as a statement. Manrope 800 is
 *     already self-hosted for /spirituality, so this costs one extra stylesheet link and no
 *     new bytes on the wire. Plex Mono keeps the labels, the numbers and the fine print,
 *     which is where it is genuinely better.
 *
 *  2. A LIGHT SECTION EXISTS. The whole site is dark olive. Three sections here invert to
 *     bone, and the flip is the single biggest reason the page stops reading as one long
 *     column. Contrast was checked in both directions rather than assumed: --chrome on
 *     --bone is 13.9:1, and the olive body text on bone is well clear of AA.
 *
 *  3. TYPE GOES MUCH BIGGER, AND MUCH SMALLER. The display step tops out near 96px and the
 *     eyebrow labels sit at 12px. A flat middle range is what made the first version of
 *     this page boring: everything was legible and nothing was loud.
 *
 *  4. MOTION IS PART OF THE ARGUMENT, NOT DECORATION. The corridor draws itself, the
 *     ticker states the compliance stack without anyone reading it as a list, and the
 *     comparison bars grow so the 0% is felt rather than parsed. All of it is CSS, all of
 *     it is off under prefers-reduced-motion, and none of it hides content when it fails —
 *     see the reveal note near the bottom, which is a bug this page already shipped once.
 *
 * Mobile-first, like site.css: unprefixed rules are the phone.
 */

.p{
  --fs-hero:clamp(2.75rem,1.3rem + 7.4vw,6rem);      /* 44 -> 96 */
  --fs-display:clamp(2rem,1.2rem + 3.6vw,3.5rem);    /* 32 -> 56 */
  --fs-huge:clamp(3.5rem,1.5rem + 10vw,8rem);        /* 56 -> 128, the stat band */
  --disp:'Manrope',ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;
  --ink:#221F16;          /* text on light sections — --chrome, named for its job here */
  --paper:#F2EFE6;        /* --bone, likewise */
  --paper-2:#E4DFCF;
  --r:18px;               /* one corner radius, used everywhere */
}

/* ---------- section furniture ----------
 *
 * site.css carries `main > section:nth-of-type(even){background:var(--band)}` — automatic
 * alternating bands, which is right for a catalogue page whose sections are written one at
 * a time. Here the bands are composed: saffron stat strip, light inversion, dark, band, and
 * so on, and an automatic every-other-one on top of that produced a saffron section that
 * silently rendered olive (measured: the stat band computed to #353022).
 *
 * These four rules turn the automation off for this page and state each background. The
 * selectors are `main.p > section` rather than `.p section` on purpose: they have to MATCH
 * the specificity of the nth-of-type rule (0,1,2) and win on load order, which they do
 * because partner.css is linked after site.css. Sections nested inside the two audience
 * tracks are not direct children of <main>, so the site rule never reached them anyway. */
main.p > section{background:transparent}
main.p > section.light{background:var(--paper)}
main.p > section.p-stats{background:var(--saffron)}
main.p > section.p-end{background:var(--saffron)}

/* ---------- section furniture ---------- */
.p section{padding:72px 0;position:relative}
.p .wrap{width:100%;max-width:1280px;margin:0 auto;padding:0 var(--gutter)}

/* The light inversion. Everything inside re-points at the ink/paper pair. */
.p .light{background:var(--paper);color:var(--ink)}
.p .light h2,.p .light h3,.p .light .big{color:var(--ink)}
.p .light p{color:#4A4433}
.p .light .eyebrow{color:#8A5A22}
.p .light .p-card{background:#fff;border-color:var(--paper-2)}
.p .light .p-card p{color:#5A5340}

.p h2{font-family:var(--disp);font-size:var(--fs-display);line-height:1.02;font-weight:800;
  letter-spacing:-.03em;text-wrap:balance;color:var(--bone)}
.p h3{font-family:var(--disp);font-size:var(--fs-xl);line-height:1.2;font-weight:700;letter-spacing:-.015em;text-wrap:balance}
.p p{font-family:var(--sans);font-size:var(--fs-l);line-height:1.6;text-wrap:pretty;color:var(--bone-dim)}
.p .eyebrow{font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.18em;text-transform:uppercase;
  color:var(--magenta);display:block;margin-bottom:16px}
/* On a phone the heading gets the full column: a cap there turned a nine-word heading into
   eight stacked lines. The cap is for wide viewports, where an unconstrained 56px heading
   would otherwise run to 90 characters.
   THE CAP IS NOT IN ch. It was, and .sec-head computes to IBM Plex Mono at 16px, so the
   intended "22 characters of a 56px display heading" resolved to 22 mono characters:
   211px. Every desktop heading rendered in a 211px column up to 607px tall. The unit has
   to be one that does not depend on the wrapper's font. */
.p .sec-head{margin-bottom:40px}
.p .sec-head p{margin-top:16px;max-width:var(--measure-s)}
.p .accent{color:var(--saffron)}
.p .accent-hot{color:var(--magenta)}

/* ---------- hero ----------
 * The corridor SVG sits behind the type on a phone at low opacity and beside it from 960px,
 * where there is room for both to be at full strength. */
.p-hero{padding:44px 0 56px!important;overflow:hidden}
.p-hero .inner{position:relative;z-index:2}

/* WHY THE HERO'S SELECTION HIGHLIGHT IS A COLOUR SWAP AND NOT A BLOCK.
 *
 * The display headings are set at line-height .96 and .98 — tighter than 1, which is the
 * whole look. A browser does not draw the selection highlight at the LINE BOX height
 * though; it draws it at the font's own ascent + descent. Measured here at 375px: font-size
 * 48.55px, line box 46.6px, selection rectangle 67px. Each line therefore overlaps the one
 * above by 20.4px, and because the backgrounds paint in document order, every line's
 * highlight covers the descenders of the line before it. Selecting the headline made it
 * look broken.
 *
 * Loosening the leading to ~1.38 would fix it and would also throw away the typography, so
 * the highlight stops being a rectangle instead: selection is shown by changing the text
 * colour, which cannot overlap anything. Only these two headings are affected; selection
 * everywhere else on the page stays conventional, because everything else is set above 1.
 *
 * The swap colour is amber rather than saffron: the second half of the headline is already
 * saffron at rest, so a saffron highlight would have left half the line looking unselected.
 *
 * Both ::selection and ::-moz-selection are needed and CANNOT be combined into one rule —
 * an unrecognised selector invalidates the whole list, so a shared block would apply in
 * neither engine. */
.p-hero h1::selection,.p-hero h1 em::selection{background:transparent;color:var(--magenta)}
.p-hero h1::-moz-selection,.p-hero h1 em::-moz-selection{background:transparent;color:var(--magenta)}
.p-end h2::selection{background:transparent;color:var(--chilli)}
.p-end h2::-moz-selection{background:transparent;color:var(--chilli)}
.p-hero h1{
  font-family:var(--disp);font-size:var(--fs-hero);line-height:.96;font-weight:800;
  letter-spacing:-.045em;text-wrap:balance;margin:20px 0 0;color:var(--bone);
}
.p-hero h1 em{font-style:normal;color:var(--saffron);display:block}
.p-hero h1{max-width:min(19em,100%)}
.p-hero .sub{font-size:var(--fs-xl);color:var(--bone);max-width:min(34em,100%);margin-top:24px;line-height:1.45}
.p-hero .cta{display:flex;flex-wrap:wrap;gap:12px;margin-top:34px}

.p-chip{display:inline-flex;align-items:center;gap:10px;font-family:var(--mono);font-size:var(--fs-2xs);
  letter-spacing:.14em;text-transform:uppercase;color:var(--saffron);border:1px solid var(--avocado);
  padding:8px 15px;border-radius:999px;font-weight:600}
.p-chip .dot{width:8px;height:8px;border-radius:50%;background:var(--saffron);flex:none;
  animation:pulse 2.4s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.7)}}

/* ---------- buttons ---------- */
.p .btn-lg{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:56px;
  padding:0 26px;border-radius:999px;font-family:var(--mono);font-size:var(--fs-m);font-weight:600;
  letter-spacing:.02em;text-decoration:none;border:2px solid transparent;cursor:pointer;
  transition:transform .18s cubic-bezier(.2,.8,.3,1),background .18s ease,color .18s ease,box-shadow .18s ease}
.p .btn-lg.pri{background:var(--saffron);color:var(--void)}
.p .btn-lg.pri:hover{transform:translateY(-3px);box-shadow:0 12px 32px -12px var(--saffron)}
.p .btn-lg.sec{border-color:var(--bone-dim);color:var(--bone)}
.p .btn-lg.sec:hover{background:var(--bone);color:var(--void);border-color:var(--bone);transform:translateY(-3px)}
.p .light .btn-lg.sec{border-color:var(--ink);color:var(--ink)}
.p .light .btn-lg.sec:hover{background:var(--ink);color:var(--paper)}
.p .btn-lg svg{flex:none;transition:transform .18s ease}
.p .btn-lg:hover svg{transform:translateX(4px)}

/* ---------- the machine-translation notice ----------
 * Present in the English source carrying `hidden`, so its text is an ordinary translatable
 * string; build-i18n.mjs drops the attribute on the seven copies where the statement is
 * true. It sits under the hero rather than at the foot, because a reader deciding whether
 * to trust a payment term should meet it before the term, not after. */
.p-i18n{background:var(--void-3);border-block:1px solid var(--chicory);padding:14px 0}
.p-i18n p{font-family:var(--mono);font-size:var(--fs-xs);line-height:1.6;color:var(--bone-dim);
  max-width:80ch}
.p-i18n b{color:var(--bone);font-weight:600}
.p-i18n a{color:var(--saffron);text-underline-offset:4px;display:inline-block;padding:6px 0;min-height:44px;line-height:32px}
.p-i18n a:hover{color:var(--bone)}

/* ---------- compliance ticker ----------
 * The stack Guldaar absorbs, stated as a moving strip. As a bulleted list this is the most
 * boring content on the page; as a ticker it reads as "there is a lot of this, and it is
 * handled" in under a second, which is the actual message. */
.p-ticker{border-block:1px solid var(--chicory);background:var(--void-3);padding:16px 0;overflow:hidden;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 8%,#000 92%,transparent)}
.p-ticker .rail{display:flex;width:max-content;animation:slide 38s linear infinite}
.p-ticker ul{display:flex;list-style:none;gap:36px;padding-right:36px;align-items:center}
.p-ticker li{font-family:var(--mono);font-size:var(--fs-s);color:var(--bone-dim);white-space:nowrap;
  display:flex;align-items:center;gap:12px;letter-spacing:.06em}
.p-ticker li::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--avocado);flex:none}
@keyframes slide{to{transform:translateX(-50%)}}
.p-ticker:hover .rail{animation-play-state:paused}

/* ---------- the stat band ----------
 * Three numbers at up to 128px on saffron. This is the page's loudest moment and it is
 * placed early on purpose: price and speed are what the visitor came to find out. */
.p-stats{background:var(--saffron);color:var(--void)}
.p-stats .grid{display:grid;gap:0}
.p-stats .stat{padding:34px 0;border-bottom:2px solid rgba(74,68,51,.22)}
.p-stats .stat:last-child{border-bottom:0}
.p-stats .n{font-family:var(--disp);font-size:var(--fs-huge);font-weight:800;line-height:.82;
  letter-spacing:-.05em;display:block}
.p-stats .n sup{font-size:.34em;vertical-align:super;letter-spacing:0;font-weight:700}
.p-stats .k{font-family:var(--mono);font-size:var(--fs-s);text-transform:uppercase;letter-spacing:.16em;
  display:block;margin-top:18px;font-weight:600}
.p-stats .d{font-family:var(--sans);font-size:var(--fs-m);color:#4A4433;margin-top:10px;max-width:32ch;line-height:1.5}

/* ---------- audience switch ---------- */
/* NOT STICKY, AND FIRST.
   It used to sit below the hero and the ticker, sticky at top:0 — the same 0 the site
   header claims, at z-index 40 against the header's 100, so the moment it stuck it parked
   underneath the bar. It now runs directly under the site nav, where a visitor decides
   which page they are on before reading a headline written for someone else. Once it is
   the first thing on the page there is nothing left for stickiness to rescue. */
.p-switch{background:var(--chrome);border-bottom:1px solid var(--chicory)}
.p-switch .inner{display:flex;gap:8px;padding:10px var(--gutter);max-width:1280px;margin:0 auto}
/* white-space:nowrap because "European retailers" wrapped to two lines while "Indian
   merchants" did not, which made the two tabs different heights and read as a mistake. The
   label steps down a size on a narrow phone rather than breaking. */
/* THE UNSELECTED TAB HAS TO LOOK LIKE A CONTROL.
 *
 * It had a transparent background AND a transparent border, so the only tab that looked
 * tappable was the one already chosen. To half the audience this page's second half simply
 * did not advertise itself: "European retailers" read as a caption sitting beside a button.
 * A visible outline is the whole fix, and it is the difference between a segmented control
 * and a label with a highlight on it. */
.p-switch a{flex:1;min-height:58px;border:2px solid var(--chicory);border-radius:999px;cursor:pointer;
  background:transparent;color:var(--bone);font-family:var(--mono);font-size:var(--fs-s);font-weight:600;
  letter-spacing:.02em;transition:background .2s ease,color .2s ease,border-color .2s ease;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;line-height:1.2;
  white-space:nowrap;padding:0 10px;text-decoration:none}
.p-switch a:hover{border-color:var(--avocado)}
@media (min-width:420px){.p-switch a{font-size:var(--fs-m);letter-spacing:.03em}}
.p-switch a .who{font-size:var(--fs-2xs);font-weight:400;letter-spacing:.12em;text-transform:uppercase;opacity:.7}
.p-switch a[aria-current="page"]{background:var(--saffron);color:var(--void);border-color:var(--saffron)}
.p-switch a[aria-current="page"] .who{opacity:.8}
.p-switch a:focus-visible{outline:3px solid var(--magenta);outline-offset:2px}

/* ---------- bento ----------
 * Deliberately uneven. A grid of six identical cards is the shape the first version of this
 * page had, and it is why it read as a specification rather than as an argument. */
.p-bento{display:grid;gap:14px}
.p-card{background:var(--void-2);border:1px solid var(--chicory);border-radius:var(--r);padding:28px 24px;
  position:relative;overflow:hidden;transition:transform .2s ease,border-color .2s ease}
.p-card:hover{transform:translateY(-4px);border-color:var(--avocado)}
.p-card h3{margin-bottom:12px}
.p-card p{font-size:var(--fs-m)}
.p-card .note{font-family:var(--mono);font-size:var(--fs-s);color:var(--bone-dim);margin-top:14px;line-height:1.6;
  padding-top:14px;border-top:1px solid var(--chicory)}
.p-card .num{font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.2em;color:var(--magenta);
  display:block;margin-bottom:16px}
/* The feature card: bigger type, a colour field, spans both columns from 720px. */
.p-card.wide{background:linear-gradient(150deg,var(--void-2),var(--void-3));border-color:var(--avocado)}
.p-card.wide h3{font-size:var(--fs-2xl);letter-spacing:-.025em}
.p-card.hot{border-left:4px solid var(--paprika)}

/* The listing mock: what a merchant's product looks like once it is on the rail. Drawn in
   CSS from real fields rather than shown as a screenshot of software that is still being
   built — a mock of a real listing is honest, a screenshot of a fiction is not. */
.p-mock{background:var(--void);border:1px solid var(--chicory);border-radius:12px;padding:16px;margin-top:20px;
  font-family:var(--mono);font-size:var(--fs-2xs)}
.p-mock .row{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-bottom:1px dashed var(--chicory);color:var(--bone-dim)}
.p-mock .row:last-child{border-bottom:0}
.p-mock .row b{color:var(--bone);font-weight:600}
.p-mock .ok{color:var(--saffron)}
.p-mock .tag{display:inline-block;background:var(--avocado);color:var(--void);padding:3px 8px;border-radius:4px;
  font-weight:700;letter-spacing:.08em}

/* ---------- price ---------- */
.p-price{background:var(--void);border:2px solid var(--saffron);border-radius:var(--r);padding:30px 24px}
.p .light .p-price{background:#fff;border-color:var(--ink)}
.p-price .big{font-family:var(--disp);font-size:clamp(3rem,1.6rem + 6vw,5rem);font-weight:800;line-height:.9;
  letter-spacing:-.05em;color:var(--bone)}
.p-price .big s{color:var(--bone-dim);font-size:.28em;font-weight:600;margin-left:12px;letter-spacing:0}
.p .light .p-price .big s{color:#7A7360}
.p-price .per{font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:.14em;text-transform:uppercase;
  color:var(--magenta);margin-top:14px}
.p .light .p-price .per{color:#8A5A22}
.p-price ul{list-style:none;margin-top:24px;display:grid;gap:0}
.p-price li{padding:14px 0;display:flex;justify-content:space-between;gap:16px;align-items:baseline;
  font-family:var(--sans);font-size:var(--fs-m);color:var(--bone-dim);border-bottom:1px solid var(--chicory)}
.p .light .p-price li{color:#5A5340;border-color:var(--paper-2)}
.p-price li:last-child{border-bottom:0}
.p-price li b{font-family:var(--mono);color:var(--bone);white-space:nowrap;font-weight:700}
.p .light .p-price li b{color:var(--ink)}
.p-price li b.zero{color:var(--saffron);font-size:var(--fs-l)}
.p .light .p-price li b.zero{color:#5C6B0E}

/* ---------- corridor stages ---------- */
.p-corridor{position:relative;padding-left:36px}
.p-corridor::before{content:"";position:absolute;left:9px;top:10px;bottom:10px;width:2px;
  background:linear-gradient(var(--saffron),var(--chicory))}
.p-stage{position:relative;padding:0 0 40px}
.p-stage:last-child{padding-bottom:0}
.p-stage::before{content:"";position:absolute;left:-32px;top:6px;width:14px;height:14px;border-radius:50%;
  background:var(--void);border:3px solid var(--saffron)}
.p-stage .when{font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.16em;text-transform:uppercase;color:var(--magenta)}
.p-stage h3{margin:8px 0 10px}
.p-stage p{font-size:var(--fs-m)}

/* ---------- refusals ---------- */
.p-no{display:grid;gap:12px;list-style:none}
.p-no li{display:flex;gap:16px;align-items:flex-start;background:var(--void-2);border:1px solid var(--chicory);
  border-radius:var(--r);padding:20px;font-family:var(--sans);font-size:var(--fs-m);color:var(--bone-dim);line-height:1.55}
.p .light .p-no li{background:#fff;border-color:var(--paper-2);color:#5A5340}
.p-no li b{display:block;color:var(--bone);font-weight:700;margin-bottom:5px;font-family:var(--disp);font-size:var(--fs-l)}
.p .light .p-no li b{color:var(--ink)}
.p-no .x{flex:none;width:30px;height:30px;border-radius:50%;background:var(--chilli);color:var(--bone);
  display:grid;place-items:center;font-family:var(--mono);font-size:var(--fs-m);font-weight:700}

/* ---------- FAQ ---------- */
.p-faq{display:grid;gap:10px}
.p-faq details{background:var(--void-2);border:1px solid var(--chicory);border-radius:var(--r);overflow:hidden}
.p-faq details[open]{border-color:var(--avocado)}
.p-faq summary{cursor:pointer;list-style:none;padding:22px;min-height:56px;display:flex;gap:18px;align-items:center;
  justify-content:space-between;font-family:var(--disp);font-size:var(--fs-l);font-weight:700;color:var(--bone);letter-spacing:-.01em}
.p-faq summary::-webkit-details-marker{display:none}
.p-faq summary::after{content:"";flex:none;width:14px;height:14px;border-right:2px solid var(--magenta);
  border-bottom:2px solid var(--magenta);transform:rotate(45deg) translate(-3px,-3px);transition:transform .2s ease}
.p-faq details[open] summary::after{transform:rotate(-135deg) translate(-3px,-3px)}
.p-faq summary:focus-visible{outline:3px solid var(--magenta);outline-offset:-3px}
/* The FAQ sits in a light section, so it needs the inverted set too — without these the
   accordion stayed dark-on-paper, which read as a foreign component dropped into the page. */
.p .light .p-faq details{background:#fff;border-color:var(--paper-2)}
.p .light .p-faq details[open]{border-color:var(--ink)}
.p .light .p-faq summary{color:var(--ink)}
.p .light .p-faq summary::after{border-color:#8A5A22}
.p .light .p-faq .body p{color:#5A5340}
.p .light .p-faq .body b{color:var(--ink)}
.p-faq .body{padding:0 22px 22px}
.p-faq .body p + p{margin-top:14px}

/* ---------- contact composer ---------- */
.p-ask{background:var(--void-2);border:2px solid var(--saffron);border-radius:var(--r);padding:28px 24px}
.p-ask .field{margin-top:20px}
.p-ask label{display:block;font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:.14em;
  text-transform:uppercase;color:var(--magenta);margin-bottom:10px}
.p-ask select,.p-ask input{width:100%;min-height:56px;padding:0 16px;border-radius:12px;background:var(--void);
  border:2px solid var(--chicory);color:var(--bone);font-family:var(--mono);font-size:var(--fs-m)}
.p-ask select:focus-visible,.p-ask input:focus-visible{outline:3px solid var(--magenta);outline-offset:1px;border-color:var(--magenta)}
.p-ask .preview{margin-top:22px;padding:18px;border-radius:12px;background:var(--void);border:1px dashed var(--avocado);
  font-family:var(--mono);font-size:var(--fs-s);color:var(--bone-dim);line-height:1.65;white-space:pre-wrap}
.p-ask .cta{display:grid;gap:12px;margin-top:22px}
.p-ask .direct{margin-top:20px;font-family:var(--mono);font-size:var(--fs-s);color:var(--bone-dim);line-height:1.7}
/* 18px tall as plain inline links. They are the fallback route for anyone who does not
   trust a prefilled button, so they get a real target rather than a courtesy mention. */
.p-ask .direct a{color:var(--saffron);display:inline-block;padding:9px 0;min-height:44px;line-height:26px}

/* ---------- closing call ---------- */
.p-end{background:var(--saffron);color:var(--void);text-align:center}
.p-end h2{color:var(--void);font-size:var(--fs-hero);line-height:.98;max-width:16ch;margin:0 auto}
.p-end p{color:#4A4433;max-width:44ch;margin:20px auto 0;font-size:var(--fs-xl)}
.p-end .cta{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:32px}
.p-end .btn-lg.pri{background:var(--void);color:var(--saffron)}
.p-end .btn-lg.pri:hover{background:var(--chrome);box-shadow:none}
.p-end .btn-lg.sec{border-color:var(--void);color:var(--void)}
.p-end .btn-lg.sec:hover{background:var(--void);color:var(--saffron);border-color:var(--void)}

/* ---------- reveal ----------
 * Content is VISIBLE BY DEFAULT and the animation is added on top. This page shipped the
 * other way round once — reveals driven by `animation-timeline: view()`, which made
 * `opacity: 0` the default state with the timeline as the only thing bringing it back. Any
 * context that does not resolve the timeline then renders a blank page: print, a screenshot,
 * an in-app WebView, an older Chromium on an Android two versions behind. Measured here, a
 * capture returned an empty viewport while the DOM reported every card at opacity 1.
 *
 * That is exactly this audience — a workshop owner opening a WhatsApp link inside WhatsApp's
 * own browser. Nothing hides until partner.js has confirmed the browser can do the work. */
.rv{opacity:1}
.js-rv .rv{opacity:0;transform:translateY(26px);transition:opacity .6s ease,transform .6s cubic-bezier(.2,.8,.3,1)}
.js-rv .rv.seen{opacity:1;transform:none}

@media (prefers-reduced-motion: reduce){
  .js-rv .rv{opacity:1;transform:none;transition:none}
  .p .btn-lg:hover,.p-card:hover{transform:none}
  .p-ticker .rail,.p-chip .dot{animation:none}
}

/* ---------- wider viewports ----------
 * Everything above this comment is the phone. These blocks add columns to it; none of them
 * is required for the page to be readable, which is why the base state is the one written
 * without a query around it. */
@media (min-width:720px){
  /* 104px top AND bottom, on eleven sections, was about 1,700px of the merchant track
     spent on nothing. 80 is the working rhythm; the three full-width moments keep more,
     below, because a loud section only reads as loud against a quieter neighbour. */
  .p section{padding:80px 0}
  .p .sec-head{max-width:min(46rem,100%)}
  .p-bento{grid-template-columns:repeat(2,1fr)}
  .p-card.wide{grid-column:1 / -1}
  .p-card{padding:32px 30px}
  .p-stats .grid{grid-template-columns:repeat(3,1fr);gap:0}
  /* The band was 522px tall to hold roughly 300px of content: 104 of section padding with
     another 44 stacked inside every stat. The numbers were never the problem. */
  .p section.p-stats{padding:72px 0}
  .p-stats .stat{border-bottom:0;border-right:2px solid rgba(74,68,51,.22);padding:32px 28px 32px 0}
  .p-stats .stat:last-child{border-right:0}
  .p-ask .cta{grid-template-columns:repeat(2,1fr)}
  .p-price{padding:40px 36px}
  .p-ask{padding:36px 32px}
  .p-no li{padding:24px 26px}
}
@media (min-width:960px){
  .p-hero{padding:72px 0 88px!important}
  .p-split{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:start}
  .p .sec-head{margin-bottom:52px}
}

/* THE DEAD HALF.
 *
 * A section was one column of full-width blocks: a heading capped at 736px inside a 1280px
 * container, and under it a stack of accordion rows running the full 1220. That left 544px
 * of empty column beside every heading on a laptop, and put a four-word summary like "Who
 * carries the legal responsibility" on a line a metre wide, where the eye has to travel the
 * whole width to find the value at the other end.
 *
 * So: heading left, content right, from 1024px up. The selector asks what a section
 * CONTAINS rather than requiring a class on each one — the page already had five sections
 * in exactly this shape and adding a sixth should not mean remembering to tag it. Sections
 * built on .p-split are excluded by the same test, because they already own their columns.
 *
 * :has() is unsupported in older browsers, and there the page keeps the single column it
 * has always had. That is the correct failure: the layout is an improvement on a wide
 * screen, never a requirement for reading. */
@media (min-width:1024px){
  .p section .wrap:has(> .sec-head + .p-rows){
    display:grid;grid-template-columns:minmax(300px,1fr) 1.9fr;gap:0 64px;align-items:start;
  }
  .p section .wrap:has(> .sec-head + .p-rows) > .sec-head{margin-bottom:0;position:sticky;top:88px}
  .p .wrap:has(> .sec-head + .p-rows) .sec-head{max-width:none}
  /* The heading column is narrower than the 46rem cap, so the cap would do nothing here
     except stop a two-line heading from using its own column. */
}

/* The trade-terms card is shorter than the rows beside it, so the section used to end with
   a dead corner under it. Sticky instead: the price stays on screen while the buyer reads
   what the price includes, which is the one place on this page where two things genuinely
   want to be visible at once. */
@media (min-width:1024px){
  #terms .p-price{position:sticky;top:88px}
}

/* The loud full-width moments keep their air, so the rhythm varies instead of flattening. */
@media (min-width:720px){
  .p section#rail,.p section.p-end{padding:104px 0}
}

/* ==========================================================================
   V3 — photography, the scroll corridor, and the take-rate calculator
   ==========================================================================
   Three additions, each replacing prose that used to sit on this page.
   The word count in <main> went from 2,587 to roughly 950; nothing was deleted,
   it moved behind a tap or into a picture.

   PHOTOGRAPHY. Self-hosted, derived by scripts/build-images.mjs into the same
   400/800/1200/1600 WebP+JPEG set as every other image here, so CSP img-src stays
   'self' and no third-party origin sees a visitor. Sources are Unsplash (licence
   permits this use); the files are images/partner-*.jpg. The pictures are MATERIAL —
   cloth, brass, silver, freight. No faces, no workshop interiors: this page sits
   beside a promise about not inventing things, and a stock artisan photographed in
   someone else's workshop next to the words "your workshop" is exactly that.
   ========================================================================== */

/* ---------- photographic hero ----------
 * The image is a background layer with a gradient scrim over it rather than an <img>
 * behind text: at this size the art direction is the scrim, and a CSS layer cannot be
 * dragged out of place by the text reflowing on a narrow phone. The <img> still exists
 * in the markup for the crawler and for anyone with images disabled. */
.p-hero{position:relative;isolation:isolate}
.p-hero .shot{position:absolute;inset:0;z-index:0;overflow:hidden}
.p-hero .shot img{width:100%;height:100%;object-fit:cover;object-position:60% 40%}
.p-hero .shot::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(34,31,22,.72) 0%,rgba(34,31,22,.58) 38%,rgba(34,31,22,.86) 78%,var(--void) 100%);
}
@media (min-width:960px){
  .p-hero .shot::after{background:linear-gradient(96deg,rgba(34,31,22,.96) 0%,rgba(34,31,22,.86) 46%,rgba(34,31,22,.34) 78%,rgba(34,31,22,.62) 100%)}
  .p-hero .shot img{object-position:72% 42%}
}
.p-hero .inner{position:relative;z-index:2}
/* The one line in the first screen that tells a European buyer this page is also for them.
   Measured before it existed: the audience switch sat 1,689px down, 2.08 screens on a
   phone, behind a hero and a stat band written entirely for merchants. */
.p-alt{margin-top:26px;font-family:var(--mono);font-size:var(--fs-s);color:var(--bone-dim)}
.p-alt a{color:var(--saffron);text-underline-offset:5px;display:inline-block;padding:8px 0;min-height:44px;line-height:28px}
.p-alt a:hover{color:var(--bone)}
/* THE OTHER AUDIENCE HAS TO SEE A CONTROL, NOT A SENTENCE.
   A European buyer meets a merchant headline, a merchant subhead and a compliance ticker
   before the audience tabs appear. This link is their exit from the first screen, and as
   plain underlined text it read as a footnote to the two buttons above it. */
.p-alt-btn{display:inline-flex;align-items:center;gap:9px;border:1px solid var(--avocado);
  border-radius:999px;padding:10px 18px!important;text-decoration:none;line-height:1.2!important;
  min-height:44px;transition:background .2s ease,color .2s ease,border-color .2s ease}
.p-alt-btn:hover{background:var(--saffron);border-color:var(--saffron);color:var(--void)!important}
/* One line of proof above the fold, because the argument that this is operated rather than
   announced was sitting eight sections down in the FAQ. */
.p-trust{margin-top:22px;font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:.04em;
  color:var(--bone-dim);display:flex;align-items:center;gap:10px}
.p-trust::before{content:"";flex:none;width:22px;height:1px;background:var(--saffron)}
.p .light .p-alt-btn{border-color:var(--ink)}

.p-scroll-cue{display:flex;align-items:center;gap:10px;margin-top:40px;font-family:var(--mono);
  font-size:var(--fs-2xs);letter-spacing:.2em;text-transform:uppercase;color:var(--bone-dim)}
.p-scroll-cue i{display:block;width:1px;height:34px;background:linear-gradient(var(--saffron),transparent);
  animation:cue 2.2s ease-in-out infinite}
@keyframes cue{0%,100%{transform:scaleY(.4);transform-origin:top;opacity:.4}50%{transform:scaleY(1);opacity:1}}

/* ---------- the scroll corridor ----------
 * One sticky viewport, four stages, driven by scroll. It replaces three text sections:
 * "what the rail carries", "two ways your goods travel" and the old bulleted corridor.
 *
 * The fallback is the whole design, not an afterthought. Without JavaScript the sticky
 * frame is not pinned and every stage renders in sequence as ordinary blocks — which is
 * to say, the markup is a readable list of four stages and the animation is an
 * enhancement laid over it. Nothing here is display:none in the base state. */
.p-rail{position:relative}
/* The frame is pinned at EVERY width, not only on desktop. The first build made it sticky
   from 960px and left the phone with four stages stacked inside a single screen — so the
   trigger band never saw a stage change and the sequence sat on stage one the whole way
   down. Measured: at a 390x844 viewport all four steps occupied 780px together.
   On a phone the picture now holds under the header while the stages scroll beneath it,
   which is the version of this that is actually worth building. */
.p-rail .sticky{position:sticky;top:84px;z-index:1}
.p-rail .frame{position:relative;border-radius:var(--r);overflow:hidden;background:var(--void-3);
  border:1px solid var(--chicory);aspect-ratio:4/3;max-height:38vh}
.p-rail .frame img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:0;
  transition:opacity .7s ease,transform 1.2s ease;transform:scale(1.06)}
.p-rail .frame img.on{opacity:1;transform:scale(1)}
.p-rail .frame::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(34,31,22,.15),rgba(34,31,22,.85))}
/* Without JS the first image is simply shown; .js-on is added by partner.js. */
/* Each <img> is the first-of-type inside its OWN <picture>, so `img:first-of-type` matched
   all four and the no-JS fallback showed every photograph stacked. The picture element is
   what has to be selected. */
.p:not(.js-on) .p-rail .frame picture:first-of-type img{opacity:1;transform:none}
.p-rail .badge{position:absolute;left:16px;bottom:16px;z-index:2;display:flex;flex-wrap:wrap;gap:8px;right:16px}
.p-rail .badge span{font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.1em;background:rgba(34,31,22,.82);
  border:1px solid var(--avocado);color:var(--saffron);padding:6px 10px;border-radius:999px;
  opacity:0;transform:translateY(6px);transition:opacity .4s ease,transform .4s ease}
.p-rail .badge span.on{opacity:1;transform:none}
.p:not(.js-on) .p-rail .badge span{opacity:1;transform:none}

/* Each stage gets most of a screen, so scrolling through the section plays it one stage at
   a time rather than showing all four at once. */
.p-steps{margin-top:26px;display:grid;gap:0}
.p-step{padding:24vh 0 24vh 20px;border-left:2px solid var(--chicory);transition:border-color .4s ease,opacity .4s ease}
.p-step .k{font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.18em;text-transform:uppercase;color:var(--bone-dim)}
.p-step h3{margin:8px 0 8px;font-size:var(--fs-xl)}
.p-step p{font-size:var(--fs-m)}
/* Inactive stages were at .42 opacity. That is a chrome value applied to CONTENT: 16px body
   copy at 6.22:1 fell to roughly 2.6:1 against the ground, under the 4.5:1 floor, and three
   of the four stages are inactive at any moment — so most of this section was unreadable to
   anyone whose eye wandered ahead of the scroll position.
   .85 is the value the measurement chose, not a guess: .72 still composited to 4.08:1, under
   the floor, so it went up until the inactive text cleared 4.5:1 against the ground. The
   emphasis given up is paid back by the saffron rule and heading on the active stage, which
   was always the stronger signal — dimming the other three was doing the same job twice and
   damaging legibility to do it. */
.js-on .p-step{opacity:.85}
.js-on .p-step.on{opacity:1;border-left-color:var(--saffron)}
.js-on .p-step.on h3{color:var(--saffron)}
@media (min-width:960px){
  .p-rail .cols{display:grid;grid-template-columns:1fr 1fr;gap:56px;align-items:start}
  .p-rail .sticky{top:104px}
  .p-rail .frame{aspect-ratio:3/4;max-height:none}
  .p-steps{margin-top:0}
  .p-step{padding:34vh 0 34vh 26px}
}

/* ---------- take-rate calculator ----------
 * The bar chart said 0% and 25%. This says: on YOUR number, you keep this much more
 * money. Same facts, one that a person feels. Every rate in it is the published rate
 * quoted elsewhere on this page — the calculator invents nothing. */
.p-calc{background:var(--void);border:2px solid var(--saffron);border-radius:var(--r);padding:26px 22px}
.p .light .p-calc{background:#fff;border-color:var(--ink)}
.p-calc .amount{font-family:var(--disp);font-size:clamp(2.5rem,1.4rem + 5vw,4.25rem);font-weight:800;
  line-height:.92;letter-spacing:-.045em;color:var(--bone);display:block}
.p .light .p-calc .amount{color:var(--ink)}
.p-calc label{display:block;font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:.14em;
  text-transform:uppercase;color:var(--magenta);margin-bottom:12px}
.p .light .p-calc label{color:#8A5A22}
.p-calc input[type=range]{width:100%;height:44px;background:transparent;-webkit-appearance:none;appearance:none;margin-top:6px}
.p-calc input[type=range]::-webkit-slider-runnable-track{height:8px;border-radius:999px;background:var(--void-3)}
.p-calc input[type=range]::-moz-range-track{height:8px;border-radius:999px;background:var(--void-3)}
.p .light .p-calc input[type=range]::-webkit-slider-runnable-track{background:var(--paper-2)}
.p .light .p-calc input[type=range]::-moz-range-track{background:var(--paper-2)}
.p-calc input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:32px;height:32px;
  border-radius:50%;background:var(--saffron);border:3px solid var(--void);margin-top:-12px;cursor:grab}
.p-calc input[type=range]::-moz-range-thumb{width:32px;height:32px;border-radius:50%;background:var(--saffron);
  border:3px solid var(--void);cursor:grab}
.p .light .p-calc input[type=range]::-webkit-slider-thumb{border-color:#fff;background:#8A8B32}
.p .light .p-calc input[type=range]::-moz-range-thumb{border-color:#fff;background:#8A8B32}
.p-calc input[type=range]:focus-visible{outline:3px solid var(--magenta);outline-offset:6px;border-radius:999px}
.p-calc .out{margin-top:26px;display:grid;gap:2px;background:var(--chicory);border-radius:12px;overflow:hidden}
.p .light .p-calc .out{background:var(--paper-2)}
.p-calc .out div{background:var(--void-2);padding:15px 16px;display:flex;justify-content:space-between;gap:14px;
  align-items:baseline;font-family:var(--sans);font-size:var(--fs-m);color:var(--bone-dim)}
.p .light .p-calc .out div{background:#fff;color:#5A5340}
.p-calc .out b{font-family:var(--mono);font-weight:700;color:var(--bone);white-space:nowrap}
.p .light .p-calc .out b{color:var(--ink)}
.p-calc .out .us{background:var(--void-3)}
.p .light .p-calc .out .us{background:#F7F4EA}
.p-calc .out .us,.p-calc .out .us b{color:var(--saffron)}
.p .light .p-calc .out .us,.p .light .p-calc .out .us b{color:#5C6B0E}
/* This is the one piece of fine print a merchant will actually read, because it is where
   the arithmetic is justified. 12px at 4.72:1 cleared AA and no more; 13px and a darker ink
   put it comfortably clear on the light ground it sits on. */
.p-calc .foot{font-family:var(--mono);font-size:var(--fs-xs);color:var(--bone-dim);margin-top:16px;line-height:1.75}
.p .light .p-calc .foot{color:#615B4B}

/* ---------- disclosure rows ----------
 * The detail that used to be body copy. Same words, one tap away, and the tap is the
 * signal that someone wants them. */
.p-rows{display:grid;gap:10px}
.p-rows details{background:var(--void-2);border:1px solid var(--chicory);border-radius:14px}
.p .light .p-rows details{background:#fff;border-color:var(--paper-2)}
.p-rows details[open]{border-color:var(--avocado)}
.p-rows summary{cursor:pointer;list-style:none;padding:18px 20px;min-height:56px;display:flex;gap:16px;
  align-items:center;justify-content:space-between;font-family:var(--disp);font-weight:700;
  font-size:var(--fs-l);color:var(--bone)}
.p .light .p-rows summary{color:var(--ink)}
.p-rows summary::-webkit-details-marker{display:none}
.p-rows summary::after{content:"+";font-family:var(--mono);color:var(--magenta);font-size:var(--fs-xl);
  flex:none;line-height:1;transition:transform .2s ease}
.p .light .p-rows summary::after{color:#8A5A22}
.p-rows details[open] summary::after{transform:rotate(45deg)}
.p-rows summary:focus-visible{outline:3px solid var(--magenta);outline-offset:-3px}
.p-rows .body{padding:0 20px 20px}
.p-rows .body p{font-size:var(--fs-m)}
.p-rows .body p + p{margin-top:12px}

/* ---------- pattern band ----------
 * A strip of real block print between sections. It does one job: it reminds a reader
 * scrolling a page about customs paperwork what is actually being shipped. */
.p-strip{height:180px;position:relative;overflow:hidden;border-block:1px solid var(--chicory)}
.p-strip img{width:100%;height:100%;object-fit:cover;object-position:center}
.p-strip::after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,var(--void),rgba(74,68,51,.35) 30%,rgba(74,68,51,.35) 70%,var(--void))}
.p-strip .cap{position:absolute;z-index:2;inset:auto 0 auto 0;top:50%;transform:translateY(-50%);text-align:center;
  font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.24em;text-transform:uppercase;color:var(--bone)}
@media (min-width:720px){.p-strip{height:240px}}

/* ---------- media card ---------- */
.p-media{border-radius:var(--r);overflow:hidden;position:relative;border:1px solid var(--chicory);aspect-ratio:4/3}
.p-media img{width:100%;height:100%;object-fit:cover;display:block}
.p-media figcaption{position:absolute;left:0;right:0;bottom:0;padding:18px 20px;
  background:linear-gradient(transparent,rgba(34,31,22,.9));font-family:var(--mono);font-size:var(--fs-s);color:var(--bone)}

/* ---------- at a glance (26 Sep 2026) ----------
 * The decisions a busy reader makes, as one label/value list, instead of behind accordions. */
.p-glance{display:grid;gap:0;border-top:1px solid var(--chicory)}
.p-glance > div{display:grid;gap:4px;padding:16px 0;border-bottom:1px solid var(--chicory)}
.p-glance dt{font-family:var(--mono);font-size:var(--fs-xs);letter-spacing:.14em;text-transform:uppercase;color:var(--saffron)}
.p-glance dd{margin:0;color:var(--bone)}
.p .light .p-glance > div,.p .light .p-glance{border-color:var(--paper-2)}
.p .light .p-glance dt{color:#8A5A22}
.p .light .p-glance dd{color:var(--ink)}
@media (min-width:720px){.p-glance > div{grid-template-columns:200px 1fr;gap:24px}}

/* ---------- styles that sell ---------- */
.p-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:14px;list-style:none}
@media (min-width:720px){.p-grid{grid-template-columns:repeat(4,1fr)}}
.p-grid li{background:#fff;border:1px solid var(--paper-2);border-radius:14px;overflow:hidden;color:var(--ink)}
.p-grid img{display:block;width:100%;aspect-ratio:1;object-fit:cover}
.p-grid .t{display:block;padding:10px 12px 0;font-size:var(--fs-s);font-weight:600;line-height:1.3}
.p-grid .pr{display:flex;justify-content:space-between;padding:6px 12px 12px;font-family:var(--mono);font-size:var(--fs-xs)}
.p-grid .pr b{color:#5C6B0E}
.p-grid .sold{font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.1em;text-transform:uppercase;color:#8A5A22;padding:0 12px 12px;display:block}

/* ---------- posters: one A4 page, printed from the browser ---------- */
.poster{max-width:900px;margin:0 auto;padding:24px var(--gutter);background:#fff;color:var(--ink)}
.poster h1{font-family:var(--disp);font-size:clamp(1.8rem,1rem + 3vw,2.6rem);line-height:1.05;margin:6px 0 10px}
.poster .p-grid{grid-template-columns:repeat(4,1fr);gap:8px}
.poster .p-grid .t{font-size:11px;padding:6px 8px 0}
.poster .p-grid .pr{padding:4px 8px 8px}
.poster .p-glance > div{padding:8px 0;grid-template-columns:150px 1fr;gap:12px}
.poster .p-glance dd,.poster .p-glance dt{color:var(--ink)}
.poster-bar{display:flex;gap:10px;flex-wrap:wrap;margin:16px 0}
.poster .btn-lg.sec{color:var(--ink);border-color:var(--ink)}
.poster-foot{margin-top:14px;font-family:var(--mono);font-size:12px}
@media print{
  @page{size:A4;margin:10mm}
  header.site,footer,.poster-bar,.p-switch{display:none!important}
  body{background:#fff}
  .poster{padding:0}
}

/* ---------- mobile-first pass (26 Sep 2026) ---------- */
/* Hero: the paragraph carries its own shade, so the photograph can show through. */
.p-hero .sub{text-shadow:0 1px 12px rgba(34,31,22,.8)}
@media (max-width:719px){
  .p-hero{padding:28px 0 40px!important}
  .p-hero .cta{margin-top:24px}
  .p-hero .cta .btn-lg{width:100%;justify-content:center}
  .p-hero .sub{margin-top:16px}
}
.p-trust .who-av{flex:none;width:32px;height:32px;border-radius:50%;background:var(--saffron);color:var(--void);
  display:grid;place-items:center;font-weight:800;font-family:var(--disp);letter-spacing:0}
.p-trust:has(.who-av)::before{display:none}
/* Stats: one row of three on a phone, number and label only. */
.p-stats .grid{grid-template-columns:repeat(3,1fr)}
.p-stats .stat{border-bottom:0;border-right:2px solid rgba(74,68,51,.22);padding:4px 10px}
.p-stats .stat:first-child{padding-left:0}
.p-stats .stat:last-child{border-right:0}
.p-stats .d{display:none}
@media (max-width:719px){
  .p section.p-stats{padding:28px 0}
  .p-stats .n{font-size:clamp(2.2rem,11vw,3.4rem)}
  .p-stats .k{font-size:10px;letter-spacing:.1em;margin-top:8px;display:block}
}
/* Glance answers in the reading face; the key figure in bold. */
.p-glance dd{font-family:var(--sans);font-size:var(--fs-m);line-height:1.55}
.p-glance dd b{font-weight:700;color:var(--saffron)}
.p .light .p-glance dd b,.poster .p-glance dd b{color:var(--ink)}
/* Steps: swipe on a phone, three across on desktop. */
.p-steps{display:grid;grid-auto-flow:column;grid-auto-columns:78%;gap:12px;overflow-x:auto;
  scroll-snap-type:x mandatory;list-style:none;padding-bottom:8px;counter-reset:st}
.p-steps li{scroll-snap-align:start;background:var(--void-2);border:1px solid var(--chicory);border-radius:var(--r);padding:22px}
.p-steps li::before{counter-increment:st;content:counter(st);display:grid;place-items:center;width:40px;height:40px;
  border-radius:50%;background:var(--saffron);color:var(--void);font-family:var(--disp);font-weight:800;font-size:1.2rem;margin-bottom:14px}
.p-steps b{display:block;font-family:var(--disp);font-size:var(--fs-l);color:var(--bone);margin-bottom:6px}
.p-steps span{font-family:var(--sans);font-size:var(--fs-m);color:var(--bone-dim);line-height:1.5}
@media (min-width:720px){.p-steps{grid-auto-flow:row;grid-template-columns:repeat(3,1fr);overflow:visible}}
/* Product grid: a swipe row on a phone, a grid from tablet up. Posters always print the grid. */
@media (max-width:719px){
  .p .p-grid:not(.poster .p-grid){display:grid;grid-auto-flow:column;grid-auto-columns:43%;grid-template-columns:none;
    overflow-x:auto;scroll-snap-type:x mandatory;padding-bottom:8px}
  .p .p-grid:not(.poster .p-grid) li{scroll-snap-align:start}
}
.p-swipe-hint{font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.12em;text-transform:uppercase;color:#8A5A22;margin-bottom:10px}
@media (min-width:720px){.p-swipe-hint{display:none}}

/* Audit fixes, 26 Sep 2026 */
.p .light .p-alt-btn{color:var(--ink)}
@media (max-width:719px){.p-grid .pr{flex-direction:column;gap:2px}}
.p-after{margin-top:24px}
.poster-h2{margin:16px 0 6px;font-size:1.1rem}
.poster-ol{margin:8px 0 0 20px}
/* Saffron on cream fails contrast; light sections take the olive the terms already use. */
.p .light .accent{color:#5C6B0E}
/* Swipe rows: a slim, on-palette scrollbar instead of the browser's white bar. */
.p-steps,.p-grid{scrollbar-width:thin;scrollbar-color:var(--saffron) transparent}

/* Final audit, 26 Sep 2026 */
/* Card text in the reading face; the badge no longer clips at narrow widths. */
.p-grid .t{font-family:var(--sans)}
.p-grid .sold{letter-spacing:.06em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Posters on a phone: two columns and a compact button row. Print keeps four. */
.poster .eyebrow{color:#8A5A22}
.poster-h2{color:var(--ink)}
.poster-bar .btn-lg{min-height:44px;padding:0 18px;font-size:var(--fs-s)}
@media (max-width:719px){
  .poster .p-grid{grid-template-columns:repeat(2,1fr);gap:10px}
  .poster .p-grid .t{font-size:13px}
  .poster .p-glance > div{grid-template-columns:1fr;gap:4px}
}
@media print{.poster .p-grid{grid-template-columns:repeat(4,1fr)!important}}

/* ---------- desktop and tablet pass (26 Sep 2026) ---------- */
/* Contact: the left column says what happens after you press send, instead of sitting empty. */
.p-next{list-style:none;counter-reset:nx;margin:28px 0 8px;display:grid;gap:14px}
.p-next li{counter-increment:nx;font-family:var(--sans);display:flex;gap:14px;align-items:flex-start;font-size:var(--fs-m);color:var(--bone);line-height:1.45}
.p-next li::before{content:counter(nx);flex:none;width:30px;height:30px;border-radius:50%;border:1.5px solid var(--saffron);
  color:var(--saffron);display:grid;place-items:center;font-family:var(--mono);font-size:var(--fs-s);font-weight:700}
@media (min-width:960px){#ask .p-split{align-items:center}}
/* Glance and terms: cards on wide screens, so no line runs 150 characters. */
@media (min-width:960px){
  section .p-glance{grid-template-columns:repeat(2,1fr);gap:14px;border-top:0}
  section .p-glance.terms{grid-template-columns:repeat(3,1fr)}
  section .p-glance > div{display:block;padding:22px 24px;border:1px solid var(--chicory);border-radius:var(--r);background:var(--void-2)}
  section .p-glance dt{margin-bottom:10px}
  section .p-glance.terms dd b{display:block;font-family:var(--disp);font-size:1.6rem;line-height:1.15;margin-bottom:2px}
}
/* Products: six across on a wide screen, two rows instead of three. */
@media (min-width:1200px){.p .p-grid:not(.poster .p-grid){grid-template-columns:repeat(6,1fr)}}
@media (max-width:959px){section .p-glance.terms dd b::after{content:" \00B7"}}
@media (min-width:960px){section .p-glance:not(.terms) > div:last-child:nth-child(odd){grid-column:1 / -1}}

/* ---------- motion pass (26 Sep 2026) ----------
 * Every hidden starting state below sits under .js-rv, which partner.js adds only when it is
 * running and motion is allowed. Without the script, or in a WebView that drops it, the page
 * is simply complete. See the .rv note above for the blank-page incident that set this rule. */

/* The route: the business in one line. */
.p-route{margin:0 0 28px}
.p-route svg{display:block;width:100%;height:auto;overflow:visible}
.p-route .track{fill:none;stroke:var(--chicory);stroke-width:2;stroke-dasharray:2 8;stroke-linecap:round}
.p-route .draw{fill:none;stroke:var(--saffron);stroke-width:3;stroke-linecap:round;stroke-dasharray:1;stroke-dashoffset:0}
.js-rv .p-route .draw{stroke-dashoffset:1;transition:stroke-dashoffset 2.6s cubic-bezier(.45,0,.55,1)}
.js-rv .p-route.seen .draw{stroke-dashoffset:0}
.p-route .stop{fill:var(--void);stroke:var(--saffron);stroke-width:3}
.p-route .parcel{fill:var(--magenta)}
.route-labels{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-top:6px;font-family:var(--mono);
  font-size:var(--fs-xs);letter-spacing:.04em;color:var(--bone);line-height:1.35}
.route-labels span:nth-child(2){text-align:center}
.route-labels span:nth-child(3){text-align:right;color:var(--saffron)}
.p-route-sec{padding-bottom:24px!important}
.p-route-sec .p-route{margin:0}

/* Staggered reveals: containers are observed, children arrive 60ms apart. */
.js-rv .stg > *{opacity:0;transform:translateY(8px);transition:opacity .3s ease,transform .3s ease;
  transition-delay:calc(var(--i,0) * 60ms)}
.js-rv .stg.seen > *{opacity:1;transform:none}
/* Shorter travel for everything else on this page than the 26px the old page used. */
.js-rv .rv{transform:translateY(10px)}

@media (prefers-reduced-motion:no-preference){
  /* Hero: a slow settle on the photograph, and the copy arriving in reading order. */
  .p-hero .shot img{animation:p-settle 14s cubic-bezier(.2,.7,.2,1) both}
  .p-hero .inner > *{animation:p-rise .6s cubic-bezier(.2,.8,.3,1) both}
  .p-hero .inner > :nth-child(2){animation-delay:.08s}
  .p-hero .inner > :nth-child(3){animation-delay:.18s}
  .p-hero .inner > :nth-child(4){animation-delay:.28s}
  /* One page to the other: a cross-fade, with the chosen tab sliding across. */
  @view-transition{navigation:auto}
  .p-switch a[aria-current="page"]{view-transition-name:p-tab}
  /* FAQ answers slide rather than jump, where the browser supports it. */
  :root{interpolate-size:allow-keywords}
  .p-rows details::details-content{height:0;overflow:clip;transition:height .3s ease,content-visibility .3s allow-discrete}
  .p-rows details[open]::details-content{height:auto}
  /* The message preview flashes when it changes, so the form visibly answers. */
  .p-ask .preview.flash{animation:p-flash .6s ease}
}
@keyframes p-settle{from{transform:scale(1.08)}to{transform:scale(1)}}
@keyframes p-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes p-flash{0%{border-color:var(--saffron);background:rgba(220,231,117,.12)}100%{}}

/* Desktop hover: cards lift, photographs lean in. Touch screens never see it. */
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .p-grid li,.p-steps li,section .p-glance > div{transition:transform .25s ease,border-color .25s ease,box-shadow .25s ease}
  .p-grid li:hover{transform:translateY(-4px);box-shadow:0 14px 30px rgba(34,31,22,.18)}
  .p-grid img{transition:transform .5s ease}
  .p-grid li:hover img{transform:scale(1.04)}
  .p-steps li:hover,section .p-glance > div:hover{border-color:var(--avocado)}
}

/* Route, second pass: thicker on phones, delivery times per leg, and an arrival moment. */
.p-route .track{stroke-width:3}
.p-route .draw{stroke-width:5}
.p-route .stop{stroke-width:4}
.route-legs{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:4px}
.route-legs span{justify-self:center;font-family:var(--mono);font-size:var(--fs-2xs);letter-spacing:.08em;text-transform:uppercase;
  color:var(--void);background:var(--saffron);border-radius:999px;padding:5px 10px;text-align:center;line-height:1.3}
.route-note{margin-top:14px;font-size:var(--fs-s)!important;color:var(--bone-dim)}
.js-rv .route-legs span{opacity:0;transform:translateY(6px);transition:opacity .4s ease,transform .4s ease}
.js-rv .p-route.seen .route-legs span:first-child{opacity:1;transform:none;transition-delay:.5s}
.js-rv .p-route.seen .route-legs span:last-child{opacity:1;transform:none;transition-delay:1.9s}
.p-route.arrived .stop:last-of-type{animation:p-pop .5s ease}
.p-route.arrived .route-labels span:last-child{animation:p-glow 1s ease}
@keyframes p-pop{50%{transform:scale(1.6)}}
@keyframes p-glow{40%{color:var(--bone)}}
.p-route .stop{transform-box:fill-box;transform-origin:center}

/* Route on wide screens: a readable size, labels under their stops. */
.p-route{max-width:880px}
.p .light .p-alt a:not(.p-alt-btn){color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.p-grid li{display:flex;flex-direction:column}
.p-grid .sold{margin-top:auto}

/* Product cards aligned with the wardrobe's (26 Sep 2026): portrait photo, no box, the
   badge as a chip on the photo, a short caption underneath. The badge sits where the eye
   lands first, so "Bestseller" is proof at a glance instead of a footnote. */
.p-grid li{position:relative;background:none;border:0;border-radius:0;overflow:visible}
.p-grid picture{display:block;overflow:hidden;border-radius:6px}
.p-grid img{aspect-ratio:4/5}
.p-grid .t{padding:10px 0 0;font-size:var(--fs-s);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.p-grid .pr{padding:4px 0 0}
.p-grid .sold{position:absolute;top:8px;left:8px;margin:0;padding:5px 9px;border-radius:999px;
  background:var(--void);color:var(--saffron);font-size:10px;letter-spacing:.08em;white-space:nowrap;overflow:visible}
.p-grid .sold::before{content:"\2605\00A0"}
.p-grid li:has(.sold:not(:empty)) .sold{box-shadow:0 2px 8px rgba(0,0,0,.25)}
.p-grid .sold.trend{background:var(--magenta);color:#fff}
.p-grid .sold.trend::before{content:"\2197\00A0"}
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .p-grid li:hover{transform:none;box-shadow:none}
}
.poster .p-grid .sold{top:6px;left:6px;font-size:9px;padding:3px 7px}
.p-grid .t{min-height:calc(2 * 1.3em + 10px);line-height:1.3}
#ask h2 + p{margin-top:12px}
#ask .direct{margin-bottom:28px}
